前面有一個博客筆者概述了關於ROS1的通信機制,現在就來通過幾個例子來講講具體的通信編程
一、話題編程
話題編程流程:
- 創建發佈者
- 創建訂閱者
- 添加編譯選項
- 運行可執行程序
1.創建一個發佈者
- ROS節點初始化
- 編寫相關的節點信息,包括髮布的話題名和消息類型
- 按一定的頻率循環發佈消息
#include <sstream>
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char **argv)
{
// ROS節點初始化
ros::init(argc, argv, "talker");
// 創建節點句柄,NodeHandle是與ROS系統通信的主要接入點,執行節點的初始化
ros::NodeHandle n;
// 創建一個Publisher,發佈名爲chatter的topic,消息類型爲std_msgs::String
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// 設置循環的頻率爲10hz
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok()) //ctrl+c時。ros::OK返回值“false"
{
// 初始化std_msgs::String類型的消息
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
// 發佈消息
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
// 循環等待回調函數
ros::spinOnce();
// 按照循環頻率延時
loop_rate.sleep();
++count;
}
return 0;
}
2.實現一個訂閱者
- ROS節點初始化
- 訂閱需要的話題
- 循環等待話題消息,接收到消息後進入callback函數
- 在callback函數中完成消息處理
#include "ros/ros.h"
#include "std_msgs/String.h"
//回調函數
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;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
3.編譯代碼
- 在cmakelist中添加鏈接庫和依賴
引用參考網站:simple advertiser/pulisher
二、服務編程
1.實現一個服務器
- 初始化ROS節點
- 創建一個server
- 循環等待服務請求,進入回調函數
- 在回調函數中完成服務功能,並反饋應答數據
#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
//接受srv文件中定義的請求(req輸入參數)和響應(res輸出參數)類型,
bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
//將輸入參數中的請求數據求和,結果放入響應變量
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle n;
//創建一個名爲add_two_ints的回調函數,註冊回調函數add()
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
//循環等待回調函數
ros::spin();
return 0;
}
2.實現一個客戶端
- 初始化ROS節點
- 創建一個client
- 發佈服務請求數據
- 等待應答結果
#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
#include <cstdlib>
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_client");
//從終端獲取兩個加數
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
}
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
//創建一個beginner_tutorials::AddTwoInts的srv文件,這裏需要在工作空間beginner_tutorials下創建一個AddTwoInts.srv文件
beginner_tutorials::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
3.配置相應cmakelist.tex的執行文件、鏈接庫、依賴
*自定義.srv文件時,要在package.xml和cmakelist.txt文件中添加功能包依賴和編譯選項
參考網站:simple server/client
三、動作編程
有時間再添加
action的接口
由上圖可知action的接口:
- goal:發佈任務目標
- cancel:請求取消任務
- status:通知客戶端當前的狀態
- feedback:週期反饋任務運行的監控數據
- result:向客戶端發送任務的執行結果,只發布一次
參考網站:action
官方網站:官方wiki
文章參考了ROS大神古月老師的文章,真的是大神(膜拜膜拜):古月居