Project

General

Profile

Download (4.6 KB) Statistics
| Branch: | Tag: | Revision:
1
#open <conv> 
2
const k_f_1 = -0.870303;
3
const k_f_2 = -31.9978;
4
const k_f_3 = -1.1566;
5
const k_f_4 = -2.78873;
6

    
7
const k_i = -0.44721;   (* servo control integral gain *)
8
const k_phidot = 25.0;  (* turn target speed gain *)
9
const k_thetadot = 7.5; (* forward target speed gain *)
10

    
11
const battery_gain = 0.001089;
12
const battery_offset = 0.625;
13

    
14
const cmd_max = 100.;
15
const deg2rad = 0.01745329238;
16
const exec_period = 0.00400000019;
17

    
18
const a_d = 0.8; 
19
const a_r = 0.996;   
20

    
21

    
22

    
23
node discrete_integrator(exec_period, in : real)
24
returns (out: real);
25
let
26
  out = 0. -> pre (exec_period * in + out);
27
tel
28

    
29
node low_pass_filter(a, in: real) 
30
returns (out : real);
31
let 
32
  out = (1.-a)*in -> (1.-a)*in + (pre out) * a;
33
tel
34

    
35
node sat(min, max, in : real)
36
returns (out: real);
37
let
38
  out = if in <= min then min else (if in>= max then max else in);
39
tel
40

    
41
node cal_reference(cmd_forward, cmd_turn : real)
42
returns (pwm_turn, theta_ref, x_11_ref,x_12_ref,x_13_ref,x_14_ref : real);
43
var theta_dot_ref: real;
44
let
45
  theta_dot_ref = low_pass_filter(a_r,k_thetadot*cmd_forward/cmd_max);
46
  theta_ref=x_11_ref;
47
  x_11_ref = discrete_integrator(exec_period,theta_dot_ref);
48
  x_12_ref = 0.;
49
  x_13_ref = theta_dot_ref;
50
  x_14_ref = 0.;
51
  pwm_turn = cmd_turn*k_phidot/cmd_max;
52
tel
53

    
54
node cal_x1 (gyro, gyro_offset, theta_m_l, theta_m_r:real)
55
returns(theta, x_11,x_12,x_13,x_14 : real);
56
var psidot, psi, theta_l, theta_r: real;
57
let
58
  psidot = (gyro - gyro_offset)*deg2rad;
59
  psi = discrete_integrator(exec_period,psidot);
60
  theta_l= theta_m_l*deg2rad+ psi;
61
  theta_r = theta_m_r*deg2rad + psi;
62
  theta = (theta_l+theta_r)/2.;
63
  x_11 = theta;
64
  x_12 = psi;
65
  x_13 = (low_pass_filter(a_d,theta) - (0. -> pre(low_pass_filter(a_d,theta))))/exec_period;
66
  x_14 = psidot;
67
tel;
68

    
69
node cal_pwm(theta_m_l, theta_m_r, pwm_turn, err, battery : real)
70
returns(pwm_l, pwm_r,  anti_windup : real);
71
var fwd, theta_diff : real;
72
let
73
fwd = cmd_max * (err/(battery*battery_gain-battery_offset));
74
pwm_l = sat(-100.,100.,fwd+pwm_turn);
75
theta_diff = theta_m_l - theta_m_r;
76
pwm_r = sat(-100.,100.,fwd-pwm_turn+12.0*theta_diff);
77
anti_windup=  pwm_l - fwd+pwm_turn;
78
tel;
79

    
80
node lego_anti_windup (in1, in2, in3, in4, cntA, cntB, cntC, battery_voltage : int; gyro_offset :  real)
81
returns (speedA, speedB, speedC : int);
82
var gyro, cmd_forward, cmd_turn, theta_m_l, theta_m_r,  pwm_turn,  theta_ref,  x_11_ref,  x_12_ref, x_13_ref, x_14_ref, theta, x_11, x_12, x_13, x_14,  errtheta, err, pwm_l, pwm_r,  anti_windup: real;
83
let
84
 cmd_forward = if in2 <= 25 then -100. else 0.;
