ROS基本程序创建与运行步骤

       

参考书籍:《人工智能点云处理及深度学习算法》

 本文为专栏《Python三维点云实战宝典》系列文章,专栏介绍地址“【python三维深度学习】python三维点云从基础到深度学习_python3d点云从基础到深度学习-CSDN博客”。配套书籍《人工智能点云处理及深度学习算法》提供更加全面和系统的解析。

        本文将详细介绍ROS程序创建和运行过程,是根据博文https://blog.csdn.net/weixin_45080292/article/details/124614363进行补充。感谢原作者详细介绍与分享。

        下面的示例程序将创建两个node(节点),一个发布模拟的GPS消息(格式为自定义,包括坐标和工作状态),另一个接受并处理该信息(计算到原点的距离)。

        

        注:传感器得到原始数据,经过ros封装为msg进行发布出去。

        

        /talker节点:向话题/gps_info中持续发布gps模拟数据。

        /listener节点:从话题/gps_info中持续订阅接收/talker所发布的数据,并进行加工处理。

1. 创建工作空间

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
// 可选择编译(空的,后面编译就行,不影响)
cd ~/catkin_ws
catkin_make

        src:这是用来存放所有 ROS 软件包源代码的目录。

        catkin_init_workspace: 这是一个 Catkin 命令,用于初始化一个 Catkin 工作空间。在这里运行该命令后,src 目录下会生成一个 CMakeLists.txt 文件,用于构建工作空间。具体是通过软链接将ros系统的cmake文件映射到src目录下,即“Creating symlink "~/catkin_ws/src/CMakeLists.txt" pointing to "/opt/ros/melodic/share/catkin/cmake/toplevel.cmake"”。

2. 创建功能包

cd ~/catkin_ws/src
catkin_create_pkg topic_demo roscpp rospy std_msgs

        catkin_create_pkg: 这是一个 Catkin 命令,用于创建一个新的 ROS 软件包。注意,相比于参考资料[1],std_msg改为了std_msgs,否则后续会报相关的错误。

        topic_demo: 指定要创建的软件包的名称,这里是 topic_demo。

        roscpp, rospy, std_msg: 这些是软件包依赖的 ROS 库,分别表示该软件包会使用到 roscpp(用于 C++ 开发)、rospy(用于 Python 开发)和 std_msg(ROS 标准消息库)这几个库。通过指定这些依赖,系统会自动在软件包的src/topic_demo/ package.xml 和 src/topic_demo/CMakeLists.txt 文件中添加相应的依赖信息,以确保构建时能正确链接这些库。

        这两条命令的作用是在 Catkin 工作空间中的 src 目录下创建一个名为 topic_demo 的新软件包,并指定该软件包需要依赖于 roscpp、rospy 和 std_msgs这三个 ROS 库。创建完成后,你就可以在 src 目录下找到 topic_demo 软件包,并开始在其中编写 ROS 节点和功能。

        后续编译可能会报错:

Could not find a package configuration file provided by "std_msg" with any of the following names:
std_msgConfig.cmake
std_msg-config.cmake
topic_demo/CMakeLists.txt:10 (find_package)

        这说明错误出现在src/topic_demo/CMakeLists.txt文件的第10行。解决方案为把第10行的std_msg改为std_msgs。src/topic_demo/package.xml也需要同步将std_msg修改为std_msgs。

3. 定义msg

cd topic_demo/
mkdir msg
cd msg
vi gps.msg

        msg: 新创建的目录名称,这里用于存放自定义消息文件,主要用于定义传感器等的数据结构。

        通过以上操作,你已经进入了 topic_demo 软件包中的 msg 目录,并且使用 vi 编辑器创建了一个名为 gps.msg 的文件,接下来你可以在其中定义自己需要的消息格式。例如,你可以在 gps.msg 文件中定义 GPS 消息的数据结构、字段等信息。编辑完成后,记得保存文件并退出编辑器。设置.msg文件定义坐标x, y和工作状态。

