Frequently Asked Questions
常见问题
RMF 具有许多系统设计约束,这些约束为交通管理带来了独特的挑战。RMF 的核心目标是促进不同供应商提供的异构移动机器人车队的系统集成,这些车队可能具有不同的技术能力。
供应商往往希望他们的计算系统独立于其他供应商。由于供应商通常负责确保其计算基础设施的正常运行时间和可靠性,因此他们可能认为与其他供应商共享计算资源是一种不可接受的责任。这意味着交通管理系统必须能够在网络上分布在不同机器上时运行。
不同的机器人平台可能具有不同的功能。目前部署的许多有价值的 AGV 平台无法动态更改其行程。一些 AGV 平台可以在收到指示时改变路线,只要它们遵循预定义的导航图即可。一些 AMR 平台可以动态地绕过其环境中的意外障碍物。由于 RMF 旨在成为一种使能技术,因此我们必须设计一个系统,使其能够最大限度地发挥所有这些不同类型系统的效用,而不会对它们中的任何一个施加不利的限制。
这些考虑导致了分布式冲突预防和分布式调度协商的当前设计。设计中有足够的空间来为符合某些要求的移动机器人类别创建更简单、更高效的子集,但这些优化可以在现有的完全通用框架之上构建,然后再添加。
谁来开门、关门和操作lifts?是机器人还是 RMF?还是两者兼而有之?
知道何时需要打开门并发送打开命令的责任属于“舰队适配器”。基本设计是:
- 车队适配器跟踪机器人的进度
- 当机器人需要通过一扇门时,车队适配器会识别这一点
- 车队适配器将向门发送打开信号
- 一旦门打开,车队适配器将命令机器人继续前进
- 一旦机器人通过门,车队适配器将命令机器人等待,直到门关闭
- 车队适配器将命令门关闭
- 一旦门关闭,车队适配器将命令机器人继续前进
车队适配器了解门的方式是通过解析提供给它的导航
图。导航图是 full_control
类型的车队适配器的必需参数。rmf_demos
显示了向车队适配器提供导航图的示例。
构建导航图的推荐方法是使用 traffic-editor
工具。rmf_demos
存储库显示了 traffic-editor
项目文件的一些示例。
但是,完全可以构建您自己的导航图。它们 使用 YAML 格式。
Are lifts supported?
适当的电梯支持(即指定可以在楼层之间移动的实际电梯,并将该信息导出到导航图中)尚未开发。
但是,出于测试和演示目的,有两个特殊的导航图边缘属性可允许 RMF 队列适配器模拟电梯使用情况。这适用于演示场景,其中已创建“模拟电梯”,该电梯接收电梯命令并传输电梯状态,但实际上不会在建筑物的任何不同楼层之间移动。例如,在实验室的地板上贴上胶带以指示“电梯舱”框,以便在不占用实际建筑物电梯的情况下进行开发和测试。
这些属性最初是为了演示目的而包含的,但它们被证明非常有用,我们可能会使它们成为官方支持的属性。由于“真实”电梯的成本和稀缺性,人们似乎对拥有模拟多层场景的单层硬件测试设置有着广泛的兴趣。
边缘属性为:
demo_mock_floor_name
: 机器人穿越边缘时所在楼层的名称demo_mock_lift_name
: 机器人穿越边缘时进入或离开的升降机的名称
这个想法是,如果您有一个单层演示环境,但想要演示与电梯的互动,那么您可以设置一个模拟“电梯”,并想象“电梯”的每一侧都通向不同的楼层,并且只有当“电梯”认为它在该楼层时,机器人才被允许进入/离开“电梯”的那一侧。这模拟了有两组门的电梯舱。
为了使这个想法更加具体,假设您有一个单层硬件测试区域,并且在地面上画了一个框,旁边有一个 LED 显示屏,显示模拟的楼层名称。模拟电梯将传输与 LED 显示的楼层相匹配的电梯状态消息。还有一些指示电梯门是打开还是关闭。您可以进一步想象,只有当电梯认为它在 L1 楼层时,才允许从“电梯”的西侧进入或离开,而只有当它认为它在 L3 楼层时,才允许从东侧进入或离开“电梯”。
在该设置中,为了让机器人“正确地”从 L1 上的航点导航到 L3 上的航点,机器人需要:
- 从西侧接近“电梯”
- 呼叫“电梯”下行至 L1
- 等待电梯状态显示电梯位于 L1 层且门打开
- 进入“电梯”(即地面上画出的方框)并请求电梯“移动”至 L3
- 等待“电梯”指示电梯已到达 L3 层且门打开
- 从东侧离开“电梯”
粗略的 ASCII 图表如下所示(数字为航点,字母为边):
1 <---a---> 2 <---b---> 3
- Waypoint 1 is on floor L1
- Waypoint 2 is inside the "lift" named LIFT001
- Waypoint 3 is on floor L3
- The properties of edge
a
are:- bidirectional: true
- demo_mock_floor_name: L1
- demo_mock_lift_name: LIFT001
- The properties of edge
b
are:- bidirectional: true
- demo_mock_floor_name: L3
- demo_mock_lift_name: LIFT001
如果多个舰队可以执行相同的任务,那么会选择哪一个?
虽然尚未实施,但已经设计了一个竞标系统,其中任务请求将转换为竞标请求。竞标请求将发送给每个舰队适配器,每个可以执行任务的舰队适配器将报告其完成任务所需的最佳估计。出价最低的舰队适配器将被分配任务。
API 和实施正在等待一些关键组件的最终完成。
一些机器人可以比其他机器人享有优先权吗?
协商系统概念确实支持优先考虑哪个机器人将容纳其他机器人。解决协商时可以使用任意度量或加权系统。但在我们当前使用的实施中,我们将所有车辆视为平等,并选择最小化所有机器人净延迟的解决方案,没有任何优先级或权重。
Since this codebase is open source, you can easily fork the code and modify it
to use any prioritization system that you'd like. Specifically, replace
rmf_traffic::schedule::QuickestFinishEvaluator()
with your own
Negotiation::Evaluator
class that behaves in whatever way you would like.
两个机器人之间保持多少距离?
这是可配置的。有两个相关参数:footprint_radius
和 vicinity_radius
。footprint_radius
表示车辆物理足迹的估计值。vicinity_radius
表示机器人需要其他车辆避开的区域的估计值。“计划冲突”定义为一辆车辆的“足迹”计划进入另一辆车辆的“附近”的情况。协商系统的工作是提出一个修复计划,使所有车辆的“足迹”远离所有其他车辆的“附近”。
作业调度是如何实现的?
调度规划器模块目前正在开发中。 到目前为止,为 RMF 开发的演示平台不需要规划器将任务调度到不同的车队,因为在迄今为止(2020 年底)完成的所有演示平台中,每种任务类型只能由一个(且只有一个)机器人车队执行。 因此,任务调度非常简单:任务分配给能够执行任务的任何车队,而其余车队则忽略任务请求。 我们目前正在开发一个真正的调度规划器和正式的任务竞标系统,我们计划将其纳入 1.2.0 版本,定于 2020 年 12 月底发布。 我们的想法是,每个可以执行任务请求的车队都会对执行任务的“成本”进行出价,出价最低的“成本”将成为赢家。 “成本”将由两个因素决定:
- 任务完成的速度
- 如果新任务需要抢占其他任务,其他任务会延迟多长时间
What is rmf_traffic
?
rmf_traffic
提供核心流量调度算法和实用程序的中间件中立实现。它不使用或依赖于 ROS 2。
What is rmf_traffic_ros2
?
rmf_traffic_ros2
提供了方便的包装器,用于将“rmf_traffic”用作分布式 ROS 2 系统的一部分。
Where is the costmap?
rmf_core
中没有成本地图表示。
成本地图是一种通常用于表示自主导航规划的体积占用率的方法。
虽然交通设施确实处理导航规划,但它们主要关注的是识别自动驾驶汽车预期路线之间的冲突。
交通设施不负责车辆在其环境中绕过静态障碍物的“本地”导航。
不同的机器人平台通常具有不同的成本地图或其他导航算法表示,其中许多可能是专有的。
最重要的是,由于机器人足迹的差异,具有相同成本地图表示的不同机器人平台可能仍需要不同的成本地图值。
由于这些因素,我们让机器人平台自己决定如何表示其成本地图。如果系统集成商在执行交通规划时考虑机器人的成本地图很重要,他们可以实现自定义 rmf_traffic::agv::RouteValidator
,在确定候选路线是否有效时使用机器人的自定义成本地图。
What is the core algorithm behind rmf_traffic
?
rmf_traffic
中 AGV 的冲突避免是通过对 A* 搜索 进行时间相关扩展来实现的
此搜索将时间考虑在内,以便能够找到穿越空间和时间的路径,这些路径可以考虑交通计划中其他代理的运动。
During negotiation, how do fleets compute their proposals?
由于该系统设计为可扩展且可适应各种场景和机器人供应商组合,包括许多目前尚不存在的组合,因此它有许多扩展的部分和挂钩。计算交通提案的顺序如下:
- 首先,车队适配器节点将收到冲突通知,告知它需要参与协商以解决时空冲突。此通知由
rmf_traffic_ros2::schedule::Negotiation
类接收。 - 为此,车队适配器创建协商通知订阅,以便在其控制下的特定机器人需要响应协商通知时,它会收到通知。
- 当机器人需要响应协商时,其实现就会被触发。
- 此实现将启动一个多线程的
Negotiate
服务,其主要实现可以在这里 找到。
多方协商中的每一步都以完全相同的方式使用 Negotiate
服务。
各个步骤之间的唯一区别在于它们需要处理哪些约束。
这些约束由传递给 respond(~)
函数的 rmf_traffic::schedule::Negotiation::Table::Viewer
对象描述。
因为可以使用相同的对象来描述图中所有不同块的约束,所以我们可以使用相同的代码来解决每个块。
还有可以根据需要调用的“拒绝”和“放弃”代码路径:
- 当其中一个舰队无法接受来自另一个舰队的提议时,将使用“拒绝”机制。 当执行拒绝时,拒绝舰队将提供一组可行轨迹(通常为 10-200 条轨迹),而收到拒绝的舰队应再次尝试为自己寻找理想的提议,但该理想提议必须至少接受拒绝时提供的一条轨迹替代方案。
- 当规划者很难找到任何解决方案时,将使用“放弃”机制。 当谈判中有许多参与者都在积极行动时,就会发生这种情况,这可能导致由于时间不一致而看似无法解决的情况。 通常,当使用放弃时,谈判会找到另一种可行的解决方案组合。 在最坏的情况下,如果谈判继续失败,机器人可能会遇到现实生活中的僵局。 当发生死锁时,参与者将保持静止,因此协商将达到稳定状态,不会受到异步不一致的负面影响。 当发生这种情况时,几乎可以保证成功解决。
前面的解释描述了“完全控制”风格的舰队适配器。“只读”和“交通灯”API 的实现略有不同。