(02)Cartographer源码无死角解析-(02) ROS基础讲解→记录编译过程及常用指令

本人讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解(02)Cartographer源码无死角解析-接如下:
(02)Cartographer源码无死角解析-(00)目录_最新无死角讲解:https://blog.csdn.net/weixin_43013761/article/details/127350885
 
文末正下方中心提供了本人 联系方式, 点击本人照片即可显示 W X → 官方认证 {\color{blue}{文末正下方中心}提供了本人 \color{red} 联系方式,\color{blue}点击本人照片即可显示WX→官方认证} 文末正下方中心提供了本人联系方式,点击本人照片即可显示WX官方认证
 

一、前言

通过上一篇博客的介绍,已经对 Cartographer 环境的搭建进行详细讲解,但是如果对ROS不太熟悉的朋友可能会比较懵逼(本人也是这样的)。所以接下来需要对ROS作一些基本的介绍。在安装ROS的时候,为了验证环境是否正常,举了一个小乌龟的例子,需要开启三个终端运行:

	#完成上述工作之后,我们再验证ROS是否安装成功,我们首先要开启三个终端,每个终端运行对应的指令如下:
	第一个终端: roscore
	第二个终端: rosrun turtlesim turtlesim_node # 会出现一个小海龟,
	第三个终端: rosrun turtlesim turtle_teleop_key # 接下来就在可以通过方向键控制海龟的移动。

其实三个终端可以理解为运行了三个可执行文件,在ROS中,运行起来的可执行文件对等于一个 node 节点,其上的 roscore 可以简单理解为服务器。推荐大家看ROS的入门视频:
【古月居】古月·ROS入门21讲 | 一学就会的ROS机器人入门教程
通过上诉视频,可以对ROS有一个基本的了解,下面呢,来做一些梳理与总结。下面是关于ROS常用操作的记录,主要是为了方便自己进行查阅使用的。
 

二、工程创建与编译

在任意目录都可以进行一个ROS新工程创建,但是一般都是在工作目录下创建:

# catkin_ws表示工程根目录也称为workspace(工作空间),src主要用于代码的存放,可以称为代码空间
mkdir -p catkin_ws/src

# 进入代码空间并初始化代码空间
cd ./catkin_ws/src/
catkin_init_workspace

# 回到工作空间进行编译(任意选一个即可)
cd ../
catkin_make
catkin_make_isolated 

# 创建一个可以运行,但不含源码的工程包,以便于给客户等其他人使用,但同时不至于泄露源码的这么一个作用
# 任选指令选择一个即可
catkin_make install  
catkin_make_isolated --install --use-ninja
catkin_make_isolated --install --use-ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=Yes

# 设置环境变量
source devel/setup.bash
source devel_isolated/setup.bash
# 或者如下
source install/setup.bash
source install_isolated/setup.bash 

# 查看环境变量
echo $ROS_PACKAGE_PATH

# 将ros空间中的所有编译经过清空,相当与删除devel和build文件夹,在执行这个步骤前需要慎重。
# catkin_make clean

如果上述指令执行完成且正确,文件的分布类似如下:
(02)Cartographer源码无死角解析-(02) ROS基础讲解→记录编译过程及常用指令_第1张图片
从上述可以看到经过 catkin_make 与 catkin_make install 之后会生成3个文件夹build、devel、install。其作用分别如下:

( 1 ) s r c ( 代码空间 ) \color{blue}(1)src(代码空间) (1)src(代码空间)→ 用于存放功能包的代码、配置文件、launch文件
( 1 ) b u i l d ( 编译空间 ) → \color{blue}(1)build(编译空间)→ (1)build(编译空间) 存放编译过程中产生的中间文件,不太用关心
( 2 ) d e v e l ( 开发空间 ) → \color{blue}(2)devel(开发空间)→ (2)devel(开发空间) 放置编译生成的可执行文件,一些库,包括脚本文件,编译生成的文件在这里运行
( 3 ) i n s t a l l ( 安装空间 ) → \color{blue}(3)install(安装空间)→ (3)install(安装空间) 用install指令安装的文件的结果

install和devel文件夹的区别,install是开发后产生的可执行文件,用于给客户使用的,devel是开发中的可执行文件,用于调试用的

