1. 程式人生 > >8、ROS使用C++編寫一個簡單的Publisher和Subscriber

8、ROS使用C++編寫一個簡單的Publisher和Subscriber

一、Publisher節點

“節點” 是一個連線著ROS框架的可執行檔案,這裡我們用C++寫一個publisher節點 (命名為”talker”) ,不斷地釋出一條資訊。

首先進入包目錄的src資料夾:

roscd beginner_tutorials
cd src

然後建立一個名為'talker.cpp'的檔案,內容為:

/*
"ros/ros.h"裡面包含了ROS系統內最常用的一些標頭檔案,包含此檔案,便可以使用ROS的核心功能。
*/
#include "ros/ros.h"

/*
"std_msgs/String"是由std_msgs包自動生成的標頭檔案,定義了String資訊型別,包含此檔案,我們就可以使用String型別
*/
#include "std_msgs/String.h" #include <sstream> /** * This tutorial demonstrates simple sending of messages over the ROS system. */ int main(int argc, char **argv) { /** * ros::init()函式需要兩個系統命令列引數argc和argv, * 由此可以執行命令列傳來的任何ROS引數和節點的重新命名 * 第三個引數是節點的名字, * 注意這裡只能使用基本命名, * 即名字裡不能含有'/' * 在使用ROS的其他部分之前,你必須呼叫ros::init() **/
ros::init(argc, argv, "talker"); /** * NodeHandle 是節點同ROS系統交流的主要介面 * NodeHandle 在構造的時候會完整地初始化本節點 * NodeHandle 析構的時候會關閉此節點 */ ros::NodeHandle n; /** * 我們通過advertise() 函式指定我們如何在給定的topic上釋出資訊 * 它會觸發對ROS master的呼叫,master會記錄話題釋出者和訂閱者 * 在advertise()函式執行之後,master會通知每一個訂閱此話題的節點 * 兩節點間由此可以建立直接的聯絡 * advertise()會返回一個Publisher物件,使用這個物件的publish方法我們就可以在此話題上釋出資訊 * 當返回的Publisher物件的所有引用都被銷燬的時候,本節點將不再是該話題的釋出者 * 此函式是一個帶模板的函式,需要傳入具體的型別進行例項化 * 傳入的型別就是要釋出的資訊的型別,在這裡是String * 第一個引數是話題名稱 * 第二個引數是資訊佇列的長度,相當於資訊的一個緩衝區 * 在我們釋出資訊的速度大於處理資訊的速度時 * 資訊會被快取在先進先出的資訊佇列裡 */
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); /** * Rate loop_rate()構造了一個Rate類的物件 * 用來指定我們釋出資訊的頻率,單位為hz,即每秒多少次 * 在我們呼叫Rate物件的sleep()方法之前,資訊釋出的頻率不會發生變化 **/ ros::Rate loop_rate(10); /** * 一個記錄我們釋出的資訊數量的計數器 * 它用來為每條資訊產生不一樣的字串 * 如'1 message','2 message'這樣 */ int count = 0; /** * roscpp預設會構造一個咱SIGINT的處理器來處理系統訊號 * 當出現以下情況之一的時候ros:ok()會返回false: * 1.接受到了一個SIGINT訊號(Ctrl-C) * 2.在程式中呼叫了ros::shutdown() * 3.所有的ros::NodeHandle物件及引用都被銷燬 **/ while (ros::ok()) { /** * 這是一個message物件,我們向其中填入資料,然後可以釋出它 */ std_msgs::String msg; /** * 我們釋出的資訊的格式為"hello world 1/2/3..." */ std::stringstream ss; ss << "hello world " << count; msg.data = ss.str(); /** * ROS_INFO是對ROS系統對printf/cout的替代 */ ROS_INFO("%s", msg.data.c_str()); /** * publish()函式用來發布資訊 * 資訊型別必須為前一步例項化advertised()時使用的模板引數的型別 * 這裡為String */ chatter_pub.publish(msg); /** * 在這個簡單的應用中,我們沒有使用任何回撥函式 * 所以ros::spinOnce()的呼叫不是必須的 * 但是一直在程式碼裡呼叫ros::spinOnce()是個好習慣 * 它可以保證你指定的回撥函式會被呼叫 */ ros::spinOnce(); /** * 呼叫Rate物件的sleep方法來使我們前面指定的資訊釋出頻率10Hz生效 */ loop_rate.sleep(); ++count; } return 0; }

各語句的功能如註釋所示,不再講解。

二、Subscriber節點

Publisher節點寫完,我們有了資訊的釋出者,接下來我們寫一個Subcriber節點來接收資訊。

同樣在beginner_tutorials包目錄的src資料夾下,建立一個名為'listener.cpp的檔案,內容為:

