cadeau
This commit is contained in:
155
src/control.ept
155
src/control.ept
@@ -1,9 +1,160 @@
|
|||||||
open Globals
|
open Globals
|
||||||
|
open Utilities
|
||||||
|
|
||||||
|
(* Define resettable integrator locally *)
|
||||||
|
node integrator_reset(x, step, ini : float; r : bool) returns (o : float)
|
||||||
|
var s, mem_s : float;
|
||||||
|
let
|
||||||
|
mem_s = ini fby s;
|
||||||
|
s = (if r then ini -. (step *. x) /. 2.0 else mem_s) +. step *. x;
|
||||||
|
o = s -. (step *. x) /. 2.0;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node pid_reset(setpoint, measurement, kp, ki, kd : float; r : bool) returns (out : float)
|
||||||
|
var error, integral, derivative, prev_error : float;
|
||||||
|
let
|
||||||
|
error = setpoint -. measurement;
|
||||||
|
integral = integrator_reset(error, timestep, 0.0, r);
|
||||||
|
|
||||||
|
prev_error = if r then 0.0 else (0.0 fby error);
|
||||||
|
derivative = (error -. prev_error) /. timestep;
|
||||||
|
|
||||||
|
out = kp *. error +. ki *. integral +. kd *. derivative;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node check_color(c : color; target : colorQ) returns (match : bool)
|
||||||
|
let
|
||||||
|
match = (decode_color(c) = target);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node go_handler(param : float; sens : sensors; r : bool)
|
||||||
|
returns (rspeed : wheels; completed : bool; arriving : bool)
|
||||||
|
var
|
||||||
|
base_speed, correction, v_left, v_right : float;
|
||||||
|
error, raw_error : float;
|
||||||
|
is_green, is_red_road, is_red_light, is_obstacle : bool;
|
||||||
|
stop_for_light, stop_for_obstacle : bool;
|
||||||
|
let
|
||||||
|
(* PID for line following with dead zone *)
|
||||||
|
raw_error = Mathext.float(sens.s_road.green - sens.s_road.red);
|
||||||
|
error = raw_error;
|
||||||
|
|
||||||
|
(* Kp=0.7, Ki=0.0, Kd=1.5 for faster alignment *)
|
||||||
|
correction = pid_reset(0.0, error, 0.7, 0.0, 1.5, r);
|
||||||
|
|
||||||
|
(* Obstacle detection *)
|
||||||
|
is_obstacle = sens.s_sonar < 50;
|
||||||
|
|
||||||
|
(* Traffic Light *)
|
||||||
|
is_red_road = check_color(sens.s_road, Red);
|
||||||
|
is_red_light = check_color(sens.s_front, Red);
|
||||||
|
stop_for_light = is_red_road and is_red_light;
|
||||||
|
|
||||||
|
stop_for_obstacle = is_obstacle;
|
||||||
|
|
||||||
|
(* Speed *)
|
||||||
|
(* Adaptive speed: slow down when error is large to handle corners *)
|
||||||
|
base_speed = if stop_for_obstacle or stop_for_light then 0.0
|
||||||
|
else (param *. 3.0) /. (1.0 +. abs(error) *. 0.05);
|
||||||
|
|
||||||
|
v_left = max_float(0.0, bound(base_speed -. correction, cMAXWHEEL));
|
||||||
|
v_right = max_float(0.0, bound(base_speed +. correction, cMAXWHEEL));
|
||||||
|
|
||||||
|
rspeed = { left = v_left; right = v_right };
|
||||||
|
|
||||||
|
(* Completion: Rising edge of Green road *)
|
||||||
|
is_green = check_color(sens.s_road, Green);
|
||||||
|
completed = rising_edge(is_green) and not r;
|
||||||
|
|
||||||
|
arriving = false;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node turn_handler(param : float; sens : sensors; r : bool)
|
||||||
|
returns (rspeed : wheels; completed : bool; arriving : bool)
|
||||||
|
var
|
||||||
|
angle_turned : float;
|
||||||
|
v_turn : float;
|
||||||
|
vL, vR : float;
|
||||||
|
d_alpha : float;
|
||||||
|
remaining : float;
|
||||||
|
prev_angle : float;
|
||||||
|
let
|
||||||
|
(* Turn in place with variable speed *)
|
||||||
|
(* Use previous angle to avoid causality loop *)
|
||||||
|
(* If reset, prev_angle should be 0.0 *)
|
||||||
|
prev_angle = if r then 0.0 else (0.0 fby angle_turned);
|
||||||
|
|
||||||
|
remaining = abs(param) -. abs(prev_angle);
|
||||||
|
|
||||||
|
(* Slow down in final 10 degrees for precision *)
|
||||||
|
v_turn = if remaining <. 10.0 then 25.0 else 35.0;
|
||||||
|
|
||||||
|
(* Param > 0: CCW (Left). vR > vL. *)
|
||||||
|
(* Param < 0: CW (Right). vL > vR. *)
|
||||||
|
|
||||||
|
rspeed = if param >. 0.0 then
|
||||||
|
{ left = -. v_turn; right = v_turn }
|
||||||
|
else
|
||||||
|
{ left = v_turn; right = -. v_turn };
|
||||||
|
|
||||||
|
(* Estimate angle *)
|
||||||
|
vL = rspeed.left *. ((pi *. cD) /. 360.0);
|
||||||
|
vR = rspeed.right *. ((pi *. cD) /. 360.0);
|
||||||
|
d_alpha = (vR -. vL) *. 180.0 /. (pi *. cB);
|
||||||
|
|
||||||
|
angle_turned = integrator_reset(d_alpha, timestep, 0.0, r);
|
||||||
|
|
||||||
|
completed = abs(angle_turned) >=. abs(param);
|
||||||
|
arriving = false;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node stop_handler() returns (rspeed : wheels; completed : bool; arriving : bool)
|
||||||
|
let
|
||||||
|
rspeed = idlew;
|
||||||
|
completed = false;
|
||||||
|
arriving = true;
|
||||||
|
tel
|
||||||
|
|
||||||
node controller(sens : sensors; iti : itielts)
|
node controller(sens : sensors; iti : itielts)
|
||||||
returns (rspeed : wheels; arriving : bool)
|
returns (rspeed : wheels; arriving : bool)
|
||||||
|
var
|
||||||
|
idx : int;
|
||||||
|
act : action;
|
||||||
|
param : float;
|
||||||
|
completed : bool;
|
||||||
|
rspeed_go, rspeed_turn, rspeed_stop : wheels;
|
||||||
|
comp_go, comp_turn, comp_stop : bool;
|
||||||
|
arr_go, arr_turn, arr_stop : bool;
|
||||||
|
current_iti : itielt;
|
||||||
|
reset_go, reset_turn : bool;
|
||||||
let
|
let
|
||||||
rspeed = { left = 00.0; right = 100.0 };
|
idx = 0 fby (if completed then (idx + 1) % itinum else idx);
|
||||||
arriving = false;
|
|
||||||
|
current_iti = iti[> idx <];
|
||||||
|
act = current_iti.act;
|
||||||
|
param = current_iti.param;
|
||||||
|
|
||||||
|
(* Detect entry into states to reset handlers *)
|
||||||
|
reset_go = rising_edge(act = Go);
|
||||||
|
reset_turn = rising_edge(act = Turn);
|
||||||
|
|
||||||
|
(* Run handlers with explicit reset signal *)
|
||||||
|
(rspeed_go, comp_go, arr_go) = go_handler(param, sens, reset_go);
|
||||||
|
|
||||||
|
(rspeed_turn, comp_turn, arr_turn) = turn_handler(param, sens, reset_turn);
|
||||||
|
|
||||||
|
(rspeed_stop, comp_stop, arr_stop) = stop_handler();
|
||||||
|
|
||||||
|
(* Select output based on current action *)
|
||||||
|
rspeed = if act = Go then rspeed_go
|
||||||
|
else if act = Turn then rspeed_turn
|
||||||
|
else rspeed_stop;
|
||||||
|
|
||||||
|
completed = if act = Go then comp_go
|
||||||
|
else if act = Turn then comp_turn
|
||||||
|
else comp_stop;
|
||||||
|
|
||||||
|
arriving = if act = Go then arr_go
|
||||||
|
else if act = Turn then arr_turn
|
||||||
|
else arr_stop;
|
||||||
tel
|
tel
|
||||||
|
|||||||
Reference in New Issue
Block a user