ROS新建工作区(workspace)与包(package)编译的实践(C++示例)

这篇具有很好参考价值的文章主要介绍了ROS新建工作区(workspace)与包(package)编译的实践(C++示例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ROS工作区是用来存放ROS工作包的目录,这些工作包,包含了ROS程序的各种文件,包括源代码、配置文件、消息文件等。所以工作区的本质是一个文件夹,用来存放接下来将要介绍的包以及构建这些包所需的文件。ROS工作区可以新建很多,它们之间都是相互独立的,在各自的工作区运行着特定的程序,这样避免了不相关的程序放在一起,也遵循着松耦合的设计理念,这样做的好处是显而易见的,同样的功能放在一起,也便于调试。

1、ROS工作区

新建工作区(目录)

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src

指定-p可以新建多个不存在的目录,也就是这条路径所有的目录,如果不存在都将新建。另外新建工作区,我们一般建立在当前用户的根目录下 ~/

初始化工作区

catkin_init_workspace
#Creating symlink "/home/yahboom/catkin_ws/src/CMakeLists.txt" pointing to "/opt/ros/melodic/share/catkin/cmake/toplevel.cmake"

这里实质是创建了一个指向toplevel.cmake的符号链接,这样做的结果,是让整个系统可见。

工作区创建并初始化好了之后,再来创建一些其他的工作区文件:

cd ~/catkin_ws
catkin_make

命令catkin_make会编译所有节点并保证所有依赖都是最新的。我们查看下src目录多出了哪些目录:ls

build  devel  src

多了一个builddevel的目录,其中build目录里面是使用C++时catkin存放库和可执行程序的地方,如果我们使用Python的情况就可以忽略build里面的内容,而devel里面主要关注setup.bash文件,运行这些文件,可以使系统使用这个工作区以及其中包含的代码。
通过下面的命令来配置,将setup.bash追加(>>)到.bashrc中去:

echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

工作区就这么愉快的新建好了。 接下来为了熟悉全面点,使用C++来做一个编译,看下需要做哪些相关操作。

2、ROS包

“包”的名字,在Ubuntu中的软件也是以包的形式存在,但是ROS中的包,跟Ubuntu的包有区别,由于专门讲机器人操作系统,所以后期说的“包”都是指代ROS包,如果是Ubuntu包就会特别说明是Ubuntu包。
创建包的命令:

catkin_create_pkg tony_code rospy

这个catkin_create_pkg命令,在前面的文章, ROS机器人操作系统Catkin的编译与常用命令的使用介绍 ,也出现过,是一种很常见的命令。

这样就成功创建了一个名为tony_code的新包,里面有CMakeLists.txtpackage.xml文件,还有一个src文件夹用来存放实际源代码,该包依赖已经存在的rospy包,如果你的包还依赖其他的包,可以在命令行中列出。

这个工作区的一个目录结构大致如下:

|---catkin_ws/
|------build/
|------devel/
|------src/
         |----CMakeLists.txt
         |----tony_code/
             |----CMakeLists.txt  package.xml  src
         |----Other/
             |----CMakeLists.txt  package.xml  src

这里会出现几个CMakeLists.txt需要区分开来,在工作区的根目录的src目录下面有一个之外,每个包里面也都有一个CMakeLists.txt

2.1、CMakeLists.txt

在上面说了除了工作区一个CMakeLists.txt之外,每个包也有一个,我们在编译包的时候,进行修改的就是对应包下面的CMakeLists.txt

这个对于熟悉Make的读者来说,就很简单了,这个文件是定义如何编译工作包里面的源代码的。
我们来查看下新建包tony_code里面的CMakeLists.txt文件的内容:cat CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(tony_code)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  rospy
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs  # Or other packages containing msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES tony_code
#  CATKIN_DEPENDS rospy
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/tony_code.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/tony_code_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_tony_code.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

CMakeLists.txt文本内容我们也大概了解到,是用于描述构建一个或多个软件项目的配置信息,通过编辑配置,CMake就可以根据项目的配置信息自动生成构建脚本,以编译、测试和安装软件项目。
按照自己的需求,需要用到什么就去掉注释,比如配置中,需要添加头文件的目录,就开启include_directories

在使用opencv时需要包含/usr/local/include/opencv/cv.h这个头文件。我们将它的目录包含进来:include_directories(/usr/local/include) 在调用函数时添加: #include "opencv/cv.h"

其他的配置,将在后面需要用到的时候,进行说明。 

2.2、package.xml 

这个package.xml文件包含了工作包的元信息,如程序包名称、版本号、依赖关系等。
我们查看下这个文件的内容:cat package.xml

<?xml version="1.0"?>
<package format="2">
  <name>tony_code</name>
  <version>0.0.0</version>
  <description>The tony_code package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="yahboom@todo.todo">yahboom</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/tony_code</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>rospy</build_depend>
  <build_export_depend>rospy</build_export_depend>
  <exec_depend>rospy</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

这个文件包含了一组和新包有关的元数据。分别来介绍下其中的节点:

name:程序包的名字,这个节点不能修改!!
version:程序包的版本号
description:程序包功能的简短描述
maintainer:程序包的维护者和修复bug的,可以多人
license:许可证
url:程序包的URL
author:程序包的作者
buildtool_depend:构建工具,在ROS里目前基本都是catkin
build_depend:依赖项
export:catkin以外的其他工具需要的信息

3、编译C++

有了上面的知识铺垫,我们用C++来写一个最简单的节点,然后对其进行编译,熟悉整个过程以及遇到的错误。

3.1、新建minimal包

按照上述介绍的,新建一个新的包,这里名字叫minimal

cd ~/catkin_ws/src
catkin_create_pkg minimal rospy

3.2、C++代码

创建包之后,我们在这个minimal包下面的src目录里建一个C++文件

cd minimal/src
gedit minimal.cpp

minimal.cpp内容如下

#include <ros/ros.h>

int main(int argc,char **argv)
{
    ros::init(argc,argv,"minimal");
    ros::NodeHandle n;
    ros::spin();
    return 0;
}

这个是最简单的C++写的一个ROS节点,包含一个ROS头文件。
ros::init(argc,argv,"minimal"); 初始化节点,并命名为minimal,相当于是命名空间
ros::NodeHandle n; 创建一个节点句柄,用来创建话题、服务和动作。在Python中不需要这样显式地创建节点句柄,因为ROS的Python接口可以隐式地实现
ros::spin(); 一直等待ROS的调度,简单理解的话,比如订阅的时候处理回调函数,会一直循环进行订阅的意思。当然后期会遇到有ros::spinOnce();这样一个函数,意思是一样的,只不过这个一般是放在循环中。

3.3、修改CMakeLists.txt

然后就是对配置文件进行修改了,这里依然需要注意,使用的是minimal这个包下面的CMakeLists.txt文件

cd ~/catkin_ws/src/minimal
gedit CMakeLists.txt

修改下面三处地方,并将注释去掉,使其生效:

find_package(catkin REQUIRED rospy)

add_executable(minimal src/minimal.cpp)

target_link_libraries(minimal ${catkin_LIBRARIES})

3.4、编译

配置好了之后,我们就开始编译:

cd ~/catkin_ws
catkin_make

这里编译的时候,需要注意的是,要回到工作区的根目录进行编译。
虽然三处地方修改了,但编译还是报如下的错误,找不到头文件ros/ros.h,这是一个很常见的错误:

Scanning dependencies of target minimal
[ 50%] Building CXX object minimal/CMakeFiles/minimal.dir/src/minimal.cpp.o
/home/yahboom/catkin_ws/src/minimal/src/minimal.cpp:1:10: fatal error: ros/ros.h: No such file or directory
 #include <ros/ros.h>
          ^~~~~~~~~~~
compilation terminated.
minimal/CMakeFiles/minimal.dir/build.make:62: recipe for target 'minimal/CMakeFiles/minimal.dir/src/minimal.cpp.o' failed
make[2]: *** [minimal/CMakeFiles/minimal.dir/src/minimal.cpp.o] Error 1
CMakeFiles/Makefile2:431: recipe for target 'minimal/CMakeFiles/minimal.dir/all' failed
make[1]: *** [minimal/CMakeFiles/minimal.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j2 -l2" failed

3.5、编译错误处理

针对上面编译的错误,在上面也有介绍,这里出现了头文件,所以需要打开include_directories

include_directories(include ${catkin_INCLUDE_DIRS}) 

然后再次编译,依然出错,启动节点管理器roscore,是可以正常启动的,所以环境变量配置是没有问题的。原因在于这里用了C++,所以需要这个roscpp依赖包,修改如下:

find_package(catkin REQUIRED COMPONENTS rospy roscpp) 

然后再次编译就没有问题了。如图:

ROS新建工作区(workspace)与包(package)编译的实践(C++示例),机器人操作系统(ROS),初始化工作区,catkin_make,创建ROS包,CMakeLists.txt,package.xml,ros/ros.h,roscpp这样就将编译的minimal可执行程序,放在了~/catkin_ws/devel/lib/minimal/minimal中。 文章来源地址https://www.toymoban.com/news/detail-691553.html

到了这里,关于ROS新建工作区(workspace)与包(package)编译的实践(C++示例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VS Code工作区用法

    背景 VS Code可以通过\\\"文件/打开文件夹\\\"来打开本地项目,但是想要打开多个项目便需要来回切换,比较费劲。此时就可以使用工作区功能,将不同的项目放置到同一个工作区中,这样切换项目的时候就会非常方便。 操作方法 打开其中一个项目 执行命令:文件 》 打开文件夹

    2024年01月25日
    浏览(48)
  • VScode 工作区配置 和 用户配置

    通常不同的项目都有不同的配置,我一般都是使用eslint和prettier一起用,所以经常会有这几个文件: 这里简单介绍一下这几个文件的作用吧。 一般有两个文件,extensions.json和settings.json。 extensions.json 文件是用来配置推荐安装的 VS Code 插件的文件。在这个文件中,你可以列出你

    2024年01月24日
    浏览(41)
  • go work 笔记 (多模块工作区)

    go 1.18 引入了功能泛型 (Generics), 同时还引入的多模块工作区 (Workspaces) 和模糊测试 (Fuzzing)。 Go 多模块工作区能够使开发者能够更容易地同时处理多个模块的工作, 如: 方便进行依赖的代码调试(打断点、修改代码)、排查依赖代码 bug 方便同时进行多个仓库/模块并行开发调试 通

    2024年02月12日
    浏览(33)
  • Git——三大分区【工作区 / 暂存区 / 版本区】

    前言 :Git作为一个版本管理工具,最核心组成思想是它的三个分区:工作区、暂存区和工作区。   Git的工作区也就是我们平时编辑代码的目录文件夹。   暂存区就是一个 暂时放置修改文件记录 的地方。以往仓库中放货物为例,向仓库中放货物总是一车车的拉,因为如

    2024年02月06日
    浏览(49)
  • git工作区删除了文件想更新回来

    删除了本地dev分支的几个文件,本地dev对应远端dev分支,想更新回来 法一、如果你知道文件夹名称或者文件名称: 法二、工作区的修改,其中就包括删除,这其实都会被git认为正常的操作,即使是你误操作 而针对你的操作,git提供了回退操作,如下图 法三,直接将本地库整

    2024年02月11日
    浏览(51)
  • Azure 机器学习 - 如何使用模板创建安全工作区

    本教程介绍如何使用 [Microsoft Bicep]和 [Hashicorp Terraform]模板创建以下 Azure 资源: Azure 虚拟网络。 以下资源在此 VNet 后面进行保护: Azure 机器学习工作区 Azure 机器学习计算实例 Azure 机器学习计算群集 Azure 存储帐户 Azure Key Vault Azure Application Insights Azure 容器注册表 Azure Bastion

    2024年02月04日
    浏览(38)
  • idea将文件移出git的工作区

    之前使用idea在commit项目时候,忘记添加.gitignore文件了,导致提交了很多无关的文件进入远程仓库,网上有教程是使用git - reset head 方法,但是这个方法只是将上一次的commit文件覆盖当前的暂存区文件,而非移除暂存区文件,所以没有用   但是在idea工具好像并没有提供将文件移

    2024年02月13日
    浏览(36)
  • 注册claude AI账号 slack工作区账号

    Claude 是建立在 slack工作区的一个AI人工助手,更像是将chatgpt集成到了会议模式,一个账号实际上拥有了你的会议室和你的AI助手,你可以让你的朋友和同事进入你的房间体验。 Claude是不是openai的产物?目前还不知道,不过就从回复速度来看,他比chatgpt和通过api调用的第三方

    2023年04月18日
    浏览(74)
  • git 将其它分支的文件检出到工作区

    主要是使用如下命令: 覆盖与 pathspec 匹配的文件的内容。当没有给出 tree-ish (通常是一个commit)时,用 index 中的内容覆盖工作树。当给出 tree-ish 时,用 tree-ish 处的内容同时覆盖 index 和工作树。 由于前一个的合并失败,index 可能包含未合并的条目。默认情况下,如果您试图从

    2023年04月09日
    浏览(28)
  • git在工作区和本地库的操作命令

     本文介绍一些开发时,常用的在工作区和本地库之间的操作命令 工作树的修改内容要提交到本地库,首先需要先添加到缓存区stage,在commit到本地库。 你开发了一段时间,可能已经忘记了修改过那几个文件 可以使用 git status 查看 工作区和缓存区的内容 ,即修改过的文件和

    2024年02月15日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包