ROS1學習筆記--通信編程

    前面有一個博客筆者概述了關於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

參考網站:action

官方網站:官方wiki


文章參考了ROS大神古月老師的文章,真的是大神(膜拜膜拜):古月居


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章