External Agent Interface¶
The External Agent Interface (EAI) can introduce externally controlled vehicles into an Aimsun Next microscopic simulation. Such external vehicles can be guided by the actions of, for example, a human driver in a simulator, an autonomous vehicle controller, or an experimental control system being tested in a simulation environment.
The data exchanged via the EAI are based on geographic locations expressed as x- and y-coordinates rather than the simulated representation of the traffic network expressed via lanes and turns.
This means that the external control logic needs no detailed knowledge of how Aimsun Next models the traffic network – it can continue to use its own network model. Data exchange relies solely on there being a shared system of common coordinates.
External vehicles are positioned on the traffic network within the simulation. The other vehicles in the simulation – the ones controlled and updated by Aimsun Next – will then react to the presence of external vehicles by following them, collaborating with their lane-change maneuvers, and including them in their assessment of gaps at junctions in the same way as they react to other 'internal' vehicles in the simulation.
Note that at every simulated time step, Aimsun Next sends a list of 'internal' vehicles (i.e. vehicles in the Aimsun network) surrounding or close to 'external' vehicles in the external application. The position of these internal vehicles is based on the center of their front bumper.
Traffic signals are exclusively controlled by Aimsun Next at all times.
Systems Architecture¶
The EAI is based on a client–server architecture in which Aimsun Next is the server, responsible for managing traffic signals and the other vehicles and pedestrians in the simulation. The client is the external controller, or simulator, which receives information about the dynamic objects in the simulation and responds with the updated positions and headings of the externally controlled vehicles.
The EAI provides the PROTO file which must be used to program the interface using a software library derived directly from this file on the host system and using the client's preferred programming language. This language must be supported by Google protocol buffers. See Protocol Buffer Interface for more information. Use this option when working with C++, C#, Java, Python, or several other languages (check the complete list in Google's Protocol Buffers).
The underlying communications mechanism is based on TCP/IP with data serialized using Google protocol buffers: a platform-independent, highly efficient communications library. The simulation and controller can sit on the same, or different, computing platforms connected by a network. This enables the external application to be developed in any programming language, without the need for in-depth knowledge of Aimsun Next.
The serialized data must be sent through a TCP/IP socket. First, the size of the serialized message as a 32-bit integer is sent in network order. Second, the serialized message itself is sent. The frequency of this communication is the same as the simulation step, which can be set as low as 10Hz (0.1s).
The /programming/External Agents Interface folder includes an implementation of the connection mechanism. See TCPSocket.h and TCPSocket.cpp in Cpp-Sample/AimsunEAConnectorLib for the implementation and Cpp-Sample/AimsunEAConnectorTester for an example of usage in C++.
As an example of how to use the EAI with a language that does not support protobuffers, there is an integration example for MATLAB written in C. You can also find it in the /programming/External Agents Interface folder.
Server Configuration and Execution¶
API Configuration¶
-
Open the Scenario editor, click the Aimsun Next APIs tab, and tick External Agent Extension.
-
Double-click External Agent Extension or click Properties.
-
Configure its properties as described in the next section (the screenshot below serves as an example only).
Configuration Options¶
-
Initial Communications Timeout(s): Set a time in seconds for which Aimsun Next will wait for the external controller to connect. After this timeout, the simulation will start without communication.
-
Message Timeout(s): Set a time in seconds for which the Protocol Buffer Interface will wait for a response. After this timeout, the communication will be closed.
-
Server Port: Select or enter the number of the server port.
-
Synchronous Communication: Tick this box to synchronize the clocks of Aimsun Next and the external software. This is the recommended setting.
Note: When this box is unticked, asynchronous communication occurs. This means there is no clock synchronization and Aimsun Next does not wait for the external agent to advance the time. You can use this option to check what happens if for any reason the external software cannot run at least as fast as real time. We recommend that this test is run just before deployment on real vehicles. However, synchronous communication should cover 90% of pre-deployment tests.
-
Number of Connections Expected: Aimsun Next can connect to multiple clients. Set the number of clients that will be expected for this simulation. The server will stop waiting for new connections if this value is reached.
-
Requires Expected Number of Connections: Tick this box if the simulation should be aborted in case that the number of established connections is lower than the expected connections.
-
Record Input Messages: This box activates the storage of the messages Aimsun Next recieves from external software during simulation. The file will be stored as replicationID_connectionID_replay.eai.
-
Record Output Messages: This box activates the storage of the messages Aimsun Next sends to external software during simulation. The file will be stored as replicationID_connectionID_replay_out.eai.
-
Detailed Vehicle Trajectory: Tick this box to apply visual smoothing to the position of vehicles as they change lanes in the main view of the Aimsun Next UI.
-
External Agent Type To Vehicle/Pedestrian Type: Select one of the five vehicle types, or the Pedestrians option, for each external agent type available.
Note: None of the behavior parameters or dynamic routing parameters defined for the selected option, which are normally used by Aimsun Next, are relevant in determining the actions of the externally controlled vehicle.
-
Vehicle Class To External Agent Type: Select which vehicle class will represent each external agent type. If no classes are selected, AGENT_NOT_DEFINED will be used as the default external agent type. If a simulated vehicle belongs to more than one vehicle class with defined external agent type translation, the lower type value will have priority.
Running the Simulation¶
-
In Windows, run the command:
Aimsun Next.exe --verbose --EVC-host --wait_to_sync --project evc_model.ang
This will start Aimsun Next as an External Vehicle Host waiting for an external controller to connect to it.
-
Separately, run the External Vehicle Controller, which is configured to connect to the Aimsun Next simulation. When both elements – simulation and controller – are running, run the simulation replication as normal. At each simulation time step, the position of the externally controlled vehicles will be updated by the linked controller. An interesting option would be to have a script that runs this external application/controller and set that script as a Pre-Run script.
Client Programming ¶
The client controller is the software which moves the externally controlled vehicles. Its sequence of operations is as follows.
-
Model creation:
-
Sets up the controller so that it uses a map that matches the same area as the simulation model. The controller might require different detailed knowledge of the area. Specifically, it might need more knowledge of street furniture or of curbs and ramps where it can transition between road and pedestrian areas. It must, however, match the simulation network in terms of road topology and the system of coordinates. The IDs of any traffic signals must also be shared between the simulation and the client controller.
-
Starting the controller:
-
Opens a connection to the simulation.
-
Creates the externally controlled vehicle(s).
-
At every time step:
-
Writes the current position of the externally controlled vehicle(s).
-
Reads the new positions of the simulated agents (vehicles and pedestrians) within a defined radius of the externally controlled vehicle(s) from the simulation.
-
Reads the new state of the traffic signals within that radius.
-
Reads the new state of the variable message signs (VMS) in that radius.
-
Presents this information to an autonomous vehicle controller or displays these vehicles and signals in a driving simulator.
-
Updates the position of the external vehicle(s) for the next time step.
-
At the end of the simulation:
-
Ends the connection.
-
Shuts down the controller.
The interface can be programmed in the controller using:
- protocol buffers in any of the supported languages
- for a system with no protocol-buffers support, e.g. MATLAB, there is an implementation example as a C library.
Sequence Diagrams¶
Case 1: Aimsun Next finishes the simulation
Case 3: Aimsun Next cancels the simulation
Protocol–Buffer Interface ¶
If the start point in coding the controller interface is the PROTO file which defines the communications protocol, then this enables the interface to be written in one of several languages, including C++, C# Java, and Python – check the complete list in Google's Protocol Buffers.
It can be compiled on any operating system to suit the requirements of the controller's software and firmware.
Using the PROTO file, a programmer will be also able to:
- include multiple externally controlled vehicles
- define the bubbles (areas from within which Aimsun Next will send information about vehicles and traffic signals) and control their size and position
- send a list of intentions to control the movement of pedestrians.
To use the PROTO file:
-
Get the ExternalAgentsConnector.proto file from the Aimsun Next installation subfolder, "/programming/External Agents Interface". Note that this file uses Protobuf Version 3.
-
Use tools supplied by Google to create the source code. This is documented on the Protocol Buffers web page.
-
Add this code as part of the project build process, typically by editing the Makefile.
Then, when programming the interface:
-
Initialization
-
Open an input stream linking to the IP address and EAI port of the computer hosting the simulation.
-
Create the externally controlled vehicles.
-
At every time step
-
Read the list of objects in the bubble(s).
-
Evaluate the controller's actions.
-
Update the positions in Aimsun Next for the externally controlled vehicles and send any information to control pedestrians if required.
-
Move to the next time step.
The code generated by the Google ProtoBuf Interface provides the structures and enumerated constants with which to build the messages and the functions required to send and receive them.
Proto file details¶
From Aimsun Next 22 onwards, you can use three messages to control the movement of pedestrians if you are using the External Agent Interface to connect your external simulation with Aimsun Next's microsimulator.
You can now override the Aimsun Next microsimulation and control whether pedestrians wait at crosswalks, cross over, or stop wherever they are in the simulation.
The messages that control this behavior are named WAIT_AT_CROSSWALK, USE_CROSSWALK, and STOP_MOVING. These messages, when sent, will override expected or 'typical' pedestrian behavior and will also override the effect of traffic signal states.
The first two are self-explanatory and the third, STOP_MOVING, means that a pedestrian will decelerate and stop but, if they are close to other pedestrians, they can still move if pushed and they will still react to obstacles.
External Agent Interface Connector for C++¶
There is an example in the folder programming\External Agents Interface\Cpp-Sample
to show how to use the interface in C++. This should be used as a starting point for a project that is going to connect to Aimsun Next via External Agent Interface.
Use cmake to setup and build the C++ example. The only external requirement is the protocol buffer and spdlog libraries, ideally via vcpkg package manager.
cd "programming\External Agents Interface\Cpp-Sample"
cmake -S . -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=$env:{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake
cmake --build build
Structure¶
- AimsunEAConnectorLib is a library that controls the connection, synchronization and flow of execution.
- AimsunEAConnectorTester is an example of how to extend this library with your own model.
This example is a tool that provides a functioning workflow, but it is a tool created so that it can be integrated in bigger projects or used as the base.
Generate External Items¶
Automatically executed after establishing a successful connection with Aimsun Next. It's intended to be used for creating the vehicle(s) and models for the external application.
void generateExternalItems();
Manage Received Data¶
On each step, it's intended to be used for handling the received data from the Aimsun Next co-simulation and setup the context (maybe fill data structures, logs, print information, etc.).
void manageReceivedData( const ExternalAgents::Out * out ) override;
Update External Items¶
Executed immediately after managing the received data, it's intended to be used for updating the vehicle(s) that will be sent and make decisions with the new context.
void updateExternalItems();
Send External Items¶
Executed immediately after updating external items, it's intended to be used for sending the vehicle(s), bubbles, pedestrian intentions or whatever the message needs to contain. It can be used as a hub to launch debugging tools, store logs, etc.
void sendExternalItems();
Clean External Items¶
Automatically executed after closing the connection with Aimsun Next. It's intended to be used for cleaning up the data structures used for the execution, since this workflow may be a small procedure inside a large program which continues to execute after the co-simulation is complete.
void cleanExternalItems();
External Agent Interface Connector for MATLAB¶
There is an example in the programming\External Agents Interface\MATLAB
folder to show how to use the interface in MATLAB.
Use cmake to setup and build the example. The only external requirements are the protocol buffer library and spdlog library, ideally using vcpkg package manager.
cd "programming\External Agents Interface\MATLAB"
cmake -S . -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=$env:{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake
cmake --build build
Sequence Diagrams for MATLAB¶
The C library that implements the interface for MATLAB has a different sequence, based on functions instead of messages.
Structures¶
Scenario Information¶
/*! Scenario information */
struct AimsunEACLoadResult
{
int timeStep; // Simulation time step in Aimsun Next (ms)
int start; // start time (virtual clock) of the simulation in ms since epoch
int duration; // duration of the simulation in ms
};
Traffic Signal ¶
/*! A traffic signal
- name: external name of the signal
- state:
NOT_DEFINED = 0
OFF = 1
GREEN = 2
YELLOW = 3
RED = 4
FLASHING_YELLOW = 5
FLASHING_RED = 6
YELLOW_BEFORE_GREEN = 7
FLASHING_GREEN_AS_GREEN = 8
FLASHING_RED_AS_RED = 9
FLASHING_YELLOW_AS_YELLOW = 10
YELLOW_AS_GREEN = 11
*/
struct AimsunEACTrafficLightState
{
char name[100]; // The external name of the signal
int state; // The state of the signal
}
VMS State ¶
/*! A variable message sign (VMS)
- external_id: External id of the VMS object.
- message: The current message shown on the VMS
*/
struct AimsunEACVMSState
{
char external_id[64];
char message[256];
}
Agent ¶
The agent structure applies to both the externally controlled vehicles and the simulation vehicles.
/*! An agent
- id: unique identifier of the agent
- x, y, z: Position of vehicle (for pedestrians, the center)
- When reading from Aimsun Next, it corresponds to the mid-position of the front bumper
- When sending to Aimsun Next, send mid-position of the rear axle
- h: heading as radians with the horizontal
- speed: agent speed in m/s
- length: in meters
- width: in meters
- type:
AGENT_NOT_DEFINED = 0
CAR = 1
BIKE = 2
TRUCK = 3
BUS = 4
PEDESTRIAN = 5
MOTORCYCLE = 6
- brakeLight : Indicates if brake light is activated
- leftTurnSignal: Indicates if left-turn signal is activated
- rightTurnSignal: Indicates if right-turn signal is activated
- minUpstreamTimeGapForLaneChange: Indicates the minimum time needed to change to a different lane in front of an upstream vehicle
*/
struct AimsunEACAgent
{
int id; // The unique identifier of the vehicle
double x; // The x coordinate of a vehicle's rear axle or a pedestrian's center point position
double y; // The y coordinate of a vehicle's rear axle or a pedestrian's center point position
double z; // The z coordinate of a vehicle's rear axle or a pedestrian's center point position
double h; // The heading as radians from the Easting
double length; // The agent length in m.
double width; // The agent width in m.
double speed; // The agent speed in m/s
bool brakeLight; // Whether the agent has the brake light on or not
bool leftTurnIndicator; // Whether the agent has the left turn indicator on or not
bool rightTurnIndicator; // Whether the agent has the right turn indicator on or not
int type; // The agent type
double minUpstreamTimeGapForLaneChange; // Indicates the minimum time needed to change to a different lane in front of an upstream vehicle
};
Functions (C Library)¶
Note: This library is a sample that uses the code generated by the PROTO files to allow communication with the External Agents Interface. Using these functions one could build a program that follows the sequence described in the MATLAB diagram to execute a co-simulation.
AimsunEACStart¶
Connects to an instance of Aimsun Next running on a host and with an open port. The default values are localhost and 1541. Returns true
if the connection has been established and false
if not.
bool AimsunEACStart( const char * host, int port );
AimsunEACStop¶
Closes the connection with the instance of Aimsun Next.
void AimsunEACStop();
AimsunEACLoad¶
Calls the load function to receive the AimsunEACLoadResult. Returns true if the connection is still open, false if otherwise.
bool AimsunEACLoad();
AimsunEACRead¶
Reads the data from Aimsun Next. Returns 0
if the connection has been lost or the message type has been read. The message types are:
-
LoadResult. Use AimsunEACGetLoadResult
-
Out. Use AimsunEACAgentsRead, AimsunEACTrafficLightsRead and AimsunEACVMSStatesRead
-
Close
-
CloseResult
int AimsunEACRead();
AimsunEACCloseReceived¶
Checks to see if the simulation has finished and the port closed. Returns true
if Aimsun Next has finished the simulation.
bool AimsunEACCloseReceived();
AimsunEACGetLoadResult¶
Returns the scenario info. Call this function after a successful call to AimsunEACRead().
AimsunEACLoadResult * AimsunEACGetLoadResult();
AimsunEACAgentsRead¶
Returns the number of vehicles around the external vehicle. Call this function after a successful call to AimsunEACRead(). The default radius of visibility is 100m.
int AimsunEACAgentsRead();
AimsunEACGetAgent¶
Reads the information of a vehicle, indexed from 0 to (AimsunEACAgentsRead() - 1). Call this function after a successful call to AimsunEACAgentsRead(). The pointer to the AimsunEACAgent structure must not be freed or reassigned.
struct AimsunEACAgent * AimsunEACGetAgent( int i );
AimsunEACTrafficLightsRead¶
Returns the number of traffic lights around the external vehicle. Call this function after a successful call to AimsunEACRead().
int AimsunEACTrafficLightsRead();
AimsunEACGetTrafficLightState¶
Reads the information pertaining to a traffic light, indexed from 0 to (AimsunEACTrafficLightsRead() - 1). Call this function after a successful call to AimsunEACTrafficLightsRead(). The pointer to the AimsunEACTrafficLightState structure must not be freed or reassigned.
struct AimsunEACTrafficLightState * AimsunEACGetTrafficLightState( int i );
AimsunEACVMSStatesRead¶
Returns the number of VMS states around the external vehicle. Call this function after a successful call to AimsunEACRead().
int AimsunEACVMSStatesRead();
AimsunEACGetVMSState¶
Reads the information of a VMS, indexed from 0 to (AimsunEACVMSStatesRead() - 1). Call this function after a successful call to AimsunEACVMSStatesRead(). The pointer to the AimsunEACVMSState structure must not be freed or reassigned.
struct AimsunEACVMSState * AimsunEACGetVMSState( int i );
AimsunEACWrite¶
Inserts or updates an external vehicle in the simulation. The position and heading of the vehicle should be set in the AimsunEACAgent structure. Note that the behavior of the vehicle is not modified by Aimsun Next – only the position is updated and therefore the speed of the vehicle is ignored. Returns false
if the data cannot be written.
bool AimsunEACWrite( struct AimsunEACAgent *agent );
AimsunEACClose¶
Asks Aimsun Next to terminate the simulation. Returns true
if this request is successfully carried out.
bool AimsunEACClose();