白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用

ROS编程-python脚本的调用

  • 动机
  • 1. ros 工作空间的创建和包的创建
    • 1.1 ros 工作空间初始化
    • 1.2 设置编译指令(ctrl+shift+B)
    • 1.2 创建ros包
  • 2. 调用自己创建的python包示例
    • 2.1 文件配置
      • 2.1.1 新建被调用的文件
      • 2.1.2 CMakeLists.txt的配置
    • 2.2 \__init__.py
    • 2.3 setup.py
  • 3. 在其他ros包中调用
    • 3.1 创建python脚本
    • 3.2 执行python脚本
    • 3.3 多聊几句

动机

能够调用包中写的python文件

1. ros 工作空间的创建和包的创建

1.1 ros 工作空间初始化

 mkdir -p learn_ros_ws/src
 cd learn_ros_ws/src/
 catkin_init_workspace
 cd ..
 catkin_make

然后我们在命令行中输入

tree  -L 1

查看文件夹中的一级目录结构
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第1张图片
下面我们将会选用vscode作为集成开发环境,继续创建ros包。

1.2 设置编译指令(ctrl+shift+B)

使用vscide中的ros插件创建包

code .

如果之前已经给vscode安装了ros插件,它会识别出这是一个ros工程,自动生成.vscode文件夹。如果事先没有安装,则可以安装后重新打开这个工程。文件结构如下:
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第2张图片
其中, c_cpp_properties.json文件记录了编程过程中,头文件和python模块的语法搜索路径,关系到变量名是否会有提示。但,跟编译的时候的搜索路径(CMakeLists.txt中规定的文件搜索路径)不是一回事。

接着我们需要创建 tasks.json文件,编辑编译的指令。
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第3张图片
选择catkin_make: build
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第4张图片
这时会弹出一个自动生成的tasks文件, 把红框的部分改为Release
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第5张图片
这时,我们只需要使用快捷键ctrl+shift+B就能够编译ros工程了,其中args 可以添加更多指令, 达到在命令行中敲指令编译一样的效果。

1.2 创建ros包

在src文件夹下右键,选择Create Catkin Package,
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第6张图片
依次输入新建包的名字,依赖的包的名字。如名字设为foo_package_1, ros依赖包输入为roscpp rospy std_msgs sensor_msgs geometry_msgs, 这样就建好一个ros包了。结果如图所示:
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第7张图片
这里有一点可以稍微留意的是,每一个ros package里面会一个src文件和src外面有一个CMakeLists.txt文件和package.xml文件。这两个文件是需要根据需求改动的。而工作空间learn_ros_ws文件夹src下的CMakeLists.txt让他做个安静的美男子就好了,不需要做任何改动。对于devel和build文件是catkin_make huild的时候自动生成的,如果想重新编译工程,可以直接把这两个文件都删掉再重新编译。值得注意的是,在执行ros空间中的可执行文件前需要在终端source一下devel文件夹下的setup.bash文件,如:

source devel/setup.bash

下面我们按照同样的流程,创建一个名为python_recall_test的包。然后ctrl+shift+B编译一下。最终我们整个ros工程的结构如下。

白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第8张图片
好,现在万事俱备,下一节我们将会介绍怎么配置建好的ros包,将其封装为一个modules供ros工程里的其他包的python脚本调用。

2. 调用自己创建的python包示例

2.1 文件配置

2.1.1 新建被调用的文件

白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第9张图片

新建一个scripts/python_recall_test文件夹,然后在其下面新建一个带有utils_foo.py文件的utils文件夹,以及一个foo.py文件。utils_foo.py文件

#! /usr/bin/env python
class WhoAreYou(object):
    def __init__(self) -> None:
        print('I am python recall test script in utils folder!')

foo.py文件则写为:

#! /usr/bin/env python
class Foo(object):
    def __init__(self) -> None:
        print('I am foo in script folder!')
   
if __name__ == '__main__':
    hello = Foo()

2.1.2 CMakeLists.txt的配置

只需要解注释 catkin_python_setup() 这个命令即可,可以ctrl+F进行搜索。注意这里改写的ros包里面CMakeLists.txt

## 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 ##
################################################

2.2 _init_.py

可以是空文件,也可以是一个全局定义的函数。这里我们将它放在scripts文件夹中。就我个人习惯而言,我会喜欢把cpp相关的文件放在include和src文件夹中,而python文件则统统扔到scripts文件夹里面。为了示意,在__init__.py中也写了一点东西。

_init_.py 的出现(只看python脚本的名字)告诉了setup.py 文件,同一目录下的所有python文件的模块都可以被外部调用。

2.3 setup.py

最后,CMakeLists.txt所指向的且在ros包中不可或缺的文件setup.py。在这个文件中规定了packages的类型,实际上也是对应我们生成的modules的名字,和调用方式,它规定了在package_dir下的python文件所在路径(此处是scripts文件夹下)。注意看下图中对应的变量名的位置, python_recall_testpython_recall_test.utils_init_.py 所在的文件目录,这个文件夹下面的所有文件都可以被当成python模块调用。

# ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD!
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# Fetch values from package.xml.
setup_args = generate_distutils_setup(
    packages=["python_recall_test", "python_recall_test.utils",], package_dir={"": "scripts"},
)
setup(**setup_args)

白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第10张图片白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第11张图片
最后我们按下ctrl+shift+B 对整个工程进行编译,这样相关的python模块就会在工程根目录的builddevel文件夹下生成某种涉及我知识盲区的链接文件。

3. 在其他ros包中调用

3.1 创建python脚本

最后就只差调用我们写好的python_recall_test 包了。同样的我们在foo_package_1中创建一个scripts文件夹,然后再在scripts文件夹下创建一个main.py脚本,脚本内容如下:

#! /usr/bin/env python
import rospy

from python_recall_test.foo import Foo
from python_recall_test.utils.utils_foo import WhoAreYou

if __name__ == '__main__':
    rospy.init_node('test_node')
    hi = Foo()
    hello = WhoAreYou()

注意留意python包导入的方式:
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第12张图片

3.2 执行python脚本

  1. 打开终端,输入
roscore
  1. 打开另一个终端或者ctrl+shift+O如果安装了terminator的话,输入工程所在的路径,然后source一下工作空间
cd learn_ros_ws/
source devel/setup.bash
rosrun foo_package_1 main.py 

白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第13张图片
程序正常执行,在同一个工程目录下,A包中python模块可以被B包中的python脚本调用的问题,解决!

3.3 多聊几句

我们再看一下vscode中的截图情况,会发现竟然没有导入路径找不到时出现的波浪号。
白给的ROS编程笔记——vscode+ros工程建立以及ros package中的python脚本封装成模块被其他脚本调用_第14张图片这是因为我们在settings.json里面设置了python的外部搜索路径,你看这个路径的写法跟setup.py文件中的package_dir是不是有点熟悉的味道。当然,关于文件索引的问题,c++的头文件路径也可以在c_cpp_properties.json 文件中定义。

以上就是,如何实现ros包中自定义的python模块被其他包调用的方法总结,需要注意的是,调用前需要source一下工程目录下devel文件夹内的setup.bash文件。

早睡早起精神好!

2022年8月29日凌晨
Dianye Huang

你可能感兴趣的:(ROS,python,vscode,ROS)