float32 x
float32 y
string state

        定义完成保存并退出,后续编译后.msg文件会自动生成一个头文件,位于编译产生的devel/include/topic_demo文件下。未编译之前不会产生该头文件,src/topic_demo/CMakeLists.txt需要进行相应修改。

4. 在src中创建.cpp文件(talker & listener)

cd  src/topic_demo/src
touch talker.cpp
touch listener.cpp

        通过以上操作,你已经在 topic_demo 软件包的 src 目录下创建了两个新的源代码文件 talker.cpp 和 listener.cpp,接下来你可以在这些文件中编写 ROS 节点的代码逻辑。例如,你可以在 talker.cpp 中编写发布 GPS 消息的节点逻辑,而在 listener.cpp 中编写订阅 GPS 消息并处理数据的节点逻辑。

        对talker.cpp进行编写,code如下:

//ROS头文件
#include <ros/ros.h>
//自定义msg产生的头文件
#include <topic_demo/gps.h>

int main(int argc, char **argv)
{
  //用于解析ROS参数,第三个参数为本节点名
  ros::init(argc, argv, "talker");

  //实例化句柄,初始化node
  ros::NodeHandle nh;

  //自定义gps msg
  topic_demo::gps msg;
  msg.x = 1.0;
  msg.y = 1.0;
  msg.state = "working";

  //创建publisher
  ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info", 1);

  //定义发布的频率 
  ros::Rate loop_rate(1.0);
  //循环发布msg
  while (ros::ok())
  {
    //以指数增长,每隔1秒更新一次
    msg.x = 1.03 * msg.x ;
    msg.y = 1.01 * msg.y;
    ROS_INFO("Talker: GPS: x = %f, y = %f ",  msg.x ,msg.y);
    //以1Hz的频率发布msg
    pub.publish(msg);
    //根据前面定义的频率, sleep 1s
    loop_rate.sleep();//根据前面的定义的loop_rate,设置1s的暂停
  }

  return 0;
} 

        总体来说,该程序作为 ROS 中的一个节点,负责以指数增长的方式生成 GPS 消息,并以约 1Hz 的频率将消息发布到名为 gps_info 的主题上。这样的节点通常被称为 "talker",因为它负责发布消息。

        对listener.cpp进行编写,code如下:

//ROS头文件
#include <ros/ros.h>
//包含自定义msg产生的头文件
#include <topic_demo/gps.h>
//ROS标准msg头文件
#include <std_msgs/Float32.h>

void gpsCallback(const topic_demo::gps::ConstPtr &msg)
{  
    //计算离原点(0,0)的距离
    std_msgs::Float32 distance;
    distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2));
    //float distance = sqrt(pow(msg->x,2)+pow(msg->y,2));
    ROS_INFO("Listener: Distance to origin = %f, state: %s",distance.data,msg->state.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback);
  //ros::spin()用于调用所有可触发的回调函数。将进入循环,不会返回,类似于在循环里反复调用ros::spinOnce()。
  ros::spin(); 
  return 0;
}

        解释部分:ros::Subscriber sub = n.subscribe(“gps_info”, 1, gpsCallback);

        (topic名称,队列长度,回调函数(指针))

        Subscriber接收到gps_info传来的消息,需要做个处理,需要用gpsCallback处理,因此需要定义函数gpsCallback。

        注:callback中用指针作为传入的参数,ConstPtr(常指针)指向gps的消息(msg)

        总体来说,该节点作为一个监听者(listener),订阅 gps_info 主题上发布的 GPS 消息,计算接收到的消息中坐标点到原点的距离,并输出到控制台。这样的节点通常被用于接收、处理和响应特定类型的消息。

5. CMakeList.txt & package.xml //配置

5.1 src/topic_demo/CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(topic_demo)
find_package(catkin REQUIRED COMPONENTS
  message_generation
  roscpp
  rospy
  std_msgs
)
 add_message_files(
   FILES
   gps.msg
#   Message2.msg
 )    // 新添加  添加自定义的msg
