Skip to content

Commit 604d2d3

Browse files
[CPP-49][CPP-143]Added the Advanced INS tab (minus fusion engine statusbar) and fixed Tracking Signals artifacts using PGM. (#67)
* Ins Tab. * Added text data fields. * [CPP-143]Fix PGM tracking signals xaxis issue. * Respond to review requests. * Respond to review requests. * Add message decimation to tracking signals plot. * Fix unittest. * Update common_constants. * Respond to review requests.
1 parent ba7b25c commit 604d2d3

26 files changed

+990
-97
lines changed
Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
use log::error;
2+
use sbp::messages::imu::{MsgImuAux, MsgImuRaw};
3+
4+
use capnp::message::Builder;
5+
use capnp::serialize;
6+
7+
use crate::console_backend_capnp as m;
8+
use crate::constants::*;
9+
use crate::errors::{CAP_N_PROTO_SERIALIZATION_FAILURE, GET_MUT_OBJECT_FAILURE};
10+
use crate::types::{Deque, MessageSender, SharedState};
11+
12+
/// AdvancedInsTab struct.
13+
///
14+
/// # Fields:
15+
///
16+
/// - `client_send`: Client Sender channel for communication from backend to frontend.
17+
/// - `imu_conf`: Storage for the Imu configuration.
18+
/// - `imu_temp`: Storage for the raw Imu temperature converted to proper units.
19+
/// - `rms_acc_x`: The calculated root mean squared imu acceleration for x axis.
20+
/// - `rms_acc_y`: The calculated root mean squared imu acceleration for y axis.
21+
/// - `rms_acc_z`: The calculated root mean squared imu acceleration for z axis.
22+
/// - `acc_x`: The stored historic Imu acceleration values along x axis.
23+
/// - `acc_y`: The stored historic Imu acceleration values along y axis.
24+
/// - `acc_z`: The stored historic Imu acceleration values along z axis.
25+
/// - `gyro_x`: The stored historic Imu angular rate values along x axis.
26+
/// - `gyro_y`: The stored historic Imu angular rate values along y axis.
27+
/// - `gyro_z`: The stored historic Imu angular rate values along z axis.
28+
/// - `shared_state`: The shared state for communicating between frontend/backend/other backend tabs.
29+
#[derive(Debug)]
30+
pub struct AdvancedInsTab<S: MessageSender> {
31+
client_sender: S,
32+
imu_conf: u8,
33+
imu_temp: f64,
34+
rms_acc_x: f64,
35+
rms_acc_y: f64,
36+
rms_acc_z: f64,
37+
acc_x: Deque<f64>,
38+
acc_y: Deque<f64>,
39+
acc_z: Deque<f64>,
40+
gyro_x: Deque<f64>,
41+
gyro_y: Deque<f64>,
42+
gyro_z: Deque<f64>,
43+
shared_state: SharedState,
44+
}
45+
46+
impl<S: MessageSender> AdvancedInsTab<S> {
47+
pub fn new(shared_state: SharedState, client_sender: S) -> AdvancedInsTab<S> {
48+
let acc_fill_val = Some(0_f64);
49+
let gyro_fill_val = Some(0_f64);
50+
AdvancedInsTab {
51+
client_sender,
52+
imu_conf: 0_u8,
53+
imu_temp: 0_f64,
54+
rms_acc_x: 0_f64,
55+
rms_acc_y: 0_f64,
56+
rms_acc_z: 0_f64,
57+
acc_x: Deque::with_size_limit(NUM_POINTS, acc_fill_val),
58+
acc_y: Deque::with_size_limit(NUM_POINTS, acc_fill_val),
59+
acc_z: Deque::with_size_limit(NUM_POINTS, acc_fill_val),
60+
gyro_x: Deque::with_size_limit(NUM_POINTS, gyro_fill_val),
61+
gyro_y: Deque::with_size_limit(NUM_POINTS, gyro_fill_val),
62+
gyro_z: Deque::with_size_limit(NUM_POINTS, gyro_fill_val),
63+
shared_state,
64+
}
65+
}
66+
67+
/// Method for preparing some rms_acc data and initiating sending of data to frontend.
68+
fn imu_set_data(&mut self) {
69+
let acc_x = &mut self.acc_x.get();
70+
let acc_y = &mut self.acc_y.get();
71+
let acc_z = &mut self.acc_z.get();
72+
let acc_range = self.imu_conf & 0xF;
73+
let sig_figs = f64::powi(2_f64, acc_range as i32 + 1_i32) / f64::powi(2_f64, 15);
74+
let (rms_x, rms_y, rms_z) = {
75+
let mut squared_sum_x: f64 = 0_f64;
76+
let mut squared_sum_y: f64 = 0_f64;
77+
let mut squared_sum_z: f64 = 0_f64;
78+
for idx in 0..NUM_POINTS {
79+
squared_sum_x += f64::powi(acc_x[idx], 2);
80+
squared_sum_y += f64::powi(acc_y[idx], 2);
81+
squared_sum_z += f64::powi(acc_z[idx], 2);
82+
}
83+
(
84+
f64::sqrt(squared_sum_x / acc_x.len() as f64),
85+
f64::sqrt(squared_sum_y / acc_y.len() as f64),
86+
f64::sqrt(squared_sum_z / acc_z.len() as f64),
87+
)
88+
};
89+
self.rms_acc_x = sig_figs * rms_x;
90+
self.rms_acc_y = sig_figs * rms_y;
91+
self.rms_acc_z = sig_figs * rms_z;
92+
self.send_data();
93+
}
94+
95+
/// Handler for Imu Aux messages.
96+
///
97+
/// # Parameters
98+
/// - `msg`: MsgImuAux to extract data from.
99+
pub fn handle_imu_aux(&mut self, msg: MsgImuAux) {
100+
match msg.imu_type {
101+
0 => {
102+
self.imu_temp = 23_f64 + msg.temp as f64 / f64::powi(2_f64, 9);
103+
self.imu_conf = msg.imu_conf;
104+
}
105+
1 => {
106+
self.imu_temp = 25_f64 + msg.temp as f64 / 256_f64;
107+
self.imu_conf = msg.imu_conf;
108+
}
109+
_ => {
110+
error!("IMU type {} not known.", msg.imu_type);
111+
}
112+
}
113+
}
114+
115+
/// Handler for Imu Raw messages.
116+
///
117+
/// # Parameters
118+
/// - `msg`: MsgImuRaw to extract data from.
119+
pub fn handle_imu_raw(&mut self, msg: MsgImuRaw) {
120+
self.acc_x.add(msg.acc_x as f64);
121+
self.acc_y.add(msg.acc_y as f64);
122+
self.acc_z.add(msg.acc_z as f64);
123+
self.gyro_x.add(msg.gyr_x as f64);
124+
self.gyro_y.add(msg.gyr_y as f64);
125+
self.gyro_z.add(msg.gyr_z as f64);
126+
self.imu_set_data();
127+
}
128+
129+
/// Package data into a message buffer and send to frontend.
130+
fn send_data(&mut self) {
131+
let mut builder = Builder::new_default();
132+
let msg = builder.init_root::<m::message::Builder>();
133+
134+
let mut tab_status = msg.init_advanced_ins_status();
135+
136+
let mut tab_points = tab_status.reborrow().init_data(NUM_INS_PLOT_ROWS as u32);
137+
138+
let mut points_vec = vec![
139+
self.acc_x.get(),
140+
self.acc_y.get(),
141+
self.acc_z.get(),
142+
self.gyro_x.get(),
143+
self.gyro_y.get(),
144+
self.gyro_z.get(),
145+
];
146+
for idx in 0..NUM_INS_PLOT_ROWS {
147+
let points = points_vec.get_mut(idx).expect(GET_MUT_OBJECT_FAILURE);
148+
let mut point_val_idx = tab_points.reborrow().init(idx as u32, points.len() as u32);
149+
for idx in 0..NUM_POINTS {
150+
let mut point_val = point_val_idx.reborrow().get(idx as u32);
151+
point_val.set_x(idx as f64);
152+
point_val.set_y(points[idx]);
153+
}
154+
}
155+
let fields_data = {
156+
vec![
157+
self.imu_temp,
158+
self.imu_conf as f64,
159+
self.rms_acc_x,
160+
self.rms_acc_y,
161+
self.rms_acc_z,
162+
]
163+
};
164+
let mut fields_data_status = tab_status
165+
.reborrow()
166+
.init_fields_data(NUM_INS_FIELDS as u32);
167+
168+
for (i, datur) in fields_data.iter().enumerate() {
169+
fields_data_status.set(i as u32, *datur);
170+
}
171+
172+
let mut msg_bytes: Vec<u8> = vec![];
173+
serialize::write_message(&mut msg_bytes, &builder)
174+
.expect(CAP_N_PROTO_SERIALIZATION_FAILURE);
175+
self.client_sender.send_data(msg_bytes);
176+
}
177+
}
178+
179+
#[cfg(test)]
180+
mod tests {
181+
use super::*;
182+
use crate::types::TestSender;
183+
use sbp::messages::imu::{MsgImuAux, MsgImuRaw};
184+
185+
#[test]
186+
fn handle_imu_raw_test() {
187+
let shared_state = SharedState::new();
188+
let client_send = TestSender { inner: Vec::new() };
189+
let mut ins_tab = AdvancedInsTab::new(shared_state, client_send);
190+
let tow = 1_u32;
191+
let tow_f = 1_u8;
192+
let acc_x = 2_i16;
193+
let acc_y = 3_i16;
194+
let acc_z = 4_i16;
195+
let gyr_x = 5_i16;
196+
let gyr_y = 6_i16;
197+
let gyr_z = 7_i16;
198+
let msg = MsgImuRaw {
199+
sender_id: Some(1337),
200+
tow,
201+
tow_f,
202+
acc_x,
203+
acc_y,
204+
acc_z,
205+
gyr_x,
206+
gyr_y,
207+
gyr_z,
208+
};
209+
let acc_xs = ins_tab.acc_x.get();
210+
let acc_ys = ins_tab.acc_y.get();
211+
let acc_zs = ins_tab.acc_z.get();
212+
let gyro_xs = ins_tab.gyro_x.get();
213+
let gyro_ys = ins_tab.gyro_y.get();
214+
let gyro_zs = ins_tab.gyro_z.get();
215+
for idx in 0..NUM_POINTS {
216+
assert!(f64::abs(acc_xs[idx] - 0_f64) <= f64::EPSILON);
217+
assert!(f64::abs(acc_ys[idx] - 0_f64) <= f64::EPSILON);
218+
assert!(f64::abs(acc_zs[idx] - 0_f64) <= f64::EPSILON);
219+
assert!(f64::abs(gyro_xs[idx] - 0_f64) <= f64::EPSILON);
220+
assert!(f64::abs(gyro_ys[idx] - 0_f64) <= f64::EPSILON);
221+
assert!(f64::abs(gyro_zs[idx] - 0_f64) <= f64::EPSILON);
222+
}
223+
assert!(f64::abs(ins_tab.rms_acc_x - 0_f64) <= f64::EPSILON);
224+
assert!(f64::abs(ins_tab.rms_acc_y - 0_f64) <= f64::EPSILON);
225+
assert!(f64::abs(ins_tab.rms_acc_z - 0_f64) <= f64::EPSILON);
226+
ins_tab.handle_imu_raw(msg);
227+
let acc_xs = ins_tab.acc_x.get();
228+
let acc_ys = ins_tab.acc_y.get();
229+
let acc_zs = ins_tab.acc_z.get();
230+
let gyro_xs = ins_tab.gyro_x.get();
231+
let gyro_ys = ins_tab.gyro_y.get();
232+
let gyro_zs = ins_tab.gyro_z.get();
233+
assert!(f64::abs(acc_xs[NUM_POINTS - 1] - acc_x as f64) <= f64::EPSILON);
234+
assert!(f64::abs(acc_ys[NUM_POINTS - 1] - acc_y as f64) <= f64::EPSILON);
235+
assert!(f64::abs(acc_zs[NUM_POINTS - 1] - acc_z as f64) <= f64::EPSILON);
236+
assert!(f64::abs(gyro_xs[NUM_POINTS - 1] - gyr_x as f64) <= f64::EPSILON);
237+
assert!(f64::abs(gyro_ys[NUM_POINTS - 1] - gyr_y as f64) <= f64::EPSILON);
238+
assert!(f64::abs(gyro_zs[NUM_POINTS - 1] - gyr_z as f64) <= f64::EPSILON);
239+
assert!(f64::abs(ins_tab.rms_acc_x - 0_f64) > f64::EPSILON);
240+
assert!(f64::abs(ins_tab.rms_acc_y - 0_f64) > f64::EPSILON);
241+
assert!(f64::abs(ins_tab.rms_acc_z - 0_f64) > f64::EPSILON);
242+
}
243+
244+
#[test]
245+
fn handle_imu_aux_test() {
246+
let shared_state = SharedState::new();
247+
let client_send = TestSender { inner: Vec::new() };
248+
let mut ins_tab = AdvancedInsTab::new(shared_state.clone(), client_send.clone());
249+
let imu_type_a = 0_u8;
250+
let imu_type_b = 1_u8;
251+
let imu_type_unknown = 2_u8;
252+
let imu_conf = 1_u8;
253+
let temp = 200;
254+
let msg = MsgImuAux {
255+
sender_id: Some(1337),
256+
imu_type: imu_type_unknown,
257+
imu_conf,
258+
temp,
259+
};
260+
assert!(f64::abs(ins_tab.imu_temp - 0_f64) <= f64::EPSILON);
261+
assert_eq!(ins_tab.imu_conf, 0_u8);
262+
ins_tab.handle_imu_aux(msg);
263+
assert!(f64::abs(ins_tab.imu_temp - 0_f64) <= f64::EPSILON);
264+
assert_ne!(ins_tab.imu_conf, imu_conf);
265+
266+
let mut ins_tab = AdvancedInsTab::new(shared_state.clone(), client_send.clone());
267+
let msg = MsgImuAux {
268+
sender_id: Some(1337),
269+
imu_type: imu_type_a,
270+
imu_conf,
271+
temp,
272+
};
273+
assert!(f64::abs(ins_tab.imu_temp - 0_f64) <= f64::EPSILON);
274+
assert_eq!(ins_tab.imu_conf, 0_u8);
275+
ins_tab.handle_imu_aux(msg);
276+
assert!(f64::abs(ins_tab.imu_temp - 23.390625_f64) <= f64::EPSILON);
277+
assert_eq!(ins_tab.imu_conf, imu_conf);
278+
279+
let mut ins_tab = AdvancedInsTab::new(shared_state, client_send);
280+
let msg = MsgImuAux {
281+
sender_id: Some(1337),
282+
imu_type: imu_type_b,
283+
imu_conf,
284+
temp,
285+
};
286+
assert!(f64::abs(ins_tab.imu_temp - 0_f64) <= f64::EPSILON);
287+
assert_eq!(ins_tab.imu_conf, 0_u8);
288+
ins_tab.handle_imu_aux(msg);
289+
assert!(f64::abs(ins_tab.imu_temp - 25.78125_f64) <= f64::EPSILON);
290+
assert_eq!(ins_tab.imu_conf, imu_conf);
291+
}
292+
293+
#[test]
294+
fn handle_imu_send_data_test() {
295+
let shared_state = SharedState::new();
296+
let client_send = TestSender { inner: Vec::new() };
297+
let mut ins_tab = AdvancedInsTab::new(shared_state, client_send);
298+
299+
assert!(f64::abs(ins_tab.rms_acc_x - 0_f64) <= f64::EPSILON);
300+
assert!(f64::abs(ins_tab.rms_acc_y - 0_f64) <= f64::EPSILON);
301+
assert!(f64::abs(ins_tab.rms_acc_z - 0_f64) <= f64::EPSILON);
302+
303+
let imu_type = 0_u8;
304+
let imu_conf = 1_u8;
305+
let temp = 200;
306+
let msg = MsgImuAux {
307+
sender_id: Some(1337),
308+
imu_type,
309+
imu_conf,
310+
temp,
311+
};
312+
ins_tab.handle_imu_aux(msg);
313+
314+
let tow = 1_u32;
315+
let tow_f = 1_u8;
316+
let acc_x = 2_i16;
317+
let acc_y = 3_i16;
318+
let acc_z = 4_i16;
319+
let gyr_x = 5_i16;
320+
let gyr_y = 6_i16;
321+
let gyr_z = 7_i16;
322+
let msg = MsgImuRaw {
323+
sender_id: Some(1337),
324+
tow,
325+
tow_f,
326+
acc_x,
327+
acc_y,
328+
acc_z,
329+
gyr_x,
330+
gyr_y,
331+
gyr_z,
332+
};
333+
ins_tab.handle_imu_raw(msg);
334+
let sig_figs = 0.0001220703125_f64;
335+
let acc_x = acc_x as f64;
336+
let acc_y = acc_y as f64;
337+
let acc_z = acc_z as f64;
338+
339+
let rms_acc_x = f64::sqrt((acc_x * acc_x) / NUM_POINTS as f64);
340+
let rms_acc_y = f64::sqrt((acc_y * acc_y) / NUM_POINTS as f64);
341+
let rms_acc_z = f64::sqrt((acc_z * acc_z) / NUM_POINTS as f64);
342+
assert!(f64::abs(ins_tab.rms_acc_x - rms_acc_x * sig_figs) <= f64::EPSILON);
343+
assert!(f64::abs(ins_tab.rms_acc_y - rms_acc_y * sig_figs) <= f64::EPSILON);
344+
assert!(f64::abs(ins_tab.rms_acc_z - rms_acc_z * sig_figs) <= f64::EPSILON);
345+
346+
let acc_x = 4_i16;
347+
let acc_y = 6_i16;
348+
let acc_z = 8_i16;
349+
let msg = MsgImuRaw {
350+
sender_id: Some(1337),
351+
tow,
352+
tow_f,
353+
acc_x,
354+
acc_y,
355+
acc_z,
356+
gyr_x,
357+
gyr_y,
358+
gyr_z,
359+
};
360+
ins_tab.handle_imu_raw(msg);
361+
let sig_figs = 0.0001220703125_f64;
362+
let acc_x = acc_x as f64;
363+
let acc_y = acc_y as f64;
364+
let acc_z = acc_z as f64;
365+
let rms_acc_x =
366+
f64::sqrt((acc_x * acc_x + (acc_x / 2_f64) * (acc_x / 2_f64)) / NUM_POINTS as f64);
367+
let rms_acc_y =
368+
f64::sqrt((acc_y * acc_y + (acc_y / 2_f64) * (acc_y / 2_f64)) / NUM_POINTS as f64);
369+
let rms_acc_z =
370+
f64::sqrt((acc_z * acc_z + (acc_z / 2_f64) * (acc_z / 2_f64)) / NUM_POINTS as f64);
371+
assert!(f64::abs(ins_tab.rms_acc_x - rms_acc_x * sig_figs) <= f64::EPSILON);
372+
assert!(f64::abs(ins_tab.rms_acc_y - rms_acc_y * sig_figs) <= f64::EPSILON);
373+
assert!(f64::abs(ins_tab.rms_acc_z - rms_acc_z * sig_figs) <= f64::EPSILON);
374+
}
375+
}

0 commit comments

Comments
 (0)