另外再说一下 catkin_make_isolated 与 catkin_make 的区别:

一、catkin_make was the first script around to build catkin workspace and is therefore used in many tutorials. It has several down sides (requiring non-standard logic in packages to declared cross-package target dependencies) and limitation (can't process plain CMake packages, requires all targets across all packages in a workspace to be unique). Therefore I wouldn't recommend to use it.
二、catkin_make_isolated is the script which was developed next which addresses all these shortcomings. It comes at the cost of being slower since it processes all packages sequentially. It is being used on build.ros.org in the devel and PR jobs. I would recommend using this if you want the most reliable solution (exclusively for ROS 1).
三、catkin_tools (called catkin build above) is similar to catkin_make_isolated but addresses the performance limitation by processing packages in parallel where possible. It also has a lot of usability features which makes it much easier to use and configure. On the downside this tool is not being actively maintained for the past years so I wouldn't recommend it either.
四、colcon is the new build tool developed for ROS 2 and works similar to catkin_tools with less usability features at the moment but being able to build any kind of packages (catkin, ament, CMake, Python setuptools, gradle, bazel, cargo, ...) on all major platforms (Linux, macOS, Windows). While developed for ROS 2 it in principle also works for ROS 1. If you are willing to use something more bleeding edge (which might come with quirks which haven't been resolved / polished yet) this might be an option. The big advantage is that the tool is very modular and actively developed and extended by multiple parties.

总的来说, catkin_make_isolated比catkin_make更好一点, catkin_make_isolated编译时,会认为每一个功能包都是一个独立的编译空间, 因此不会像catkin_make需要求所有定义的目标变量名必须是唯一值以免冲突, 而colcon工具目前主要在ros2上开发应用,当然也可以适用于ros1的开发。

 

三、创建功能包

创建代码的时候一定要创建功能包,创建的代码一定要放在功能包中,不能放在src文件中。功能包的创建是要放在src文件夹中的,记得设置完环境变量之后,执行echo $ROS_PACKAGE_PATH 这个指令,检查下环境变量是否成功,只有设置成功环境变量之后,系统才能找到你创建的工作空间,以及工作空间下的功能包,

# 先进入到工作空间,然后进入到代码空间
cd catkin_ws/src

# 误直接执行,直接执行会报错,这是讲解指令
catkin_create_pkg <packge_name> <depend1> <depend2> <depend3>

上述是记录 catkin_create_pkg 的用法,packge_name表示包包名,depend1、depend2、depend3 都是编译过程需要的依赖
比如下面举例创建一个真实包:

# 创建功能包
catkin_create_pkg learning_topic rospy roscpp  std_msgs geometry_msgs turtlesim 

如果功能包创建成功目录分布应该如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/ba28a7d9e82c45649f8e2ea377542fbe.png#pic_center(02)Cartographer源码无死角解析-(02) ROS基础讲解→记录编译过程及常用指令_第2张图片
第一个src为前面的代码空间,子目录的src是用于存放功能包的代码的。可以看到功能包中有两个比较重要的文件,那就是:

( 1 ) C m a k e L i s t s . t x t → \color{blue}(1)CmakeLists.txt→ (1)CmakeLists.txt描述功能包的编译规则,使用的cmake语法,例如找到功能包,如何编译cpp代码,需要哪些库,在CMakeList文件中需要添加需要build的文件信息,把哪个文件build成什么名字等等

( 2 ) p a c k a g e . x m l → \color{blue}(2)package.xml→ (2)package.xml这个文件是用来描述跟这个功能包相关的信息,比如说功能包的名字,版本号,作者信息等等,开园许可证类型,还有功能包所需要的依赖信息,如果缺少功能包的话就会报错,如果在创建功能包的时候没有添加全依赖项,可以在这个文件中添加(build_depend\exec_depend)

下面来举一个例子,也就是实现一个功能包,代码比较简单,答应 hellow word 即可。在工作空间中的 work_space/src/test_pkg 中编写代码文件 velocity_publisher.cpp。
https://github.com/guyuehome/ros_21_tutorials/blob/master/learning_topic/src/velocity_publisher.cpp

编写完成之后,还需要需要告诉系统如何去编译这个文件,即在 work_space/src/test_pkg/CmakeLists.txt 文件中添加如下如下代码,本人为154行添加,即其属于 Build 中的内容:

# 将cpp文件编译成名为velocity_publisher
add_executable(velocity_publisher src/velocity_publisher.cpp)

# 设置链接库  将velocity_publisher用到的相关的库链接起来
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})