85
 cmd_turn = 0.;
86
 gyro = int_to_real(in3);
87
 theta_m_l = int_to_real(cntC);
88
 theta_m_r = int_to_real(cntB);
89

    
90
 (pwm_turn, theta_ref, x_11_ref,  x_12_ref, x_13_ref, x_14_ref) = cal_reference(cmd_forward, cmd_turn);
91

    
92
 (theta, x_11,  x_12, x_13, x_14) = cal_x1(gyro, gyro_offset, theta_m_l, theta_m_r);
93
 
94
 errtheta = discrete_integrator(exec_period, (theta_ref-theta)*k_i + 0. -> pre(anti_windup*0.1));
95
 
96
 err = errtheta + k_f_1*(x_11_ref-x_11) + k_f_2*(x_12_ref-x_12)+ k_f_3*(x_13_ref-x_13) +k_f_4*(x_14_ref-x_14);
97
 
98
 (pwm_l,pwm_r,  anti_windup) = cal_pwm(theta_m_l, theta_m_r, pwm_turn, err, int_to_real(battery_voltage));
99

    
100
  speedA = 0;
101
  speedB = real_to_int(pwm_r);
102
  speedC = real_to_int(pwm_l);
103
tel
104

    
105

    
106
node lego_anti_windup_real (in1, in2, in3, in4, cntA, cntB, cntC, battery_voltage : real; gyro_offset :  real)
107
returns (speedA, speedB, speedC : real);
108
var gyro, cmd_forward, cmd_turn, theta_m_l, theta_m_r,  pwm_turn,  theta_ref,  x_11_ref,  x_12_ref, x_13_ref, x_14_ref, theta, x_11, x_12, x_13, x_14,  errtheta, err, pwm_l, pwm_r,  anti_windup: real;
109
let
110
 cmd_forward = if in2 <= 25. then -100. else 0.;
111
 cmd_turn = 0.;
112
 gyro = in3;
113
 theta_m_l = cntC;
114
 theta_m_r = cntB;
115

    
116
 (pwm_turn, theta_ref, x_11_ref,  x_12_ref, x_13_ref, x_14_ref) = cal_reference(cmd_forward, cmd_turn);
117

    
118
 (theta, x_11,  x_12, x_13, x_14) = cal_x1(gyro, gyro_offset, theta_m_l, theta_m_r);
119
 
120
 errtheta = discrete_integrator(exec_period, (theta_ref-theta)*k_i + 0. -> pre(anti_windup*0.1));
121
 
122
 err = errtheta + k_f_1*(x_11_ref-x_11) + k_f_2*(x_12_ref-x_12)+ k_f_3*(x_13_ref-x_13) +k_f_4*(x_14_ref-x_14);
123
 
124
 (pwm_l,pwm_r,  anti_windup) = cal_pwm(theta_m_l, theta_m_r, pwm_turn, err, battery_voltage);
125

    
126
  speedA = 0.;
127
  speedB = pwm_r;
128
  speedC = pwm_l;
129
tel
130

    
131

    
132

    
133
(*
134
node automate(in1, in2, in3, in4, cntA, cntB, cntC, battery_voltage : int)
135
returns (speedA, speedB, speedC : int);
136
var 
137
  cnt :  int;  gyro_offset :  real;
138
let
139
  cnt = 1 -> pre(cnt) +1;
140
  gyro_offset = int_to_real(in3) -> int_to_real(in3)/int_to_real(cnt) + (int_to_real(cnt-1)/int_to_real(cnt))*pre(gyro_offset);
141
  (speedA, speedB, speedC) = if cnt <= 250 then (0,  0,  0) else top(in1, in2, in3, in4, cntA, cntB, cntC, battery_voltage,  gyro_offset);
142
tel
143
*)
(3-3/10)