ROS系统底层原理及代码剖析(2)

本文详细解析了ROS中的catkin_init_workspace命令的工作原理,包括创建CMakeLists.txt文件、使用Python脚本创建符号链接以及CMakeLists.txt内容的生成过程。同时介绍了命令执行后的文件分析和工作空间构建流程。
摘要由CSDN通过智能技术生成

一、ros命令 catkin_init_workspace 分析

创建ros工作空间的步骤:

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

我们可以看到一行打印的消息:(请记住这行消息,下面会用到)

$ Creating symlink "~/catkin_ws/src/CMakeLists.txt" pointing to "/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake"

1. catkin_init_workspace 命令运行

  catkin_init_workspace 命令会在当前src目录下创建一个 CMakeLists.txt 文件,这是一个用于catkin工作空间的顶层CMakeLists.txt文件。该文件的主要作用是搜索catkin,并将其包含到工作空间中。CMakeLists.txt的源文件:在这里

  catkin_init_workspace命令实则为运行一个py文件,它的文件位置如下:

$ which catkin_init_workspace
$ /opt/ros/kinetic/bin/catkin_init_workspace

  打开这个py文件,可以看到:

from catkin.init_workspace import init_workspace  # noqa: E402
###
###...省略..###
###
    workspace = os.path.abspath(args.workspace)
    if not os.path.isdir(workspace):
        parser.error('Workspace "%s" does not exist' % workspace)
    try:
        init_workspace(workspace)

  我们可以在我们的电脑中找到包含函数init_workspace的py文件,如下:

$ sudo find / -name init_workspace*
$ /opt/ros/kinetic/lib/python2.7/dist-packages/catkin/init_workspace.py

  该文件位置:在这里 也可以找到
  打开这个init_workspace.py文件,可以看到:

def _symlink_or_copy(src, dst):
    try:
        os.symlink(src, dst)
        print('Creating symlink "%s" pointing to "%s"' % (dst, src))

  根据这里的print()函数和上面的那条打印消息我们可以知道 dst 和 src 分别是:

$ ~/catkin_ws/src/CMakeLists.txt
$ /opt/ros/kinetic/share/catkin/cmake/toplevel.cmake

  它这里使用了Pythonos.symlink()函数,用于创建符号链接,src是我们要创建符号链接的源文件或目录的路径,而dst则是新的符号链接的路径。符号链接其实是一种类似于快捷方式的文件系统对象,它可以指向另一个文件或目录。
  其实这个CMakeLists.txt的内容和toplevel.cmake的内容完全一样,ros在编译使用CMakeLists.txt时,实际上相当于使用了toplevel.cmake,然后再调用这个目录下面的其它cmake函数完成编译。

2. 命令运行后产生的文件分析

  我们再来看看这个 CMakeLists.txt 文件,打开这个文件我们可以看到:

cmake_minimum_required(VERSION 3.0.2)
project(Project)
set(CATKIN_TOPLEVEL TRUE)

set(_cmd "catkin_find_pkg" "catkin" "${CMAKE_SOURCE_DIR}")
execute_process(COMMAND ${_cmd}
  RESULT_VARIABLE _res
  OUTPUT_VARIABLE _out
  ERROR_VARIABLE _err
  OUTPUT_STRIP_TRAILING_WHITESPACE
  ERROR_STRIP_TRAILING_WHITESPACE
)

  execute_process()是CMake提供的一个命令,用于在构建过程中执行外部命令或脚本,RESULT_VARIABLE 表示命令的返回值将会被保存在这个 _res 变量中,可以用来判断命令是否执行成功。OUTPUT_VARIABLE 表示命令的标准输出将会被保存在这个 _out 变量中,可以用来获取命令的输出结果。
  首先这里使用execute_process命令执行catkin_find_pkg命令来查找catkin包,而catkin_find_pkg命令实则在执行一个py文件,用于查找给定名称的ROS软件包并返回其相对路径。该py文件位置是:

$ which catkin_find_pkg
$ /usr/bin/catkin_find_pkg

  我们知道 ${CMAKE_SOURCE_DIR} 就是指当前代码的目录,又因为当前这个CMakeLists.txt文件是通过软链接得到的,所以使用execute_process的命令完全可以看成在 /opt/ros/kinetic/share/catkin/cmake 目录下面执行了下面的命令:

