本次的实验目标是利用C++发布一个话题消息,让订阅者海龟可视化界面按照我们想要的方式进行运动。
完整的流程如下:
一个工作空间可以编译多个节点,所以之后的实验不会在创建一个新的工作空间。
Step1 创建一个工作空间工作空间其实就是项目所在的空间,假如我需要在桌面创建一个工作空间:
mkdir myWS # 创建一个文件夹作为工作空间
mkdir -p myWS/src # 创建一个源代码空间
catkin_make # 利用catkin_make帮助我们补充剩余的空间
junwu@Room:~/Desktop/myWS$ tree -L 1 . ├── build ├── devel └── src 3 directories, 0 files
可以看出工作空间自动帮我们创建了符合ros工作空间的结构,新增文件夹build、devel。
Step2 工作空间/src创建一个package按照package命名规则:由全小写、dash(-
) 、underscore(_
)和数字组成的字符串,注意添加要用到的依赖项:
catkin_create_pkg ask-turtlerun roscpp rospy std_msgs geometry_msgs turtlesim # 这个包名为ask-turtlerun 依赖包有roscpp rospy geometry_msgs turtlesim std_msgs
junwu@Room:~/Desktop/myWS$ tree -L 1 . ├── build ├── devel └── src 4 directories, 0 files
创建之后,有一个同名的文件夹将会出现在工作空间/src下。一般有多少个功能包,我们就有多少功能包同名文件夹。下面是新建的功能包结构:
. ├── CMakeLists.txt ├── include │ └── ask-turtlerun ├── package.xml └── src 3 directories, 2 files
这个文件夹包含一个CMakeLists.txt(用来编译的指导文件),一个头文件夹include
,和一个源文件夹src
和一个描述功能包的描述文件package.xml
。实现的代码一般应该放在对应功能包文件夹的src文件夹中(方便管理)。
在我们新创建功能包文件夹的src下创建一个main.cpp源代码文件,其内容如下:
#include //ROS功能文件
#include //ROS内置的信号类型支持
int main(int argc, char **argv)
{
ros::init(argc, argv, "velocityPub"); //这个程序的节点名,将来可以在rqt_graph中看到
ros::NodeHandle n; //节点管理器句柄,这个对象可以用来发布消息
ros::Publisher turtle_vel_pub = n.advertise("/turtle1/cmd_vel", 10);
//节点管理器调用advertise方法,向话题为"/turtle1/cmd_vel"
//发布一个消息类型为geometry_msgs::Twist的消息,10表示缓冲队列长度(也就是没来得及处理的数据暂存长度)
//Tips:查看消息类型 rosmsg list 查看指定消息类型详细信息 rosmsg info + xxx
// 查看话题 topic list 查看话题详细信息 ros info +xxx
//返回发布者句柄,这一步相当于注册,实际发送还是要发布者发送(也就是发布者句柄)
ros::Rate loop_rate(10); //这个是ROS的sleep
int count = 0;
while (ros::ok()) //如果ROS程序执行正常
{
geometry_msgs::Twist vel_msg; //声明一个消息类型变量
vel_msg.linear.x = 0.5; //赋值
vel_msg.angular.z = 0.2;
turtle_vel_pub.publish(vel_msg); //通过发布者句柄发送这个消息
ROS_INFO("Publish turtle velocity[%0.2f ms,%0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z);
//ROS_INFO就是为了格式化打印消息的
loop_rate.sleep(); //控制发送频率,不要太快
}
return 0;
}
Step4 修改编译规则并编译
修改编译规则其实就是修改包的CMakeLists.txt文件,让它:
- 生成可执行程序
- 链接ROS编译库(catkin_LIBARARIES)
在这个CMakeLists.txt里面已经有详尽的注释,如果学习过CMake这个应该很好理解,添加如下语句:
add_executable(Demo src/main.cpp)
target_link_libraries(${catkin_LIBRARIES})
大概在这个位置上: 接下来就可以进行编译了(编译应该回到工作空间目录),显示如下信息代表编译完成。
-- Build files have been written to: /home/junwu/Desktop/myWS/build #### #### Running command: "make -j16 -l16" in "/home/junwu/Desktop/myWS/build" #### Scanning dependencies of target Demo [ 50%] Building CXX object ask-turtlerun/CMakeFiles/Demo.dir/src/main.cpp.o [100%] Linking CXX executable /home/junwu/Desktop/myWS/devel/lib/ask-turtlerun/Demo [100%] Built target DemoFinal 测试
在此之前,将这个工作空间添加到环境变量,以便ROS找到这个自定义位置的ROS功能包,有两种方法:
- 直接source到环境变量后rosrun
- 添加到
~/.bashrc
中
这里我直接添加到~/.bashrc
,这样做的好处是,我下一个实验也不用敲入了(偷懒)。
运行结果如下: 补充,rqt_graph观察通信情况:
看上去没有什么问题,
/velocityPub
节点与/turtlesim
之间正在用消息类型为/turtle1/cmd_vel
进行数据交互。