#include "ros/ros.h"
#include "std_msgs/String.h"

/**
 * 傳給NodeHandle.subscribe()的回撥函式
 * 它的引數是一個share_ptr型別的只能指標,功能這裡不細講
 */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");

  ros::NodeHandle n;

  /**
   * 引數1:話題名稱
   * 引數2:資訊佇列長度
   * 引數3:回撥函式,每當一個資訊到來的時候,這個函式會被呼叫
   * 返回一個ros::Subscriber類的物件,當此物件的所有引用都被銷燬是,本節點將不再是該話題的訂閱者
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
  /**
   * 呼叫ros::spin()函式,進入一個迴圈
   * 不斷地接受資訊,然後執行回撥函式,知道ros::ok()返回false
   */ 
  ros::spin();

  return 0;
}

程式碼比較簡單,功能如註釋所示。

三、構建專案

1、修改CMakeList.txt

繼續使用我們上一節使用的自己建立的beginner_tutorial包。

此包的CMakeLists.txt檔案應該如下所示(移除不必要的註釋之後):

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

我們需要新增以下內容:

include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

最終的CMakeLists.txt應該像這樣:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(FILES Num.msg)
add_service_files(FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

這將建立兩個可執行檔案talkerlistenner,預設存放於~/catkin_ws/devel/lib/<package name>

2、解釋

add_dependencies(talker
beginner_tutorials_generate_messages_cpp
)

add_dependencies宣告某CMake target對另外的CMake target的依賴。

這確保了在我們使用某個包裡定義的資訊型別之前生成它們的標頭檔案。在我們使用其他包的資訊型別的時候,也要新增類似這樣的依賴。例如再新增一條:

add_dependencies(talker
  beginner_tutorials_generate_messages_cpp
  roscpp_generate_messages_cpp
  )

3、構建

進入我們工作空間的頂層目錄執行:

catkin_make  

等待一會兒專案即可構建成功。

四、執行節點

首先要啟動ROS:

roscore

然後進入工作目錄將包匯出到全域性:

cd ~/catkin_ws
source ./devel/setup.bash

執行talker節點:

rosrun beginner_tutorials talker 

將看到類似於:

[ INFO] [1461049103.046522470]: hello world 0
[ INFO] [1461049103.146694944]: hello world 1
[ INFO] [1461049103.246582083]: hello world 2
[ INFO] [1461049103.346603146]: hello world 3
[ INFO] [1461049103.446525742]: hello world 4
[ INFO] [1461049103.546518768]: hello world 5

執行listener節點:

rosrun beginner_tutorials listener 

將看到類似於:

[ INFO] [1461049221.914537834]: I heard: [hello world 3]
[ INFO] [1461049222.014228659]: I heard: [hello world 4]
[ INFO] [1461049222.114193464]: I heard: [hello world 5]
[ INFO] [1461049222.214291045]: I heard: [hello world 6]
[ INFO] [1461049222.314210593]: I heard: [hello world 7]
[ INFO] [1461049222.414272158]: I heard: [hello world 8]

節點執行成功。

相關推薦

8ROS使用C++編寫一個簡單PublisherSubscriber

一、Publisher節點 “節點” 是一個連線著ROS框架的可執行檔案,這裡我們用C++寫一個publisher節點 (命名為”talker”) ,不斷地釋出一條資訊。 首先進入包目錄的src資料夾: roscd beginner_tutorials

如何用Java編寫一個簡單的服務器客戶機

exce 解決 對賬 location exceptio acc 明顯 隊列 客戶 今天我要向大家介紹的是自己編寫的一個比較簡單的服務器和客戶機程序,註意一下哦,比較簡單。好了,閑話休提,砸門直入主題。 小編先從客戶機和服務器的模型開始講解。

編寫一個簡單的TCP服務端客戶端

不同的 大連 終端 服務器端 com 讀寫 所有 字數 資料 下面的實驗環境是linux系統。 效果如下: 1.啟動服務端程序,監聽在6666端口上 2.啟動客戶端,與服務端建立TCP連接 3.建立完TCP連接,在客戶端上向服務端發送消息 4.斷開

使用libeventboost編寫一個簡單的tcp伺服器

寫這個東西主要是為了學習libevent的基本用法,以及學習下boost的執行緒庫。 程式結構比較簡單:   1. 首先是建立一個監聽socke。   2. 將這個監聽的socket繫結到一個event事件上,然後等待有客戶過來連線。   3. 如果響應到監聽so

ROS 編寫一個簡單的釋出者訂閱者(C++)

0 編寫釋出者節點 節點是在ROS裡面的一個專業術語,它可以被ROS的網路所連結。在這裡我們將建立一個名叫“talker”的釋出者節點,它將連續的廣播一個訊息。 改變你現在的位置到你之前在catkin 工作區域裡建立的beginner_tutorials 包。 0.1 程

ROS學習--(十二)編寫一個簡單的釋出器(publisher

1.mkdir -p ~/catkin_ws/src/beginner_tutorials/src 先在beginner_tutorials下建立一個src。 -p的意思是如果路徑中有不存在的資料夾,則建立 2。在新建的資料夾裡面新建cpp檔案,talker

(九)用C++編寫簡單publishersubscriber

cmake_minimum_required(VERSION 2.4.6) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) # Set the build type. Options are: # Coverage : w/ debu

【原】shell編寫一個簡單的jmeter自動化壓測腳本

image tac vbo 用戶數 osx dot png das uvc 在公司做壓力測試也挺長時間了,每次測試前環境數據準備都需要話費較長時間,所以一直在考慮能不能將整個過程實現自動化進行,於是就抽空寫了一個自動化腳本,當然這個腳本目前功能十分簡陋,代碼也不完善,很有很

Golang中使用heap編寫一個簡單高效的定時器模塊

true pop 邏輯 .com light 初始化 callback before cell 定時器模塊在服務端開發中非常重要,一個高性能的定時器模塊能夠大幅度提升引擎的運行效率。使用Golang和heap實現一個通用的定時器模塊,代碼來自:https://github.

手把手教你編寫一個簡單的PHP模塊形態的後門

cpp rest xtu job ring 事先 們的 original call 看到Freebuf 小編發表的用這個隱藏於PHP模塊中的rootkit,就能持久接管服務器文章,很感興趣,苦無作者沒留下PoC,自己研究一番,有了此文 0×00. 引言 PHP是一個非常流行

編寫一個簡單的單元測試用例

ide bsp span log 加減乘除 self teardown __main__ str 開發一個簡單的計算器,用於計算兩個數的加減乘除,示例: 1 class Calculator(): 2 ‘‘‘實現簡單的加減乘除‘‘‘ 3 def _

使用js編寫一個簡單的運動框架

parse 獲取當前值 進一步 filter 獲取 win logs alt htm 下班後,,沒事搗鼓搗鼓個人的小愛好。 首先,說明我的這個運動框架(css所有屬性)也是常見的框架一種,健壯性並不是太好,對於新手學習倒是挺好,,若是大神,老司機請拐彎。

編寫一個簡單登錄驗證需要記錄日誌,Servlet中的Cookie

cookie java servlet j2ee javaweb 登錄驗證並記錄日誌之前介紹了如何使用Server、mysql、tomcat等知識點編寫了一個簡單的登錄驗證。但是現在有了一個新的需求,我想要在登錄成功的時候往數據庫記錄一條日誌,登錄失敗的時候也要記錄一下。這個日誌要記錄用戶

如何用VBS編寫一個簡單的惡搞腳本

程序 一個 復制 文件夾 組合 不支持 文字 sendkeys 選項 windows系統的電腦, 首先右擊桌面,選擇新建-文本文檔,在桌面上新建一個文本文檔; 隨後打開計算機或者是我的電腦,點擊其中的組織(xp系統多為工具),選擇下面的文件夾和搜索

編寫一個簡單的Web應用

AC info 覆蓋 圖片 ram cnblogs 類目 基於 div 上一篇我們搭建了一個簡單的Web應用:http://www.cnblogs.com/lay2017/p/8468515.html 本文將基於上一篇搭建的應用,編寫一些內容 編寫Servlet類 編寫J

用 Go 編寫一個簡單的 WebSocket 推送服務

年輕 sync 狀態 升級 ati .com 客戶端 我們 png 用 Go 編寫一個簡單的 WebSocket 推送服務 本文中代碼可以在 github.com/alfred-zhong/wserver 獲取。 背景 最近拿到需求要在網頁上展示報警信息。以往報警信息都

練習題,使用多線程編寫一個簡單的文本處理工具

tar 處理工具 utf txt nco opened odin 文本處理工具 while 一. 練習題要求:  編寫一個簡單的文本處理工具,具備三個任務,一個接收用戶輸入,一個將用戶輸入的內容格式化成大寫,一個將格式化後的結果存入文件二. 分析:  三個任務,那就是三個線

編寫一個簡單的C++程式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

編寫一個簡單的記事本(C#實現)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using Syste

Python 進階—編寫一個簡單的web 伺服器

使用Python 庫的bottle 可以執行一個純淨的Python 服務,該服務會響應HTTP 請求 1. 首先安裝bottle(基於Python3) sudo apt-get install python3-bottle 2. 建立頁面的程式碼 from bottle