Multiple Vehicle Coordination
Overview
The AERPAW vehicle library (aerpawlib) has support for multiple vehicle coordination. The authoritative documentation for aerpawlib is here, including the multiple vehicle coordination documentation. In what follows we show one simple way of leveraging aerpawlib for coordinating multiple vehicle. In particular, in this version, a central coordinator is in charge of synchronizing the movement of two vehicles (the structure scales trivially to any number of vehicles). Other ways of coordinating multiple vehicles (e.g., without a central coordinator, or with multiple central coordinators) are possible. The figure on the right shows the four processes involved in coordinating two vehicles with a central coordinator.
Setup
For setting up a coordinated application, the Experimenter should use a message broker. The message broker can be started in any of the E-VMs (i.e., it can be colocated with a vehicle or at a fixed node). It is up to the Experimenter to start the message broker and then point the other agents to the broker. The message broker acts as a routing agent between each of the elements.
The message broker process is included in the aerpawlib and can be started as follows (the parameters for the script, connection and vehicle are not used and can be anything):
python -m aerpawlib --run-proxy --script a --conn a --vehicle a
Then each of the other scripts are being started with a pointer to the message broker. For example, for vehicle 1 script:
python -m aerpawlib --vehicle drone --conn 127.0.0.1:14570 \
--zmq-identifier VEHICLE1 --zmq-proxy-server 127.0.0.1 \
--script vehicle1_script
where :
--vehicle specifies the vehicle type
--conn specifies the connection to the drone (IP address and port)
--zmq-identifier specifies how the the process will be identified in the messages
--zmq-proxy-server specifies the IP address of the broker
--script specifies what script will this vehicle run
The call for vehicle 2 is similar.
The call for the coordinator is then:
python -m aerpawlib --vehicle none --conn a --skip-init \
--zmq-identifier COORDINATOR --zmq-proxy-server 127.0.0.1 \
--script coordinator_script --file orbit.plan
with obvious values (there is no vehicle to connect to, same proxy server IP address, and using the coordinator script). The --skip-init is used to skip the vehicle initialization procedure (as there is no vehicle to control for the coordinator)
All processes that are expected to use a message broker should define classes which inherit from class ZmqStateMachine (as opposed as independent scripts which inherit from StateMachine).
Support for Coordination
The Message broker supports several means for communications between the connected processes:
Triggering a remote state transition from a process in a different process. For example, for the coordinator to trigger the coordinated action in vehicle 1, it could run:
await self.transition_runner(VEHICLE1, "perform_coordinated_action"), where VEHICLE1 is the identifier for Vehicle 1, and "perform_coordinated_action" is the state Vehicle 1 will transition into.
Calling a remote callback function from a process in a different process (and, optionally, returning a value). For example when Vehicle 1 completed the current action it can inform the coordinator by calling a coordinator function:
await self.transition_runner(COORDINATOR, "callback_done_with_vehicle1_action") where COORDINATOR is the process ID of the coordinator, and callback_done_with_vehicle1_action is the function that will be called back (must be defined in the coordinator script)
Exposing a field (e.g., a variable) from one process to another process. For example, to share the current position from one vehicle to a coordinator:
the vehicle exposes the position variable:
@expose_field_zmq(name="position")
async def get_drone_position(self, drone: Drone):
return drone.position
and the coordinator reads it:
vehicle_position = await self.query_field(VEHICLE1, "position")
where VEHICLE1 is the ID of the vehicle process, and "position" is the variable exposed by the vehicle.
A Simple Coordination Pattern
The figure on the right shows a typical coordination strategy for one coordinator and two vehicles. The scheme generalizes trivially to multiple vehicles. The three scripts start independently in the stated indicated by the red arrows; the two vehicles enter a wait loop, waiting for the coordinator to trigger a state transition (using a remote state transition) to the next state (e.g., coordinated takeoff, landing, or waypoint navigation). The two vehicles can take different amount of times to complete their actions. As soon as a vehicle completes their action, they inform the coordinator of their completion (by using a remote callback function) and enter the idle state (wait_loop), waiting for the coordinator to trigger the next coordinated action (which, is then very similar to the one shown in the figure).
As an example example of a coordinated application, we provide a sample application called The Tracer and the Orbiter.