回到 work_space/重新编译,且重新设置环境变量:

# 回到工作空间重新编译,且重新设置环境变量
cd ../
catkin_make install
source devel/setup.bash

打印类似如下,则表示成功:
(02)Cartographer源码无死角解析-(02) ROS基础讲解→记录编译过程及常用指令_第3张图片
然后开启两个终端,分别运如下指令:

roscore
rosrun learning_topic velocity_publisher

 

四、常用指令

下面的指令,我们以前面的小海龟为例,所以请大家运行三个终端,运行起小海龟的程序。

1、roscore

启动一个roscore就相当于是开启了一个rosmaster,也就是管理器
 

2、rosrun

rosrun指令的第一个参数是功能包的名字,如果这个时候双击tab按钮,则会显示这个功能包下面的所有节点,选择一个节点执行。如前面的指令:

rosrun learning_topic velocity_publisher

 

3、rosnode

 

4、rosbag

rospack profile #查看包的路径,其功能与 echo $ROS_PACKAGE_PATH 是比较类似的
rospack list #列举目前所有安装的packge

 

5、rostopic

rostopic list #可以看到所有话题
rostopic info  <话题>   # 可以看到话题信息,如 rostopic info /map

 

6、rosservice

 

7、rosparam

 

8、rosmsg

 

9、rossrv

 

10、rossrv

 

11、rqt开头,可视化

执行rqt_graph可以看到各个节点之间的相互关系,如下如下所示:
(02)Cartographer源码无死角解析-(02) ROS基础讲解→记录编译过程及常用指令_第4张图片
另外还可以直接执行rqt,界面出来的之后,选择左上角的 Plugins→introspection→Node Graph 也可以达到一样的效果。

 

五、roslaunch使用

        在运行小海龟示例的时候,需要同时开启三个终端来运行程序,感觉很十分的麻烦,更别说三个以上的程序了。roslaunch是ROS提供的一个启动工具,它能够使得启动多个ROS节点的过程变得简单,同时也简化了ROS参数服务器进行参数设置的过程。roslaunch配置文件使用XML语言编写,文件以.launch为扩展名,放在package的launch文件夹下,最简单的launch文件→简单来说:launch文件就是可以同时启动多个节点,在一个XML格式的文件内将需要同时启动的节点一一罗列出来),其与 rosrun 相比,只能运行一个节点, roslaunch可以同时运行多个节点。

# 使用方式,首先指定包名,然后再指定 launch 文件
roslaunch <package_name> <launch_file_name>

# 如上上一篇博客使用的:
roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

# 也可以同如下方法一样,roslaunch+launch文件的绝对路径。因为launch文件可以不被包含于package中,执行launch文件的绝对路径即可。
oslaunch /my_work/ROS/work/cartographer_detailed_comments_ws/src/cartographer_ros/cartographer_ros/launch/demo_backpack_2d.launch   bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

 

六、launch文件

1、launch 格式

①launch文件是XML文件,每个XML文件必须有一个根元素。而launch文件的根元素由一对launch 标签定义。

<launch>
...
launch>

launch文件中的其他元素必须都在这一对标签之间。开始为 ,结束为,注意有一个斜杠!!表示结束,这是配对的,有头必有尾。

②launch文件的核心是一系列节点元素node elements,每个节点元素node element启动一个节点node。一个node element包含三个必须的属性:pkg, type, name。pkg和type属性指出ROS应该运行哪个pkg中的哪个node,注意:此处的type是可执行文件的名称,而name则是可以任意给出的,它覆盖了原有文件中ros::init指定的node name。

<node
  pkg="package_name" type="executable_name" name="node_name"
/>

最后的“/”是必不可少的,表示一个节点的结束。也可以写成,如果该节点中有其他标签,则必须使用这种形式。
 

2、include

include element为包含其他launch文件,包括这些launch文件的所有节点nodes和参数parameters。常用


