I am working on integrating OpenVINS with an ArduPilot-based system using external vision as the primary navigation source.
Setup
-
Platform: ArduPilot (SITL / real vehicle)
-
VIO: OpenVINS publishing
/ov_msckf/odomimu(Odometry) -
Camera: mounted at ~45° tilt
-
ROS 2 environment
-
Previously used a custom MAVLink bridge to send:
-
VISION_POSITION_ESTIMATE -
VISION_SPEED_ESTIMATE
-
What I’ve done
-
Converted OpenVINS output (Z-up frame) to NED and sent via MAVLink
-
Verified that VIO trajectory matches ground truth when GPS is enabled
-
Disabled GPS and configured EKF3 for external navigation:
-
EK3_SRC1_POSXY = 6 -
EK3_SRC1_POSZ = 6(also tested with baro) -
EK3_SRC1_VELXY = 6 -
EK3_SRC1_VELZ = 6 -
EK3_SRC1_YAW = 6
-
-
Set EKF origin at startup
-
Disabled compass (to avoid yaw conflicts)
-
Tuned EKF gates and noise parameters for VIO
Observed behavior
-
Vehicle takes off correctly and reaches target altitude
-
After reaching altitude, it starts rotating unexpectedly
-
Shortly after, EKF reports variance errors
-
System becomes unstable
Key observation
-
With GPS enabled → system is stable and trajectory matches ground truth
-
With GPS disabled (VIO only) → instability appears after takeoff
-
VIO itself appears accurate
Questions
-
Is sending
VISION_POSITION_ESTIMATE+VISION_SPEED_ESTIMATEdirectly sufficient, or is MAVROS/odometry/inrecommended? -
Could this issue be caused by:
-
Frame mismatch (ENU vs NED, FLU vs FRD)?
-
Incorrect covariance values?
-
Improper yaw alignment or initialization?
-
Camera tilt (45°) not properly accounted for?
-
-
Is there a recommended workflow for initializing EKF origin and yaw when using VIO-only (no GPS)?
-
Are there specific EKF3 parameters that are critical for stable VIO-only operation beyond the standard
EK3_SRC1_*settings?
Any guidance or debugging suggestions would be greatly appreciated.