导航概念
此页面旨在帮助新机器人研究人员熟悉移动机器人导航的概念,特别是理解和使用本项目所需的概念。
ROS 2
ROS 2 是 Nav2 使用的核心中间件。如果您对此不熟悉,请在继续之前访问 the ROS 2 documentation。
Action Server
与 ROS 一样,action servers 是控制长时间运行任务(如导航)的常见方式。该栈更广泛地使用 actions,在某些情况下,没有简单的主题接口。对于 ROS 2 的开发人员来说,理解 action servers 更为重要。可以在 ROS 2 documentation 中找到一些简单的 CLI 示例。
action servers 类似于标准的服务服务器。客户端将请求某个任务的完成,但该任务可能需要较长时间。例如,将推土机的铲斗向上移动,或让机器人向右移动 10 米。在这种情况下,action servers 和客户端允许我们在另一个进程或线程中调用长时间运行的任务,并返回其结果的 future。
此时可以阻塞直到 action 完成,但您可能想偶尔检查 action 是否完成,并继续在客户端线程中处理工作。由于是长时间运行的任务,action servers 还会向其客户端提供反馈。该反馈可以是任何内容,并在 ROS 的 .action
文件中与请求和结果类型一起定义。在推土机示例中,请求可能是一个角度,反馈可能是剩余的移动角度,而结果是成功或失败的布尔值及最终角度。在导航示例中,请求可能是一个位置,反馈可能是它导航的时间和到目标的距离,结果是成功的布尔值。
反馈和结果可以通过在 action 客户端注册回调来同步收集。也可以通过异步请求共享未来对象的信息来收集。两者都需要旋转客户端节点以处理回调组。该堆栈中使用 action 服务器与最高级别的行为树 (BT) 导航器通过 NavigateToPose 动作消息进行通信。
它们还用于 BT NavigateToPose``与后续较小的 action 服务器进行通信,以计算计划、控制努力和恢复。每个 action 服务器在 ``nav2_msgs
中都有其独特的 .action
类型以与服务器进行交互。
生命周期节点和绑定
生命周期节点(更准确地说,是管理节点)是ROS 2特有的。更多信息可查看`found here <https://design.ros2.org/articles/node_lifecycle.html>`_。这些节点包含用于启动和关闭ROS 2服务器的状态机转换。这有助于ROS系统在启动和关闭时实现确定性行为,同时也帮助用户以合理的方式构建程序,以便于商业用途和调试。
当节点启动时,它处于未配置状态,仅处理节点的构造函数,构造函数中不应包含任何ROS网络设置或参数读取。通过启动系统或提供的生命周期管理器,需要将节点转换为非活动状态以进行配置。之后,可以通过进入激活阶段来激活节点。
此状态将允许节点处理信息,并完全设置为运行。配置阶段触发 on_configure()
方法,该方法将设置所有参数、ROS网络接口以及为安全系统分配的所有动态内存。激活阶段触发 on_activate()
方法,该方法将激活ROS网络接口并设置程序中的任何状态以开始处理信息。
要关闭节点,我们将进入非激活、清理、关闭状态,并最终结束于最终状态。在这些阶段中,网络接口被停用并停止处理,释放内存,干净地退出。
生命周期节点框架在本项目中得到了广泛应用,所有服务器都利用了它。对于所有ROS系统来说,最好在可能的情况下使用生命周期节点。
在Nav2中,我们使用LifecycleNodes的封装,nav2_util LifecycleNode
。这个封装简化了典型应用中LifecycleNodes的复杂性。它还包含生命周期管理器的绑定连接,以确保服务器在过渡到活动状态后保持活动。如果服务器崩溃,它会通知生命周期管理器,并将系统过渡到非活动状态,以防止关键故障。有关详细信息,请参阅从Eloquent到Foxy的文档。
行为树
行为树(Behavior Trees, BT)在复杂机器人任务中变得越来越普遍。它们是一个任务完成的树结构,为定义多步骤或多状态应用程序创建了一个更具可扩展性和人类可理解的框架。这与有限状态机(Finite State Machine, FSM)形成对比,后者可能有数十个状态和数百个转换。举个例子,足球机器人就是一个例子。如果将足球比赛的逻辑嵌入到FSM中,将会面临许多可能的状态和规则,这样的挑战性和出错概率都很高。此外,像从左、右或中间射门这样的选择建模尤其模糊。使用BT时,可以创建并重用基本原语,例如“踢”、“走”、“去球”等,适用于多种行为。更多信息可以在这本书中找到。我强烈建议阅读第1-3章,以便对术语和工作流程有一个良好的理解。大约只需30分钟。
行为树为导航逻辑提供了正式的结构,可以用于创建复杂系统,同时也可以使用高级工具进行可验证和验证的正确性分析。将应用逻辑集中在行为树中,并且使用独立的任务服务器(仅通过树传递数据)允许进行正式分析。
对于这个项目,我们使用 BehaviorTree CPP V4 作为行为树库。我们创建可以构建成树的节点插件,放在``BT Navigator``内部。节点插件被加载到BT中,当树的XML文件被解析时,注册的名称被关联。在此时,我们可以通过行为树进行导航。
使用此库的一个原因是它能够加载子树。这意味着Nav2行为树可以加载到另一个更高层的BT中,将此项目作为节点插件。例如,在足球比赛中,可以将Nav2行为树用作“去球”节点,并将球检测作为更大任务的一部分。此外,我们提供了 ``NavigateToPoseAction``插件(以及其他插件),使得Nav2堆栈可以通过常规的动作接口从客户端应用程序中调用。
其他系统也可以用来设计复杂的自主行为,即层次有限状态机(Hierarchical FSM, HFSM)。由于在机器人及相关行业的广泛使用和用户需求,选择了行为树。然而,由于Nav2的独立任务服务器的特性,未来在有兴趣和贡献的情况下,提供一个 ``nav2_hfsm_navigator``包并不是难事。
导航服务器
规划器和控制器是导航任务的核心。恢复机制用于将机器人从不良状态中解救出来,或尝试处理各种问题,使系统具备容错能力。平滑器可以用于对规划路径的进一步质量改进。在本节中,将分析这些一般概念及其在本项目中的应用。
规划器、控制器、平滑器和恢复服务器
本项目中的四个动作服务器分别是规划器、行为、平滑器和控制器服务器。
这些动作服务器用于托管算法插件的地图,以完成各种任务。 它们还托管算法插件用于计算输出的环境表示。
规划器、平滑器和控制器服务器将在运行时配置要使用的名称(别名)和算法类型。 这些类型是已注册的插件库名称,名称是任务的别名。 一个例子是使用名称``FollowPath``的 DWB 控制器,因为它遵循参考路径。 在这种情况下,DWB 的所有参数都将放置在该命名空间中,例如``FollowPath.<param>``。
然后,这三个服务器会公开与其任务相对应的操作接口。
当行为树勾选相应的 BT 节点时,它将调用操作服务器来处理其任务。
服务器内部的操作服务器回调将通过映射到特定算法的名称(例如 FollowPath
)调用所选算法。
这允许用户将行为树中使用的算法抽象为算法类。
例如,您可以拥有 ``N``个插件控制器来跟随路径、与充电器对接、避开动态障碍物或与工具交互。
将所有这些插件放在同一个服务器中,允许用户使用单个环境表示对象,而重复的成本很高。
对于行为服务器,每个行为也包含自己的名称,但是,每个插件也将公开自己的特殊操作服务器。 这样做是因为可以创建各种各样的行为操作,而这些操作无法共享单个简单的接口。 行为服务器还包含本地成本图的成本图订阅者,从控制器服务器接收实时更新,以计算其任务。 我们这样做是为了避免拥有本地成本图的多个实例,因为复制这些实例在计算上是昂贵的。
或者,由于 BT 节点是调用操作的简单插件,因此可以创建新的 BT 节点来调用具有其他操作类型的其他操作服务器。 建议尽可能始终使用提供的服务器。 如果由于插件或操作接口而需要新服务器,则可以与框架一起维持。 新服务器应使用新类型和插件接口,类似于提供的服务器。 需要创建一个新的 BT 节点插件来调用新的操作服务器 - 但是,通过大量使用服务器和插件,Nav2 repo 本身不需要分叉或修改。
如果您发现需要插件库定义或操作类型的新接口,请提交工单,看看我们是否可以在相同的接口中纠正该问题。
规划
规划器的任务是计算一条路径来完成某个目标函数。 路径也可以称为路线,具体取决于所选的命名法和算法。 两个典型示例是计算到达目标的计划(例如从当前位置到目标)或完整覆盖(例如覆盖所有自由空间的计划)。 规划器将可以访问全局环境表示和缓冲到其中的传感器数据。 规划器可以编写为:
计算最短路径
计算完整覆盖路径
计算沿稀疏或预定义路线的路径
Nav2 中规划器的一般任务是计算从当前姿势到目标姿势的有效且可能最佳的路径。 但是,存在许多受支持的计划和路线类别。
控制器
控制器,在 ROS 1 中也称为本地规划器,是我们遵循全局计算路径或完成本地任务的方式。 控制器将能够访问本地环境表示,以尝试计算基站要遵循的可行控制力。 许多控制器将在空间中向前投射机器人,并在每次更新迭代时计算本地可行路径。 控制器可以写入:
遵循路径
使用里程表框架中的检测器与充电站对接
登上电梯
与工具交互
控制器在 Nav2 中的一般任务是计算有效的控制力以遵循全局规划。 但是,存在许多类控制器和本地规划器。 该项目的目标是所有控制器算法都可以成为此服务器中的插件,用于常见的研究和工业任务。
行为
恢复行为是容错系统的主要支柱。 恢复的目标是处理系统的未知或故障情况并自主处理它们。 示例可能包括感知系统中的故障,导致环境表示充满假障碍物。 然后将触发清晰的成本图恢复以允许机器人移动。
另一个示例是,如果机器人由于动态障碍物或控制不佳而被卡住。 如果允许,后退或原地旋转,允许机器人从不良位置移动到可以成功导航的自由空间。
最后,在完全失败的情况下,可以实施恢复以引起操作员的注意以寻求帮助。 这可以通过电子邮件、短信、Slack、Matrix 等完成。
重要的是要注意,行为服务器可以保存任何行为以共享对昂贵资源(如成本图或 TF 缓冲区)的访问,而不仅仅是恢复行为。每个可能都有自己的 API。
平滑器
由于规划器搜索的路径的最优性标准通常与现实情况相比有所降低,因此额外的路径细化通常是有益的。 为此目的引入了平滑器,通常负责减少路径粗糙度和平滑突然旋转, 但也用于增加与障碍物和高成本区域的距离,因为平滑器可以访问全局环境表示。
当将不同的规划器与不同的平滑器组合在一起或需要对平滑进行特定控制(例如仅平滑路径的特定部分)时,使用单独的平滑器而不是作为规划器的一部分的平滑器是有利的。
Nav2 中平滑器的一般任务是接收路径并返回其改进版本。 但是,对于不同的输入路径,存在改进的标准和获取它们的方法,为可以在此服务器中注册的大量平滑器创造了空间。
机器人足迹
值得注意的是,在成本地图中,我们将机器人的足迹设置为半径为 robot_radius
的圆,或者如果机器人不是圆形,则设置为表示任意多边形的点向量 footprint
。这也可以使用成本地图的 ``~/footprint``主题随时间进行调整,该主题将根据机器人状态的变化(例如连接的操纵器的移动、拾起托盘或其他调整机器人形状的操作)随时间更新多边形。然后,规划器和控制器将自动使用该多边形。
航点跟踪
航点跟踪是导航系统的基本功能。它告诉我们的系统如何使用导航到达多个目的地
nav2_waypoint_follower
包含一个航点跟踪程序,该程序带有用于特定任务执行器的插件接口。
如果您需要前往给定位置并完成特定任务(如拍照、拿起盒子或等待用户输入),这将非常有用。
这是一个不错的演示应用程序,演示了如何在示例应用程序中使用 Nav2。
但是,它不仅可以用于示例应用程序。 车队经理/调度员有两种思路:
哑机器人;智能集中调度员
智能机器人;哑集中调度员
在第一种思路中, nav2_waypoint_follower
足以创建生产级的机器人解决方案。由于自主系统/调度程序在分配任务时会考虑机器人的姿势、电池电量、当前任务等因素,因此机器人上的应用程序只需担心手头的任务,而无需担心系统完成请求任务的其他复杂性。在这种情况下,您应该将对航点跟随器的请求视为 1 个工作单元(例如,仓库中的 1 次挑选、1 个安全巡逻环、1 个过道等)以执行任务,然后返回调度程序执行下一个任务或请求充电。在这个学派中,航点跟随应用程序仅比导航高一级,低于系统自主应用程序。
在第二个中, nav2_waypoint_follower
是一个很好的示例应用程序/概念证明,但您确实需要机器人上的航点跟随/自主系统在制定强大的解决方案方面发挥更大的作用。在这种情况下,您应该使用 nav2_behavior_tree
包创建一个自定义应用程序级行为树,使用导航来完成任务。这可以包括子树,例如在返回码头的任务中检查充电状态或在更复杂的任务中处理超过 1 个工作单元。很快,将会有一个 ``nav2_bt_waypoint_follower``(名称可能会调整),它将允许您更轻松地创建此应用程序。在这个学派中,航点跟随应用程序与系统自主性更紧密地联系在一起,或者在许多情况下,就是系统自主性。
两者都没有比另一个更好,它高度依赖于您的机器人正在完成的任务、在什么样的环境中以及有哪些可用的云资源。对于给定的业务案例,这种区别通常非常明显。
当“robot_localization <https://github.com/cra-ros-pkg/robot_localization/>”使用 navsat_transform
节点提供全局定位时, nav2_waypoint_follower
还支持 GPS 航点跟踪 - 但也可以由 Fuse 或任何其他来源提供。
在 nav2_waypoint_follower
中有一个名为 /follow_gps_waypoints
的动作服务器,它可以直接接收以 GPS 坐标表示的目标,将它们转换为全局框架中的笛卡尔目标,并将它们作为笛卡尔航点执行。
状态估计
根据社区标准,在导航项目中,需要提供 2 个主要转换。
定位系统(本地化、地图绘制、SLAM)提供 map
到 odom
的转换,里程计系统提供 odom
到 base_link
的转换。
Note
使用导航系统时, 无需 在机器人上使用激光雷达。无需使用基于激光雷达的防撞、 定位或 SLAM。但是,我们确实提供了说明并支持使用激光雷达对这些事物进行久经考验的实现。 使用基于视觉或深度的定位系统和使用其他传感器进行防撞,您可以同样成功。 唯一的要求是您在选择实现时遵循以下标准。
标准
REP 105 定义了导航和更大的 ROS 生态系统所需的框架和约定。 应始终遵循这些约定,以利用社区中丰富的定位、里程计和 SLAM 项目。
简而言之,REP-105 表示您必须至少为您的机器人构建一个包含完整 map
-> odom
-> base_link
-> [sensor frames]
的 TF 树。
TF2 是 ROS 2 中用于表示和获取时间同步变换的时间变量变换库。
全球定位系统 (GPS、SLAM、运动捕捉) 的工作是至少提供 map
-> odom
变换。
然后,里程计系统的作用是提供 odom
-> base_link
转换。
相对于 base_link
的其余转换应为静态的,并在 URDF 中定义。
全球定位:定位和 SLAM
全球定位系统 (GPS、SLAM、运动捕捉) 的工作是至少提供 map
-> odom
转换。
我们提供 amcl
,这是一种基于粒子滤波器的自适应蒙特卡罗定位技术,用于在静态地图中进行定位。
我们还提供 SLAM Toolbox 作为默认 SLAM 算法,用于定位和生成静态地图。
这些方法还可以产生其他输出,包括位置主题、地图或其他元数据,但它们必须提供该转换才能有效。
可以使用机器人定位将多种定位方法融合在一起,下面将进一步讨论。
里程计
里程计系统的作用是提供 odom
-> base_link
转换。
里程计可以来自许多来源,包括激光雷达、雷达、车轮编码器、VIO 和 IMU。
里程计的目标是根据机器人运动提供平滑连续的局部框架。
全球定位系统将更新相对于全局框架的转换,以解释里程计漂移。
机器人定位 通常用于这种融合。
它将接收各种类型的 N
传感器,并为 TF 和主题提供连续平滑的里程计。
典型的移动机器人设置可能以这种方式融合来自车轮编码器、IMU 和视觉的里程计。
然后可以使用平滑的输出来进行精确运动的航位推算,并在全局位置更新之间准确更新机器人的位置。
环境表示
环境表示是机器人感知其环境的方式。 它还充当各种算法和数据源的中心定位,以将其信息组合到单个空间中。 然后,控制器、规划器和恢复器将使用此空间来安全高效地计算其任务。
成本图和图层
当前的环境表示是成本地图。 成本地图是一个规则的 2D 网格,其中包含未知、空闲、占用或膨胀的成本。 然后搜索此成本地图以计算全局计划或采样以计算局部控制工作量。
各种成本地图层都作为插件库插件实现,以将信息缓冲到成本地图中。 这包括来自激光雷达、雷达、声纳、深度图像等的信息。 在将传感器数据输入到成本地图层之前对其进行处理可能是明智的,但这取决于开发人员。
可以创建成本地图层来检测和跟踪场景中的障碍物,以便使用摄像头或深度传感器避免碰撞。 此外,可以创建图层以根据某些规则或启发式算法在算法上更改底层成本地图。 最后,它们可用于将实时数据缓冲到 2D 或 3D 世界中以进行二进制障碍物标记。
Costmap Filters
想象一下,您正在注释地图文件(或任何图像文件),以便根据注释地图中的位置执行特定操作。标记/注释的示例可能是禁区以避免在内部进行规划,或者在标记区域内使像素属于最大速度。此注释地图称为“过滤器蒙版”。就像覆盖在表面上的蒙版一样,它可以或不能与主地图具有相同的大小、姿势和比例。过滤器蒙版的主要目标是提供在地图上标记区域的能力,这些区域具有一些附加功能或行为变化。
成本地图过滤器是一种基于成本地图层的方法,将空间相关的行为变化(在过滤器蒙版中注释)应用于 Nav2 堆栈。 成本地图过滤器作为成本地图插件实现。 这些插件被称为“过滤器”,因为它们通过标记在过滤器蒙版上的空间注释来过滤成本地图。 为了制作过滤后的代价地图并改变机器人在注释区域中的行为,过滤器插件会读取来自过滤器掩码的数据。
此数据被线性转换为过滤器空间中的特征图。
有了此转换后的特征图以及地图/代价地图,任何传感器数据和当前机器人坐标过滤器都可以更新底层代价地图并根据机器人所在的位置改变其行为。
例如,可以使用代价地图过滤器实现以下功能:
机器人永远不会进入的禁区/安全区。
限速区。进入这些区域的机器人的最大速度将受到限制。
工业环境和仓库中移动的机器人的首选车道。
其他形式
存在各种其他形式的环境表示。 这些包括:
梯度图,类似于代价图,但表示表面梯度以检查可遍历性
3D 代价图,以 3D 形式表示空间,但也需要 3D 规划和碰撞检查
网格图,类似于梯度图,但具有多个角度的表面网格
“矢量空间”,接收传感器信息并使用机器学习来检测要跟踪的单个项目和位置,而不是缓冲离散点。