注意,执行该launch文件时,roslaunch会搜索该package下的所有子目录;因此,必须给出package_name。如 Cartographer_ros中的
src/cartographer_ros/cartographer_ros/launch/demo_backpack_2d.launch 文件编写如下:

<launch>
  <param name="/use_sim_time" value="true" />

  <include file="$(find cartographer_ros)/launch/backpack_2d.launch" />

  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_2d.rviz" />
  <node name="playbag" pkg="rosbag" type="play"
      args="--clock $(arg bag_filename)" />
launch>

 

3、include 与 参数

便于launch文件重构,roslaunch支持launch arguments,即arguments或者args,类似于局部变量。注意:尽管argument和parameter有时可互换,但他们在ROS中的意义完全不同。Parameters是ROS系统使用的数值,存在parameter server上,nodes可通过ros::param::get函数编程得到,用户可通过rosparam获取。与之不同,arguments仅在launch文件内部有意义,nodes不能直接获取它们的值。

<arg name="arg_name">  //声明argument

launch文件中的每个argument都必须有指定值。赋值方法有好几种。

//在命令行赋值
roslaunch package_name launch_file_name arg-name:=arg_value

//第二种,在声明argument时赋值
<arg name="arg_name" default="arg_name"/>
<arg name="arg_name" value="arg_name"/>

上面两行的区别在于,命令行参数可以覆盖default,但是不能重写value的值。一旦声明某个argument并赋值后,我们可以通过arg使用该argument。

$(arg arg-name) 

如果该行出现,roslaunch将会用给定arg-name的值替换其左边的值(即赋值给左边)。另外可以将argument值传给included launch文件:

<include file="path-to-file">
<arg name="arg_name" value="arg_value"/>
......
include>

若在launch文件中,launch文件及其包含的launch文件出现相同的arguments(参数),则需在launch文件及included launch文件中同时写:

<arg name="arg_name" value="$(arg arg_name)"/>

第一个arg_name表示include launch文件中的argument;第二个arg_name表示当前launch文件中的argument
其结果是指定的argument在当前launch文件及include launch文件中都有相同的值。
 

4、创建groups

group element可以再大型的launch文件中将指定的节点nodes组织起来。它有两个用处:其一,group可以将几个nodes放进同一个namespace

<group ns="namespace">
<node pkg=".." .../>
<node pkg=".." .../>
......
group>

注意,如果group node已经有它自己的namespace,并且是relative name,那么该node的namespace是其relative name,并以group namespace为后缀。其二,group可以同时启动或者终止一组nodes

<group if="0 or 1"> 
......
group>

如果该属性的值是1,一切正常;如果该属性的值为0,那么group内所有的nodes都不会运行。同理,除了if,还有unless。

<group unless="0 or 1">
......
group>

注意,这些属性的合法值只有0和1。另外,group element中只能使用ns,if,unless这三个属性。
nbsp;
 

5、remap重映射

remap用于修改节点nodes当前使用的名称。

重映射相当于重命名,每次需提供一个原始的名字original name和一个新的名字new name。每次node节点使用它的original name, ROS client library都会将其替换为remap name重命名了的名字。创建remap name两种方法:首先对于单个node,在命令行进行remap(remap对象可以是node,topic等)。

original-name:=new-name
如:rosrun turtlesim turtlesim_node turtle1/pose:=tim

另外就是在launch文件内remap names,使用remap element

 <remap from="original_name" to "new_name">

如果remap出现在launch文件开头,作为launch文件的子元素,则该remap将被用于后续所有的nodes;如果remap作为某个node的子元素,则只用于该节点。在ROS进行remap之前,remap的所有name,包括original和new names,都将被解析为global names。所以,remap之后所有的名字通常都是relative names。
 

6、group中的param

group标签中的param标签的作用等同于rosparam set命令,node标签中的param标签设置为该节点的子元素。在launch文件中也支持等同与rosparam load 功能的rosparam标签,用于一次性加载大量的参数到参数服务器中。

<rosparam command="load" file="path-to-param-file" />

这里的file是.yaml类型,所需要设置的参数放到该文件中。

 
 
 

你可能感兴趣的:(#,机器人,自动驾驶,无人机,增强现实,Cartographer)