任务提交
ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html
文章目录
管理机器人车队需要能够以编程方式向机器人发送任务并实时接收反馈。 此外,通常需要协调多个机器人之间的任务以完成单个目标。 任务提交系统解决了这两个需求。
任务
在 ISAAC 中,任务由两部分定义:
-
定义任务整体行为的行为树(参见行为树)(即,导航到一个航路点)。
-
ISAAC 应用程序配置,用于设置任务参数(即导航到哪个航路点)。
一旦任务开始,它有三种可能的状态:
-
RUNNING:
任务正在进行中,定义任务的行为树当前正在运行。 -
失败的
定义任务的行为树已通过 reportFailure 停止。 -
成功
定义任务的行为树已通过 reportSuccess 停止。
MissionProto 消息用于对任务进行编码,MissionStatusProto 消息对任务状态进行编码。
任务客户端子系统
任务客户端子系统是一个 ISAAC 子图,可以添加到应用程序以使其能够接收任务。 它位于 //packages/behavior_tree/apps:missions
以下应用程序使用任务客户端子系统,可用作如何将其集成到应用程序中的示例:
-
flatsim
//packages/flatsim/apps:flatsim -
navsim
//apps/navsim:navsim_navigate -
carter
//apps/carter:carter
任务客户端子系统由以下部分组成:
-
Mission Codelet 通过触发行为树来启动任务并报告正在运行的任务的状态。
-
允许机器人连接到外部任务服务器以接收和报告任务的 JsonTcpClient Codelet。
-
一个 JsonMockup 小码,它定期将机器人的名称传输到 JsonTcpClient 小码,以促进机器人识别。
任务小码
任务小码是一种特殊类型的行为,使机器人能够执行任务。 任务小码附加到行为树。 当任务小码接收到 MissionProto 时,会发生以下情况:
-
任务小代码读取 MissionProto 的配置参数并使用它来设置 ISAAC 应用程序配置。
-
任务小码启动底层行为树。
-
当底层行为树正在运行时,任务小码会定期传输具有“RUNNING”状态的 MissionStatusProto 以指示任务正在进行中。
-
当行为树完成时,任务小代码发送最终的 MissionStatusProto,其中包含“SUCCESS”或“FAILURE”状态,具体取决于行为树是报告成功还是失败。
-
任务小码侦听新的 MissionProto 消息以开始新的任务。
此外,任务可能会被抢占。 如果任务小代码在任务已经运行时收到 MissionProto,它会停止行为树并为当前正在运行的任务发送状态为“FAILURE”的 MissionStatusProto。 然后它继续正常运行新任务。
JsonTcpClient 小代码
JsonTcpClient 允许通过 JSON 序列化原型消息与 TCP 服务器进行双向通信。 将 JsonTcpClient 与任务小码结合使用有几个好处:
-
JSON 是机器和人类可读的。 这使得使用 ISAAC 以外的框架(例如 Web 框架)来实现任务服务器成为可能。
-
提供了一个 JsonTcpServer GEM,它允许轻松开发基于 ISAAC 的任务服务器。
-
客户端/服务器网络模型比发布者/订阅者网络模型更适合具有动态数量机器人的系统。
JsonTcpClient 收到的任何 capnp 消息都被序列化为换行符分隔的 JSON 对象并发送到 TCP 服务器。 同样,从 TCP 服务器接收到的任何 JSON 对象都被反序列化为 capnp 消息并由 JsonTcpClient codelet 传输。
消息被序列化为 JSON,如下所示:
{"header": {...}, "payload": {...}}
其中
-
header:
一个 JSON 序列化的 MessageHeaderProto,其中包含有关消息的元数据,例如 UUID、发布时间和消息所属的频道。 -
payload:
JSON 序列化的 capnp 原型消息。
注意
所有 64 位整数都必须序列化为字符串以匹配协议缓冲区库的行为(请参阅 https://developers.google.com/protocol-buffers/docs/proto3#json)。
JsonTcpClient 当前不支持数据缓冲区。 JsonTcpClient 当前不支持使用数据缓冲区的 Proto,例如 TensorProto 或 ImageProto。
任务服务器子系统
任务服务器子系统由两个 Python 类组成:MissionServer 和 JsonTcpServer。 对于 ISAAC 应用程序,这些类可以作为 GEM 合并到 Python codelet 中。 这些类也可以由非 ISAAC 应用程序直接使用。
任务服务器子系统存在于 //packages/missions:missions 的源代码中。
JsonTcpServer 类
JsonTcpServer 类是 JsonTcpClient codelet 的服务器端副本。 JsonTcpServer 创建一个 TCP 服务器并侦听来自 TCP 客户端的连接。 TCP 协议允许多个客户端同时连接到单个服务器,同样,一个 JsonTcpServer 允许同时连接多个 JsonTcpClient。 JsonTcpServer 类为每个连接的客户端实例化一个 JsonTcpClientConnection 类,以处理与该客户端的通信。
MissionServer 类
MissionServer 类提供了一个方便的接口来向机器人提交任务、跟踪提交任务的状态以及协调不同机器人之间的任务。 在内部,MissionServer 实例化了一个 JsonTcpServer 类,用于侦听来自机器人的连接。
任务依赖
通常,必须协调分布在多个机器人之间的许多任务才能实现单一目标。 MissionServer 类通过允许基于有向无环图 (DAG) 的任务依赖性来促进这一点。 定义任务时,它可能有一个它所依赖的“上游”任务列表。 在所有“上游”任务都成功完成之前,任务不会被安排运行。 如果任何“上游”任务失败,任务将被取消。
下图显示了使用任务依赖项的示例用例。 两台机器人叉车(“fork01”和“fork02”)和一个机械臂(“arm01”)协调完成一个目标:将箱子从一个托盘转移到另一个托盘。
机器人识别
当 MissionServer 收到连接时,重要的是要识别哪个机器人已连接,以便可以向其派遣正确的任务。 这是通过使用特殊的“名称通道”来实现的。 当机器人第一次连接到 MissionServer 时,MissionServer 等待机器人在“名称通道”上发送一个 TextProto。 然后解析 TextProto 的内容并将其解释为连接所属的机器人的名称。 然后在该连接上提交为该机器人排队的所有任务。
示例用法
下面的代码显示了如何使用 MissionServer 类的示例:
from packages.missions import Mission, MissionServer
# Status codes that indicate a mission hasn't yet completed
INCOMPLETE_STATUSES = (Mission.Status.CREATED,
Mission.Status.QUEUED,
Mission.Status.STARTED,
Mission.Status.RUNNING)
# Create the mission server, listen on port 9998, and listen for robot
# names on the "name" channel.
server = MissionServer(port=9998, name_channel="name")
# Create 2 missions: The first mission is "upstream" to the second mission,
# which means that the first mission must finish before the second mission
# can be scheduled.
mission_1_config = {
# ISAAC Node config JSON to configure the mission.
# ...
}
mission_2_config = {
# ISAAC Node config JSON to configure the mission.
# ...
}
mission_1 = Mission(robot="carter-01", channel="mission",
config=mission_1_config)
mission_2 = Mission(robot="carter-02", channel="mission",
config=mission_1_config,
upstream=[mission_1])
# Submit the missions to the server.
server.submit(mission_1)
server.submit(mission_2)
# Wait for all missions to complete. Since mission_2 is downstream from
# mission_1, if mission_2 is complete, then mission_1 must be complete.
while (mission_2.status in INCOMPLETE_STATUSES)
time.sleep(1)
示例应用程序
//packages/missions/apps:mission_server 中提供了示例任务服务器应用程序。 此应用程序创建一个 MissionServer 类,从 JSON 文件中读取任务列表,将任务提交到任务服务器,并等待任务完成。 输入 json 文件必须遵循以下架构:
{
"missions": [
{...},
{...},
{...},
{...}
]
}
“任务”数组中的每个条目都是一个定义任务的 json 对象,可能包含以下字段:
Key | Type | Default | Description |
---|---|---|---|
robot | string | None | The name of the robot to submit the mission to. |
channel | string | “mission” | The JsonTcpServer channel to send the MissionProto on. |
status_channel | string | “mission_status” | The JsonTcpServer channel the MissionStatusProto is received on. |
config | json object | {} | The ISAAC application config to embed in the MissionProto. |
start_timeout | float | 5 | The start timeout of the mission, in seconds. If the mission is not acknowledged by the robot before this timeout elapses, then the mission is aborted. |
timeout | float | inf | The run timeout of the mission, in seconds. If the mission is not completed by the robot before this timeout elapses, then the mission is aborted. |
upstream | list of integers | [] | A list of missions that are “upstream” from this mission. Missions are provided as non-negative integers, which are indices into the “missions” array in the JSON. A mission is not scheduled until all “upstream” missions are complete. |
使用 Flatsim 运行
为 flatsim 应用程序提供了一个示例任务 json 文件。 该文件包含四个任务,它们在两个不同的机器人之间进行协调。 要测试此场景,请打开三个不同的终端并输入以下命令:
# Terminal 1: Start Mission Server
cd isaac/sdk
bazel run packages/missions/apps:mission_server -- $PWD/packages/missions/apps/flatsim.json
# Terminal 2: Start flatsim for carter-01
bazel run //packages/flatsim/apps:flatsim -- --demo demo_1 --mission_robot_name carter-01
# Terminal 3: Start flatsim for carter-02
bazel run //packages/flatsim/apps:flatsim -- --demo demo_1 --mission_robot_name carter-02
利用Carter运行
为 carter 应用程序提供了一个示例任务 json 文件。 该文件包含在一个机器人上协调的三个任务。 要测试此场景,首先,将 carter 应用程序部署到您的 Carter 机器人上。
接下来,在地图上确定三个航路点供卡特穿越,记下每个航路点的 x 位置、y 位置和旋转。 打开 sdk/packages/missions/apps/carter.json 文件并将每个任务中的航点替换为您的地图航点。 下面的示例显示了第一个任务的 x_position、y_position 和旋转的放置位置
{
"robot": "carter-01",
"channel": "mission",
"status_channel": "mission_status",
"config": {
"goals.goal_behavior": {
"isaac.navigation.SelectorBehavior": {
"desired_behavior": "path",
"report_child_status": true
}
},
"goals.path": {
"Plan2Generator": {
"waypoints": [
[rotation, x_position, y_position]
],
"report_success": true
},
"FollowPath": {
"report_success_on_arrival": true
}
}
}
}
使用以下命令在 x86 计算机上启动任务服务器:
cd isaac/sdk
bazel run //packages/missions/apps:mission_server packages/missions/apps/carter.json
然后,ssh 进入 carter 并启动 carter 应用程序
# Set to the IP address of the x86 machine that is running the mission server
MISSION_HOST=...
# The full path of the map json file
MAP=...
# The full path of the robot json file
ROBOT=...
./run apps/carter/carter.py --map_json $MAP --robot_json $ROBOT \
--mission_host $MISSION_HOST --mission_robot_name carter-01
现在卡特应该开始接受并完成来自任务服务器的任务。
更多精彩内容:
https://www.nvidia.cn/gtc-global/?ncid=ref-dev-876561