参考https://www.cnblogs.com/yrm1160029237/p/9991014.html,对原有博客进行了改进。ROS菜鸟,如有不对望指正。
注:一个源码编译的CMakeLists.txt对应一个package。(个人理解)
1、编写发布器publisher
- 初始化ROS系统;
- 在ROS网络内广播将要在chatter话题上发布
std_msgs::Strring
类型的消息; - 以每秒10次的频率在
chatter
上发布消息。
在ros_test
目录下创建test/src/talker.cpp
文件:
mkdir ~/ros_test/test/src
cd ~/ros_test/test/src
gedit talker.cpp
将下面的源码复制到talker.cpp
中
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
int main(int argc, char **argv)
{
/**
* 初始化ROS可指定节点的名称。节点的名称必须唯一(名称内不能包含/等符号)
*/
ros::init(argc, argv, "talker");
/**
* 为这个进程的节点创建一个句柄。
* 第一个创建的NodeHandle会为节点进行初始化,
* 最后一个销毁的NodeHandle则会释放该节点所占用的所有资源
*/
ros::NodeHandle n;
/**
* 告诉ROS我们将在chatter(话题名)上发布std_msgs::String消息类型的消息。
* 如果发布的消息的频率太高,缓冲区中的消息在大于1000个的时候就会开始丢失先前发布的消息。
* advertise返回一个ros::Publisher对象,它有两个作用:
* 1、它有一个publish()成员函数可以让你在topic上发布消息;
* 2、如果消息类型不对,它会拒绝发布。
*/
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
/**
* 设置每秒10次的频率
*/
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
/**
* 可以用printf/cout等函数代替
*/
ROS_INFO("%s", msg.data.c_str());
/**
* 向所有订阅chatter话题的节点发布消息
*/
chatter_pub.publish(msg);
/**
* 没有这一句,则你的回调函数就永远也不会被调用
*/
ros::spinOnce();
/**
* 调用ros::Rate对象来休眠一段时间以使得发布频率为10Hz
*/
loop_rate.sleep();
++count;
}
return 0;
}
2、编写订阅器subscriber
- 初始化ROS系统;
- 订阅chatter话题;
- 进入自循环,等待消息的到达;
- 当消息到达,调用chatterCallback()函数;
在ros_test
目录下创建test/src/listener.cpp
文件:
#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());
}
void chatterCallback(const std_msgs::String::ConstPtr &msg, std::string p, int s)
{
ROS_INFO("I heard: [%s], %s, %d", msg->data.c_str(), p.c_str(), s);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
/**
* 告诉ROS我们要订阅chatter话题上的消息。
* 当有消息发布到这个话题上时,ROS就会调用chatterCallback()函数。
* 第二个参数上消息队列大小,以防我们处理消息的速度不够快,
* 当缓冲到达1000条消息后,再有新的消息到来就将开始丢弃先前接收的消息。
*/
ros::Subscriber sub = n.subscribe("chatter", 1000, &chatterCallback);
/**
* 当回调函数有多个参数时,可以采用boost::bing()函数作为传递参数。
* 在使用过程中需注意,subscribe的模板函数,在传入boost::function类型时,需要传入模板参数。
* 即chatterCallback()的第一个参数类型,std_msgs::String::ConstPtr,
* 因此传入模板参数是std_msgs::String。
* 如果在类里实现,则需要输入this,如下:
* boost::bind(&chatterCallback, this, _1, p, s)
*/
std::string p = "10";
int s = 10;
//ros::Subscriber sub = n.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&chatterCallback, _1, p, s));
/**
* 进入自循环,可以尽可能快的调用消息回调函数。
*/
ros::spin();
return 0;
}
3、编写CMakeLists.txt
在在ros_test
目录下创建test/CMakeLists.txt
文件:
cmake_minimum_required(VERSION 2.8.3)
project(ros_test)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)
#add_message_files(DIRECTORY msg FILES Num.msg)
#add_service_files(DIRECTORY srv FILES AddTwoInts.srv)
#generate_messages(DEPENDENCIES std_msgs)
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)
4、编写package.xml
在ros_test
目录下创建test/package.xml
:
<?xml version="1.0"?>
<package format="2">
<name>ros_test</name>
<version>0.0.0</version>
<description>The ros_test package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="wdh@todo.todo">wdh</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/pcl_test</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>pcl_ros</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_export_depend>pcl_ros</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<exec_depend>pcl_ros</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
5、编译与运行
编译有两种方式:
1、采用camke的方式:
# 编译
mkdir ~/ros_test/test/build
cd ~/ros_test/test/build
cmake ..
make
# 运行
# 打开第一个终端,输入如下命令
roscore
# 打开第二个终端,输入如下命令
cd ~/ros_test/test/build
./devel/lib/ros_test/listener
# 打开第三个终端,输入如下命令
cd ~/ros_test/test/build
./devel/lib/ros_test/talker
执行完以上命令,就可以在第二个和第三个终端看到消息输出。
2、采用catkin_make的方式:
# 编译
cd ~/ros_test
catkin_make
#运行
打开第一个终端,输入如下命令
roscore
打开第二个终端,输入如下命令
cd ~/ros_test
./devel/lib/ros_test/listener
打开第二个终端,输入如下命令
cd ~/ros_test
./devel/lib/ros_test/talker
执行完以上命令,就可以在第二个和第三个终端看到消息输出。