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


    动机

    能够调用包中写的python文件

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

    1.1 ros 工作空间初始化

     mkdir -p learn_ros_ws/src
     cd learn_ros_ws/src/
     catkin_init_workspace
     cd ..
     catkin_make
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后我们在命令行中输入

    tree  -L 1
    
    • 1

    查看文件夹中的一级目录结构
    在这里插入图片描述
    下面我们将会选用vscode作为集成开发环境,继续创建ros包。

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

    使用vscide中的ros插件创建包

    code .
    
    • 1

    如果之前已经给vscode安装了ros插件,它会识别出这是一个ros工程,自动生成.vscode文件夹。如果事先没有安装,则可以安装后重新打开这个工程。文件结构如下:
    在这里插入图片描述
    其中, c_cpp_properties.json文件记录了编程过程中,头文件和python模块的语法搜索路径,关系到变量名是否会有提示。但,跟编译的时候的搜索路径(CMakeLists.txt中规定的文件搜索路径)不是一回事。

    接着我们需要创建 tasks.json文件,编辑编译的指令。
    在这里插入图片描述
    选择catkin_make: build
    在这里插入图片描述
    这时会弹出一个自动生成的tasks文件, 把红框的部分改为Release
    在这里插入图片描述
    这时,我们只需要使用快捷键ctrl+shift+B就能够编译ros工程了,其中args 可以添加更多指令, 达到在命令行中敲指令编译一样的效果。

    1.2 创建ros包

    在src文件夹下右键,选择Create Catkin Package,
    在这里插入图片描述
    依次输入新建包的名字,依赖的包的名字。如名字设为foo_package_1, ros依赖包输入为roscpp rospy std_msgs sensor_msgs geometry_msgs, 这样就建好一个ros包了。结果如图所示:
    在这里插入图片描述
    这里有一点可以稍微留意的是,每一个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包,将其封装为一个modules供ros工程里的其他包的python脚本调用。

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

    2.1 文件配置

    2.1.1 新建被调用的文件

    在这里插入图片描述

    新建一个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!')
    
    • 1
    • 2
    • 3
    • 4

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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 ##
    ################################################
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述在这里插入图片描述
    最后我们按下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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意留意python包导入的方式:
    在这里插入图片描述

    3.2 执行python脚本

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

    在这里插入图片描述
    程序正常执行,在同一个工程目录下,A包中python模块可以被B包中的python脚本调用的问题,解决!

    3.3 多聊几句

    我们再看一下vscode中的截图情况,会发现竟然没有导入路径找不到时出现的波浪号。
    在这里插入图片描述这是因为我们在settings.json里面设置了python的外部搜索路径,你看这个路径的写法跟setup.py文件中的package_dir是不是有点熟悉的味道。当然,关于文件索引的问题,c++的头文件路径也可以在c_cpp_properties.json 文件中定义。

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

    早睡早起精神好!

    2022年8月29日凌晨
    Dianye Huang

  • 相关阅读:
    【历史上的今天】7 月 21 日:施乐退出计算机市场;《世界版权公约》制定;苹果推出 Apple Airport
    YSA Toon (Anime/Toon Shader)
    css选择器(通配符、(元素、类、id)、后代(子代、所有后代)、兄弟(相邻兄弟、所有兄弟)、属性(属性、指定值的属性)、交集并集)
    “蔚来杯“2022牛客暑期多校训练营4 M题: Monotone Chain
    Android 源码 <Activity> 桌面启动一 [5]
    3.k8s dashboard设置域名登录案例(ingress版本为1.3.1)
    Redis Desktop Manager可视化工具
    使用POI生成Excel下拉框
    五、线程池和定时器
    形态的两种相似性
  • 原文地址:https://blog.csdn.net/huangdianye/article/details/126562693