VOXL OpenVINS Server 1.0
Visual Inertial Odometry Server for VOXL Platform
Loading...
Searching...
No Matches
VoxlVars.cpp
Go to the documentation of this file.
1/**
2 * @file VoxlVars.cpp
3 * @brief Global variable definitions for VOXL OpenVINS server
4 * @author Zauberflote
5 * @date 2025
6 * @version 1.0
7 *
8 * This file contains the definitions of all global variables declared in VoxlVars.h.
9 * It provides the actual storage for system state, configuration parameters,
10 * and operational variables used throughout the VIO system.
11 */
12
13#include "VoxlVars.h"
14#include "VoxlCommon.h"
15#include <atomic>
16#include <memory>
17#include <mutex>
18#include <vector>
19#include <string>
20#include <cmath>
21#include <algorithm>
22
23// ============================================================================
24// CORE VIO MANAGER
25// ============================================================================
26
27/** @brief VIO manager options */
28ov_msckf::VioManagerOptions vio_manager_options;
29
30/** @brief Main VIO manager instance */
31std::unique_ptr<ov_msckf::VioManager> vio_manager;
32
33// ============================================================================
34// ATOMIC STATE VARIABLES
35// ============================================================================
36
37/** @brief Main process running flag */
38volatile int main_running = 1;
39
40/** @brief Current VIO state (initializing, tracking, etc.) */
41std::atomic<uint8_t> vio_state(0);
42
43/** @brief VIO error codes */
44std::atomic<uint32_t> vio_error_codes(0);
45
46/** @brief Flag indicating that system should reset */
47std::atomic<bool> reset_requested(false);
48
49/** @brief Flag indicating if system is currently resetting */
50std::atomic<bool> is_resetting(false);
51
52/** @brief Counter which increments on resets */
53std::atomic<uint32_t> reset_num_counter{0};
54
55/** @brief Number of callbacks inside the system */
56std::atomic<uint32_t> active_callbacks{0};
57
58/** @brief Mutex used by reset thread */
59std::mutex reset_mtx;
60
61/** @brief Reset conditional variable */
62std::condition_variable reset_cv;
63
64/** @brief Flag indicating if system is armed */
65std::atomic<bool> is_armed(false);
66
67/** @brief Flag indicating if camera is connected */
68std::atomic<bool> is_cam_connected(false);
69
70/** @brief Flag indicating if IMU is connected */
71std::atomic<bool> is_imu_connected(false);
72
73// ============================================================================
74// SERVER CONFIGURATION VARIABLES
75// ============================================================================
76
77/** @brief Enable automatic reset functionality */
79
80/** @brief Maximum velocity threshold for auto reset */
82
83/** @brief Maximum velocity covariance for instant reset */
85
86/** @brief Maximum velocity covariance for timeout reset */
88
89/** @brief Timeout duration for velocity covariance reset (seconds) */
91
92/** @brief Minimum number of features for auto reset */
94
95/** @brief Minimum feature timeout for auto reset (seconds) */
97
98/** @brief Minimum amount of time after initialization that quality is held low (CEP) */
100
101/** @brief Auto fallback timeout (seconds) */
103
104/** @brief Minimum velocity for auto fallback */
106
107/** @brief Enable continuous yaw checks */
109
110/** @brief Fast yaw threshold */
111float fast_yaw_thresh = 0.0f;
112
113/** @brief Fast yaw timeout (seconds) */
115
116// ============================================================================
117// QUALITY HYSTERESIS THRESHOLD CONFIGURATION
118// ============================================================================
119
120/** @brief Quality low threshold for INITIAL state */
122
123/** @brief Quality low threshold for GOOD state */
125
126/** @brief Quality high threshold for recovery */
128
129/** @brief Consecutive samples for INITIAL→BAD transition */
131
132/** @brief Consecutive samples for INITIAL→GOOD transition */
134
135/** @brief Consecutive samples for BAD→GOOD transition */
137
138/** @brief Consecutive samples for GOOD→BAD transition */
140
141/** @brief using_stereo */
143
144/** @brief Base folder for yaml configuration files */
145char folder_base[CHAR_BUF_SIZE] = "/etc/modalai/VoxlConfig/starling2";
146
147/** @brief Enable debug output */
148int en_debug = 0;
149
150/** @brief Enable verbose output */
152
153/** @brief Configuration only mode */
155
156/** @brief Enable IMU body measurements */
157bool en_imu_body = false;
158
159// ============================================================================
160// SENSOR CONFIGURATION VARIABLES
161// ============================================================================
162
163/** @brief IMU device name */
164char imu_name[64];
165
166/** @brief Active IMU model */
167imu_model_t imu_model = IMU_MODEL_UNKNOWN;
168
169/** @brief Vector of camera configuration information */
170std::vector<cam_info> cam_info_vec;
171
172// ============================================================================
173// IMU-SPECIFIC VARIABLES
174// ============================================================================
175
176/** @brief Timestamp of last IMU data (nanoseconds) */
177volatile int64_t last_imu_timestamp_ns = 0;
178
179/** @brief Estimated IMU sampling rate in Hz */
180std::atomic<double> imu_rate_hz(1024.0);
181
182/** @brief Global frame transform instance */
184
185// ============================================================================
186// CAMERA-SPECIFIC VARIABLES
187// ============================================================================
188
189/** @brief Takeoff camera identifier */
191
192/** @brief Enable takeoff camera functionality */
194
195/** @brief Vector of takeoff camera identifiers */
196std::vector<int> takeoff_cams;
197
198/** @brief Timestamp of last camera data (nanoseconds) */
199volatile int64_t last_cam_time = 0;
200
201/** @brief Number of cameras currently in use */
203
204/** @brief Altitude z */
205std::atomic<float> alt_z(0.0f);
206
207/** @brief Takeoff altitude threshold */
209
210/** @brief Occlude stereo left */
212
213/** @brief Occlude stereo right */
215
216/** @brief Fusion rate in milliseconds */
217float fusion_rate_dt_ms = 20.0; // 50Hz
218
219// ============================================================================
220// PIPE COMMUNICATION VARIABLES
221// ============================================================================
222
223/** @brief Camera pipe channels array */
225
226// ============================================================================
227// IMAGE PROCESSING VARIABLES
228// ============================================================================
229
230/** @brief Image ring buffer for processing */
232
233bool sync_config = true; ///< Flag to indicate if configuration synchronization is enabled
234
235// ============================================================================
236// FRAME TRANSFORM IMPLEMENTATION
237// ============================================================================
238
239void voxl::FrameTransform::update(const imu_data_t &data)
240{
241 if (!en_imu_body)
242 {
243 printf("[INFO] IMU body measurements are disabled, THIS WON'T WORK AS EXPECTED.\n");
244 }
245
246 if (is_initialized)
247 {
248 detectJerk(data);
249 return; // CHECK IF WE HAVE ALREADY DONE THIS
250 }
251
252 // FOR NOW WE ARE CHECKING WITH ONE SAMPLE -- PARTIALLY ASSUMING STATIC INITIALIZATION
253 // MAX ELEMENT NORM IS THE AXIS WHERE GRAVITY IS MOST PREDOMINANT
254 Eigen::Vector3d accel(data.accl_ms2[0], data.accl_ms2[1], data.accl_ms2[2]);
255 accel = accel / accel.norm();
256
257 Eigen::Vector3d grav_versor_expected = Eigen::Vector3d::UnitZ(); // Assuming gravity is along Z
258 // now correct for negative z
259 grav_versor_expected = -grav_versor_expected;
260 auto dot_product = accel.dot(grav_versor_expected);
261 dot_product = std::max(-1.0, std::min(1.0, dot_product));
262 double angle_rad = std::acos(dot_product);
263 double angle_deg = angle_rad * 180.0 / M_PI;
264 gravity_axis = Axis::Z;
265 gravity_direction = Direction::NEGATIVE;
266 printf("[INFO] IMU Initialization: Gravity angle = %.2f degrees\n", angle_deg);
267 if (angle_deg > 15.0)
268 {
269 printf("[ERROR] IMU Initialization: Gravity angle too large, cannot initialize\n");
270 is_initialized = false;
271 return;
272 }
273 else
274 {
275 printf("[INFO] IMU Initialization: Gravity angle within acceptable range\n");
276 is_initialized = true;
277 }
278
279
280 printf("[INFO] Frame transform initialized - Gravity axis: %d, Direction: %d\n",
281 static_cast<int>(gravity_axis),
282 static_cast<int>(gravity_direction));
283}
284void voxl::FrameTransform::detectJerk(const imu_data_t &data)
285{
286 // C++17 real-time optimization: Load velocity once with proper memory ordering
287 const float vel_mag_current = vel_mag.load(std::memory_order_acquire);
288
289 // FIX: Only skip jerk detection if in-flight AND we've completed at least one full cycle
290 // This prevents deadlock on first initialization
291 if (vel_mag_current > VEL_MAG_JERK_THRESHOLD)
292 {
293 // In-flight: Only reset if we've already collected enough samples
294 // This allows first initialization to complete even if there's movement
295 if (current_total_samples >= expected_total_samples * 0.5f)
296 {
297 resetJerkDetection();
298 return;
299 }
300 // Otherwise, continue collecting samples for initial calibration
301 }
302 // C++17 Real-time optimization: Construct vectors in-place, avoid temporaries
303 const Eigen::Vector3d acc_sample(data.accl_ms2[0], data.accl_ms2[1], data.accl_ms2[2]);
304 const Eigen::Vector3d gyro_sample(data.gyro_rad[0], data.gyro_rad[1], data.gyro_rad[2]);
305
306 // Accumulate data for jerk detection
307 if (current_total_samples <= expected_total_samples * 0.5f)
308 {
309 avg_acc_1t0 += acc_sample;
310 avg_gyro_1t0 += gyro_sample;
311 acc1t0_samples.push_back(acc_sample);
312 gyro1t0_samples.push_back(gyro_sample);
313 current_total_samples += 1.0f;
314 return;
315 }
316 else if (current_total_samples > expected_total_samples * 0.5f && current_total_samples < expected_total_samples)
317 {
318 // In the second half of the window
319 avg_acc_2t1 += acc_sample;
320 avg_gyro_2t1 += gyro_sample;
321 acc2t1_samples.push_back(acc_sample);
322 gyro2t1_samples.push_back(gyro_sample);
323 current_total_samples += 1.0f;
324 }
325 else if (current_total_samples >= expected_total_samples)
326 {
327 // already have enough samples for this window, now compute variance per window segment
328
329 double var_acc1t0 = 0.0, var_gyro1t0 = 0.0, var_acc2t1 = 0.0, var_gyro2t1 = 0.0;
330
331 avg_acc_1t0 /= acc1t0_samples.size();
332 avg_gyro_1t0 /= gyro1t0_samples.size();
333 avg_acc_2t1 /= acc2t1_samples.size();
334 avg_gyro_2t1 /= gyro2t1_samples.size();
335
336 // note that the # of samples for the same segment is the same for acc and gyro
337 for (size_t i = 0; i < acc1t0_samples.size(); ++i)
338 {
339 var_acc1t0 += (acc1t0_samples[i] - avg_acc_1t0).dot(acc1t0_samples[i] - avg_acc_1t0);
340 var_gyro1t0 += (gyro1t0_samples[i] - avg_gyro_1t0).dot(gyro1t0_samples[i] - avg_gyro_1t0);
341 }
342 var_acc1t0 = std::sqrt(var_acc1t0 / (acc1t0_samples.size() - 1));
343 var_gyro1t0 = std::sqrt(var_gyro1t0 / (gyro1t0_samples.size() - 1));
344
345 for (size_t i = 0; i < acc2t1_samples.size(); ++i)
346 {
347 var_acc2t1 += (acc2t1_samples[i] - avg_acc_2t1).dot(acc2t1_samples[i] - avg_acc_2t1);
348 var_gyro2t1 += (gyro2t1_samples[i] - avg_gyro_2t1).dot(gyro2t1_samples[i] - avg_gyro_2t1);
349 }
350 var_acc2t1 = std::sqrt(var_acc2t1 / (acc2t1_samples.size() - 1));
351 var_gyro2t1 = std::sqrt(var_gyro2t1 / (gyro2t1_samples.size() - 1));
352 if (en_debug)
353 {
354 printf("Accelerometer variance: %f, %f\n", var_acc1t0, var_acc2t1);
355 printf("Gyroscope variance: %f, %f\n", var_gyro1t0, var_gyro2t1);
356 }
357 // C++17: Use structured bindings conceptually - evaluate jerk conditions
358 bool accel_jerk_detected = false;
359 bool gyro_jerk_detected = false;
360
361 switch (jerk_opt)
362 {
363 case JerkOption::ACCEL_ONLY:
364 accel_jerk_detected = (var_acc1t0 > ACC_VAR_THRESHOLD || var_acc2t1 > ACC_VAR_THRESHOLD);
365 break;
366 case JerkOption::GYRO_ONLY:
367 gyro_jerk_detected = (var_gyro1t0 > GYRO_VAR_THRESHOLD || var_gyro2t1 > GYRO_VAR_THRESHOLD);
368 break;
369 case JerkOption::ACCEL_AND_GYRO:
370 accel_jerk_detected = (var_acc1t0 > ACC_VAR_THRESHOLD || var_acc2t1 > ACC_VAR_THRESHOLD);
371 gyro_jerk_detected = (var_gyro1t0 > GYRO_VAR_THRESHOLD || var_gyro2t1 > GYRO_VAR_THRESHOLD);
372 break;
373 case JerkOption::NONE:
374 // Jerk detection disabled - report as jerked (non-static)
375 resetJerkDetection();
376 return;
377 }
378
379 // FIX: Report jerk status but DON'T reset counters - allows detection to continue
380 // This prevents infinite reset loops on first initialization
381 has_acc_jerk.store(accel_jerk_detected, std::memory_order_release);
382 has_gyro_jerk.store(gyro_jerk_detected, std::memory_order_release);
383 non_static.store(accel_jerk_detected || gyro_jerk_detected, std::memory_order_release);
384 avg_acc_1t0.setZero(); // avg_acc_2t1;
385 avg_gyro_1t0.setZero(); // avg_gyro_2t1;
386 avg_acc_2t1.setZero();
387 avg_gyro_2t1.setZero();
388 current_total_samples = 0; // static_cast<float>(acc2t1_samples.size());
389 acc1t0_samples.clear(); // acc2t1_samples;
390 gyro1t0_samples.clear(); // gyro2t1_samples;
391 acc2t1_samples.clear(); // acc2t1_samples;
392 gyro2t1_samples.clear(); // gyro2t1_samples;
393
394 return;
395 }
396}
397
398void voxl::FrameTransform::resetJerkDetection()
399{
400 has_acc_jerk.store(true, std::memory_order_release);
401 has_gyro_jerk.store(true, std::memory_order_release);
402 non_static.store(true, std::memory_order_release);
403 // reset for next window
404 // note that we do not reset the entirity of the window, but only the second half
405 avg_acc_1t0.setZero(); // avg_acc_2t1;
406 avg_gyro_1t0.setZero(); // avg_gyro_2t1;
407 avg_acc_2t1.setZero();
408 avg_gyro_2t1.setZero();
409 current_total_samples = 0; // static_cast<float>(acc2t1_samples.size());
410 acc1t0_samples.clear(); // acc2t1_samples;
411 gyro1t0_samples.clear(); // gyro2t1_samples;
412 acc2t1_samples.clear();
413 gyro2t1_samples.clear();
414}
415// ============================================================================
416// JERK DETECTION VARIABLES
417// ============================================================================
418
419/**
420 * @brief Flag indicating if accelerometer jerk is detected
421 */
422std::atomic<bool> has_acc_jerk(false);
423
424/**
425 * @brief Flag indicating if gyroscope jerk is detected
426 */
427std::atomic<bool> has_gyro_jerk(false);
428
429/**
430 * @brief Non-static flag for jerk detection
431 */
432std::atomic<bool> non_static(false);
433
434/**
435 * @brief Window size in seconds for jerk detection
436 */
437double window_size_s = 1.0;
438
439std::atomic<float> vel_mag(0.0f); ///< Current velocity magnitude
Common definitions and utilities for the VOXL OpenVINS server.
int en_verbose
Enable verbose output.
Definition VoxlVars.cpp:151
bool occlude_stereo_right
Occlude stereo right.
Definition VoxlVars.cpp:214
int cameras_used
Number of cameras currently in use.
Definition VoxlVars.cpp:202
volatile int64_t last_cam_time
Timestamp of last camera data (nanoseconds)
Definition VoxlVars.cpp:199
float fusion_rate_dt_ms
Fusion rate in milliseconds.
Definition VoxlVars.cpp:217
volatile int64_t last_imu_timestamp_ns
Timestamp of last IMU data (nanoseconds)
Definition VoxlVars.cpp:177
int camera_pipe_channels[MAX_CAM_CNT]
Camera pipe channels array.
Definition VoxlVars.cpp:224
volatile int main_running
Main process running flag.
Definition VoxlVars.cpp:38
char folder_base[CHAR_BUF_SIZE]
Base folder for yaml configuration files.
Definition VoxlVars.cpp:145
std::atomic< uint32_t > active_callbacks
Number of callbacks inside the system.
Definition VoxlVars.cpp:56
ov_msckf::VioManagerOptions vio_manager_options
VIO manager options.
Definition VoxlVars.cpp:28
int quality_initial_to_bad_count
Consecutive samples for INITIAL→BAD transition.
Definition VoxlVars.cpp:130
int quality_low_thresh_initial
Quality low threshold for INITIAL state.
Definition VoxlVars.cpp:121
int takeoff_cam
Takeoff camera identifier.
Definition VoxlVars.cpp:190
int quality_bad_to_good_count
Consecutive samples for BAD→GOOD transition.
Definition VoxlVars.cpp:136
float fast_yaw_thresh
Fast yaw threshold.
Definition VoxlVars.cpp:111
int en_auto_reset
Enable automatic reset functionality.
Definition VoxlVars.cpp:78
float auto_fallback_timeout_s
Auto fallback timeout (seconds)
Definition VoxlVars.cpp:102
float auto_reset_max_velocity
Maximum velocity threshold for auto reset.
Definition VoxlVars.cpp:81
char imu_name[64]
IMU device name.
Definition VoxlVars.cpp:164
voxl::FrameTransform frame_transform
Global frame transform instance.
Definition VoxlVars.cpp:183
bool en_cont_yaw_checks
Enable continuous yaw checks.
Definition VoxlVars.cpp:108
bool occlude_stereo_left
Occlude stereo left.
Definition VoxlVars.cpp:211
int quality_good_to_bad_count
Consecutive samples for GOOD→BAD transition.
Definition VoxlVars.cpp:139
float auto_reset_max_v_cov_timeout_s
Timeout duration for velocity covariance reset (seconds)
Definition VoxlVars.cpp:90
double window_size_s
Window size in seconds for jerk detection.
Definition VoxlVars.cpp:437
std::mutex reset_mtx
Mutex used by reset thread.
Definition VoxlVars.cpp:59
float auto_reset_max_v_cov
Maximum velocity covariance for timeout reset.
Definition VoxlVars.cpp:87
int using_stereo
using_stereo
Definition VoxlVars.cpp:142
float ok_state_grace_timeout_s
Minimum amount of time after initialization that quality is held low (CEP)
Definition VoxlVars.cpp:99
voxl::img_ringbuf_packet * img_ringbuf
Image ring buffer for processing.
Definition VoxlVars.cpp:231
bool en_imu_body
Enable IMU body measurements.
Definition VoxlVars.cpp:157
float auto_reset_min_feature_timeout_s
Minimum feature timeout for auto reset (seconds)
Definition VoxlVars.cpp:96
float auto_fallback_min_v
Minimum velocity for auto fallback.
Definition VoxlVars.cpp:105
float takeoff_alt_threshold
Takeoff altitude threshold.
Definition VoxlVars.cpp:208
imu_model_t imu_model
Active IMU model.
Definition VoxlVars.cpp:167
int en_takeoff_cam
Enable takeoff camera functionality.
Definition VoxlVars.cpp:193
std::atomic< uint32_t > reset_num_counter
Counter which increments on resets.
Definition VoxlVars.cpp:53
float fast_yaw_timeout_s
Fast yaw timeout (seconds)
Definition VoxlVars.cpp:114
int auto_reset_min_features
Minimum number of features for auto reset.
Definition VoxlVars.cpp:93
std::unique_ptr< ov_msckf::VioManager > vio_manager
Main VIO manager instance.
Definition VoxlVars.cpp:31
std::vector< int > takeoff_cams
Vector of takeoff camera identifiers.
Definition VoxlVars.cpp:196
int quality_high_thresh
Quality high threshold for recovery.
Definition VoxlVars.cpp:127
int en_debug
Enable debug output.
Definition VoxlVars.cpp:148
std::vector< cam_info > cam_info_vec
Vector of camera configuration information.
Definition VoxlVars.cpp:170
float auto_reset_max_v_cov_instant
Maximum velocity covariance for instant reset.
Definition VoxlVars.cpp:84
int quality_low_thresh_good
Quality low threshold for GOOD state.
Definition VoxlVars.cpp:124
int quality_initial_to_good_count
Consecutive samples for INITIAL→GOOD transition.
Definition VoxlVars.cpp:133
int config_only
Configuration only mode.
Definition VoxlVars.cpp:154
std::condition_variable reset_cv
Reset conditional variable.
Definition VoxlVars.cpp:62
bool sync_config
Flag to indicate if configuration synchronization is enabled.
Definition VoxlVars.cpp:233
Global variable declarations and constants for VOXL OpenVINS server.
#define VEL_MAG_JERK_THRESHOLD
Velocity magnitude threshold for jerk detection.
Definition VoxlVars.h:46
std::atomic< bool > non_static
Non-static flag for jerk detection.
std::atomic< bool > is_resetting
VIO reset state flag.
std::atomic< uint8_t > vio_state
Current VIO system state.
std::atomic< bool > is_armed
System armed state.
std::atomic< float > alt_z
Altitude z.
std::atomic< bool > has_acc_jerk
Flag indicating if accelerometer jerk is detected.
std::atomic< uint32_t > vio_error_codes
VIO error codes.
std::atomic< float > vel_mag
Velocity Magnitude.
#define ACC_VAR_THRESHOLD
Accelerometer variance threshold for motion detection.
Definition VoxlVars.h:45
imu_model_t
Enumeration of supported IMU models.
Definition VoxlVars.h:666
std::atomic< bool > is_imu_connected
IMU connection state.
std::atomic< bool > reset_requested
Should reset floag.
std::atomic< bool > has_gyro_jerk
Flag indicating if gyroscope jerk is detected.
std::atomic< double > imu_rate_hz
Estimated IMU sampling rate in Hz.
std::atomic< bool > is_cam_connected
Camera connection state.
#define CHAR_BUF_SIZE
Standard character buffer size.
Definition VoxlVars.h:303
#define GYRO_VAR_THRESHOLD
Gyro variance threshold for motion detection.
Definition VoxlVars.h:44
#define MAX_CAM_CNT
Maximum number of cameras supported by VOXL2.
Definition VoxlVars.h:296
Structure for handling IMU frame transformations.
Definition VoxlVars.h:82
Structure to hold image data packet for the ring buffer.
Definition VoxlVars.h:61