Skip to content

Commit

Permalink
Fill in fleet integration sections
Browse files Browse the repository at this point in the history
  • Loading branch information
mxgrey committed Jun 22, 2020
1 parent e873eaf commit 12f6b30
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 12 deletions.
34 changes: 31 additions & 3 deletions src/integration_fleets.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
# Fleet Integration
# Mobile Robot Fleet Integration

Here we will cover integrating a mobile robot fleet that offers the **Path** control category of fleet adapter. This means we assume the mobile robot fleet manager allows us to specify explicit paths for the robot to follow, and that the path can be interrupted at any time and replaced with a new path. Furthermore, each robot's position will be updated live as the robots are moving.
Here we will cover integrating a mobile robot fleet that offers the **Full Control** category of fleet adapter. This means we assume the mobile robot fleet manager allows us to specify explicit paths for the robot to follow, and that the path can be interrupted at any time and replaced with a new path. Furthermore, each robot's position will be updated live as the robots are moving.

## Route Map

Before such a fleet can be integrated, you will need to procure or produce a route map as described in the [previous section](./integration_nav-maps.md).
Before such a fleet can be integrated, you will need to procure or produce a route map as described in the [previous section](./integration_nav-maps.md). The fleet adapter uses the route map to plan out feasible routes for the vehicles under its control, taking into account the schedules of all other vehicles. It will also use the route map to decide out how to negotiate with other fleet adapters when a scheduling conflict arises. The adapter will only consider moving the robots along routes that are specified on the route map, so it is important that the route coverage is comprehensive. At the same time, if there are extraneous waypoints on the route map, the adapter might spend more time considering all the possibilities than what should really needed, so it is a good idea to have a balance of comprehensiveness and leanness.

## C++ API

