AMBF ROS通信模块 / ambf_ros_modules
在 AMBF 中,可通过 ROS 实现用户和机器人/机械臂之间的通信控制。具体采用的是 server/client 模式,即在 AMBF 中插入 ObjectCommPlugin/WorldCommPlugin 等插件,在这些插件中,包含了相应类型的 RosComServer。RosComServer 中包含了 Cmd 和 State,周期性的向外发送 State,并且接收/更新 Cmd;在 ObjectCommPlugin/WorldCommPlugin 中,会周期性的从 RosCommServer 中读取 Cmd,并通过自身的 Controller 生成响应的力矩、位置等,写入到物理引擎中。
1. ros_comm_plugin
Plugin 是 AMBF 中的一种机制,通过在各个对象中附加 Plugin 并在仿真循环中周期性调用,从而实现附加的功能。例如,afObjectPlugin
包含 init(..)
graphicsUpdate()
physicsUpdate(..)
等函数,分别在不同的仿真阶段被调用。
在 ObjectCommunicationPlugin
中,包含了各类 RosComServer,例如 ambf_comm::Actuator
ambf_comm::RigidBody
ambf_comm::Vehicle
等,分别负责从相应的对象接收指令/发送状态。具体而言,在 ObjectCommunicationPlugin::physicsUpdate(double dt)
函数中,依次执行了 xxxFetchCommand(..)
和 xxxUpdateState(...)
函数,分别对应获取指令和发送状态。其中,在 xxxFetchComman(...)
函数中,从 RosComServer 获取指令(这里有这样的设定,在若干个仿真步骤期间,RosComServer 中的指令是同一个,因为用户发送指令的周期不会很频繁。但是,Plugin 重复性从 RosComServer 中获取同一个指令并不会影响控制效果),根据自身的控制器,生成具体的关节力矩/位置等信息,写入到物理引擎中;接下来,在 xxxUpdateState(...)
中,更新 RosComServer 中的状态,RosComServer 也会周期性的通过 ROS 向外发送,(两者的周期可能不一样,因此,在写入和发送的时候,会有锁定)。下面,以 ambf_comm::RigidBody
为例,介绍响应的实现。
对于刚体而言,在其通信插件 ObjectCommunicationPlugin
中,新建了 std::shared_ptr<ambf_comm::RigidBody m_rigidBodyCommPtr
(即 RosComServer):(一)在获取指令阶段(即函数 afObjectCommunicationPlugin::rigidBodyFetchCommand(...)
中),读取了当前 RosComServer 中的指令 ambf_msgs::RigidBodyCmd afCommand = m_rigidBodyCommPtr->get_command()
,然后对指令进行解析,并执行相应的操作。例如,如果是 ambf_msgs::RigidBodyCmd::TYPE_FORCE
,则直接向刚体写入力和力矩;如果是 ambf_msgs::RigidBodyCmd::TYPE_POSITION
,当刚体是 isStaticOrKinematicObject()
,则直接写入;否则就通过自身的 controller 计算相应的力矩/速度等。此外,还会设定刚体上所附加的关节的信息,等。(二)在发送状态阶段(即函数 afObjectCommunicationPlugin::rigidBodyUpdateState(...)
中),从物理引擎中读取该刚体的信息,写入到 m_rigidBodyCommPtr
中,并启用其通信(主要是保证其是一直开着的),即 m_rigidBodyCommPtr->enableComm()
。那么,在 RosComServer 中,其会周期性地向 ROS 发送该刚体地状态信息。
2. ambf_ros_modules
在这一部分,主要包含 ambf_msgs、ambf_server 和 ambf_client 三部分。其中,ambf_msgs 定义了各种 ROS Message;ambf_server 定义了前述 Plugin 中使用的通信 Server,仅供 ros_comm_plugin 调用;ambf_client 中则定义了与之对应地通信 Client,供用户使用。
2.1. ambf_msgs
这一部分是标准的 ROS Message,具体可参见 ROS 资料等,在这里不再赘述。
2.2 ambf_server
ambf_server 的主要功能有两个:一是接收 ROS Message 并向 Plugin 提供指令,二是接收 Plugin 写入的状态数据并发送 ROS Message。因此,其最核心的成员变量和函数有 m_State
m_Cmd
和 run_publishers()
sub_cb(..)
。具体来说,ambf_server 会向 ROS::Node 订阅指令消息,并由 sub_cb(..)
处理,也就是简单的存储接收到的指令;此外,ambf_server 会开一个线程,执行 run_publishers()
函数,具体就是将当前的状态数据发送出去。下面,以 ambf_comm::RigidBody
为例,介绍 ambf_server 的工作流程。
(略)
2.3. ambf_client
ambf_client 的主要功能也是两个:一是接收 ROS Message 并向用户展示机器人当前状态数据,二是接收用户写入的控制指令并发送 ROS Message。因此,其最核心的成员变量和函数有 m_State
m_Cmd
和 run_publisher()
sub_cb(..)
。具体来说,ambf_client 会向 ROS::Node 订阅状态数据消息,并由 sub_cb(..)
处理,也就是简单的存储接收到的指令;此外,ambf_client 也会开一个线程,执行 run_publishers()
函数,具体就是将当前的指令发送出去。此外,ambf_client 还有 apply_command()
函数,也是立即将指令发送出去。下面,以 ambf_client::RigidBody
为例,介绍 ambf_client 的工作流程。
(略)
另外,为了方便用户采用 python 控制物理引擎中的机器人,采用 python 重写了上述 ambf_client,并把所有类型的 ambf_xxx 都放到了 Client
中,详见 ambf_ros_modules/ambf_client/python 目录。具体也不展开了。
2.4. ambf_env
为了契合人工智能/强化学习算法在 AMBF 中的应用,基于 gym 建立了 AmbfEnv
,实现了 environment、observation、reward等功能。具体参见 ambf_ros_modules/ambf_client/python/ambf_env.py 。
3. 小结
略