【一学就会的ROS基础入门教程 】03-1 ROS基础编程:ROS工作空间的创建、话题topic的发布与接收、以及话题消息的自定义使用
- 文前白话
- 1、创建工作空间与功能包
- 关于工作空间的介绍
- 创建开发工作空间主要的终端操作命令步骤
- 创建功能包
- 2、简单的话题发布与接收
- 发布者Publisher的编程实现(发布 Topic)
- 订阅者Suberscriber的编程实现(接收 Topic)
- 注:实现语言C++ 和 Python
- 3、话题消息的自定义与使用
文前白话
本篇系列博客是依据哔站视频 【古月居】ROS 21讲 入门教程,学习整理,用于记录实践过程,加强学习,在系列整理的章节引导篇博客中,附带课程的课件和代码,需要的可以自行翻阅下载,共同学习。水平有限,若有整理错误之处,还请给予留言反馈,不胜感激。
系列整理的章节引导篇博客链接: 一学就会的ROS基础入门教程系列.
- 本篇从ROS的相关应用编程继续学习: ROS工作空间的创建、话题topic的发布与接收、以及话题消息的自定义使用。
1、创建工作空间与功能包
关于工作空间的介绍
- 具体的文件夹理解:
- src : 存放代码的空间(功能包的代码、配置文件、lunach文件)
- build: 编译空间(存放编译过程中产生的中间文件)
- devel: 开发空间(编译生成的可执行文件、库、脚本)
- Install: 安装空间 (install 指令生成的结果存放空间)
创建开发工作空间主要的终端操作命令步骤
- 具体的步骤解析:
- 1、从创建工作空间&初始化(创建文件夹src)
2、在工作空间下进行编译:
创建功能包
- 实际操作:在创建的 src 文件夹下:
- 执行创建命令:
- CMakeLists.txt 和 package.xml 的作用:
功能包必须有的文件,package.xml 是介绍功能包的信息:名称、版本、功能、开发者信息、开源许可证、依赖信息等等。
CMakeLists.txt :描述功能包编译的规则,编译时候需要依赖的库
- 编译完成后,要运行功能包的某一个程序文件,先要设置一下工作空间的环境变量:
执行:
source devel/setup.bash
- 设置以后,才能让系统找得到工作空间,并且找到工作空间对应的功能包
-
echo $ROS_PACKAGE_PATH 是 ros 自身的环境变量,它会通过环境变量查找所有ros功能包的路径, 只有经过 设置功能包的 source devel/setup.bash 后, ROS_PACKAGE_PATH (ros 自身的环境变量)才会包含创建的工作空间的路径,才能找到对应的功能包,运行程序文件。
-
为了避免每次创建功能包,忘记执行环境变量的配置,可以将 source devel/setup.bash 命令复制添加到 .bashrc 的配置文件里面:
** .bashrc在根目录下: (CTRL+h 可以显示隐藏文件)**
-
这样,就不用每次都在终端进行这个工作空间的环境变量的配置。(重启终端生效)
2、简单的话题发布与接收
发布者Publisher的编程实现(发布 Topic)
原理图示:
1、创建功能包:
2、创建话题发布者的代码
-
发布话题的逻辑步骤:
-
话题发布代码
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "velocity_publisher");
ros::NodeHandle n;
ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
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("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]",
vel_msg.linear.x, vel_msg.angular.z);
loop_rate.sleep();
}
return 0;
}
3、 配置话题发布者代码的编译规则:
-
其实就是,规定编译可执行文件生成的文件名、链接相关的依赖库;
-
将上述两句指令,拷贝到 CMakeLists.txt 文件中
-
对于指令的解释:
-
add_executable(velocity_publisher src/velocity_publisher. cpp)
-
作用:描述将哪一个程序文件(velocity_publisher. cpp),编译成哪一个可执行文件(velocity_publisher src)
-
target_link_libraries(velocity_publisher S(catkin_LIBRARIES])
-
作用: 帮助将生成的可执行文件与ROS 的一些库建立连接(c++的库)、
-
4、进行功能包的编译
5、设置环境变量:
6、终端下运行功能包:
订阅者Suberscriber的编程实现(接收 Topic)
逻辑原理图:
具体操作:
1、在功能包的 src 中创建 话题订阅者的代码:
#include <ros/ros.h>
#include "turtlesim/Pose.h"
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "pose_subscriber");
ros::NodeHandle n;
ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
ros::spin();
return 0;
}
2、配置话题订阅者代码编译规则:
将:
添加到:
3、 进行编译
catkin_make
4、配置环境变量:
5、终端下运行订阅话题:
注:实现语言C++ 和 Python
- 功能包的实现既可以是c++也可以是 python 语言,区别在于,python脚本语言不用进行编译。
3、话题消息的自定义与使用
-
现有的 ros 话题消息无法满足需求,可以自己来定义/发布话题
逻辑原理:
具体操作步骤:
1、自定义话题消息
- 在功能包的文件夹下创建自定义消息存放的文件夹:msg(方便查找管理)
- 注:.msg 文件格式既不是c++也不是python文件,它是 ros 在编译过程中,结合具体的定义来变成对应的 c++ 或者 python 程序。
2、 设置编译规则:
3、在工作空间下进行编译:
4、通过程序调用生成的头文件:
#include <ros/ros.h>
#include "learning_topic/Person.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "person_publisher");
ros::NodeHandle n;
ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
ros::Rate loop_rate(1);
int count = 0;
while (ros::ok())
{
learning_topic::Person person_msg;
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = learning_topic::Person::male;
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info: name:%s age:%d sex:%d",
person_msg.name.c_str(), person_msg.age, person_msg.sex);
loop_rate.sleep();
}
return 0;
}
#include <ros/ros.h>
#include "learning_topic/Person.h"
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d",
msg->name.c_str(), msg->age, msg->sex);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "person_subscriber");
ros::NodeHandle n;
ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
ros::spin();
return 0;
}
5、配置topic发布/接收代码编译规则:
- 即是:在功能包文件夹下的 CMakeList.txt 中,添加:
- 其中,add_dependencies…
(有一些代码是动态生成的,需要把生成的可执行文件与动态生成的程序产生依赖关系;用来动态的跟我们生成的头文件产生连接(与自定义的消息产生连接))
6、编译并在终端运行发布者和订阅者:
- 将代码放在对应的python文件夹中:
- 除去不用编译,其他步骤同c++版本步骤一致。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)