This project simulates creating orders for cars. This can be used for integration testing of the Fleet Protocol stack.
The application reads all scenarios from the directory specified in the configuration. Each scenario is a JSON file that describes a sequence of missions for a car. The application creates a simulation for each scenario.
The application creates an HTTP client. It checks if the fleet management HTTP API is available. If it's not, it tries again after some time. The sleep time and number of retries are constants in the code. The sleep time is increasing with each retry.
Then it creates routes and stops from the scenario files. If they already exist and are the same, this step is skipped. If they exist with different data (e.g. different coordinates), the application logs an error and stops.
The application then starts to monitor the cars. It periodically retrieves the list of cars from the fleet management HTTP API and checks if each car is communicating. If a car is communicating and there is an available scenario that is not active, the application starts a simulation for that car in a new goroutine.
Each simulation first orders the car to the starting station of the scenario, so the simulations are deterministic.
Then, it runs the missions in its scenario in sequence.
If the loop configuration value is set to true
the simulation repeats the missions infinitely.
Otherwise, it runs the missions once and then stops once they are all done.
- --broker-ip=<ipv4> - IP address of the MQTT broker
- --broker-port=<port> - port of the MQTT broker
Files are distributed into folders depending on the company and car name they will be used for.
For example scenario for company BringAuto
with car name CAR1
will be stored in /bringauto/car1/scenario.json
.
Each car folder can contain multiple scenario files, but right now one scenario per car is supported, the first correct
file
will be run and the other files will be ignored
All scenarios from the company directory will be played in parallel. The application gets the company folder from a config.
Example scenarios are stored in virtual-fleet scenarios folder in JSON format.
scenarios/
├── companyA/ <-- company folder, passed to the app in config
│ ├── car1/
│ │ └── scenario.json
│ └── car2/
│ │ └── scenario.json
└── companyB/
├── car1/
│ └── scenario.json
└── car2/
└── scenario.json
JSON files contain the information about the map file that is used for missions (name or path to it), starting station and list of missions.
The starting station defines in which station the simulation will start. Order with starting_station is sent to the car as an initial mission. Once this initial mission is completed, the first mission is started.
Each mission contains a delay, the mission's name, and a list of stops. Delay sets the time, after which the mission is started. This time is counted since the previous mission started. Example with comments:
{
"map": "London.osm", -- name of the map of the vehicle, has no effect on the simulation, only informative
"starting_station": "London National Theatre", -- first order for the car, missions are started when the car is in this station
"missions": [ -- mission list
{
"delay_seconds": 0, -- delay after the previous mission is started
"name": "mission1",
"stops": [ -- stop list
{
"name": "London National Theatre"
},
{
"name": "Cross Station"
}
],
"route": "Short" -- route containing the stops
},
{
"delay_seconds": 150, -- delay after the previous mission is started. This mission will start 150 seconds after 'mission1'
"name": "mission2",
"stops": [
{
"name": "Oasis Academy"
},
{
"name": "London Waterloo"
}
],
"route": "Long"
}
],
"routes": [
{
"name": "Short",
"stations": [
{
"name": "London National Theatre",
"position": {
"latitude": 51.50719991926,
"longitude": -0.11572123647,
"altitude": 0
}
},
{
"name": "Cross Station",
"position": {
"latitude": 51.50847034843,
"longitude": -0.12557298213,
"altitude": 0
}
},
]
},
{
"name": "Long",
"stations": [
{
"name": "London Waterloo",
"position": {
"latitude": 51.50423320901,
"longitude": -0.11283786178,
"altitude": 0
}
},
{
"name": "London National Theatre",
"position": {
"latitude": 51.50719991926,
"longitude": -0.11572123647,
"altitude": 0
}
},
{
"name": "Oasis Academy",
"position": {
"latitude": 51.50031457906,
"longitude": -0.11135928467,
"altitude": 0
}
}
]
}
]
}
This scenario will create the order ["London National Theatre"], then play the mission ["London National Theatre", "Cross Station" ] from map London.osm from timestamp 0 to 150 (calculated from reaching the starting station of the given scenario) and after that time interval, it will switch to the second mission [ "Oasis Academy", "London Waterloo" ]
Run the build script from the project folder:
bash build.sh
Run the app:
./virtual-fleet-management -config <config.json>
- host - address of the server where the virtual fleet will be running
- api-key - API key for the Fleet Management HTTP API
- scenario-dir - path to the directory with scenarios.
<scenario_dir>/<car_name>/scenario.json
- common approach is to name the scenario directory as company
- inside the
scenario-dir
, there can be directories for multiple cars, all of them can be played at same time.
- log-path - path to the log directory
- loop - optional argument, if set to
true
the scenarios will be looped infinitely. Iffalse
each scenario will be played only once.
Arguments
api-key
andscenario-dir
can be overridden by the command line arguments.
Build the image using:
docker build --tag bringauto/virtual-fleet-management .
Run the image using:
docker run -ti --rm -v <local/path/to/config>:<config_path> bringauto/virtual-fleet-management -config=<config_path>