224bool g_stereo_calib_valid =
false;
236void voxl::FrameTransform::update(
const imu_data_t &data)
238 static bool warned_no_imu_body =
false;
242 printf(
"[WARN] IMU body measurements are disabled, THIS WON'T WORK AS EXPECTED.\n");
243 warned_no_imu_body =
true;
258 Eigen::Vector3d accel(data.accl_ms2[0], data.accl_ms2[1], data.accl_ms2[2]);
259 double amag = accel.norm();
265 Eigen::Vector3d accel_n = accel / amag;
266 Eigen::Vector3d grav_versor_expected = -Eigen::Vector3d::UnitZ();
267 double dot_product = std::max(-1.0, std::min(1.0, accel_n.dot(grav_versor_expected)));
268 double angle_deg = std::acos(dot_product) * 180.0 / M_PI;
269 gravity_axis = Axis::Z;
270 gravity_direction = Direction::NEGATIVE;
278 printf(
"[WARN] IMU init: gravity angle %.2f deg > imu_init_max_gravity_angle_deg %.2f deg -- holding "
279 "sensor feed (opt-in level gate; set <0 for any-attitude)\n",
281 is_initialized =
false;
285 is_initialized =
true;
286 printf(
"[INFO] Frame transform initialized (gravity angle %.2f deg, axis Z-, any-attitude feed enabled)\n", angle_deg);
288void voxl::FrameTransform::detectJerk(
const imu_data_t &data)
291 const Eigen::Vector3d acc_sample(data.accl_ms2[0], data.accl_ms2[1], data.accl_ms2[2]);
292 const Eigen::Vector3d gyro_sample(data.gyro_rad[0], data.gyro_rad[1], data.gyro_rad[2]);
295 if (current_total_samples <= expected_total_samples * 0.5f)
297 avg_acc_1t0 += acc_sample;
298 avg_gyro_1t0 += gyro_sample;
299 acc1t0_samples.push_back(acc_sample);
300 gyro1t0_samples.push_back(gyro_sample);
301 current_total_samples += 1.0f;
304 else if (current_total_samples > expected_total_samples * 0.5f && current_total_samples < expected_total_samples)
307 avg_acc_2t1 += acc_sample;
308 avg_gyro_2t1 += gyro_sample;
309 acc2t1_samples.push_back(acc_sample);
310 gyro2t1_samples.push_back(gyro_sample);
311 current_total_samples += 1.0f;
313 else if (current_total_samples >= expected_total_samples)
317 double var_acc1t0 = 0.0, var_gyro1t0 = 0.0, var_acc2t1 = 0.0, var_gyro2t1 = 0.0;
319 avg_acc_1t0 /= acc1t0_samples.size();
320 avg_gyro_1t0 /= gyro1t0_samples.size();
321 avg_acc_2t1 /= acc2t1_samples.size();
322 avg_gyro_2t1 /= gyro2t1_samples.size();
325 for (
size_t i = 0; i < acc1t0_samples.size(); ++i)
327 var_acc1t0 += (acc1t0_samples[i] - avg_acc_1t0).dot(acc1t0_samples[i] - avg_acc_1t0);
328 var_gyro1t0 += (gyro1t0_samples[i] - avg_gyro_1t0).dot(gyro1t0_samples[i] - avg_gyro_1t0);
330 var_acc1t0 = std::sqrt(var_acc1t0 / (acc1t0_samples.size() - 1));
331 var_gyro1t0 = std::sqrt(var_gyro1t0 / (gyro1t0_samples.size() - 1));
333 for (
size_t i = 0; i < acc2t1_samples.size(); ++i)
335 var_acc2t1 += (acc2t1_samples[i] - avg_acc_2t1).dot(acc2t1_samples[i] - avg_acc_2t1);
336 var_gyro2t1 += (gyro2t1_samples[i] - avg_gyro_2t1).dot(gyro2t1_samples[i] - avg_gyro_2t1);
338 var_acc2t1 = std::sqrt(var_acc2t1 / (acc2t1_samples.size() - 1));
339 var_gyro2t1 = std::sqrt(var_gyro2t1 / (gyro2t1_samples.size() - 1));
342 printf(
"Accelerometer variance: %f, %f\n", var_acc1t0, var_acc2t1);
343 printf(
"Gyroscope variance: %f, %f\n", var_gyro1t0, var_gyro2t1);
346 bool accel_jerk_detected =
false;
347 bool gyro_jerk_detected =
false;
351 case JerkOption::ACCEL_ONLY:
354 case JerkOption::GYRO_ONLY:
357 case JerkOption::ACCEL_AND_GYRO:
361 case JerkOption::NONE:
363 resetJerkDetection();
369 has_acc_jerk.store(accel_jerk_detected, std::memory_order_release);
370 non_static.store(accel_jerk_detected || gyro_jerk_detected, std::memory_order_release);
371 avg_acc_1t0.setZero();
372 avg_gyro_1t0.setZero();
373 avg_acc_2t1.setZero();
374 avg_gyro_2t1.setZero();
375 current_total_samples = 0;
376 acc1t0_samples.clear();
377 gyro1t0_samples.clear();
378 acc2t1_samples.clear();
379 gyro2t1_samples.clear();
385void voxl::FrameTransform::resetJerkDetection()
388 non_static.store(
true, std::memory_order_release);
391 avg_acc_1t0.setZero();
392 avg_gyro_1t0.setZero();
393 avg_acc_2t1.setZero();
394 avg_gyro_2t1.setZero();
395 current_total_samples = 0;
396 acc1t0_samples.clear();
397 gyro1t0_samples.clear();
398 acc2t1_samples.clear();
399 gyro2t1_samples.clear();
Common definitions and utilities for the VOXL OpenVINS server.
int en_verbose
Enable verbose output.
bool occlude_stereo_right
Occlude stereo right.
int cameras_used
Number of cameras currently in use.
volatile int64_t last_cam_time
Timestamp of last camera data (nanoseconds)
volatile int64_t last_imu_timestamp_ns
Timestamp of last IMU data (nanoseconds)
int camera_pipe_channels[MAX_CAM_CNT]
Fusion rate in milliseconds.
volatile int main_running
Main process running flag.
char folder_base[CHAR_BUF_SIZE]
Base folder for yaml configuration files.
std::atomic< uint32_t > active_callbacks
Number of callbacks inside the system.
ov_msckf::VioManagerOptions vio_manager_options
VIO manager options.
int quality_initial_to_bad_count
Consecutive samples for INITIAL→BAD transition.
int quality_low_thresh_initial
Quality low threshold for INITIAL state.
int quality_bad_to_good_count
Consecutive samples for BAD→GOOD transition.
float fast_yaw_thresh
Auto fallback timeout (seconds)
int en_auto_reset
Enable automatic reset functionality.
float auto_reset_max_velocity
Maximum velocity threshold for auto reset.
float stereo_z_max
far depth bound for epipolar search (m)
char imu_name[64]
IMU device name.
voxl::FrameTransform frame_transform
Global frame transform instance.
modal_flow::StereoCalib g_stereo_calib
composed by VoxlConfigure
bool occlude_stereo_left
Occlude stereo left.
int quality_good_to_bad_count
Consecutive samples for GOOD→BAD transition.
float auto_reset_max_v_cov_timeout_s
Maximum velocity covariance for instant reset.
float stereo_z_min
near depth bound for epipolar search (m)
std::mutex reset_mtx
Mutex used by reset thread.
int using_stereo
using_stereo
float imu_init_max_gravity_angle_deg
Server-side IMU frame-transform bring-up gravity gate (degrees)
float ok_state_grace_timeout_s
Minimum amount of time after initialization that quality is held low (CEP)
bool en_imu_body
Enable IMU body measurements.
float auto_reset_min_feature_timeout_s
Minimum feature timeout for auto reset (seconds)
float takeoff_alt_threshold
Takeoff altitude threshold.
imu_model_t imu_model
Active IMU model.
std::atomic< uint32_t > soft_reset_num_counter
Counter which increments only on SOFT (front-end-preserving) resets, so field logs can distinguish so...
std::atomic< uint32_t > reset_num_counter
Counter which increments on resets (hard + soft)
float fast_yaw_timeout_s
Fast yaw timeout (seconds)
int auto_reset_min_features
Minimum number of features for auto reset.
std::unique_ptr< ov_msckf::VioManager > vio_manager
Main VIO manager instance.
int quality_high_thresh
Quality high threshold for recovery.
int en_debug
Enable debug output.
std::vector< cam_info > cam_info_vec
Vector of camera configuration information.
int quality_low_thresh_good
Quality low threshold for GOOD state.
int quality_initial_to_good_count
Consecutive samples for INITIAL→GOOD transition.
int config_only
Configuration only mode.
std::condition_variable reset_cv
Reset conditional variable.
bool sync_config
Flag to indicate if configuration synchronization is enabled.
Global variable declarations and constants for VOXL OpenVINS server.
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< 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.
#define ACC_VAR_THRESHOLD
Accelerometer variance threshold for motion detection.
imu_model_t
Enumeration of supported IMU models.
std::atomic< bool > is_imu_connected
IMU connection state.
std::atomic< bool > reset_requested
Should reset floag.
std::atomic< bool > soft_reset_requested
Flag indicating that a front-end-preserving SOFT reset was requested.
std::atomic< bool > is_cam_connected
Camera connection state.
#define CHAR_BUF_SIZE
Standard character buffer size.
#define GYRO_VAR_THRESHOLD
Gyro variance threshold for motion detection.
#define MAX_CAM_CNT
Maximum number of cameras supported by VOXL2.