## Generate added messages and services with any dependencies listed here
 generate_messages(
  DEPENDENCIES
  std_msgs
)      //  新添加   生成msg对应的头文件
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

add_executable(talker src/talker.cpp )
#必须添加add_dependencies,否则找不到自定义的msg产生的头文件
add_dependencies(talker topic_demo_generate_messages_cpp)    // 新添加
target_link_libraries(talker ${catkin_LIBRARIES})   // 新添加

add_executable(listener src/listener.cpp )  // 新添加
add_dependencies(listener topic_demo_generate_messages_cpp)  // 新添加
target_link_libraries(listener ${catkin_LIBRARIES})  // 新添加

        上述内容只需要在第1步通过catkin_init_workspace自动生成的CMakeLists.txt中直接修改即可。

        add_executable(talker src/talker.cpp ):将名为 talker.cpp 的源文件编译为一个可执行文件 talker。add_dependencies(talker topic_demo_generate_messages_cpp):添加依赖项,确保在构建 talker 可执行文件之前生成自定义消息类型所需的头文件。target_link_libraries(talker ${catkin_LIBRARIES}):将 talker 可执行文件链接到 ROS 编译系统所需的库。

        add_executable(listener src/listener.cpp ):将名为 listener.cpp 的源文件编译为一个可执行文件 listener。add_dependencies(listener topic_demo_generate_messages_cpp):添加依赖项,确保在构建 listener 可执行文件之前生成自定义消息类型所需的头文件。target_link_libraries(listener ${catkin_LIBRARIES}):将 listener 可执行文件链接到 ROS 编译系统所需的库。

        这些指令主要用于配置ROS工程中的CMake构建系统,确保编译和链接过程正确地处理了自定义消息生成的头文件,并将所需的库链接到最终生成的可执行文件中。这样做可以确保在构建ROS节点时正确处理自定义消息类型,并使节点能够顺利编译和运行。

        编译报错 Unknown CMake command "add_message_files"。经检查,在 CMakeLists.txt文件中的find_packag函数中忘了增加对message_generation的依赖,修改完后编译成功。上述示例中已经增加了message_generation的依赖。

5.2 src/topic_demo/package.xml

<?xml version="1.0"?>
<package>
  <name>topic_demo</name>
  <version>0.0.0</version>
  <description>The publish_subscribe_demo package</description>
  <maintainer email="xxxxx">davidhan</maintainer>
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>message_generation</build_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>
  <run_depend>message_runtime</run_depend>   // 新添加

  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

        如果后续编译报错如下:

Error(s) in package '/home/yehx/test/ros_ws/src/topic_demo/package.xml':
Error(s):
- The manifest of package "topic_demo" (with format version 2) must not contain the following tags: run_depend
- Please replace <run_depend> tags with <exec_depend> tags.

        这可能是因为在ros2中需要用exec_depend代替run_depend,因此只需要将package.xml中的run_depend全部替换成exec_depend即可。

6. 编译

$ cd ~/catkin_ws
$ catkin_make

        编译运行结果如下所示。

7. 运行topic_demo

        7.1 运行talker

cd ~/catakin_ws
source devel/setup.bash
rosrun topic_demo talker

        7.2 运行listener

        打开另一个终端,输入如下命令:

cd ~/catakin_ws
source devel/setup.bash
rosrun topic_demo listener

8. 查看消息节点

        显示node之间关系

rqt_graph

        显示node,并查看某节点属性

rosnode list
rosnode info /*nodename*

9. 参考资料

[1] https://blog.csdn.net/weixin_45080292/article/details/124614363

更多python与C++技巧、计算机视觉基础到实践完整指南、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。

本文为专栏《Python三维点云实战宝典》系列文章,专栏介绍地址“【python三维深度学习】python三维点云从基础到深度学习_python3d点云从基础到深度学习-CSDN博客”。配套书籍《人工智能点云处理及深度学习算法》提供更加全面和系统的解析。

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding的叶子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值