VOXL OpenVINS Server 1.0
Visual Inertial Odometry Server for VOXL Platform
Loading...
Searching...
No Matches
VoxlHK.h
Go to the documentation of this file.
1/**
2 * @file VoxlHK.h
3 * @brief Housekeeping and data publishing for VOXL OpenVINS
4 * @author Zauberflote
5 * @date 2025
6 * @version 1.0
7 *
8 * This header defines the housekeeping system for the VOXL OpenVINS server,
9 * including data publishing, angular velocity calculations, and coordinate
10 * frame transformations. It provides the interface for outputting VIO data
11 * to external systems.
12 */
13
14#ifndef VOXL_HK_H
15#define VOXL_HK_H
16#pragma once
17
18// Standard includes
19#include <atomic>
20#include <memory>
21
22// Third-party includes
23#include <modal_pipe.h>
24#include <modal_json.h>
25#include <voxl_common_config.h>
26#include <core/VioManager.h>
27#include <core/VioManagerOptions.h>
28#include <types/LandmarkRepresentation.h>
29#include <cstring>
30#include <state/State.h>
31#include <state/StateHelper.h>
32#include <types/Landmark.h>
33#include <types/Type.h>
34#include <feat/Feature.h>
35#include <cmath>
36#include <algorithm>
37#include <thread>
38#include <chrono>
39#include <Eigen/Eigenvalues>
40// Local includes
41#include "VoxlVars.h"
42#include "VoxlCommon.h"
43
44namespace voxl
45{
46
47 // ============================================================================
48 // ENUMERATIONS
49 // ============================================================================
50
51 /**
52 * @enum ANG_VEL_TYPE
53 * @brief Types of angular velocity calculations
54 *
55 * This enumeration defines the different methods available for calculating
56 * angular velocity from quaternion data.
57 */
58 enum class ANG_VEL_TYPE
59 {
60 QUAT_DIRTY, ///< Dirty quaternion-based angular velocity
61 RPY_DIRTY, ///< Dirty roll-pitch-yaw based angular velocity
62 IMU_BIAS ///< IMU bias-corrected angular velocity
63 };
64
65 // ============================================================================
66 // UTILITY FUNCTIONS
67 // ============================================================================
68
69 /**
70 * @brief Calculate dirty angular velocity from quaternions
71 *
72 * This function computes the angular velocity using a "dirty" method that
73 * directly differentiates quaternions. It's computationally efficient but
74 * may not be as accurate as more sophisticated methods.
75 *
76 * @param q_k Current quaternion (4x1 vector)
77 * @param q_km1 Previous quaternion (4x1 vector)
78 * @param dt Time difference in seconds
79 * @return Angular velocity vector (3x1) in radians per second
80 */
81 inline Eigen::Matrix<double, 3, 1> dirtyOmega(const Eigen::Matrix<double, 4, 1> &q_k,
82 const Eigen::Matrix<double, 4, 1> &q_km1,
83 double dt)
84 {
85 dt *= 1e9; // Convert to nanoseconds for VOXL
86 if (dt <= 0.0)
87 {
88 return Eigen::Vector3d::Zero(); // Bad dt
89 }
90 if (q_k.isZero(0) || q_km1.isZero(0))
91 {
92 return Eigen::Vector3d::Zero(); // First call
93 }
94
95 Eigen::Matrix<double, 4, 1> dq = ov_core::quat_multiply(q_k, ov_core::Inv(q_km1));
96 return (2.0 / dt) * dq.head<3>();
97 }
98
99 /**
100 * @brief Get OpenVINS to FRD coordinate frame transformation matrix
101 *
102 * This function returns the rotation matrix that transforms from the
103 * OpenVINS coordinate frame to the Front-Right-Down (FRD) coordinate frame
104 * commonly used in aerospace applications.
105 *
106 * TODO: Port this for greater possibility of orientations --> case by case etc
107 *
108 * @return 3x3 rotation matrix from OpenVINS to FRD frame
109 */
110 inline const Eigen::Matrix3d &R_OV_FRD()
111 {
112 static const Eigen::Matrix3d R{
113 (Eigen::Matrix3d() << 1, 0, 0, 0, -1, 0, 0, 0, -1).finished()};
114 return R;
115 }
116
117 // ============================================================================
118 // PUBLISHER CLASS
119 // ============================================================================
120
121 /**
122 * @class Publisher
123 * @brief Singleton class for publishing VIO data
124 *
125 * This class manages the publication of VIO data to external systems through
126 * pipe interfaces. It implements the singleton pattern to ensure only one
127 * instance exists throughout the application lifecycle.
128 *
129 * The publisher handles:
130 * - VIO state data formatting
131 * - Track base information
132 * - Coordinate frame transformations
133 * - Data packet generation and transmission
134 */
136 {
137 public:
138 /**
139 * @brief Get singleton instance
140 * @return Reference to the singleton Publisher instance
141 */
143 {
144 static Publisher instance;
145 return instance;
146 }
147
148 // Delete copy constructor and assignment operator for singleton
149 Publisher(const Publisher &) = delete;
150 Publisher &operator=(const Publisher &) = delete;
151
152 /**
153 * @brief Start the publisher
154 *
155 * Initializes the publisher and prepares it for data transmission.
156 */
157 void start();
158
159 /**
160 * @brief Control pipe callback function
161 *
162 * Callback function to handle control pipe messages
163 */
164 static void ov_vio_control_pipe_cb(int ch, char *string, int bytes, void *context);
165
166 /**
167 * @brief Publish VIO data
168 *
169 * Publishes the current VIO state and tracking information to external
170 * systems through the configured pipe interfaces.
171 *
172 * @param state Current VIO state
173 * @param used_features_map Map of used features at current timestamp
174 */
175 void publish(std::shared_ptr<ov_msckf::State> state,
176 std::map<double, std::vector<std::shared_ptr<ov_core::Feature>>> used_features_map = {});
177
178 /**
179 * @brief Stop the publisher
180 *
181 * Stops the publisher and cleans up resources.
182 */
183 void stop();
184
185 /**
186 * @brief Check if auto-reset should be triggered
187 *
188 * Evaluates current VIO state and error conditions to determine
189 * if an automatic reset should be triggered.
190 *
191 * @param state Current VIO state
192 * @param quality Current quality value
193 * @param n_features Number of tracked features
194 * @param V_uncertainty Velocity uncertainty
195 * @param yawrate Calculated yaw rate from angular velocity
196 * @param current_velocity Current velocity magnitude
197 * @param vel_x X-component of velocity
198 * @param vel_y Y-component of velocity
199 * @return true if auto-reset should be triggered, false otherwise
200 */
201 bool should_auto_reset(std::shared_ptr<ov_msckf::State> state,
202 int quality,
203 int n_features,
204 double V_uncertainty,
205 double yawrate,
206 double current_velocity,
207 double vel_x,
208 double vel_y);
209
210 /**
211 * @brief Calculate Quality of the VIO state
212 *
213 * This function computes the quality score based on the features used at
214 * the current timestamp. The quality calculation considers:
215 * 1. Grid distribution: 5x5 grid per camera with 50 features target (2 per grid)
216 * 2. SLAM features: weighted by covariance largest eigenvalue and quality field
217 * 3. MSCKF features: weighted by quality field and number of measurements
218 *
219 * @param used_features_map Map of used features at the current timestamp
220 * @param slam_features Map of SLAM features from the state
221 * @param state Current VIO state for covariance access
222 * @return Quality score (0-100, higher is better)
223 */
224 double calcQuality(const std::map<double, std::vector<std::shared_ptr<ov_core::Feature>>> &used_features_map,
225 std::unordered_map<size_t, std::shared_ptr<ov_type::Landmark>> &slam_features,
226 std::shared_ptr<ov_msckf::State> state);
227
228 /**
229 * @brief Set the first packet flag
230 *
231 * This function sets the first packet flag to the provided value.
232 *
233 * @param first_packet The value to set the first packet flag to
234 */
235 void set_first_packet(bool first_packet_)
236 {
237 first_packet = first_packet_;
238 };
239 // ADD BLANK PUBLISHER TO INDICATE MISSING SENSORS
240 void publishBlank();
241
242 private:
243 /**
244 * @brief Private constructor for singleton pattern
245 */
246 Publisher();
247
248 /**
249 * @brief Private destructor for singleton pattern
250 */
251 ~Publisher();
252
253 // ============================================================================
254 // PRIVATE MEMBER VARIABLES
255 // ============================================================================
256
257 /** @brief Flag indicating if this is the first packet */
258 bool first_packet = true;
259
260 /** @brief VIO data packet structure */
261 vio_data_t vio_packet;
262
263 /** @brief Previous VIO state for differential calculations */
264 std::shared_ptr<ov_msckf::State> past_state;
265
266 /** @brief Previous quaternion for angular velocity calculation */
267 Eigen::Matrix<double, 4, 1> past_q_I_G;
268
269 /** @brief Type of angular velocity calculation to use */
271 };
272
273 // ============================================================================
274 // HEALTH CHECK CLASS
275 // ============================================================================
276
277 /**
278 * @class HealthCheck
279 * @brief Health monitoring system for VOXL OpenVINS
280 *
281 * This class provides comprehensive health monitoring capabilities for
282 * the VIO system, including error code monitoring, system state checks,
283 * and performance monitoring. It runs at 30Hz and continuously monitors
284 * the system health.
285 */
287 {
288 public:
289 /**
290 * @brief Get singleton instance
291 * @return Reference to the singleton HealthCheck instance
292 */
294 {
295 static HealthCheck instance;
296 return instance;
297 }
298
299 // Delete copy constructor and assignment operator for singleton
300 HealthCheck(const HealthCheck &) = delete;
301 HealthCheck &operator=(const HealthCheck &) = delete;
302
303 /**
304 * @brief Start the health check system
305 *
306 * Initializes and starts the health monitoring thread that runs at 30Hz.
307 * The thread continuously monitors system health and error conditions.
308 */
309 void start();
310
311 /**
312 * @brief Stop the health check system
313 *
314 * Stops the health monitoring thread and performs cleanup.
315 */
316 void stop();
317
318 /**
319 * @brief Check if health monitoring is running
320 * @return true if health check is active, false otherwise
321 */
322 bool isRunning() const { return running_.load(); }
323
324 /**
325 * @brief Clear specific error codes
326 *
327 * Clears the specified error codes from the global error state.
328 * This is useful when errors are resolved and should no longer
329 * be reported.
330 *
331 * @param error_mask Bit mask of error codes to clear
332 * @param clear_all If true, clear all error codes
333 */
334 static void clearErrorCodes(uint32_t error_mask)
335 {
336 clearErrorCodes(error_mask, false);
337 }
338 static void clearErrorCodes(uint32_t error_mask, bool clear_all);
339
340 private:
341 /**
342 * @brief Private constructor for singleton pattern
343 */
344 HealthCheck();
345
346 /**
347 * @brief Private destructor for singleton pattern
348 */
349 ~HealthCheck();
350
351 /**
352 * @brief Main health check loop
353 *
354 * Runs at 30Hz and performs comprehensive health monitoring including:
355 * - Error code analysis and logging
356 * - System state validation
357 * - Performance monitoring
358 * - Auto-reset condition checking
359 */
360 void healthCheckLoop();
361
362 /**
363 * @brief Analyze and log error codes
364 *
365 * Examines the current error codes and logs detailed information
366 * about any active errors or warnings.
367 */
368 void analyzeErrorCodes();
369
370 /**
371 * @brief Check system connectivity
372 *
373 * Monitors the connection status of cameras and IMU, logging
374 * any disconnection events or connectivity issues.
375 */
376 void checkSystemConnectivity();
377
378 /**
379 * @brief Monitor system performance
380 *
381 * Tracks system performance metrics including processing rates,
382 * memory usage, and timing statistics.
383 */
384 void monitorSystemPerformance();
385
386 /**
387 * @brief Check auto-reset conditions
388 *
389 * Evaluates whether auto-reset conditions are met based on
390 * current system state and error conditions.
391 */
392 void checkAutoResetConditions();
393
394 /**
395 * @brief Handle VINS reset command
396 *
397 * This function is invoked when a reset command is received.
398 * It performs the necessary actions to reset the VIO system.
399 */
400 void checkVINSResetRequest();
401
402 /**
403 * @brief Perform a hard reset of the VIO system
404 *
405 * This function creates a fresh instance of the
406 * VIO manager and reinitializes the system.,
407 */
408 int doHardReset();
409
410 // ============================================================================
411 // PRIVATE MEMBER VARIABLES
412 // ============================================================================
413
414 /** @brief Flag indicating if health check is running */
415 std::atomic<bool> running_{false};
416
417 /** @brief Health check thread */
418 std::thread health_thread_;
419
420 /** @brief Last error code state for change detection */
421 uint32_t last_error_codes_{0};
422
423 /** @brief Last VIO state for change detection */
424 uint8_t last_vio_state_{0};
425
426 /** @brief Last IMU connection state for change detection */
427 bool last_imu_connected_{false};
428
429 /** @brief Last camera connection state for change detection */
430 bool last_cam_connected_{false};
431
432 /** @brief Used to track the first camera connection */
433 bool first_camera_connection_seen_{false};
434
435 /** @brief Timestamp of last health check */
436 int64_t last_health_check_ns_{0};
437
438 /** @brief Counter for health check iterations */
439 uint64_t health_check_count_{0};
440
441 /** @brief Mutex for thread safety */
442 mutable std::mutex health_mutex_;
443
444 /** @brief Timeout interval before we can reset again */
445 const uint64_t INIT_FAILURE_TIMEOUT_NS = 2000000000; // 2 seconds
446
447 /** @brief Timestamp of last reset */
448 uint64_t time_of_last_reset = 0;
449 };
450
451} // namespace voxl
452
453#endif // VOXL_HK_H
Common definitions and utilities for the VOXL OpenVINS server.
Global variable declarations and constants for VOXL OpenVINS server.
Health monitoring system for VOXL OpenVINS.
Definition VoxlHK.h:287
void start()
Start the health check system.
bool isRunning() const
Check if health monitoring is running.
Definition VoxlHK.h:322
static void clearErrorCodes(uint32_t error_mask)
Clear specific error codes.
Definition VoxlHK.h:334
void stop()
Stop the health check system.
static HealthCheck & getInstance()
Get singleton instance.
Definition VoxlHK.h:293
Singleton class for publishing VIO data.
Definition VoxlHK.h:136
void set_first_packet(bool first_packet_)
Set the first packet flag.
Definition VoxlHK.h:235
void publish(std::shared_ptr< ov_msckf::State > state, std::map< double, std::vector< std::shared_ptr< ov_core::Feature > > > used_features_map={})
Publish VIO data.
static Publisher & getInstance()
Get singleton instance.
Definition VoxlHK.h:142
static void ov_vio_control_pipe_cb(int ch, char *string, int bytes, void *context)
Control pipe callback function.
void stop()
Stop the publisher.
void start()
Start the publisher.
bool should_auto_reset(std::shared_ptr< ov_msckf::State > state, int quality, int n_features, double V_uncertainty, double yawrate, double current_velocity, double vel_x, double vel_y)
Check if auto-reset should be triggered.
double calcQuality(const std::map< double, std::vector< std::shared_ptr< ov_core::Feature > > > &used_features_map, std::unordered_map< size_t, std::shared_ptr< ov_type::Landmark > > &slam_features, std::shared_ptr< ov_msckf::State > state)
Calculate Quality of the VIO state.
Main namespace for VOXL OpenVINS server components.
ANG_VEL_TYPE
Types of angular velocity calculations.
Definition VoxlHK.h:59
@ IMU_BIAS
IMU bias-corrected angular velocity.
@ QUAT_DIRTY
Dirty quaternion-based angular velocity.
@ RPY_DIRTY
Dirty roll-pitch-yaw based angular velocity.
const Eigen::Matrix3d & R_OV_FRD()
Get OpenVINS to FRD coordinate frame transformation matrix.
Definition VoxlHK.h:110
Eigen::Matrix< double, 3, 1 > dirtyOmega(const Eigen::Matrix< double, 4, 1 > &q_k, const Eigen::Matrix< double, 4, 1 > &q_km1, double dt)
Calculate dirty angular velocity from quaternions.
Definition VoxlHK.h:81