找人做网站注意哪些,健身器材 网站模版,浏览器73qcc,湖北最新数据消息ROS学习笔记#xff08;二#xff09;#xff1a;话题通信、服务通信的了解和对应节点的搭建#xff08;C和Python#xff09; 前言一、Topics话题通信#xff08;C#xff09;0、自定义msg消息类型文件1、发布者#xff08;Publisher#xff09;2、订阅者#xff08… ROS学习笔记二话题通信、服务通信的了解和对应节点的搭建C和Python 前言一、Topics话题通信C0、自定义msg消息类型文件1、发布者Publisher2、订阅者Subscriber3、更改配置 二、Services服务通信C0、定义srv服务类型文件1、客户端Client2、服务端Service3、更改配置 前言
在ros这种分布式框架中各个节点可以独立的运行但是在实际运用的多数情况下各个节点之间都需要有一定的联系或者说是信息的共享因此在程序的设计上各节点之间的通信尤为重要。 官方wiki教程链接ROS Tutorials 如下所示可让我们对ros通信机制有初步的了解其中也包括了对应通信节点的搭建。
关于工作空间的搭建参考第一篇文章 ROS学习笔记一安装ROS并搭建一个自己的ROS工作空间 这里主要记录在程序上如何实现节点通信。
一、Topics话题通信C
话题通信是指节点间以发布订阅的方式进行通信大体流程为发布者以一定的频率不断地在某个话题上发送消息出去然后订阅者在ros masters这个平台上通过话题名称发现发布者发送了消息然后接收其消息进行处理。可同时存在多个订阅者关注同一个话题也可同时存在多个发布者在同一个话题上发布消息当然一个订阅者也可以关注多个话题一个发布者也可以发布多个话题。 关于话题通信官方的C案例链接Writing a Simple Publisher and Subscriber (C)
0、自定义msg消息类型文件
首先在该功能包下创建msg文件夹然后在创建一个.msg文件。即
mkdir msg
touch msg/xx.msg该文件的编写格式为 类型 名称
如: int32 num_hi然后需要进入package.xml更改配置分别添加下面两行
build_dependmessage_generation/build_dependexec_dependmessage_runtime/exec_depend即下图所示 然后进入CmakeLists.txt添加如下配置此处代表该功能包的依赖包 这里的add_message_files打开注释后还要将文件改成自己的msg文件如下所示 如下所示打开generate_messages的注释为srv文件添加std_msgs依赖。 再打开如下的注释并加入message_runtime此处代表了find_package中的包的依赖包。 完成配置后回到工作空间主目录再次编译然后就会生成如下所示的C和python的msg头文件。 需要使用自定义的msg时以上述的num.msg为例如下所示操作即可。
#include topics/num.h // 调用自定义消息类型的头文件topics::num num; // 用于引用自定义的类型
num.num_hi xx; // 赋值之后把num.num_hi当成正常的变量用就行了。
1、发布者Publisher
pub.cpp程序
#include ros/ros.h
#include std_msgs/String.hint main(int argc, char **argv)
{setlocale (LC_ALL, ); // 防止中文乱码std_msgs::String msg; // 定义发送数据类型int count 1;ros::init(argc, argv, talker); // 初始化ros节点ros::NodeHandle n; // 定义节点句柄// 定义发布者ros::Publisher pub n.advertisestd_msgs::String(what, 1000);//ros::Rate rate(10); // 设置发布频率为10HZwhile (ros::ok()) // 节点正常运行时返回true{std::stringstream ss;ss data count;msg.data ss.str();pub.publish(msg); // 将话题内容msg发送出去给所有的订阅者ROS_INFO(发布的消息为%s, msg.data.c_str()); // 打印datacount 1;//rate.sleep(); // 对应频率改变睡眠时长}return 0;
}程序大部分都写了注释这些再补充记录一下 1、ros::Publisher定义了一个发布者对象上文程序中的what为话题名称1000为数据的缓冲区长度std_msgs::String指该话题的消息类型为String类型。 2、关于那个 ros::ok() 返回flase的条件如下 (1)、判定终端输入Ctrl - C停止程序的运行 (2)、出现同名的节点 (3)、程序调用了ros::shutdown() (4)、节点句柄被销毁 3、ROS_INFO是printf的替代品可用于打印某些数据至终端。 4、c_str()指向该字符数组的指针。 5、ros::Rate如上方设置为10HZ其会根据上次调用sleep()的时间来配置这次的睡眠时间以保持10HZ的发布速率。
2、订阅者Subscriber
sub.cpp程序
#include ros/ros.h
#include std_msgs/String.h// 消息回调函数
void what_callback(const std_msgs::String::ConstPtr msg)
{ROS_INFO(订阅到的消息为%s, msg-data.c_str());
}int main(int argc, char **argv)
{setlocale (LC_ALL, ); // 防止中文乱码ros::init(argc, argv, listeners); // 初始化ros节点ros::NodeHandle n; // 定义节点句柄// 定义订阅者ros::Subscriber sub n.subscribe(what, 1000, what_callback);ros::spin(); // 进入循环调用消息回调函数。return 0;
}程序大部分都写了注释这些再补充记录一下 1、ros::Subscriber定义订阅者对象what为话题名称1000为数据的缓冲区长度what_callback为消息回调函数。 2、消息回调函数上述程序中定义了what_callback()为消息回调函数在定义订阅者时配置为当话题what有新消息发布时调用一次消息回调函数what_callback()。 3、ros::spin()进入循环调用消息回调函数当ros::ok()返回 false 后退出因此该循环类似于while (ros::ok())可参考发布者的第2点补充。
3、更改配置
关于配置的更改参考第一篇文章的 (3、创建节点文件并配置编译依据文件中的更改配置文件例如该话题通信功能包的配置更改首先打开功能包中的CMakeLists.txt文件然后如下所示进行添加替换即可如下所示。
add_executable(pub src/pub.cpp)
add_executable(sub src/sub.cpp)target_link_libraries(pub${catkin_LIBRARIES}
)
target_link_libraries(sub${catkin_LIBRARIES}
)完成后回到工作空间主目录进行catkin_make编译一下然后source一下再运行pub和sub即可当然工作前提是ros master运行中即有一个终端已经运行了roscore。3个终端命令分别如下
roscoresource ./devel/setup.bash
rosrun topics pubsource ./devel/setup.bash
rosrun topics sub效果如下
二、Services服务通信C
服务通信是指节点间以请求响应的方式进行通信大体流程为客户端节点发送请求给服务端节点服务端节点接收到请求后处理消息再发出响应给客户端节点以此实现节点间的通信在通信和服务端处理消息期间客户端的单线程是处在阻塞状态的。 关于服务通信官方的C的案例链接Writing a Simple Service and Client (C)
0、定义srv服务类型文件
首先在该功能包下创建msg文件夹然后在创建一个.msg文件。即
mkdir srv
touch srv/xx.srv该文件的编写格式为
客户端请求
---
服务端响应
如
int32 request_num
---
int32 response_num然后和自定义msg一样需要进入package.xml更改配置分别添加下面两行
build_dependmessage_generation/build_dependexec_dependmessage_runtime/exec_depend然后进入CmakeLists.txt添加如下配置此处代表该功能包的依赖包 然后和自定义msg不同的是这里需要添加的配置是add_service_files而不是add_message_files即打开add_service_files的注释并改成自己的srv文件如下所示 如下所示打开generate_messages的注释为srv文件添加std_msgs依赖。 再打开如下的注释并加入message_runtime此处代表了find_package中的包的依赖包。 完成配置后回到工作空间主目录再次编译然后就会生成如下所示的C和python的srv头文件。 下文将使用该自定义的服务类型进行节点间的通信。
1、客户端Client
client.cpp程序
#include ros/ros.h
#include services/numm.h // 此处添加的头文件为功能包名/srv文件名.hint main(int argc, char **argv)
{bool flag;setlocale (LC_ALL, ); // 防止中文乱码ros::init(argc, argv, client); // 初始化ros节点ros::NodeHandle n; // 定义节点句柄// 定义客户端ros::ServiceClient client n.serviceClientservices::numm(why);ros::Rate rate(1); // 设置发布频率为1HZservices::numm srv;srv.request.request_num 1; // 赋请求值while(1){flag client.call(srv); // 获取返回值并赋值给flagif(flag){ROS_INFO(请求成功已将请求值×10收到的响应为%d, srv.response.response_num); // 打印出响应内容srv.request.request_num 1;}else{ROS_INFO(请求失败。);}rate.sleep(); // 对应频率改变睡眠时长 }
}程序大部分都写了注释这些再补充记录一下 1、ros::ServiceClient定义了一个客户端对象上文程序中的why为服务名称 services::numm 指服务类型即自定义的srv文件中的服务类型。 2、client.call(srv)调用服务时将会处于堵塞状态调用成功则返回trueresponse中的值为有效值调用成功则返回flaseresponse中的值将为无效值。
注一些和话题通信重复的程序在话题通信那块有注释。
2、服务端Service
service.cpp程序
#include ros/ros.h
#include services/numm.h // 此处添加的头文件为功能包名/srv文件名.h// 参数1当前功能包下的srv文件的请求参数2当前功能包下的srv文件的响应
bool service_callback(services::numm::Request request, services::numm::Response response)
{int pending_num request.request_num; // 获取客户端请求赋值为待处理数据ROS_INFO(收到的请求为%d, pending_num); // 打印dataresponse.response_num pending_num * 10; // 处理数据×10return true;
}int main(int argc, char **argv)
{setlocale (LC_ALL, ); // 防止中文乱码ros::init(argc, argv, service); // 初始化ros节点ros::NodeHandle n; // 定义节点句柄// 定义服务端ros::ServiceServer service n.advertiseService(why, service_callback);ros::spin(); // 进入循环调用消息回调函数。
}程序大部分都写了注释这些再补充记录一下 1、ros::ServiceServer定义服务端对象why为话题名称service_callback为服务回调函数。 2、服务回调函数上述程序中定义了service_callback()为服务回调函数在定义服务端时配置为当话题why有新消息发布时调用一次服务回调函数service_callback()。
注一些和话题通信重复的程序在话题通信那块有注释。
3、更改配置
关于配置的更改参考第一篇文章的 (3、创建节点文件并配置编译依据文件中的更改配置文件例如该话题通信功能包的配置更改首先打开功能包中的CMakeLists.txt文件然后如下所示进行添加替换即可如下所示。
add_executable(cli src/client.cpp)
add_executable(ser src/service.cpp)add_dependencies(cli ${PROJECT_NAME}_gencpp)
add_dependencies(ser ${PROJECT_NAME}_gencpp)target_link_libraries(cli${catkin_LIBRARIES}
)
target_link_libraries(ser${catkin_LIBRARIES}
)完成后回到工作空间主目录进行catkin_make编译一下然后source一下再运行pub和sub即可当然工作前提是ros master运行中即有一个终端已经运行了roscore。3个终端命令分别如下
roscoresource ./devel/setup.bash
rosrun services sersource ./devel/setup.bash
rosrun services cli效果如下