$ catkin_find_pkg catkin /opt/ros/kinetic/share/catkin/cmake

  这个命令的意思就是说在 /opt/ros/kinetic/share/catkin/cmake 下寻找catkin包。这将不会找到 catkin包的(大家可以试试这个命令),因为 catkin 包是指 /opt/ros/kinetic/share/catkin/ 这个文件夹。你可能会说找不到怎么办,别急往下看,

if(_res EQUAL 0)
  set(catkin_EXTRAS_DIR "${CMAKE_SOURCE_DIR}/${_out}/cmake")
  include(${catkin_EXTRAS_DIR}/all.cmake NO_POLICY_SCOPE)
  add_subdirectory("${_out}")

  如果成功找到catkin,_res 的结果会是 0,则会将catkin_EXTRAS_DIR设置为catkin的cmake目录,并通过include命令包含all.cmake文件,以让其在同一作用域中运行。然后,它使用add_subdirectory命令将catkin包含到工作空间中。
  当然这里未找到catkin包,将会跳到下面的代码:在这里 58行

  find_package(catkin QUIET
    NO_POLICY_SCOPE
    PATHS ${catkin_search_path}
    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)

  如果未找到catkin,_res 的结果会是 1,则会搜索 catkin_search_path 环境变量中指定的路径,以查找catkin工作空间。如果找到,则使用find_package命令将catkin包含到工作空间中。这里的 ${catkin_search_path} 是指目录 /opt/ros/melodic

  其中,参数catkin表示要查找的软件包的名称。QUIET参数表示在查找过程中不输出任何信息,NO_POLICY_SCOPE参数表示不检查任何CMake策略,而是使用默认值。PATHS参数指定了查找路径,这里使用了变量${catkin_search_path},它是一个由catkin构建系统定义的变量,表示catkin软件包的搜索路径。NO_DEFAULT_PATH参数表示不使用默认的查找路径,NO_CMAKE_FIND_ROOT_PATH参数表示不在根目录中查找。

  找到catkin软件包后,将会调用一个CMake的函数,如下:

catkin_workspace()

  上面这个函数定义在一个cmake文件中,在这里
  打开这个文件后,这里我们先来看函数 em_expand()的内容

  assert(catkin_EXTRAS_DIR)
  em_expand(
    ${catkin_EXTRAS_DIR}/templates/order_packages.context.py.in
    ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/order_packages.py
    ${catkin_EXTRAS_DIR}/em/order_packages.cmake.em
    ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/order_packages.cmake
    )
这里的 ${catkin_EXTRAS_DIR} 是指 /opt/ros/melodic/share/catkin/cmake
这里的 ${CMAKE_CURRENT_BINARY_DIR} 是指 ~/catkin_ws/build (其实就是你工作空间下面的build文件夹)

  该函数 em_expand()也是定义在一个cmake文件中(在这里),它的作用是在你工作空间下面的 build/catkin_generated/ 里,根据模板文件生成 order_packages.py 和 order_packages.cmake 文件。

  该函数执行结束后,会在 order_packages.cmake 文件中会生成一些变量比如 CATKIN_ORDERED_PACKAGES 它用来存储你 src 下面所有功能包的名字,具体请看下面:

CATKIN_ORDERED_PACKAGES  是一个列表,包含了按顺序排列的所有包的名称。
CATKIN_ORDERED_PACKAGE_PATHS  是一个列表,包含了按顺序排列的所有包的路径。
CATKIN_ORDERED_PACKAGES_IS_META  是一个列表,里面是布尔类型值,表示这些包是否为元包。一般都为False。元包是一个虚拟包,它不包含任何源代码,但是可以用于组合和管理其他包。
CATKIN_ORDERED_PACKAGES_BUILD_TYPE  是一个列表,表示所有包的构建类型。构建类型一般都为catkin。

  知道上面变量的类型后,我们创建个功能包,就可以知道catkin_workspace()函数后面的情况,大部分功能包可以看成下面这种情况:

foreach(index RANGE ${range})
	if(${build_type} MATCHES catkin)
		message(STATUS "~~  - ${name}")
endforeach()

foreach(index RANGE ${range})
	elseif(${build_type} MATCHES catkin)
		message(STATUS "+++ processing catkin package: '${name}'")
		message(STATUS "==> add_subdirectory(${path})")
		add_subdirectory(${path})
endforeach()

  这里先是打印了功能包信息的日志,然后使用 add_subdirectory() 命令将功能包的 CMakeLists.txt 文件所在的目录添加到当前项目中,使其成为当前项目的一部分。
  到这里ros命令 catkin_init_workspace 分析结束。

  • 58
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值