本文主要参考了coding思想的博客(很有效果),再加上自己的实际操作过程中遇到的问题和自己的理解。
先说下本人的硬件设备:Ubuntu16.04LST、ROS乌龟版。
第一步:创建ROS工作空间
$ mkdir -p ~/Document/zb_ros_workspace/src //zb_ros_workspace是工作空间目录,src工作空间下的原文件目录
然后cd进入该工作空间的src,注意将来会有很多src目录,请注意。
$ catkin_init_workspace //在工作空间中创建CMakeList.txt文件,知道的都明白,该文件是主要为了编译C++源文件的
cd ..到工作空间,我是cd到zb_rose_workspace中,编译
$ catkin_make //编译工作空间,只能在工作空间目录进行,注意只能再工作空间里编译其他地方不会成功。反正本喵是这样哒。
再工作空间里看看是否有build和devel文件夹的呢
$ source devel/setup.bash //重新加载setup.bash文件,你也可以通过关闭终端重新打开来重新加载,这一步也很重要,一定要有。
第二步:在工作空间里创建ROS功能包
cd到工作空间的src文件夹下,这个文件夹本喵发现是用来放各种不同功能的ROS功能包的。
$ catkin_create_pkg chapter2_tutorials std_msgs roscpp //chapter2_tutorials是功能包名字,std_msgs和roscpp是依赖项,std_msgs包含了常见道消息类型,表示基本数据类型和其他基本道消息构造,如多维数组。roscpp 使用C++ 实现ROS的各种功能。如果你还要使用Python库,还需要在最后边添加 rospy
第三步:编译ROS功能包
还是cd到工作空间编译
$ catkin_make //编译工作空间下的所有包,依然是要到工作空间下编译
第四步:创建节点
cd到ros功能包的src下,区别于工作空间的src哦
只有创建2个文件,我是以C++为例的,座椅自己创建了ex1.cpp和ex2.cpp
ex1.cpp里放如下内容,本喵还不填熟悉代码意思但是为了学习整体框架不影响,后续会学习的。
#include "ros/ros.h"
#include "std_msgs/String.h"//
#include <sstream>///包含要使用的文件类型
int main(int argc, char **argv)
{
ros::init(argc, argv, "example1_a");//启动该节点并设置其名称,名称必须唯一
ros::NodeHandle n;//设置节点进程的句柄
ros::Publisher pub = n.advertise<std_msgs::String>("message", 1000);//将节点设置成发布者,并将所发布>主题道类型和名称告知节点管理器。第一个参数是消息的名称:message,第二个是缓冲区道大小。如果主题发布数据速度较快,那么将缓冲区设置为1000个消息。
ros::Rate loop_rate(10);//设置发送数据道频率为10Hz
while (ros::ok())//当收到Ctrl+C的按键消息或ROS停止当前节点运行时,ros::ok()库会执行停止节点运行道命令
{
//创建一个消息变量,变量类型必须符合发送数据的要求
std_msgs::String msg;
std::stringstream ss;
ss << " I am the example1_a node ";
msg.data = ss.str();
//ROS_INFO("%s", msg.data.c_str());
pub.publish(msg);//消息被发布
ros::spinOnce();//如果一个订阅者出现,ROS就会更新和读取所有主题
loop_rate.sleep();//按照10Hz的频率将程序挂起
}
return 0;
}
ex2.cpp放如下内容
#include "ros/ros.h"
#include "std_msgs/String.h"
void messageCallback(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, "example1_b");
ros::NodeHandle n;
/创建一个订阅者,并从主题获取以message为名称的消息数据。设置缓冲区为1000个消息,处理消息句柄的回调函数>为messageCallback
ros::Subscriber sub = n.subscribe("message", 1000, messageCallback);
ros::spin()库是节点读取数据道消息响应循环,当消息到达的时候,回调函数就会被调用。当按下Ctrl+C时,节点会退出消息循环,于是循环结束。
ros::spin();
return 0;
}
第五步:编译节点
因为本例节点是创建的C++编写的节点,所以懂得都知道要用CMakeList.txt文件喽
在其中添加或者取消屏蔽如下内容
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(ex1 src/ex1.cpp)
add_executable(ex2 src/ex2.cpp)
add_dependencies(ex1
zb_pkg_1_generate_messages_cpp)
add_dependencies(ex2
zb_pkg_1_generate_messages_cpp)
target_link_libraries(ex1 ${catkin_LIBRARIES})
target_link_libraries(ex2 ${catkin_LIBRARIES})
具体里面代码啥意思,请看大神SXH_Android的博客,我还是在学写JNI时学的了。
还是cd到工作空间,编译
$ catkin_make --pkg zb_pkg_1
首先打开一个终端输入roscore,这就代表着ros启动了。也可以用$ rosnode list查看是否运行,没报错就是运行了。
第六步:运行节点
再打开一个终端,上一个终端不要关呀。
先cd到工作空间呀,一定要。
行终端运行
$ catkin_make --pkg zb_pkg_1
$ source devel/setup.bash
$ rosrun zb_pkg_1 ex1
运行成功后出现空白行,处于等待状态
再打开一个终端,好多终端呀,没办法。。
还是cd到工作空间。
$ catkin_make --pkg zb_pkg_1
$ source devel/setup.bash
$ rosrun zb_pkg_1 ex2