static void _psmove_orientation_fusion_complementary_marg_update( PSMoveOrientation *orientation_state, float delta_t, const glm::vec3 ¤t_omega, const glm::vec3 ¤t_g, const glm::vec3 ¤t_m) { // Get the direction of the magnetic fields in the identity pose PSMove_3AxisVector identity_m= psmove_orientation_get_magnetometer_calibration_direction(orientation_state); glm::vec3 k_identity_m_direction = glm::vec3(identity_m.x, identity_m.y, identity_m.z); // Get the direction of the gravitational field in the identity pose PSMove_3AxisVector identity_g= psmove_orientation_get_gravity_calibration_direction(orientation_state); glm::vec3 k_identity_g_direction = glm::vec3(identity_g.x, identity_g.y, identity_g.z); // Angular Rotation (AR) Update //----------------------------- // Compute the rate of change of the orientation purely from the gyroscope // q_dot = 0.5*q*omega glm::quat q_current= orientation_state->quaternion; glm::quat q_omega = glm::quat(0.f, current_omega.x, current_omega.y, current_omega.z); glm::quat q_derivative = (q_current*0.5f) * q_omega; // Integrate the rate of change to get a new orientation // q_new= q + q_dot*dT glm::quat q_step = q_derivative * delta_t; glm::quat ar_orientation = q_current + q_step; // Make sure the resulting quaternion is normalized ar_orientation= glm::normalize(ar_orientation); // Magnetic/Gravity (MG) Update //----------------------------- const glm::vec3* mg_from[2] = { &k_identity_g_direction, &k_identity_m_direction }; const glm::vec3* mg_to[2] = { ¤t_g, ¤t_m }; glm::quat mg_orientation; // Always attempt to align with the identity_mg, even if we don't get within the alignment tolerance. // More often then not we'll be better off moving forward with what we have and trying to refine // the alignment next frame. psmove_alignment_quaternion_between_vector_frames( mg_from, mg_to, 0.1f, q_current, mg_orientation); // Blending Update //---------------- // The final rotation is a blend between the integrated orientation and absolute rotation from the earth-frame float mg_wight = orientation_state->fusion_state.complementary_marg_state.mg_weight; orientation_state->quaternion= psmove_quaternion_normalized_lerp(ar_orientation, mg_orientation, mg_wight); // Update the blend weight orientation_state->fusion_state.complementary_marg_state.mg_weight = lerp_clampf(mg_wight, k_base_earth_frame_align_weight, 0.9f); }
static void _psmove_orientation_fusion_complementary_marg_update( PSMoveOrientation *orientation_state, float delta_t, const Eigen::Vector3f ¤t_omega, const Eigen::Vector3f ¤t_g, const Eigen::Vector3f ¤t_m) { // TODO: Following variable is unused PSMoveMadgwickMARGState *marg_state = &orientation_state->fusion_state.madgwick_marg_state; // Get the direction of the magnetic fields in the identity pose PSMove_3AxisVector identity_m= psmove_orientation_get_magnetometer_calibration_direction(orientation_state); Eigen::Vector3f k_identity_m_direction = Eigen::Vector3f(identity_m.x, identity_m.y, identity_m.z); // Get the direction of the gravitational field in the identity pose PSMove_3AxisVector identity_g= psmove_orientation_get_gravity_calibration_direction(orientation_state); Eigen::Vector3f k_identity_g_direction = Eigen::Vector3f(identity_g.x, identity_g.y, identity_g.z); // Angular Rotation (AR) Update //----------------------------- // Compute the rate of change of the orientation purely from the gyroscope // q_dot = 0.5*q*omega Eigen::Quaternionf q_omega = Eigen::Quaternionf(0.f, current_omega.x(), current_omega.y(), current_omega.z()); Eigen::Quaternionf q_derivative = Eigen::Quaternionf(orientation_state->quaternion.coeffs()*0.5f) * q_omega; // Integrate the rate of change to get a new orientation // q_new= q + q_dot*dT Eigen::Quaternionf q_step = Eigen::Quaternionf(q_derivative.coeffs() * delta_t); Eigen::Quaternionf ar_orientation = Eigen::Quaternionf(orientation_state->quaternion.coeffs() + q_step.coeffs()); // Make sure the resulting quaternion is normalized ar_orientation.normalize(); // Magnetic/Gravity (MG) Update //----------------------------- const Eigen::Vector3f* mg_from[2] = { &k_identity_g_direction, &k_identity_m_direction }; const Eigen::Vector3f* mg_to[2] = { ¤t_g, ¤t_m }; Eigen::Quaternionf mg_orientation; bool mg_align_success = psmove_alignment_quaternion_between_vector_frames( mg_from, mg_to, 0.1f, orientation_state->quaternion, mg_orientation); // Blending Update //---------------- if (mg_align_success) { // The final rotation is a blend between the integrated orientation and absolute rotation from the earth-frame float mg_wight = orientation_state->fusion_state.complementary_marg_state.mg_weight; orientation_state->quaternion = psmove_quaternion_normalized_lerp(ar_orientation, mg_orientation, mg_wight); // Update the blend weight orientation_state->fusion_state.complementary_marg_state.mg_weight = lerp_clampf(mg_wight, k_base_earth_frame_align_weight, 0.9f); } else { orientation_state->quaternion = ar_orientation; } }