The C++ API for full-control automated guided vehicle (AGV) fleets can be found in the [`rmf_fleet_adapter`](https://github.com/osrf/rmf_core/tree/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv) package of the `rmf_core` repo. The API consists of four critical classes:

* [`Adapter`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv/Adapter.hpp) - Initializes and maintains communication with the other core RMF systems. Use this to register one or more fleets and receive a `FleetUpdateHandle` for each fleet.
* [`FleetUpdateHandle`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv/FleetUpdateHandle.hpp) - Allows you to configure a fleet by adding robots and specifying settings for the fleet (e.g. specifying what types of deliveries the fleet can perform). New robots can be added to the fleet at any time.
* [`RobotUpdateHandle`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv/RobotUpdateHandle.hpp) - Use this to update the position of a robot and to notify the adapter if the robot's progress gets interrupted.
* [`RobotCommandHandle`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv/RobotCommandHandle.hpp) - This is a pure abstract interface class. The functions of this class must be implemented to call upon the API of the specific fleet manager that is being adapted.

The basic workflow of developing a fleet adapter is the following:

1. Create an application that links to the `rmf_fleet_adapter` library.
2. Have the application read in runtime parameters in whatever way is desired (e.g. command line arguments, configuration file, ROS parameters, REST API calls, environment variables, etc).
3. Construct a route graph for each fleet that this application is providing the adapter for (a single adapter application can service any number of fleets), and/or parse the route graph from a yaml file using the [`rmf_fleet_adapter::agv::parse_graph`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/include/rmf_fleet_adapter/agv/parse_graph.hpp) utility.
4. Instantiate an `rmf_fleet_adapter::agv::Adapter` using `Adapter::make(~)` or `Adapter::init_and_make(~)`.
5. Add the fleets that the application will be responsible for adapting, and save the `rmf_fleet_adapter::agv::FleetUpdateHandlePtr` instances that are passed back.
6. Implement the `RobotCommandHandle` class for the fleet manager API that is being adapted.
7. Add the robots that the adapter is responsible for controlling. The robots can be added based on the startup configuration, or they can be dynamically added during runtime as they are discovered over the fleet manager API (or both).
- When adding a robot, you will need to create a new instance of the custom `RobotCommandHandle` that you implemented.
- You will also need to provide a callback that will be triggered when the adapter is finished registering the robot. This callback will provide you with a new `RobotUpdateHandle` for your robot. It is imperative to save this update handle so you can use it to update the robot's position over time.
8. As new information arrives from the fleet manager API, use the collection of `RobotUpdateHandle`s to keep the adapter up-to-date on the robots' positions.

An example of a functioning fleet adapter application can be found in the [`full_control` backwards-compatability adapter](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_adapter/src/full_control/main.cpp). This is a fleet adapter whose fleet-side API is the "Fleet Driver API", which is a deprecated prototype API for the RMF **Full Control** category of fleet adapters. This fleet adapter exists temporarily to maintain backwards compatibility with the old "Fleet Driver" implementations and to serve as an example of how to implement a fleet adapter using the new C++ API.

## Python Bindings

You may also choose to use Python to implement your fleet adapter. You can find Python bindings for the C++ API in [this repo](https://github.com/osrf/rmf_fleet_adapter_python). The Python bindings literally just port the C++ API into Python so that you can develop your fleet adapter using Python instead of C++. The above API and workflow are exactly the same, just in Python instead. This should be very useful for fleets that use REST APIs, because you'll have access to tools like [Swagger](https://swagger.io/tools/open-source/getting-started/) which can help you generate client code for the fleet's REST API server.
9 changes: 4 additions & 5 deletions src/integration_free-fleet.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

### Free Fleet
# Free Fleet

In the event that the user wishes to integrate a standalone mobile robot which doesn't come with its own fleet management system, the open source fleet management system `free_fleet` could be used.

Expand All @@ -13,7 +12,7 @@ In this section, we will address 4 different approaches of using `free_fleet` to

<img src="images/free_fleet_block_diagram.png">

#### ROS 1 Navigation Stack
## ROS 1 Navigation Stack

An implementation of a `free_fleet` client that works with a ROS 1 navigation stack can be found in the [repository](https://github.com/osrf/free_fleet). The implementation expects the transforms of the mobile robot to be fully defined, the mobile robot to accept navigation commands via the `move_base` action library, as well as publishing its battery status published using the `sensor_msgs/BatteryState` message.

Expand Down Expand Up @@ -110,15 +109,15 @@ Furthermore, an example of this configuration can be found in the repository as

After successful builds for both ROS 1 and ROS 2 workspaces, the simulation can be launched following [these instructions](https://github.com/osrf/free_fleet#turtlebot3-simulation), which also includes a ROS 2 `free_fleet` server, publishing fleet state messages and accepting mode and navigation requests over ROS 2 messages and topics.

#### ROS 2 Navigation Stack
## ROS 2 Navigation Stack

An implementation for a robot using ROS 2 would be similar to a ROS 1 navigation stack described earlier. At this time, the ROS 2 `free_fleet` client is still under development. This section will be updated once the refactoring, implementation and testing has been completed.

The same ready `free_fleet` server implementation in the repository will work in this scenario, as the interfaces provided by the fleet adapters are still the same ROS 2 messages and topics.

If required in the meantime, users can implement their own `free_fleet` client, by working with the `free_fleet` library that contains the base implementation and API for the DDS communication. This will be further elaborated in the next section [Custom Navigation Stack](#custom-navigation-stack).

#### Developer Navigation Stack
## Developer Navigation Stack

In this implementation, it is assumed that the software running on the mobile robot was written by the robot developers themselves (or their immediate subcontractors) and the developers fully understand and have access to their robot's internal control software, API's and interfaces. This level of understanding and access will be necessary for implementing your own `free_fleet` client wrapper. The block diagram below illustrate this configuration.

Expand Down
69 changes: 69 additions & 0 deletions src/integration_read-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Read-only Fleet Integration

In this section, we will cover the prototype API for integrating the **Read Only** category of mobile robot fleets. This means we assume the mobile robot fleet manager only allows RMF to see updates about where its robots are located and where they intend to go, but it does not offer any control over where the robots are going or how they can move around. This type of adapter is primarily aimed at legacy systems that were developed before RMF and did not anticipate the possibility of a third-party being able to command the robots.

## Fleet Driver API

The Fleet Driver API was an experimental API developed in the early stages of the RMF research project. It can still be used for a read-only fleet adapter implementation until an officially supported C++ API comes out to replace it.

The Fleet Driver API uses ROS2 messages from the [`rmf_fleet_msgs`](https://github.com/osrf/rmf_core/tree/master/rmf_fleet_msgs) package. To use this API, you will want to write a ROS2 application (using either rclcpp or rclpy) which we will refer to as the *Fleet Driver*. The job of the Fleet Driver is to transmit [`rmf_fleet_msgs/FleetState`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_msgs/msg/FleetState.msg) messages out to the `"fleet_states"` topic.

Inside the `FleetState` message is the `name` field. Be sure to fill in the correct name for your fleet state. There is also a collection of [`rmf_fleet_msgs/RobotState`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_msgs/msg/RobotState.msg) messages. For integrating a read-only fleet with RMF, the most crucial fields of the `RobotState` message are:

* `name` - The name of the robot whose state is being specified.
* `location` - The current location of the robot.
* `path` - The sequence of locations that the robot will be traveling through.

Inside the [`rmf_fleet_msgs/Location`](https://github.com/osrf/rmf_core/blob/master/rmf_fleet_msgs/msg/Location.msg) message, the `t` field (which represents time) is generally ignored by the read-only fleet adapter. We assume that it is too cumbersome for your Fleet Driver to make timing predictions, so we have the read-only fleet adapter make the predictions for you based on the traits of the vehicle.

## Configuring the Read Only Fleet Adapter

For the prototype read-only integration, there are two applications that need to be launched:

1. The Fleet Driver mentioned above which you write specifically for your fleet's custom API
2. The `read_only` fleet adapter which must be launched through ROS2

To launch the fleet adapter, you will need to use `ros2 launch` and include `rmf_fleet_adapter/fleet_adapter.launch.xml` file with the required parameters filled in. An example of this using the XML front-end of ros2 launch [can be found in `rmf_demos`](https://github.com/osrf/rmf_demos/blob/master/demos/launch/include/adapters/caddy_adapter.launch.xml), copied below:

```
<?xml version='1.0' ?>
<launch>
<arg name="fleet_name" default="caddy" description="Name of this fleet of caddy robots"/>
<group>
<include file="$(find-pkg-share rmf_fleet_adapter)/fleet_adapter.launch.xml">
<!-- The name and control type of the fleet -->
<arg name="fleet_name" value="$(var fleet_name)"/>
<arg name="control_type" value="read_only"/>
<!-- The nominal linear and angular velocity of the caddy -->
<arg name="linear_velocity" value="1.0"/>
<arg name="angular_velocity" value="0.6"/>
<!-- The nominal linear and angular acceleration of the caddy -->
<arg name="linear_acceleration" value="0.7"/>
<arg name="angular_acceleration" value="1.5"/>
<!-- The radius of the circular footprint of the caddy -->
<arg name="footprint_radius" value="1.5"/>
<!-- Other robots are not allowed within this radius -->
<arg name="vicinity_radius" value="5.0"/>
<arg name="delay_threshold" value="1.0"/>
</include>
</group>
```

The critical parameters are:

* `fleet_name`: This must match the `name` value that the Fleet Driver gives to its `FleetState` messages.
* `control_type`: This must be `"read_only"`.
* `linear_velocity`, `angular_velocity`, `linear_acceleration`, and `angular_acceleration`: These are estimates of the kinematic properties of the vehicles. For the sake of effective scheduling, it is preferable to overestimate these values than underestimate them, so it is best to think of these parameters as upper bounds for the values.
* `footprint_radius`: The radius of physical space that the vehicle occupies. This should cover the maximum extent of the physical footprint.
* `vicinity_radius`: The radius around the robot in which other robots are forbidden to physically enter. It is assumed that another robot entering this radius will interfere with the ability of this robot to operate.

When the launch file and Fleet Driver application are both ready, you can launch them side-by-side and the integration of the read-only fleet adapter will be complete.
8 changes: 4 additions & 4 deletions src/rmf-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ However, to minimize the duplication of integration effort, we have identified 4
different broad categories of control that we expect to encounter among various
real-world fleet managers.

* **Path** *(API available)* - RMF is provided with status and full control over the paths that each individual mobile robot uses when navigating through the environment. This control level provides the highest overall efficiency and compliance with RMF, which allows RMF to minimize stoppages and deal with unexpected scenarios gracefully.
* **Full Control** *(API available)* - RMF is provided with live status updates and full control over the paths that each individual mobile robot uses when navigating through the environment. This control level provides the highest overall efficiency and compliance with RMF, which allows RMF to minimize stoppages and deal with unexpected scenarios gracefully.

* **Traffic Light** *(API not available yet)* - RMF is given the status as well as pause/resume control over each mobile robot, which is useful for deconflicting traffic schedules especially when sharing resources like corridors, lifts and doors.

* **Read Only** *(Preliminary API available)* - RMF is not given any control over the mobile robots but is provided with regular status updates. This will allow other mobile robot fleets with higher control levels to avoid conflicts with this fleet. _Note that any shared space is allowed to have a maximum of just one "Read Only" fleet in operation. Having none is ideal!_

* **No Control** *(Not compatible)* - This will prevent other fleets to coordinate with it through RMF, and will likely cause deadlocks when sharing the same navigable environment or resource. This level will not function with an RMF-enabled environment.
* **No Interface** *(Not compatible)* - Without any interface to the fleet, other fleets cannot coordinate with it through RMF, and will likely result in deadlocks when sharing the same navigable environment or resource. This level will not function with an RMF-enabled environment.

In short, the more collaborative a fleet is with RMF, the more harmoniously all of the fleets and systems are able to operate together. Note again that there can only ever be one "Read Only" fleet in a shared space, as any two or more of such fleets will make avoiding deadlock or resource conflict nearly impossible.

Currently we provide a reusable C++ API (as well as Python bindings) for integrating the **Path** control category. A preliminary ROS2-message API is available for the **Read Only** control category, but that API will be deprecated in favor of a C++ API (with Python bindings available) in a future release. The **Traffic Light** control category is compatible with the core RMF scheduling system, but we have not yet implemented a reusable API for it. To implement a **Traffic Light** fleet adapter, a system integrator would have to use the core traffic schedule and negotiation APIs directly, as well as implement the integration with the various infrastructure APIs (e.g. doors, lifts, and dispensers).
Currently we provide a reusable C++ API (as well as Python bindings) for integrating the **Full Control** category of fleet. A preliminary ROS2-message API is available for the **Read Only** category, but that API will be deprecated in favor of a C++ API (with Python bindings available) in a future release. The **Traffic Light** control category is compatible with the core RMF scheduling system, but we have not yet implemented a reusable API for it. To implement a **Traffic Light** fleet adapter, a system integrator would have to use the core traffic schedule and negotiation APIs directly, as well as implement the integration with the various infrastructure APIs (e.g. doors, lifts, and dispensers).

The API for the **Path** control category is described in the [Mobile Robot Fleets](./integration_fleets.md) section, and the **Read Only** category is described in the [Read Only Fleets](./integration_read-only.md) section.
The API for the **Full Control** category is described in the [Mobile Robot Fleets](./integration_fleets.md) section, and the **Read Only** category is described in the [Read Only Fleets](./integration_read-only.md) section.

0 comments on commit 12f6b30

Please sign in to comment.