跳转到内容

3. 二次开发接口概述

上述软件系统中模块大多数均使用 AimRT 作为底层框架,AimRT 是一款对标 ROS2 的机器人运行时底层框架,由智元机器人公司在 2024/09 开源,AimRT 中提供了两种基本的底层通信方式,分别为 Channel 和 RPC(更多内容可以参考 AimRT 官方文档),其中两种通信方式又可以对应多个不同通信后端。

为降低二次开发心智负担,我们为二次开发提供了两种形式使用较为简单和通用的接口,分别为 HTTP JSON RPC 和 ROS2 Topic,其中 HTTP JSON RPC 适用于低频接口多对一调用,ROS2 Topic 适用于高频接口多对多调用。以下为二

针对开发语言,二次开发程序并不限制任何开发语言,只要能收发 HTTP 消息即可调用所有 HTTP JSON RPC 接口,只要支持 ROS2 Humble with Fastdds 即能收发 ROS2 话题消息即可调用所有本体 ROS2 Topic 接口。

这里给出两个具体的接口调用示例,建立更加清晰的接口认知:

以下为获取电池电量的命令行 RPC 请求示例

Terminal window
curl -i -H 'content-type:application/json' \
-H 'timeout: 1000' -X POST 'http://192.168.100.100:56421/rpc/aimdk.protocol.HalBmsService/GetBmsState' \
-d '{}'

其中

  • 192.168.100.110 为机器人 X86 工控机的 IP 地址,这里填写的两块工控机互联的 IP 地址,可在 ORIN 上执行调用,如需远程调用,可将该 IP 改为机器人 X86 开发板 WiFi 网卡对应的 IP(可通过 AimMaster 软件查看或在 X86 上执行 ip a 进行查询)。
  • 56421 相应服务的 HTTP 端口号,这个一般会在详细接口示例中给出。
  • content-type:application/json 为请求头,表示请求体为 json 格式,必须要加上这个请求头。
  • timeout: 1000 为请求头,表示请求超时时间,单位为毫秒,这里设置为 1000 毫秒,即 1 秒,该字段可以不设置。
  • aimdk.protocol.HalBmsService/GetBmsState 为获取电池状态的 RPC 接口名称,各个接口的具体名称在对应接口的文档和示例中可以找到。
  • '{}' 为请求体,这里为空代表其中的字段都为默认值,如果需要传入特定字段,可以传入 json 字符串,例如 '{"bms_state": 1}' 表示传入 bms_state 字段,值为 1(仅为举例,具体字段名称和值需要参考对应接口的文档和示例)。

话题接口采用 ROS2 原生话题,机上默认使用 ROS2 Humble with Fastdds,在调用任意 ROS2 Topic 接口之前必须设置一些环境变量,如下:

Terminal window
source /opt/ros/humble/setup.bash
export ROS_DOMAIN_ID=232
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE=/agibot/software/v0/entry/bin/cfg/ros_dds_configuration.xml

如果您的程序需要以 root 权限启动则将上述 dds 配置文件改为使用以下配置文件:

Terminal window
export FASTRTPS_DEFAULT_PROFILES_FILE=/agibot/software/v0/entry/bin/cfg/privileged_ros_dds_configuration.xml

ros_dds_configuration.xml 中同时启用了共享内存通信和 udp 通信,而在 privileged_ros_dds_configuration.xml 中则仅启用了 udp 通信,用以规避共享内存的权限问题。

注意环境变量仅在当前终端有效,若新开终端则需重新设置

另外还需注意机上话题默认 QoS 为

history: keep_last
depth: 10
reliability: best_effort

使用时需保持 QoS 一致以保证通信顺畅。

