Skip to content

Commit 5ea3f95

Browse files
no interaction by default; reorg for controller code
1 parent 3ba733c commit 5ea3f95

File tree

5 files changed

+314
-111
lines changed

5 files changed

+314
-111
lines changed

controller.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { vec3, vec4, mat4, quat } from 'https://esm.sh/gl-matrix';
2+
3+
export default class Controller{
4+
constructor(){
5+
}
6+
evaluate_step(state){
7+
const q_des = [0, 0, 0, 1];
8+
const stateDict = JSON.parse(state.get_state());
9+
const params = JSON.parse(state.get_parameters());
10+
11+
const p = vec3.fromValues(...stateDict['position']);
12+
const q = quat.fromValues(
13+
stateDict['orientation'][1],
14+
stateDict['orientation'][2],
15+
stateDict['orientation'][3],
16+
stateDict['orientation'][0]
17+
);
18+
const v = vec3.fromValues(...stateDict['linear_velocity']);
19+
const omega = vec3.fromValues(...stateDict['angular_velocity']);
20+
21+
const m = params['dynamics']['mass'];
22+
const g = -params['dynamics']['gravity'][2];
23+
const l = 0.028;
24+
const k_q = params['dynamics']['rotor_torque_constants'][0];
25+
const [a, b, c] = params['dynamics']['rotor_thrust_coefficients'][0];
26+
27+
const k_p = 3.0;
28+
const k_d = 2.0;
29+
const k_R = 1.0;
30+
const k_omega = 0.1;
31+
32+
const p_des = vec3.fromValues(0, 0, 0);
33+
const v_des = vec3.fromValues(0, 0, 0);
34+
35+
const e_p = vec3.create();
36+
vec3.subtract(e_p, p, p_des);
37+
const e_v = vec3.create();
38+
vec3.subtract(e_v, v, v_des);
39+
40+
const a_des = vec3.create();
41+
vec3.scale(a_des, e_p, -k_p);
42+
const temp = vec3.create();
43+
vec3.scale(temp, e_v, -k_d);
44+
vec3.add(a_des, a_des, temp);
45+
46+
const T = m * (a_des[2] + g);
47+
48+
const q_des_conj = quat.create();
49+
quat.conjugate(q_des_conj, q_des);
50+
const q_err = quat.create();
51+
quat.multiply(q_err, q_des_conj, q);
52+
53+
if (q_err[3] < 0){
54+
quat.scale(q_err, q_err, -1);
55+
}
56+
57+
const e_R = vec3.fromValues(q_err[0], q_err[1], q_err[2]);
58+
vec3.scale(e_R, e_R, 2);
59+
60+
const tau = vec3.create();
61+
vec3.scale(tau, e_R, -k_R);
62+
const temp2 = vec3.create();
63+
vec3.scale(temp2, omega, -k_omega);
64+
vec3.add(tau, tau, temp2);
65+
66+
const A_inv = mat4.fromValues(
67+
1/4, -1/(4*l), -1/(4*l), -1/(4*k_q),
68+
1/4, -1/(4*l), 1/(4*l), 1/(4*k_q),
69+
1/4, 1/(4*l), 1/(4*l), -1/(4*k_q),
70+
1/4, 1/(4*l), -1/(4*l), 1/(4*k_q)
71+
);
72+
const controlInputs = vec4.fromValues(T, tau[0], tau[1], tau[2]);
73+
const f = vec4.create();
74+
vec4.transformMat4(f, controlInputs, A_inv);
75+
76+
const f_clipped = [
77+
Math.max(0, f[0]),
78+
Math.max(0, f[1]),
79+
Math.max(0, f[2]),
80+
Math.max(0, f[3])
81+
];
82+
83+
function solveRPM(fi) {
84+
const discriminant = b * b - 4 * a * (c - fi);
85+
if (discriminant < 0 || fi < c) {
86+
return 0.0;
87+
}
88+
const rpm = (-b + Math.sqrt(discriminant)) / (2 * a);
89+
return Math.max(0.0, Math.min(1.0, rpm));
90+
}
91+
92+
const action = f_clipped.map(solveRPM);
93+
94+
return action;
95+
}
96+
reset() {
97+
}
98+
}
99+

index.css

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ body {
3838
text-align: center;
3939
}
4040
button{
41-
padding: 10px 20px;
41+
padding: 5px 10px;
4242
font-size: 16px;
4343
}
4444
#perturbation-id-input{
@@ -142,4 +142,39 @@ canvas{
142142
text-overflow: ellipsis;
143143
overflow: hidden;
144144
white-space: nowrap;
145+
}
146+
147+
148+
#controller-options-container{
149+
display: flex ;
150+
flex-direction: row;
151+
align-items: center;
152+
justify-content: center;
153+
}
154+
155+
#controller-selector-container{
156+
margin-right: 15px;
157+
}
158+
#controller-selector-form{
159+
display: flex;
160+
flex-direction: column;
161+
margin-block-end: 0em;
162+
}
163+
164+
#controller-container{
165+
display: none;
166+
}
167+
168+
#policy-container{
169+
display: grid;
170+
grid-template-columns: auto auto;
171+
grid-template-rows: auto auto;
172+
gap: 10px;
173+
}
174+
.policy-container-item{
175+
display: flex;
176+
align-items: center;
177+
}
178+
#controller-code{
179+
min-width: 700px;
145180
}

index.html

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,35 @@
4949
<div id="status"></div>
5050
<div id="sim-container"></div>
5151
<div id="controls-box">
52-
<div class="controls-container">
53-
<span>Checkpoint:</span>
54-
<span id="checkpoint-name">default</span>
55-
<button id="default-checkpoint-btn">Default</button>
56-
</div>
57-
<div class="controls-container">
58-
<span>Observations:</span>
59-
<input type="text" id="observations">
60-
</input>
52+
<div id="controller-options-container">
53+
<div id="controller-selector-container">
54+
<form id="controller-selector-form">
55+
<label>
56+
<input type="radio" name="choice" value="policy" checked>
57+
Policy
58+
</label>
59+
<label>
60+
<input type="radio" name="choice" value="controller">
61+
Controller
62+
</label>
63+
</form>
64+
</div>
65+
<div id="policy-container" class="controller-container">
66+
<span class="policy-container-item">Checkpoint:</span>
67+
<div class="policy-container-item">
68+
<span id="checkpoint-name">default</span>
69+
<button id="default-checkpoint-btn">Default</button>
70+
</div>
71+
<span class="policy-container-item">Observations:</span>
72+
<div class="policy-container-item">
73+
<input type="text" id="observations">
74+
</input>
75+
</div>
76+
</div>
77+
<div id="controller-container" class="controller-container">
78+
<textarea id="controller-code" rows=10 value="(x, u) => x.map((v, i) => v + u[i] * 0.1)"></textarea>
79+
</div>
80+
6181
</div>
6282
<div class="controls-container">
6383
<span class="slider-container">

0 commit comments

Comments
 (0)