天天看点

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

一、ROS通讯编程类型

分为以下三种

1.话题编程

2.服务编程

3.动作编程

二、话题编程

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

三、创建发布者

在功能包learn_communication/src/目录下添加talker.cpp文件:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

1.添加都文件

//添加ROS包
#include "ros/ros.h"
//添加ROS string变量
#include "std_msgs/String.h"
           

2.Ros结点初始化,定义结点名称

3.创建结点句柄

通过创建结点句柄,方便我们对结点进行管理(包括发布者,订阅者等等的管理)

//创建结点句柄
 ros::NodeHandle n;
           

4.创建发布者

创建一个Publisher的对象,发布名为chatter的话题,消息类型为std_msg::String,发布者队列长度为1000(将数据放入队列,避免发布过快,接受者收不到)

5.发布消息

//发布消息
chatter_pub.publish(msg);
           

6.完整代码

//添加ROS包
#include "ros/ros.h"
//添加ROS string变量
#include "std_msgs/String.h"

int main(int argc, char **argv)
{

 //ROS结点初始化
 //创建talker结点
 ros::init(argc,argv,"talker");
 
 //创建结点句柄
 ros::NodeHandle n;
 
 //创建一个Publisher,发布名为chatter的话题,消息类型为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())
{
 //初始化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;
}
           

四、创建订阅者

1.初始化ROS结点

//初始化ROS结点
  ros::init(argc,char **argv,"listrner");
           

2.创建结点句柄

//创建结点句柄
  ros::NodeHandle n;
           

3.创建一个订阅者

并且绑定订阅的话题,收到消息的回调函数

//创建一个接受者,订阅名为chatter的话题,注册回调函数chatterCallback
  ros::Subscriber sub = n.subscribe("chatter",1000,chatterCallback);
           

4.创建回调函数

//接收消息的回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard :{%s}",msg->data.c_str());
}
           

5.循环等待回调函数

//循环等待回调函数
  ros::spin();
           

6.完整代码

#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结点
  ros::init(argc,argv,"listrner");

  //创建结点句柄
  ros::NodeHandle n;
  //创建一个接受者,订阅名为chatter的话题,注册回调函数chatterCallback 1000代表消息队列的大小
  ros::Subscriber sub = n.subscribe("chatter",1000,chatterCallback);

  //循环等待回调函数
  ros::spin();
return 0;
}
           

五.编译代码

当我们用c++写完这两个结点功能后,需要将代码编译为可执行文件(用python写就不用编译,Python本身就是可执行文件)

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

1.更改编译配置文件

更改功能包目录下的CMakeLists.txt文件:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

将add_executable(${PROJECT_NAME}_node src/learing_communication_node.cpp)取消注释,并更改内容

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

更改为:

意思是将src目录下的talker.cpp编译为talker可执行文件

链接第三方库:

因为这里没用到其他库,只有ROS默认的库,所以我们链接catkin_LIBRARIES

更改后的完整内容为:

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

2.编译

在工作空间目录 catkin_ws下打开终端:

命令:

catkin_make
           
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

编译完成:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

可以在devl目录下看见我们编译完成的可执行程序:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

六,运行可执行文件

1.启动rosMaster

新建终端

roscore
           
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

2.启动listener

用rosrun命令

rosrun功能包名 结点名

rosrun learing_communication talker
           
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

3.启动listener

rosrun learing_communication listener
           

我们可以发现发送和接收保持同步

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

七、自定义话题

前面的话题我们都是发送一个string类型的数据,但是我们想要发送一组有类型的数据怎么办呢?德国自定义话题来解决

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

1.定义msg文件

在功能包目录下创建msg文件夹(存放msg文件)

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

在文件夹下创建person.msg文件

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

定义person相关信息,并且可以定义常量(unknown,male,female):

string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2
           
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

2.在package.xml中添加功能包依赖

打开功能包目录下的package.xml添加以下:

<build_depend>message_generation</build_depend> 
<exec_depend>message_runtime</exec_depend>
           

注意:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

3.在Cmakelist.txt添加编译选项

打开功能包目录下的cmakelist.txt做以下更改

• find_package( ……  message_generation)
• catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime)
• add_message_files(FILES Person.msg) generate_messages(DEPENDENCIES  std_msgs)
           

添加功能包:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

添加编译时的依赖:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

指定消息文件的目录:

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

4.编译

将msg文件编译成对应语言的头文件:

在工作空间根目录进行编译

catkin_make
           

可以看见他编译成不同语言接口供我们使用

ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

5.查看自定义消息

rosmsg show person
           
ROS机器人004-ROS通信编程(话题编程,自定义话题消息)一、ROS通讯编程类型二、话题编程三、创建发布者四、创建订阅者五.编译代码六,运行可执行文件七、自定义话题

证明该消息编译没问题,可以使用头文件包含进行使用了