1首先是catkin工作空间中ROS package包的文件形式
创建一个包,添加依赖
zhangxuhnr@zhangxuhnr-Lenovo-IdeaPad-S415-Touch:~/catkin_ws/src$ catkin_create_pkg talker_listener std_msgs rospy roscpp
Created file talker_listener/package.xml
Created file talker_listener/CMakeLists.txt
Created folder talker_listener/include/talker_listener
Created folder talker_listener/src
Successfully created files in /home/zhangxuhnr/catkin_ws/src/talker_listener. Please adjust the values in package.xml.
这样包内自动多了package.xml ,CMakeLists.txt, include和src文件夹
然后是更新package.xml
package.xml主要包括包的名称,标签(添加对包的描述),维护者和邮箱,许可协议(一些常见的开源许可协议有BSD、MIT、Boost Software License、GPLv2、GPLv3、LGPLv2.1和LGPLv3,一般是BSD协议),依赖项(
build_depend
buildtool_depend
run_depend
test_depend(这个没见过)
)
将一些注释的东西删掉,最后变得简洁
<?xml version="1.0"?>
<package format="2">
<name>talker_listener</name>
<version>0.0.0</version>
<description>The talker_listener package</description>
<maintainer email="[email protected]">zhangxuhnr</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>std_msgs</run_depend>
</package>
http://wiki.ros.org/catkin/CMakeLists.txt中有详细描述
CMakeLists.txt 包括以下内容
必需的CMake版本(cmake_minimum_required)
包名称(project())
查找构建所需的其他CMake / Catkin包(find_package())
启用Python模块支持(catkin_python_setup())
消息/服务/动作生成器(add_message_files(),add_service_files(),add_action_files())
调用消息/服务/动作生成(generate_messages())
指定包构建信息导出(catkin_package())
要构建的库/可执行文件(add_library()/ add_executable()/ target_link_libraries())
测试构建(catkin_add_gtest())
安装规则(install())
find_package()
catkin REQUIRED
如果项目依赖于其他包,它们会自动变成catkin的组件
COMPONENTS
roscpp
rospy
std_msgs
catkin_package()
在使用add_library()或add_executable()声明任何目标之前,必须调用此函数
INCLUDE_DIRS - 包的导出包含路径(即cflags)
LIBRARIES - 项目中导出的库
CATKIN_DEPENDS - 该项目所依赖的其他catkin项目
DEPENDS - 此项目依赖的非catkin CMake项目。
catkin_package( INCLUDE_DIRS include LIBRARIES ${PROJECT_NAME} CATKIN_DEPENDS roscpp nodelet DEPENDS eigen opencv)
include_directories的参数应该是find_package调用生成的* _INCLUDE_DIRS变量以及需要包含的任何其他目录
如果您使用catkin和Boost
$ {Boost_INCLUDE_DIRS} $ {catkin_INCLUDE_DIRS}
第一个参数“include”表示包中的include /目录也是路径的一部分
要指定必须构建的可执行目标,我们必须使用add_executable()
add_library() CMake的功能是用来指定库来构建。默认情况下,catkin构建共享库
使用target_link_libraries()函数指定可执行目标链接的库。这通常在add_executable()调用之后完成
target_link_libraries(<executableTargetName>,<lib1>,<lib2>,... <libN>)
CMake工作流程
$ mkdir build
$ cd build
$ cmake ..
$ make
编写talker.cpp,
#include "ros/ros.h"//ros/ros.h引入了ROS系统中大部分常用的头文件
#include "std_msgs/String.h"//引用了std_msgs/Sting消息,它存放在std_msgs packages里,是由String.msg文件自动生成的头文件,定义了一种 string data
#include <sstream>
//C++引入ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含<sstream>这个头文件。
/**
*此程序用ROS发送消息
*/
int main(int argc,char *argv[])
{
ros::init(argc,argv,"talker");//初始化ROS,指定节点名称
ros::NodeHandle n;//为这个进程的节点创建一个句柄,第一个创建的NodeHandle会为节点进行初始化,最后一个销毁的会清理节点使用的所有资源
ros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter",1000);//告诉master我们将要在chatter topic上发布一个std_msgs/String的消息,1000是发布序列大小,缓冲区中的消息在大于1000个的时候就会丢弃之前的消息
//NodeHandle.advertise()返回一个ros::publish对象,有一个publish()成员函数让你在topic上发布消息,如果消息类型不对拒绝发布
ros::Rate loop_rate(10);//ros::Rate对象允许指定自循环的频率,记录上一次调用Rate::sleep()后的时间,并休眠到下一个频率周期时间
int count=0;
while(ros::ok())//ros::ok()安装一个SIGINT句柄,在按键ctrl+c,返回False
{
std_msgs::String msg;//使用一个由msg文件产生的“消息自适应”类在ROS网络中广播消息
std::stringstream ss;
ss<<"hello world"<<count;
msg.data=ss.str();//String消息只有一个数据data
ROS_INFO("%s",msg.data.c_str());
chatter_pub.publish(msg);//向所有连接到chatter topic的节点发送了消息
ros::spinOnce();//调用回调函数,此程序不接受回调,最好加上
loop_rate.sleep();//休眠一段时间来使发布频率为10Hz
++count;
}
return 0;
}
编写listener.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr&msg)//const [包名]::[消息文件名][ConstPtr]&
{
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);//NodeHandle::subscribe()返回ros::Subscriber对象,你必须让它处于活动状态直到你不再想订阅该消息。
ros::spin();//ros::spin()进入自循环,可以尽可能快的调用消息回调函数
return 0;
}