ROS : 修改ROS源代码(overlaying package)

本文介绍如何使用 ROS 的 overlaying 机制覆盖并修改已安装的 package,如 ros_tutorials 和 gmapping,以便进行定制化的开发和实验。

       ROS官方或者其他个人提供了很多package供大家使用,但是随着学习的深入,很多人可能想去修改这些package的源代码,ROS提供了一种称之为overlaying的机制。它允许ROS原有安装的package你修改的package共存,譬如安装ROS的时候已经安装了用于二维SLAM的gmapping包,但是你要修改源代码,而又想保存好ROS原已安装的,ROS运行的时候还要能够找到你修改的那个package,而不是使用原装的,这时候overlaying机制就派上用场了。

       该博客分为两部分:

       (1) 用ros_tutorials package作为例子讲解overlaying机制的使用

       (2) 如何overlaying gmapping包


       这篇博客中我们将覆盖ros官方的ros_tutorials 包,如果你没用安装过这个包,请先进行如下准备工作:

       1.安装ros_tutorials 

  • $ sudo apt-get install ros-groovy-ros-tutorials

这个包中包含了ROS的一些教程,如用于仿真的渔龟turtlesim等。接下来我们看看这个包安装到了哪里?在终端中输入:

  • $ roscd rospy_tutorials
    $ pwd

/opt/ros/hydro/share/rospy_tutorials
可以看到这个package和大多数ROS原装的package一样,放在了ROS安装时的文件夹里。

       我们自己如果想要改动这个代码该如何做呢?


ROS的overlaying机制华丽登场:       

       在学习此篇博客的时候,博主猜想读者您应该熟练使用ROS做了一些工作了,这时候的你已经有了一个catkin工作空间(如LZ的 catkin_ws),在这个工作空间中(catkin_ws/src)已经有了很多你自己或者其他网友提供的package(如usb_cam,beginner_tutorials)。为了overlaying 工作的进行,博主强烈建议另外再新建一个catkin空间,专门用来做覆盖原始package的工作

  • $ mkdir -p ~/overlay_ws
    $ cd ~/overlay_ws
创建好以后(其实就只是建了个新文件夹),再新建/src文件夹,并使用wstool

  • $ mkdir -p ~/overlay_ws/src
    $ cd ~/overlay_ws/src
    $ wstool init
接下来,就是将ros_tutorials package复制到这个新的工作空间中(overlay_ws/src):

  • $ git clone git://github.com/ros/ros_tutorials.git
    $ wstool update

          如图所示:

      

       复制进来之后,按找以前学习的步奏应该就是使用catkin_make编译这个文件了。但是这里是要overlay,也就是覆盖原来的package,好让ROS运行的时候能够找到我们自己修改了的这个package。在做准备工作的时候,我们已经知道ros_tutorials 安装在ROS安装文件夹(/opt/ros/hydro)下。所以我们要先source一下这个环境,说明我们要覆盖的ros_tutorials在那个环境中:

  • $ source /opt/ros/hydro/setup.bash

       注意:这一步其实没必要做,因为安装ROS的时候,我们已经把这句话写到了/.bashrc文件中,每次启动终端时会自动调用这句命令。不信的话,你可以使用gedit ~/.bashrc命令来打开在这个文件,看它的最后一行。但是,这里强调这一步是为了告诉你,有时候你要覆盖的package可能是在你自己的另一个catkin工作空间中(如catkin_ws),如你的工作空间catkin_ws中有一个自己的机器人驱动包robot_dirver,然后你也想在overlay_ws空间中覆盖他,进行一些修改再进行试验,那你就要使用如下的source来说明一下原有的package所在的环境了,更详细的请参考ROS官方wiki里的第四部分chaining catkin worksapces

$ source ~/caktin_ws/devel/setup.bash
          声明完你要覆盖的package所处的环境以后,就可以编译了

  • $ cd ~/overlay_ws/
    $ catkin_make
          到此,所有的工作已经完成,接下来调用ros_tutorials这个包试试,

在使用这前,别忘了source overlay_ws这个工作空间:

  • $ source ~/overlay_ws/devel/setup.bash
接下来看看调用ros_tutorials包,ROS会调用哪个?

  • $ roscd rospy_tutorials
    $ pwd
~/overlay_ws/src/ros_tutorials/rospy_tutorials

      

       这个时候结果很明显,但是ROS原装的那个/opt/ros/hydro里的那个ros_tutorials也还存在,如果你不想调用自己修改了的,而去用原装的package那怎么做?

       很简单,只要不使用source overlay_ws,而是使用source /opt/ros...就行,总结起来如下:

