![ROS 2机器人开发:从入门到实践](https://wfqqreader-1252317822.image.myqcloud.com/cover/209/51975209/b_51975209.jpg)
2.1.1 Python示例
ROS 2提供了丰富的Python版本的客户端接口库,让你通过简单的调用即可完成节点的创建。
在主目录下创建chapt2/文件夹,并用VS Code打开该文件夹,接着创建ros2_python_node.py文件,在文件中编写代码清单2-1的内容。
代码清单2-1 一个最简单的Python节点
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/44_01.jpg?sign=1738887390-sOyIq8jiiZ9zFOmhzyCqGf0nb3IrIU4y-0-c760d9314f13cda6baa65162caf834b4)
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/45_01.jpg?sign=1738887390-9cMESOgnKU1K3GSzbdn8FFX4pWLDd4Lh-0-5b6c1203439b4ad8e47a8218f2abc396)
如代码清单2-1所示,首先导入ROS 2提供的Python版本客户端库rclpy,从rclpy库的node模块中导入Node类。然后定义了一个main函数,在函数里调用rclpy的init方法为接下来的通信分配资源,接着创建一个名为python_node的Node类实例,有了node实例,就可以通过它来订阅或者发布话题了,通信并不是本节的重点,所以这里没有进行任何操作。
创建完节点后,使用spin方法启动该节点,spin方法恰如其名,它会不断地循环检查被其运行的节点是否收到新的话题数据等事件,直到该节点被关闭为止。之后,rclpy.shutdown()方法用于清理分配的资源并确认节点是否被关闭。
在了解了每一行代码的作用后,运行代码,按Ctrl+Shift+~键可以快速地在VS Code内打开集成终端,输入代码清单2-2中的命令运行代码。
代码清单2-2 使用Python执行节点
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/45_02.jpg?sign=1738887390-eZWHZd2M3Lv6lLQwgvpoNTCA55owrgov-0-da77ba039cece6944a488988514ce452)
运行后会发现终端并没有任何输出和提示,此时不要怀疑代码有问题,节点其实已经运行起来了。按Ctrl+Shift+5键可以在VS Code原有的终端旁添加一个新的终端,在终端中输入代码清单2-3所示的命令。
代码清单2-3 使用命令行查询节点列表
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/45_03.jpg?sign=1738887390-qlnqgI91daAeSslDclRJJJ8PdvLejUDx-0-4689ea39657d3d5e8fed00b70eba38f0)
代码清单2-3中的ros2 node list是ROS 2命令行工具的节点模块下的命令之一,用于查看当前的节点列表,看到/python_node就代表我们的第一个ROS 2节点启动成功了。但启动后没有一点提示显然不太友好,所以修改代码清单2-1中的main函数,加一句输出,如代码清单2-4所示。
代码清单2-4 添加输出的节点代码
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/45_04.jpg?sign=1738887390-U0uIPn1cPu8QVbsWiuS331chZNDvnujb-0-0d33631f18b72dde5cefde05f0c01ab5)
这里我们加了一句输出指令,但并没有使用你所熟悉的print函数,而是先通过node实例调用get_logger()获取日志记录器,接着调用日志记录器的info方法输出了一句话。
接着来运行测试一下,在刚刚运行节点的终端里,按Ctrl+C键,该命令可以打断当前终端运行的程序,输入代码清单2-5所示的命令并运行。
代码清单2-5 运行带日志输出的Python节点
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/46_01.jpg?sign=1738887390-lpgPd8kGFGpDyi5y1JrDQehaiTaQ2GXF-0-7f6a60951a3190d8db810744f4eb72f9)
可以看到这里不仅输出了我们想要的内容,还输出了日志的级别、时间和节点信息。如果你想查看更多日志信息,可以通过环境变量RCUTILS_CONSOLE_OUTPUT_FORMAT修改输出的日志格式,使用如代码清单2-6所示的设置就可以在输出消息的同时输出代码所在的函数和行号。
代码清单2-6 使用环境变量输出更多的信息
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/46_02.jpg?sign=1738887390-JOJv4hu3RdKRHmBbYlM8VJ3WiLYDuFHH-0-8e3340bbc0bd46db200355903a628321)
使用{}包含特定单词就可以表示对应的消息,除了上面代码使用的三个外,还有表示日志级别的severity、表示日志记录器名的name、表示文件名字的file_name、表示时间戳的time以及表示纳秒时间戳的time_as_nanoseconds。
第一个Python节点到这里就算写完了,但在写代码的时候好像没有提示,这是因为没有安装Python插件。如图2-1所示,打开VS Code的扩展,搜索Python,安装第一个插件即可。
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/46_03.jpg?sign=1738887390-hIrx2lwox6lvWrWSQ40yjnDdkKKnWeX8-0-f87e56eb6372cb0062539e2f88f46d20)
图2-1 安装插件
再次编辑代码时你会发现如图2-2所示的提示。把鼠标指针长时间悬停在某个函数上,函数注释就会随之跳出,如图2-3所示。
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/46_04.jpg?sign=1738887390-KxDRS7M0LJ4ZvYuBiao0xkS5LvRZrPXO-0-75f683b9d9dbef3ffa387777f4da3056)
图2-2 代码提示
![](https://epubservercos.yuewen.com/6232B7/30716170307984306/epubprivate/OEBPS/Images/46_05.jpg?sign=1738887390-HHnlgIFurFTtYckUp9elQCBa162Bu6dA-0-51d87ab3452a215cca79c5edf81a6e02)
图2-3 函数注释