Johan ARCILE

Depot initial.

Showing 20 changed files with 14916 additions and 0 deletions
File mode changed
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 128
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=103
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=290
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= -1
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 1
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {4,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 128
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 128
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=290
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=290
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= -1
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= -1
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {0,0,0}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {9,9,9}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 116
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 128
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=103
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=290
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=280
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= -2
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 1
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {true,false,false}; // says if receptor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=300
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=300
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {true,false,false}; // says if receptor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 100; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=300
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=300
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=150
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,true,false}; // says if receptor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 129
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=286
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=15
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,true,false}; // says if receptor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 100; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 129
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=280
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=280
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=504
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=40
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=135
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,false,false}; // says if receptor is disabeled for each vehicle with a boolean
const bool disabeled_emetor[nb_car] := {true,false,false}; // says if emetor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 135
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 135
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=206
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=206
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,false,false}; // says if receptor is disabeled for each vehicle with a boolean
const bool disabeled_emetor[nb_car] := {true,false,false}; // says if emetor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 100; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 135
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 135
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=280
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=280
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=206
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=206
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,false,false}; // says if receptor is disabeled for each vehicle with a boolean
const bool disabeled_emetor[nb_car] := {false,true,false}; // says if emetor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 127
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 126
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 128
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=208
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=300
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
const bool disabeled_receptor[nb_car] := {false,false,false}; // says if receptor is disabeled for each vehicle with a boolean
const bool disabeled_emetor[nb_car] := {false,true,false}; // says if emetor is disabeled for each vehicle with a boolean
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 160; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
else{
return y_to_lane(car[n].posY);
}
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
else return 0;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(!disabeled_receptor[n] and !disabeled_emetor[id]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 131
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=150
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=222
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=222
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=440
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=440
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second, must have S has GCD
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
bool nego[nb_car-1]; // signal to other vehicles a negociation intent (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
bool nego[nb_car-1]; // keeps who ask negociation
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
if(car[id].nego[n-1]) data[n].nego[id] := true;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
if(car[id].nego[n]) data[n].nego[id-1] := true;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Checking negociations
car[id].delay := temp_del;
for(n : int[0,nb_car-1]){
if(prio[n]==false and ((id&gt;n and data[id].nego[n]) or (id&lt;n and data[id].nego[n-1]))){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, max_acceleration, read_goal(id,n), 0);
prio[n] := true;
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del ++;
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
if(id&lt;n) data[id].nego[n-1] := false;
if(id&gt;n) data[id].nego[n] := false;
temp_del := car[id].delay;
}
prio[n] := false;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
// Negociation request
// computing whished trajectory
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, max_acceleration, car[id].goal, 0);
// negotiate if there is a priority vehicle changing lane on an adjacent one and its intention is in conflict with wished trajectory
for(n : int[0,nb_car-1]){
if(prio[n] and possible_collision(long[id], lat[id], long[n], lat[n]) and y_to_lane(car[id].posY) != y_to_lane(car[n].posY)){
if(id&lt;n) car[id].nego[n-1] := true;
if(id&gt;n) car[id].nego[n] := true;
}
}
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>A[] true
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>car[2].posX == LengthX and car[2].posX &gt; car[0].posX --&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 159
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=0
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=156
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=114
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -5
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
clock x_Ter; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second, must be greater than S
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {7,3,0}; // initial controller clock value for each vehicle in 1/scale seconds
// Terminal
const int ter_freq := 50; // activation sample of the terminal in 1/scale second, must be greater than S
const int max_com_ter := 10; // max communication delay for terminal in 1/scale second, must be smaller than ter_freq
const int min_com_ter := 5; // min communication delay for terminal in 1/scale second, must be smaller or equals to max_com_ter
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
typedef int[0,(LengthDelay*scale)/S] RangeSub; // delay range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
RangeA ordered_acc; // keeps ordered acceleration
RangeDelay ordered_delay; // keeps ordered delay
RangeSub submission_time; // count how long should follow orders
}data[nb_car];
//Data structure for the terminal
RangeLane ter_goal[nb_car]; // keeps vehicles' goal
RangeDelay ter_delay[nb_car]; // keeps vehicles' delay
bool to_order[nb_car]; // id of vehicles to send orders
RangeA temp_ordered_acc[nb_car]; // keeps acceleration to order
RangeDelay temp_ordered_delay[nb_car]; // keeps delay to order
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
// Send goal and data value to terminal
ter_goal[id] := car[id].goal;
ter_delay[id] := car[id].delay;
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Applying orders from terminal
if(data[id].submission_time &gt; 0){
data[id].submission_time --;
temp_acc := data[id].ordered_acc;
temp_del := (data[id].submission_time*S)/scale;
if(temp_del*2 &lt; (data[id].submission_time*S*2)/scale) temp_del++;
if(data[id].submission_time == 0) data[id].ordered_acc := 0;
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
void ter_computation(){
// Vehicles current trajectory
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
// Keeps vehicle's actual trajectory when computing whished one
RangeX temp_long[traj_range];
RangeY temp_lat[traj_range];
// Computation buffers
bool prio[nb_car];
RangeDelay temp_del;
RangeA temp_acc;
// Computing vehicles' current trajectory or possible trajectory if they have been ordered previously
for(n : int[0,nb_car-1]){
if(to_order[n]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, max_acceleration, ter_goal[n], 0);
to_order[n] := false;
}
else compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, ter_goal[n], ter_delay[n]);
}
// Searching problems that could be avoided
for(id : int[0,nb_car-1]){
// Keep actual trajectory
temp_long := long[id];
temp_lat := lat[id];
// Computing whished trajectory
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, max_acceleration, ter_goal[id], 0);
// Detect if there is a priority vehicle changing lane on an adjacent one and its intention is in conflict with wished trajectory
for(n : int[0,nb_car-1]){
if(car[n].on_the_road and (car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) and possible_collision(long[id], lat[id], long[n], lat[n]) and y_to_lane(car[id].posY) != y_to_lane(car[n].posY)){
// Computing modified priority list for vehicle n
for(m : int[0,nb_car-1]){
if(car[m].on_the_road){
if(car[n].posX &lt; car[m].posX or (car[n].posX == car[m].posX and car[n].posY &lt; car[m].posY) or m == id) prio[m] := true;
else prio[m] := false;
}
else prio[m] := false;
}
//Checking alternative trajectories (delay++ in acc--)
temp_acc := car[n].acceleration;
temp_del := ter_delay[n];
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_del &lt; LengthDelay) temp_del++;
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_acc + max_acceleration &gt; car[id].acceleration + car[n].acceleration and temp_acc &gt; min_acceleration){ // better overall acceleration
if(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del)){
temp_del := 0;
temp_acc--;
}
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(!wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del)){
to_order[n] := true;
temp_ordered_acc[n] := temp_acc;
temp_ordered_delay[n] := temp_del;
}
}
}
}
}
void give_orders(){
for(n : int[0,nb_car-1]){
if(to_order[n]){
data[n].ordered_acc := temp_ordered_acc[n];
data[n].submission_time := (temp_ordered_delay[n]*scale)/S;
}
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name>Terminal</name>
<location id="id0" x="-1411" y="-1657">
<name x="-1436" y="-1691">s1</name>
<label kind="invariant" x="-1453" y="-1640">x_Ter&lt;= max_com_ter</label>
</location>
<location id="id1" x="-1691" y="-1657">
<name x="-1717" y="-1691">s0</name>
<label kind="invariant" x="-1734" y="-1640">x_Ter &lt;= ter_freq</label>
</location>
<init ref="id1"/>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="guard" x="-1615" y="-1674">x_Ter&gt;= min_com_ter</label>
<label kind="assignment" x="-1598" y="-1657">give_orders()</label>
</transition>
<transition>
<source ref="id1"/>
<target ref="id0"/>
<label kind="guard" x="-1598" y="-1742">x_Ter&gt;=ter_freq</label>
<label kind="synchronisation" x="-1564" y="-1708">k?</label>
<label kind="assignment" x="-1632" y="-1725">x_Ter=0, ter_computation()</label>
<nail x="-1691" y="-1725"/>
<nail x="-1411" y="-1725"/>
</transition>
</template>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id2" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id3" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id2"/>
<target ref="id3"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id4" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id5" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id6" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id4"/>
<transition>
<source ref="id4"/>
<target ref="id6"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id5"/>
<target ref="id6"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id5"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id7" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id8" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id9" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id7"/>
<transition>
<source ref="id7"/>
<target ref="id9"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id8"/>
<target ref="id9"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id8"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id10" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id11" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id12" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id10"/>
<transition>
<source ref="id10"/>
<target ref="id12"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id11"/>
<target ref="id12"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id12"/>
<target ref="id11"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
Ter = Terminal();
system Environment, VehicleA, VehicleB, VehicleC, Ter;
</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 133
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 138
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 138
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=140
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -5
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -2
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 2
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 2
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 146
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 146
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=90
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=90
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 20; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second, must have S has GCD
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {7,3,0}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
bool nego[nb_car-1]; // signal to other vehicles a negociation intent (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
bool nego[nb_car-1]; // keeps who ask negociation
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
if(car[id].nego[n-1]) data[n].nego[id] := true;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
if(car[id].nego[n]) data[n].nego[id-1] := true;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Checking negociations
car[id].delay := temp_del;
for(n : int[0,nb_car-1]){
if(prio[n]==false and ((id&gt;n and data[id].nego[n]) or (id&lt;n and data[id].nego[n-1]))){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, max_acceleration, read_goal(id,n), 0);
prio[n] := true;
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del ++;
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
if(id&lt;n) data[id].nego[n-1] := false;
if(id&gt;n) data[id].nego[n] := false;
temp_del := car[id].delay;
}
prio[n] := false;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
// Negociation request
// computing whished trajectory
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, max_acceleration, car[id].goal, 0);
// negotiate if there is a priority vehicle changing lane on an adjacent one and its intention is in conflict with wished trajectory
for(n : int[0,nb_car-1]){
if(prio[n] and possible_collision(long[id], lat[id], long[n], lat[n]) and y_to_lane(car[id].posY) != y_to_lane(car[n].posY)){
if(id&lt;n) car[id].nego[n-1] := true;
if(id&gt;n) car[id].nego[n] := true;
}
}
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>A[] true
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 130
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 136
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=70
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=114
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -5
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -2
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
clock x_Ter; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 200; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second, must be greater than S
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {0,3,7}; // initial controller clock value for each vehicle in 1/scale seconds
// Terminal
const int ter_freq := 50; // activation sample of the terminal in 1/scale second, must be greater than S
const int max_com_ter := 10; // max communication delay for terminal in 1/scale second, must be smaller than ter_freq
const int min_com_ter := 5; // min communication delay for terminal in 1/scale second, must be smaller or equals to max_com_ter
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
typedef int[0,(LengthDelay*scale)/S] RangeSub; // delay range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
RangeA ordered_acc; // keeps ordered acceleration
RangeDelay ordered_delay; // keeps ordered delay
RangeSub submission_time; // count how long should follow orders
}data[nb_car];
//Data structure for the terminal
RangeLane ter_goal[nb_car]; // keeps vehicles' goal
RangeDelay ter_delay[nb_car]; // keeps vehicles' delay
bool to_order[nb_car]; // id of vehicles to send orders
RangeA temp_ordered_acc[nb_car]; // keeps acceleration to order
RangeDelay temp_ordered_delay[nb_car]; // keeps delay to order
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
// Send goal and data value to terminal
ter_goal[id] := car[id].goal;
ter_delay[id] := car[id].delay;
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Applying orders from terminal
if(data[id].submission_time &gt; 0){
data[id].submission_time --;
temp_acc := data[id].ordered_acc;
temp_del := (data[id].submission_time*S)/scale;
if(temp_del*2 &lt; (data[id].submission_time*S*2)/scale) temp_del++;
if(data[id].submission_time == 0) data[id].ordered_acc := 0;
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
void ter_computation(){
// Vehicles current trajectory
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
// Keeps vehicle's actual trajectory when computing whished one
RangeX temp_long[traj_range];
RangeY temp_lat[traj_range];
// Computation buffers
bool prio[nb_car];
RangeDelay temp_del;
RangeA temp_acc;
// Computing vehicles' current trajectory or possible trajectory if they have been ordered previously
for(n : int[0,nb_car-1]){
if(to_order[n]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, max_acceleration, ter_goal[n], 0);
to_order[n] := false;
}
else compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, ter_goal[n], ter_delay[n]);
}
// Searching problems that could be avoided
for(id : int[0,nb_car-1]){
// Keep actual trajectory
temp_long := long[id];
temp_lat := lat[id];
// Computing whished trajectory
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, max_acceleration, ter_goal[id], 0);
// Detect if there is a priority vehicle changing lane on an adjacent one and its intention is in conflict with wished trajectory
for(n : int[0,nb_car-1]){
if(car[n].on_the_road and (car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) and possible_collision(long[id], lat[id], long[n], lat[n]) and y_to_lane(car[id].posY) != y_to_lane(car[n].posY)){
// Computing modified priority list for vehicle n
for(m : int[0,nb_car-1]){
if(car[m].on_the_road){
if(car[n].posX &lt; car[m].posX or (car[n].posX == car[m].posX and car[n].posY &lt; car[m].posY) or m == id) prio[m] := true;
else prio[m] := false;
}
else prio[m] := false;
}
//Checking alternative trajectories (delay++ in acc--)
temp_acc := car[n].acceleration;
temp_del := ter_delay[n];
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_del &lt; LengthDelay) temp_del++;
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_acc + max_acceleration &gt; car[id].acceleration + car[n].acceleration and temp_acc &gt; min_acceleration){ // better overall acceleration
if(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del)){
temp_del := 0;
temp_acc--;
}
while(wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(!wished_behaviour_not_safe(n,prio,long,lat,temp_acc,ter_goal[n],temp_del)){
to_order[n] := true;
temp_ordered_acc[n] := temp_acc;
temp_ordered_delay[n] := temp_del;
}
}
}
}
}
void give_orders(){
for(n : int[0,nb_car-1]){
if(to_order[n]){
data[n].ordered_acc := temp_ordered_acc[n];
data[n].submission_time := (temp_ordered_delay[n]*scale)/S;
}
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name>Terminal</name>
<location id="id0" x="-1411" y="-1657">
<name x="-1436" y="-1691">s1</name>
<label kind="invariant" x="-1453" y="-1640">x_Ter&lt;= max_com_ter</label>
</location>
<location id="id1" x="-1691" y="-1657">
<name x="-1717" y="-1691">s0</name>
<label kind="invariant" x="-1734" y="-1640">x_Ter &lt;= ter_freq</label>
</location>
<init ref="id1"/>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="guard" x="-1615" y="-1674">x_Ter&gt;= min_com_ter</label>
<label kind="assignment" x="-1598" y="-1657">give_orders()</label>
</transition>
<transition>
<source ref="id1"/>
<target ref="id0"/>
<label kind="guard" x="-1598" y="-1742">x_Ter&gt;=ter_freq</label>
<label kind="synchronisation" x="-1564" y="-1708">k?</label>
<label kind="assignment" x="-1632" y="-1725">x_Ter=0, ter_computation()</label>
<nail x="-1691" y="-1725"/>
<nail x="-1411" y="-1725"/>
</transition>
</template>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id2" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id3" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id3"/>
<target ref="id3"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id2"/>
<target ref="id3"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id4" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id5" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id6" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id4"/>
<transition>
<source ref="id4"/>
<target ref="id6"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id5"/>
<target ref="id6"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id5"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id7" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id8" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id9" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id7"/>
<transition>
<source ref="id7"/>
<target ref="id9"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id8"/>
<target ref="id9"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id8"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id10" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id11" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id12" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id10"/>
<transition>
<source ref="id10"/>
<target ref="id12"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id11"/>
<target ref="id12"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id12"/>
<target ref="id11"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
Ter = Terminal();
system Environment, VehicleA, VehicleB, VehicleC, Ter;
</system>
<queries>
<query>
<formula>A[] true
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 134
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 138
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 138
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=138
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=142
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -5
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 2
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 2
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Scale
const int scale = 100;
// System parameters (define size of the data structure)
const int S := 10; // sample period, in 1/scale seconds
const int L := 50000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Constants and data structure obtained from system parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
// Environment constraints
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marking[nb_lane+1] := {0,(350*scale)/GranY,(700*scale)/GranY,LengthY}; // lateral position of markings separating lanes (junction is lane 0)
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
const int nb_car := 3; // number of vehicles (&gt;= 2)
typedef int[0,nb_car-1] RangeId; // ids range
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {0,3000,4000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,875,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {3000,1500,2000}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {7,3,0}; // initial controller clock value for each vehicle in 1/scale seconds
// Control related information
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Querries memory
int[0,20*scale/S] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (controller)
RangeD direction; // lateral speed (controller)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (controller)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (controller)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
//Begining of editable module related functions
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
//End of editable module related functions
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//Begining of editable module related variables
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
//End of editable module related variables
if(car[id].on_the_road){
//Begining of editable module
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying controller's choices
car[id].goal := temp_goal;
car[id].delay := temp_del;
//End of editable module
//Applying controller's choices
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
//This part concerns querries
bool querry_collision(){
// Evaluate if two vehicle collide.
// A vehicle's position is the center of a rectangle that represents the vehicle with given length and width
// Therefore, by checking if an other vehicle position is present in a space that has twice those mesurments, we can evaluate collision between two vehicles.
for(n : int[0,nb_car-1]){
for(m : int[0,nb_car-1]){
if(n!=m and car[n].on_the_road and car[m].on_the_road){
if(car[n].posX &lt; car[m].posX + C_len and car[n].posX &gt; car[m].posX - C_len){
if(car[n].posY &lt; car[m].posY + C_wid and car[n].posY &gt; car[m].posY - C_wid) return true;
}
}
}
}
return false;
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
system Environment, VehicleA, VehicleB, VehicleC;</system>
<queries>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].posX == LengthX and car[0].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[0].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].posX == LengthX and car[1].posX &gt; car[2].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].posX == LengthX and car[2].posX &gt; car[1].posX
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 146
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and nb_updates+1 &gt;= 146
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and nb_updates+1 &gt;= 144
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and nb_updates+1 &gt;= 132
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=95
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[1].on_the_road and time_to_collision(0,1) &lt;=95
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[2].on_the_road and time_to_collision(0,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[2].on_the_road and time_to_collision(1,2) &lt;=10000
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -2
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[0].on_the_road and car[0].acceleration &lt;= -2
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[1].on_the_road and car[1].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>E&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
<query>
<formula>A&lt;&gt; car[2].on_the_road and car[2].acceleration &lt;= 3
</formula>
<comment>
</comment>
</query>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>
// Scale
const int scale = 100;
// Abstraction parameters (defines level of abstraction)
const int S := 10; // sample period, in 1/scale seconds
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Road parameters
const int L := 60000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marks[nb_lane+1] := {0,350,700,R}; // lateral position of markings separating lanes in 1/scale meters
// Vehicles parameters (to change the number of vehicle in the system, change nb_car value, adjust the size of the sets bellow, set the appropriate number of automaton in system definition and add the needed transitions to A0)
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int nb_car := 3; // number of vehicles (&gt;= 2)
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {1,4,8}; // initial controller clock value for each vehicle in 1/scale seconds
//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
clock C4; // in 1/scale seconds
clock C5; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Constants and data types obtained from parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int marking[nb_lane+1] := {(marks[0]*scale)/GranY,(marks[1]*scale)/GranY,(marks[2]*scale)/GranY,(marks[3]*scale)/GranY}; // normalized lateral position of markings separating lanes
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
typedef int[0,nb_car-1] RangeId; // ids range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Decision related parameters
const int navigation_points := 2; // number of coordinate on a navigation list
const int navigation_list[nb_car][navigation_points][3] := {
{{0,0,2},{LengthX,1,1}},
{{0,0,2},{LengthX,1,1}},
{{J_end,1,2},{LengthX,1,1}}
}; // GPS trajectory for each vehicle in list of {posX,lane(min),lane(max)}, each car MUST have a complete trajectory that goes up to horizon value
const int safety_length := 200; // longitudinal safety distance of a vehicle in 1/scale meters
const int safety_width := 50; // lateral safety distance of a vehicle in 1/scale meters
const int traj_length := 1000; // length of the predicted trajectory in 1/scale seconds
const int delay_step := 100; // delay step in 1/scale seconds
const int max_delay := 500; // maximum delay in 1/scale seconds
// Constants and data types obtained from decision related parameters
const int S_len := (safety_length*scale)/GranX; // normalized safety length of a vehicle
const int S_wid := (safety_width*scale)/GranY; // normalized safety width of a vehicle
const int traj_range := traj_length/S; // range of the predicted trajectory (number of points)
const int LengthDelay := max_delay/delay_step;
typedef int[0,LengthDelay] RangeDelay; // delay range
// Querries memory
int[0,L/(S*min_speed)] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (vehicle)
RangeD direction; // lateral speed (vehicle)
RangeLane goal; // signal to other vehicles the lane this vehicle is trying to reach (vehicle)
RangeDelay delay; // signal to other vehicles how long the vehicle is waiting before applying its intention (vehicle)
}car[nb_car];
struct{
RangeLane goal[nb_car-1]; // keeps other vehicles' goal
RangeDelay delay[nb_car-1]; // keeps other vehicles' delay
}data[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
void communicate(RangeId id){
// Send goal and data value to other vehicles
for(n : int[0,nb_car-1]){
if(id&lt;n){
data[n].goal[id] := car[id].goal;
data[n].delay[id] := car[id].delay;
}
if(id&gt;n){
data[n].goal[id-1] := car[id].goal;
data[n].delay[id-1] := car[id].delay;
}
}
}
// Give the goal value that id knows about n
RangeLane read_goal(RangeId id, RangeId n){
if(id&gt;n) return data[id].goal[n];
if(id&lt;n) return data[id].goal[n-1];
return car[id].goal;
}
// Give the delay value that id knows about n
RangeDelay read_delay(RangeId id, RangeId n){
if(id&gt;n) return data[id].delay[n];
if(id&lt;n) return data[id].delay[n-1];
return car[id].delay;
}
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
// Put the new value of the flag in regard to GPS trajectory
RangeLane navigation(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(navigation_list[id][i][1] &gt; y_to_lane(car[id].posY)) return navigation_list[id][i][1];
if(navigation_list[id][i][2] &lt; y_to_lane(car[id].posY)) return navigation_list[id][i][2];
return y_to_lane(car[id].posY);
}
}
return y_to_lane(car[id].posY);
}
// Tells if vehicle can change lane in regard to GPS trajectory
bool far_point(RangeId id){
for(i : int[0,navigation_points-1]){
if(navigation_list[id][i][0]&gt;car[id].posX){
if(((navigation_list[id][i][0]-car[id].posX)*GranX)/(car[id].speed*GranV)&lt;4) return false;
}
}
return true;
}
// Computes a predicted trajectory based on parameters
void compute_traj(RangeX&amp; traj_X[traj_range], RangeY&amp; traj_Y[traj_range], RangeX posX, RangeY posY, RangeV speed, RangeA acceleration, RangeLane goal, RangeDelay d){
int[-S,max_delay] delay := d*delay_step; //conversion of the delay in 1/scale seconds unit
RangeD direction; //virtual direction
// At each sample, choose a direction, mimic an update of the environment, then store the position in the trajectory data structure
for(i: int[0,traj_range-1]){
//Choosing virtual direction
direction := 0;
if(y_to_lane(posY) &lt; goal) direction := 1;
if(y_to_lane(posY) &gt; goal) direction := -1;
if(direction == 0){
if(posY &lt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := 1;
if(posY &gt; (marking[y_to_lane(posY)]+marking[y_to_lane(posY)+1])/2) direction := -1;
}
//update longitudinal position
if((((2*speed)+acceleration)/p)*2 &lt; (((2*speed)+acceleration)*2)/p and posX &lt; LengthX) posX++; // upper rounded when rest is &gt; 0.5
if(posX + (((2*speed)+acceleration)/p) &gt;= LengthX) posX := LengthX;
else posX += ((2*speed)+acceleration)/p;
//update speed
if(speed + acceleration &gt; max_speed) speed := max_speed;
else if(speed + acceleration &lt; min_speed) speed := min_speed;
else speed += acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(delay &gt; 0) delay -= S;
else{
if(direction == -1 and posY &gt; 1) posY--;
if(direction == 1 and posY &lt; LengthY) posY++;
}
//Storing data
if(posX &lt; LengthX){
traj_X[i] := posX;
traj_Y[i] := posY;
}
else traj_X[i] := 0;
}
}
// Check if there is a possible collision beetween two trajectories
bool possible_collision(RangeX&amp; traj_X1[traj_range], RangeY&amp; traj_Y1[traj_range], RangeX&amp; traj_X2[traj_range], RangeY&amp; traj_Y2[traj_range]){
// For each point in trajectory one, check if the point of trajectory two with the same timed indicator is in the neighborhood
for(i : int[0,traj_range-1]){
if(traj_X1[i] != 0 and traj_X2[i] != 0){ // do not check if no value
if(traj_X1[i] &lt; traj_X2[i] + C_len + S_len and traj_X1[i] &gt; traj_X2[i] - C_len - S_len){
if(traj_Y1[i] &lt; traj_Y2[i] + C_wid + S_wid and traj_Y1[i] &gt; traj_Y2[i] - C_wid - S_wid) return true;
}
}
}
return false;
}
// Check wished trajectory against prioritary vehicles wished trajectory
bool wished_behaviour_not_safe(RangeId id, bool prio[nb_car], RangeX long[nb_car][traj_range], RangeY lat[nb_car][traj_range], RangeA acceleration, RangeLane goal, RangeDelay delay){
compute_traj(long[id], lat[id], car[id].posX, car[id].posY, car[id].speed, acceleration, goal, delay);
for(n : int[0,nb_car-1]){
if(id != n and prio[n] and possible_collision(long[id], lat[id], long[n], lat[n])) return true;
}
// check obstacles
for(i : int[0,traj_range-1]){
if(long[id][i] &gt; J_end and lat[id][i] &lt; J_sup) return true; // junction lane after end of zone
if(long[id][i] &lt; J_beg and lat[id][i] &lt; J_sup and lat[id][i] &gt; J_inf) return true; // beetween junction lane and highway out of the junction zone
}
return false;
}
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
bool prio[nb_car]; // list of prioritary vehicles
RangeX long[nb_car][traj_range];
RangeY lat[nb_car][traj_range];
RangeDelay temp_del;
RangeLane temp_goal;
if(car[id].on_the_road){
// Choosing best possible choices in regard of GPS indication
car[id].goal := navigation(id);
temp_acc := max_acceleration;
temp_del := 0;
temp_goal := car[id].goal;
// Computing the list of other vehicles that have priority
for(n : int[0,nb_car-1]){
if(car[n].on_the_road){
if(car[id].posX &lt; car[n].posX or (car[id].posX == car[n].posX and car[id].posY &lt; car[n].posY)) prio[n] := true;
else prio[n] := false;
}
else prio[n] := false;
}
// Computing other vehicles' trajectory
for(n : int[0,nb_car-1]){
compute_traj(long[n], lat[n], car[n].posX, car[n].posY, car[n].speed, car[n].acceleration, read_goal(id,n), read_delay(id,n));
}
// Finding a suitable behaviour closest to the original intention and respecting prioritary vehicles intention
// variation speed
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_acc &gt; min_acceleration){
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay and far_point(id)) temp_del++;
//overtaking obstacle (left)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal + 1 &lt;= nb_lane-1 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal + 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
//overtaking obstacle (right)
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and car[id].goal - 1 &gt;= 0 and far_point(id)){
temp_del := 0;
temp_goal := car[id].goal - 1;
// checking if possible with delay
while(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del) and temp_del &lt; LengthDelay) temp_del++;
}
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_del := 0;
temp_acc--;
temp_goal := car[id].goal;
}
}
// Urgent behaviour
if(wished_behaviour_not_safe(id,prio,long,lat,temp_acc,temp_goal,temp_del)){
temp_goal := y_to_lane(car[id].posY);
temp_del := 0;
}
// Computing new direction
if(temp_del == 0){
if(y_to_lane(car[id].posY) &lt; temp_goal) temp_dir := 1;
if(y_to_lane(car[id].posY) &gt; temp_goal) temp_dir := -1;
if(temp_dir == 0){
if(car[id].posY &lt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := 1;
if(car[id].posY &gt; (marking[y_to_lane(car[id].posY)]+marking[y_to_lane(car[id].posY)+1])/2) temp_dir := -1;
}
}
//Applying decision
car[id].goal := temp_goal;
car[id].delay := temp_del;
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A4</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id11" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id12" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C4&lt;=max_com_delay[id]</label>
</location>
<location id="id13" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C4&lt;=freq[id]</label>
</location>
<init ref="id11"/>
<transition>
<source ref="id11"/>
<target ref="id13"/>
<label kind="assignment" x="-263" y="-85">C4=init_clock[id]</label>
</transition>
<transition>
<source ref="id12"/>
<target ref="id13"/>
<label kind="guard" x="-42" y="-102">C4&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id13"/>
<target ref="id12"/>
<label kind="guard" x="-25" y="-178">C4&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C4=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A5</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id14" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id15" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C5&lt;=max_com_delay[id]</label>
</location>
<location id="id16" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C5&lt;=freq[id]</label>
</location>
<init ref="id14"/>
<transition>
<source ref="id14"/>
<target ref="id16"/>
<label kind="assignment" x="-263" y="-85">C5=init_clock[id]</label>
</transition>
<transition>
<source ref="id15"/>
<target ref="id16"/>
<label kind="guard" x="-42" y="-102">C5&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id16"/>
<target ref="id15"/>
<label kind="guard" x="-17" y="-178">C5&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C5=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
VehicleD = A4(3);
VehicleE = A5(4);
system Environment, VehicleA, VehicleB, VehicleC;
</system>
<queries>
</queries>
</nta>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
<declaration>//INSTRUCTION : Change the values of the parameters bellow
// Scale
const int scale = 100;
// Abstraction parameters (defines level of abstraction)
const int S := 10; // sample period, in 1/scale seconds
const int GranA := 100; // granularity of the acceleration expressed in 1/scale meters per second squared
const int NormX := 100; // maximal loss of precision during a second in 1/scale meters (&gt;= (GranA*S/scale)/2)
// Road parameters
const int L := 60000; // length of the road segment, in 1/scale meters
const int R := 1050; // width of the road segment, in 1/scale meters
const int length_vehicle := 500; // length of a vehicle in 1/scale meters
const int width_vehicle := 200; // width of a vehicle in 1/scale meters
const int begin_junction := 20000; // begining of junction lane in 1/scale meters
const int end_junction := 40000; // end of junction lane in 1/scale meters
const int nb_lane := 3; // number of lanes, including junction (&gt;= 2)
const int marks[nb_lane+1] := {0,350,700,R}; // lateral position of markings separating lanes in 1/scale meters
// Vehicles parameters (to change the number of vehicle in the system, change nb_car value, adjust the size of the sets bellow, set the appropriate number of automaton in system definition and add the needed transitions to A0)
const int V_min := 1000; // min value of longitudinal speed, in 1/scale meters per second
const int V_max := 4000; // max value of longitudinal speed, in 1/scale meters per second
const int A_min := -500; // min value of longitudinal acceleration, in 1/scale meters per second squared
const int A_max := 300; // max value of longitudinal acceleration, in 1/scale meters per second squared
const int W := 100; // maximal absolute value of the lateral speed expressed in 1/scale meters per second
const int nb_car := 3; // number of vehicles (&gt;= 2)
const int freq[nb_car] := {10,10,10}; // activation sample of the controler for each vehicle in 1/scale second
const int min_com_delay[nb_car] := {3,3,3}; // min communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int max_com_delay[nb_car] := {4,4,4}; // max communication delay for each vehicle in 1/scale second, must be smaller than the vehicle's controller sample
const int init_posX[nb_car] := {5000,0,2000}; // initial longitudinal position for each vehicle in 1/scale meters
const int init_posY[nb_car] := {525,525,175}; // initial lateral position for each vehicle in 1/scale meters
const int init_V[nb_car] := {2000,3500,2820}; // initial longitudinal speed for each vehicle in 1/scale meters per second
const int init_A[nb_car] := {3,3,3}; // initial longitudinal acceleration for each vehicle in 1/scale meters per second squared
const int init_clock[nb_car] := {1,4,8}; // initial controller clock value for each vehicle in 1/scale seconds
//Global clocks
clock C1; // in 1/scale seconds
clock C2; // in 1/scale seconds
clock C3; // in 1/scale seconds
clock C4; // in 1/scale seconds
clock C5; // in 1/scale seconds
//Synchronisation channel
broadcast chan k;
// Constants and data types obtained from parameters
const int GranV := GranA*S; // granularity of the longitudinal speed expressed in 1/scale/scale meters per second
const int GranX := NormX*S; // granularity of the longitudinal position expressed in 1/scale/scale meters
const int GranY := W*S; // granularity of the lateral position expressed in 1/scale/scale meters
const int p := 2*NormX*scale/GranV; // used for posX update
const int LengthX := (L*scale)/GranX; // normalized length of the road segment
const int LengthY := (R*scale)/GranY; // normalized width of the road segment
const int min_speed := (V_min*scale)/GranV; // normalized min value of longitudinal speed
const int max_speed := (V_max*scale)/GranV; // normalized max value of longitudinal speed
const int min_acceleration := A_min/GranA; // normalized min value of longitudinal acceleration
const int max_acceleration := A_max/GranA; // normalized max value of longitudinal acceleration
const int C_len := (length_vehicle*scale)/GranX; // normalized length of a vehicle
const int C_wid := (width_vehicle*scale)/GranY; // normalized width of a vehicle
const int marking[nb_lane+1] := {(marks[0]*scale)/GranY,(marks[1]*scale)/GranY,(marks[2]*scale)/GranY,(marks[3]*scale)/GranY}; // normalized lateral position of markings separating lanes
const int J_beg := (begin_junction*scale)/GranX; // used for posX and posY update
const int J_end := (end_junction*scale)/GranX; // used for posX and posY update
const int J_inf := marking[1]-(C_wid/2); // used for posY update
const int J_sup := marking[1]+(C_wid/2); // used for posY update
typedef int[0,LengthX] RangeX; // longitudinal position range
typedef int[1,LengthY] RangeY; // lateral position range
typedef int[min_speed,max_speed] RangeV; // speed range
typedef int[min_acceleration,max_acceleration] RangeA; // acceleration range
typedef int[-1,1] RangeD; // direction range
typedef int[0,nb_car-1] RangeId; // ids range
typedef int[0,nb_lane-1] RangeLane; // lanes range
// Decision related parameters
//INSTRUCTION : Define here as constants any complementary parameters you need for your decision protocol
// Constants and data types obtained from decision related parameters
//INSTRUCTION : For each decision related variable and variable to be communicate, duplicate the following line and replace VAR with the variable and [min_rangeVAR,max_rangeVAR] by the range you need for this variable.
typedef int[min_rangeVAR,max_rangeVAR] RangeVAR;
// Querries memory
int[0,L/(S*min_speed)] nb_updates;
// Information structure for each vehicle, the parenthesis indicate wich automaton updates the variable
struct{
bool on_the_road; // tells if the vehicle is on or out of the road (environment)
RangeX posX; // longitudinal position of the car (environment)
RangeY posY; // lateral position of the car (environment)
RangeV speed; // longitudinal speed (environment)
RangeA acceleration; // longitudinal acceleration (vehicle)
RangeD direction; // lateral speed (vehicle)
//INSTRUCTION : For each decision related variable and variable to be communicate, duplicate the following line and replace VAR with the variable.
RangeVAR VAR;
}car[nb_car];
struct{
//INSTRUCTION : For each variables to be communicate, duplicate the following line and replace VAR with the variable.
RangeVAR VAR[nb_car-1];
}comm[nb_car];
void update(){
bool unempty := false;
for(id : int[0,nb_car-1]) if(car[id].on_the_road) unempty := true;
if(unempty) nb_updates++;
for(id : int[0,nb_car-1]){
//initialization (only occurs once)
if(car[id].on_the_road == false){
if(car[id].posX == 0){
car[id].on_the_road := true;
car[id].posX := (init_posX[id]*scale)/GranX;
car[id].posY := (init_posY[id]*scale)/GranY;
car[id].speed := (init_V[id]*scale)/GranV;
car[id].acceleration := (init_A[id]*scale)/GranA;
}
}
else{
//update longitudinal position
if((((2*car[id].speed)+car[id].acceleration)/p)*2 &lt; (((2*car[id].speed)+car[id].acceleration)*2)/p and car[id].posX &lt; LengthX) car[id].posX++; // upper rounded when rest is &gt; 0.5
if(car[id].posX + (((2*car[id].speed)+car[id].acceleration)/p) &gt;= LengthX){
car[id].posX := LengthX;
car[id].on_the_road := false;
}
else car[id].posX += ((2*car[id].speed)+car[id].acceleration)/p;
if(car[id].posX &gt; J_end and car[id].posY &lt; J_sup) car[id].on_the_road := false; // car is out of the road if did not change lane before the end of junction lane
//update speed
if(car[id].speed + car[id].acceleration &gt; max_speed) car[id].speed := max_speed;
else if(car[id].speed + car[id].acceleration &lt; min_speed) car[id].speed := min_speed;
else car[id].speed += car[id].acceleration; // adjust speed regarding the variation choosen by the controler
//update lateral position
if(car[id].direction == -1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to go on junction lane before the junction starts
if(car[id].posY &gt; 1) car[id].posY--;
}
}
if(car[id].direction == 1 and car[id].on_the_road){
if((car[id].posX &lt;= J_end and car[id].posX &gt;= J_beg) or car[id].posY &gt;= J_sup or car[id].posY &lt;= J_inf){ // forbiding to get out of junction lane before the junction starts
if(car[id].posY &lt; LengthY) car[id].posY++;
}
}
if(car[id].posX &lt; J_beg and car[id].posY &lt; J_sup and car[id].posY &gt; J_inf) car[id].on_the_road := false; // car is out of the road if beetween junction lane and highway out of the junction zone
}
}
}
// Send comm variables value to other vehicles
void communicate(RangeId id){
for(n : int[0,nb_car-1]){
if(id&lt;n){
//INSTRUCTION : For each comm variable, duplicate the following line and replace VAR with the variable.
comm[n].VAR[id] := car[id].VAR;
}
if(id&gt;n){
//INSTRUCTION : For each comm variable, duplicate the following line and replace VAR with the variable.
comm[n].VAR[id-1] := car[id].VAR;
}
}
}
//INSTRUCTION : For each comm variable, duplicate the following function and replace VAR with the variable.
// Give the VAR value that id knows about n
RangeLane read_VAR(RangeId id, RangeId n){
if(id&gt;n) return comm[id].VAR[n];
if(id&lt;n) return comm[id].VAR[n-1];
return car[id].VAR;
}
// Tells which lane matches with a given lateral position
RangeLane y_to_lane(RangeY y){
for(i : int[1,nb_lane]){
if(y&lt;=marking[i]) return i-1;
}
return nb_lane-1; // for compilation needs
}
//INSTRUCTION : Define here all the subfunctions to be used in decision main function. Must not modifiy any variable in the data sctruture.
void decision(RangeId id){
RangeD temp_dir;
RangeA temp_acc;
//INSTRUCTION : Define here variables to be used in decision main function.
if(car[id].on_the_road){
//INSTRUCTION : Define here decision main function. Must not modifiy any variable in the data sctruture.
//Applying decision
//INSTRUCTION : Define here new values for decision related variables in car[id].
car[id].direction := temp_dir;
car[id].acceleration := temp_acc;
}
}
// Time to collision between two vehicles in 1/scale seconds, dont go above 100s
int time_to_collision(RangeId id1, RangeId id2){
// set buffers
int px_a, px_b, vx_a, vx_b, py_a, py_b, vy_a, vy_b, X_in, X_out, Y_in, Y_out;
if(car[id1].posX &gt; car[id2].posX){
px_a := car[id2].posX;
px_b := car[id1].posX;
vx_a := car[id2].speed;
vx_b := car[id1].speed;
}
else{
px_a := car[id1].posX;
px_b := car[id2].posX;
vx_a := car[id1].speed;
vx_b := car[id2].speed;
}
if(car[id1].posY &gt; car[id2].posY){
py_a := car[id2].posY;
py_b := car[id1].posY;
vy_a := car[id2].direction;
vy_b := car[id1].direction;
}
else{
py_a := car[id1].posY;
py_b := car[id2].posY;
vy_a := car[id1].direction;
vy_b := car[id2].direction;
}
// compute X_in and X_out
if(vx_a &gt; vx_b){
// X_in if faster A
if(((px_b-px_a-C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_in := ((px_b-px_a-C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_in := 100*scale;
// X_out if faster A
if(((px_b-px_a+C_len)*GranX)/((vx_a-vx_b)*GranV) &lt; 100) X_out := ((px_b-px_a+C_len)*GranX*scale)/((vx_a-vx_b)*GranV);
else X_out := 100*scale;
}
else{
// X_in if faster B or equal speed
if(px_b-px_a-C_len &gt; 0) X_in := 100*scale;
else X_in := 0;
// X_out if faster B
if(vx_a &lt; vx_b){
if(((px_b-px_a-C_len)*GranX)/((vx_b-vx_a)*GranV) &lt; 100) X_out := ((px_b-px_a-C_len)*GranX*scale)/((vx_b-vx_a)*GranV);
else X_out := 100*scale;
}
// X_out if equal speed
else{
if(px_b-px_a-C_len &gt; 0) X_out := 0;
else X_out := 100*scale;
}
}
// compute Y_in and Y_out
if(vy_a &gt; vy_b){
// Y_in if faster A
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_in := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_in := 100*scale;
// Y_out if faster A
if(((py_b-py_a+C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a+C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
else{
// Y_in if faster B or equal speed
if(py_b-py_a-C_wid &gt; 0) Y_in := 100*scale;
else Y_in := 0;
// Y_out if faster B
if(vy_a &lt; vy_b){
if(((py_b-py_a-C_wid)*S)/((vy_a-vy_b)*scale) &lt; 100) Y_out := ((py_b-py_a-C_wid)*S)/(vy_a-vy_b);
else Y_out := 100*scale;
}
// Y_out if equal speed
else{
if(py_b-py_a-C_wid &gt; 0) Y_out := 0;
else Y_out := 100*scale;
}
}
// compute TTC
if(X_in &lt;= Y_in and Y_in &lt;= X_out) return Y_in;
if(Y_in &lt;= X_in and X_in &lt;= Y_out) return X_in;
return 100*scale;
}</declaration>
<template>
<name x="5" y="5">A0</name>
<declaration>clock C0; // in 1/scale seconds</declaration>
<location id="id0" x="-161" y="0">
<name x="-178" y="-34">I</name>
<urgent/>
</location>
<location id="id1" x="-17" y="0">
<name x="-42" y="-34">s0</name>
<label kind="invariant" x="-34" y="17">C0&lt;=S</label>
</location>
<init ref="id0"/>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-229" y="-204">C0&lt;S and C1&lt;freq[0] and C2&lt;freq[1] and C3&gt;=freq[2]</label>
<label kind="synchronisation" x="-25" y="-187">k!</label>
<nail x="-348" y="-187"/>
<nail x="280" y="-187"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-170" y="-161">C0&lt;S and C1&lt;freq[0] and C2&gt;=freq[1]</label>
<label kind="synchronisation" x="-25" y="-144">k!</label>
<nail x="-272" y="-144"/>
<nail x="212" y="-144"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-110" y="-119">C0&lt;S and C1&gt;=freq[0]</label>
<label kind="synchronisation" x="-25" y="-102">k!</label>
<nail x="-195" y="-102"/>
<nail x="144" y="-102"/>
</transition>
<transition>
<source ref="id1"/>
<target ref="id1"/>
<label kind="guard" x="-42" y="-76">C0&gt;=S</label>
<label kind="synchronisation" x="34" y="-59">k!</label>
<label kind="assignment" x="-76" y="-59">C0=0,update()</label>
<nail x="-119" y="-59"/>
<nail x="76" y="-59"/>
</transition>
<transition>
<source ref="id0"/>
<target ref="id1"/>
<label kind="assignment" x="-119" y="0">update()</label>
</transition>
</template>
<template>
<name>A1</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id2" x="-289" y="-85">
<name x="-306" y="-119">I</name>
<urgent/>
</location>
<location id="id3" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C1&lt;=max_com_delay[id]</label>
</location>
<location id="id4" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C1&lt;=freq[id]</label>
</location>
<init ref="id2"/>
<transition>
<source ref="id2"/>
<target ref="id4"/>
<label kind="assignment" x="-263" y="-85">C1=init_clock[id]</label>
</transition>
<transition>
<source ref="id3"/>
<target ref="id4"/>
<label kind="guard" x="-42" y="-102">C1&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id4"/>
<target ref="id3"/>
<label kind="guard" x="-25" y="-178">C1&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C1=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A2</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id5" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id6" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C2&lt;=max_com_delay[id]</label>
</location>
<location id="id7" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C2&lt;=freq[id]</label>
</location>
<init ref="id5"/>
<transition>
<source ref="id5"/>
<target ref="id7"/>
<label kind="assignment" x="-263" y="-85">C2=init_clock[id]</label>
</transition>
<transition>
<source ref="id6"/>
<target ref="id7"/>
<label kind="guard" x="-42" y="-102">C2&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id7"/>
<target ref="id6"/>
<label kind="guard" x="-25" y="-178">C2&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C2=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A3</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id8" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id9" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C3&lt;=max_com_delay[id]</label>
</location>
<location id="id10" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C3&lt;=freq[id]</label>
</location>
<init ref="id8"/>
<transition>
<source ref="id8"/>
<target ref="id10"/>
<label kind="assignment" x="-263" y="-85">C3=init_clock[id]</label>
</transition>
<transition>
<source ref="id9"/>
<target ref="id10"/>
<label kind="guard" x="-42" y="-102">C3&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id10"/>
<target ref="id9"/>
<label kind="guard" x="-17" y="-178">C3&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C3=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A4</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id11" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id12" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C4&lt;=max_com_delay[id]</label>
</location>
<location id="id13" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C4&lt;=freq[id]</label>
</location>
<init ref="id11"/>
<transition>
<source ref="id11"/>
<target ref="id13"/>
<label kind="assignment" x="-263" y="-85">C4=init_clock[id]</label>
</transition>
<transition>
<source ref="id12"/>
<target ref="id13"/>
<label kind="guard" x="-42" y="-102">C4&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id13"/>
<target ref="id12"/>
<label kind="guard" x="-25" y="-178">C4&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C4=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<template>
<name>A5</name>
<parameter>int[0,nb_car-1] id</parameter>
<location id="id14" x="-289" y="-85">
<name x="-299" y="-119">I</name>
<urgent/>
</location>
<location id="id15" x="161" y="-85">
<name x="136" y="-110">s1</name>
<label kind="invariant" x="102" y="-68">C5&lt;=max_com_delay[id]</label>
</location>
<location id="id16" x="-102" y="-85">
<name x="-127" y="-110">s0</name>
<label kind="invariant" x="-153" y="-68">C5&lt;=freq[id]</label>
</location>
<init ref="id14"/>
<transition>
<source ref="id14"/>
<target ref="id16"/>
<label kind="assignment" x="-263" y="-85">C5=init_clock[id]</label>
</transition>
<transition>
<source ref="id15"/>
<target ref="id16"/>
<label kind="guard" x="-42" y="-102">C5&gt;=min_com_delay[id]</label>
<label kind="assignment" x="-25" y="-85">communicate(id)</label>
</transition>
<transition>
<source ref="id16"/>
<target ref="id15"/>
<label kind="guard" x="-17" y="-178">C5&gt;=freq[id]</label>
<label kind="synchronisation" x="25" y="-161">k?</label>
<label kind="assignment" x="-34" y="-144">C5=0, decision(id)</label>
<nail x="-102" y="-145"/>
<nail x="161" y="-145"/>
</transition>
</template>
<system>Environnment = A0();
VehicleA = A1(0);
VehicleB = A2(1);
VehicleC = A3(2);
VehicleD = A4(3);
VehicleE = A5(4);
system Environnment, VehicleA, VehicleB, VehicleC;
</system>
<queries>
</queries>
</nta>