$ source /opt/ros/hydf/setup.bash 
$ roscd rospy_tutorials
$ pwd
/opt/ros/hydro/share/rospy_tutorials

$ source ~/overlay_ws/devel/setup.bash
$ roscd rospy_tutorials
$ pwd
/home/<user>/overlay_ws/src/ros_tutorials/rospy_tutorials
      
       以上博文记录了如何覆盖简单的package,内容绝大部分都来自ROS官方wiki,LZ只是加入了一些简单的理解。

那如何覆盖gmapping?

       其实覆盖gmapping包步奏和上面的没有区别,这里主要是理清gmapping包中迷惑大家的地方。如果你去gmapping的ROS wiki官方页面,你会发现有两个包gmapping和openslam_gmapping,如下图所示:

       

        这很容易让初学者迷惑,为啥有两个?

        这是由于gmapping算法实现的正宗源代码是来自开源项目openslam,ROS的开发者提供了gmapping包和openslam_gmapping包,他们作用各不相同。其中openslam_gmapping是gmapping创始者Grisetti开发的对外开放的gmapping库,里面有各种函数和接口供使用者调用。而ROS中的gmapping包是ROS开发者调用openslam_gmapping 中的函数而完成gmapping的所有功能(包括读取数据(scan,odom),处理数据(粒子滤波,scan match 等),发布数据(map,tf关系等) ),openslam_gmapping包可以理解为opencv,gmapping包可以理解为用opencv中函数实现的一个机器视觉工程。

         因此要修改真正的gmapping算法,应该去修改openslam_gmapping中的东西。当然也许你也只是想改改gmapping包而不去修改SLAM原算法,譬如将gmapping得到的最优粒子的轨迹记录到txt中等。所以在overlay gmapping时,同时把两个包都覆盖:

        openslam_gmapping包的地址:https://github.com/rosperception/openslam_gmapping

        gmapping包的地址: https://github.com/ros-perception/slam_gmapping

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

$ cd ~/overlay_ws/src 
$ git clone https://github.com/rosperception/openslam_gmapping.git
$ git clone https://github.com/ros-perception/slam_gmapping.git
$ wstool update
$ source /opt/ros/hydro/setup.bash
$ cd ~/overlay_ws
$ catkin_make

编译完以后,没有错误,就可以按自己需要对gmapping代码进行修改了,只是每次要是想调用自己修改的gmapping代码,要记得source一下overlay_ws工作环境,然后再调用就行了。