以下为订阅关节状态的 ROS2 Topic 示例脚本。

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSHistoryPolicy, QoSProfile, QoSReliabilityPolicy
from sensor_msgs.msg import JointState
class JointStateSubscriber(Node):
def __init__(self, topic_name: str):
super().__init__("joint_state_subscriber")
self.topic_name = topic_name
qos_profile = QoSProfile(
history=QoSHistoryPolicy.KEEP_LAST, depth=10, reliability=QoSReliabilityPolicy.BEST_EFFORT
)
self.subscription = self.create_subscription(JointState, topic_name, self.listener_callback, qos_profile)
def listener_callback(self, msg: JointState):
self.get_logger().info(f"=== Received {self.topic_name} ===")
self.get_logger().info(f" header: {msg.header}")
self.get_logger().info(f" name: {msg.name}")
self.get_logger().info(f" position: {msg.position}")
self.get_logger().info(f" velocity: {msg.velocity}")
self.get_logger().info(f" effort: {msg.effort}")
def main(args=None):
rclpy.init(args=args)
# 手臂关节状态: /motion/control/arm_joint_state
# 脖子关节状态: /motion/control/neck_joint_state
joint_state_node = JointStateSubscriber("/motion/control/arm_joint_state")
try:
rclpy.spin(joint_state_node)
except KeyboardInterrupt:
pass
finally:
joint_state_node.destroy_node()
rclpy.shutdown()
if __name__ == "__main__":
main()

为保证机上 ROS2 通信稳定性,我们修改了机上 DDS 通信的默认配置文件,限制了 ROS2 流量仅可在 x86 和 orin 工控机之间流动,不会发往外部,对于非 root 进程默认启用了共享内存通信和 UDP 通信,相应配置文件在两块工控机上的 /agibot/software/v0/entry/bin/cfg/ros_dds_configuration.xml,其中 ORIN 上的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<dds>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>UDPv4_transport</transport_id>
<type>UDPv4</type>
<sendBufferSize>10388608</sendBufferSize>
<receiveBufferSize>10388608</receiveBufferSize>
<interfaceWhiteList>
<address>192.168.100.110</address>
</interfaceWhiteList>
</transport_descriptor>
<transport_descriptor>
<transport_id>SHM_transport</transport_id>
<type>SHM</type>
<segment_size>8388608</segment_size>
<port_queue_capacity>1024</port_queue_capacity>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="participant_profile" is_default_profile="true">
<rtps>
<useBuiltinTransports>false</useBuiltinTransports>
<userTransports>
<transport_id>SHM_transport</transport_id>
<transport_id>UDPv4_transport</transport_id>
</userTransports>
</rtps>
</participant>
</profiles>

其中网卡白名单配置了 192.168.100.110,该 IP 为 ORIN 与 X86 互联的网卡 IP,添加该 IP 确保了 ORIN 上发布和订阅的话题能够正常与 X86 工控机进行通信,如需在三方 PC 或加装的工控机上接受和发送对应的 ROS2 Topic,需要在白名单(/agibot/software/v0/entry/bin/cfg/ros_dds_configuration.xml /agibot/software/v0/entry/bin/cfg/privileged_ros_dds_configuration.xml 都需要加)中添加一项本机网卡 ip,一般为 192.168.2.50,对应背部左侧调试网口,添加完成后重启机器人通过有线连接至对应网口即可进行相应 ROS2 通信。

而针对 X86 工控机,背部右侧调试网口为 dhcp 模式,如需将 X86 上的 ROS2 通信与三方 PC/工控机打通需要先配置该网口为手动指定 IP 模式指定固定 IP 为 192.168.2.150(修改 /etc/netplan/01-netcfg.yaml),然后与三方 PC 进行直连或通过交换机连接,网络拓扑如下:

其中如果只需连接一台工控机则无需交换机直接网线直连即可,此时则需将 X86 工控机上的 dds 白名单添加一项 192.168.2.150(/agibot/software/v0/entry/bin/cfg/ros_dds_configuration.xml /agibot/software/v0/entry/bin/cfg/privileged_ros_dds_configuration.xml 都需要加)。

两个进程使用非对称 dds 白名单在 ROS2 Humble 版本有时会导致不可预测的通信问题,请务必确保 dds 白名单配置保持一致。

参考:https://github.com/eProsima/Fast-DDS/pull/3733