(转载请注明作者和出处:http://blog.csdn.net/heyijia0327 未经允许请勿用于商业用途)


reference:

1. http://wiki.ros.org/catkin/Tutorials/workspace_overlaying

2. http://answers.ros.org/question/120771/gmapping-pacakage-overlaying-with-catkin-workspaces/

3. http://answers.ros.org/question/123756/how-to-modify-the-slam_gmapping-node-on-a-turtlebot/



<think> 我们被要求介绍 `ros::package::getPath` 的使用方法和功能。根据提供的引用,我们可以总结如下: **功能**: `ros::package::getPath` 是 ROS 中用于获取指定 ROS 包在文件系统中的绝对路径的函数。这对于需要访问包内资源(如配置文件、模型文件、脚本等)的节点程序非常有用。 **使用方法**: 1. **包含头文件**:在使用该函数之前,需要包含头文件 `<ros/package.h>`。 2. **调用函数**:调用 `ros::package::getPath("package_name")`,其中 `package_name` 是你要查询的 ROS 包的名字(字符串类型)。 3. **返回值**:函数返回一个 `std::string` 类型的字符串,即该包的绝对路径。 **注意事项**: - 确保查询的包已经安装且在 `ROS_PACKAGE_PATH` 环境变量中能够找到。 - 如果包不存在,该函数会抛出 `ros::package::PackageNotFoundException` 异常。 **示例代码**: ```cpp #include <ros/ros.h> #include <ros/package.h> // 必须包含的头文件 int main(int argc, char** argv) { ros::init(argc, argv, "get_package_path_example"); // 获取包名为 "my_package" 的路径 std::string path = ros::package::getPath("my_package"); ROS_INFO("Package path: %s", path.c_str()); return 0; } ``` **配置修改**(根据引用[1]): 在使用该函数时,有时需要修改 `CMakeLists.txt` 和 `package.xml` 文件以确保正确链接依赖。 1. **CMakeLists.txt**:添加对 `roscpp` 的依赖(如果还没有的话): ```cmake find_package(catkin REQUIRED COMPONENTS roscpp ) ``` 2. **package.xml**:添加对 `roscpp` 的依赖: ```xml <build_depend>roscpp</build_depend> <exec_depend>roscpp</exec_depend> ``` **常见问题**(引用[1][2][3]): - 问题:未包含头文件导致编译错误。 解决:添加 `#include <ros/package.h>`。 - 问题:包名错误或包未找到。 解决:检查包名拼写,并确保该包已安装且在ROS工作空间中。 **总结**: `ros::package::getPath` 是一个方便的工具,用于在运行时获取ROS包的路径,使得程序可以动态访问包内资源。使用时需要注意异常处理(例如包不存在的情况)以及构建系统的配置。 §§相关问题§§ 1. 如何处理 `ros::package::getPath` 抛出的包不存在异常? 2. 除了 `getPath`,ROS 包管理 API 还提供了哪些常用函数? 3. 在 ROS2 中是否有类似 `ros::package::getPath` 的功能? 4. 如何在不使用 `ros::package::getPath` 的情况下获取当前包的路径? </think> ### `ros::package::getPath` 使用方法及功能介绍 #### **1. 核心功能** `ros::package::getPath` 是 ROS 中用于 **获取指定 ROS 包在文件系统中的绝对路径** 的关键函数[^1]。其主要用途包括: - ✅ **定位资源文件**:快速找到包内的配置文件(如 YAML/XML)、模型文件(URDF/Mesh)、脚本等[^3]。 - ✅ **动态路径构建**:避免硬编码路径,使代码可移植到不同系统环境[^2]。 - ✅ **跨包访问**:在节点中访问其他 ROS 包的资源(如地图、参数配置)[^1]。 --- #### **2. 使用方法** ##### **基础调用** ```cpp #include <ros/ros.h> #include <ros/package.h> // 必须包含的头文件[^1][^2] int main() { // 获取包名为 "my_package" 的绝对路径 std::string path = ros::package::getPath("my_package"); ROS_INFO("Package path: %s", path.c_str()); return 0; } ``` **输出示例**: `/home/user/catkin_ws/src/my_package` ##### **关键步骤** 1. **头文件包含**: ```cpp #include <ros/package.h> // 必需[^2][^3] ``` 2. **构建配置**(`CMakeLists.txt`): ```cmake find_package(catkin REQUIRED COMPONENTS roscpp # 依赖 roscpp[^1] ) target_link_libraries(your_node ${catkin_LIBRARIES}) ``` 3. **包声明**(`package.xml`): ```xml <build_depend>roscpp</build_depend> <exec_depend>roscpp</exec_depend> ``` --- #### **3. 常见问题与解决** | **问题现象** | **原因** | **解决方案** | |----------------------------|---------------------------|------------------------------------------| | 编译错误:未定义 `getPath` | 缺少头文件或链接库 | 添加 `#include <ros/package.h>`[^2][^3] 并检查 `CMakeLists.txt`[^1] | | 返回空路径 | 包名拼写错误或未安装 | 用 `rospack list` 验证包名[^1] | | 运行时崩溃 | 未初始化 ROS 节点 | 先调用 `ros::init()`[^3] | --- #### **4. 典型应用场景** ```cpp // 加载包内的配置文件 std::string config_path = ros::package::getPath("nav_config") + "/params/mapping.yaml"; // 访问模型文件(URDF) std::string urdf_path = ros::package::getPath("robot_description") + "/urdf/robot.urdf"; // 执行包内脚本 std::string script_path = ros::package::getPath("utils") + "/scripts/calibration.py"; system(("python3 " + script_path).c_str()); ``` --- #### **5. 注意事项** 1. **异常处理**: 包不存在时会抛出 `ros::package::PackageNotFoundException`,建议用 `try-catch` 捕获: ```cpp try { std::string path = ros::package::getPath("unknown_package"); } catch (const ros::package::PackageNotFoundException& e) { ROS_ERROR("Package not found: %s", e.what()); } ``` 2. **性能优化**: 避免在高频回调中多次调用,应在初始化阶段缓存路径[^3]。 3. **ROS 2 差异**: ROS 2 中使用 `ament_index_cpp` 替代,接口为 `get_package_share_directory()`。
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值