Biorbd
KalmanReconsIMU.cpp
1 #define BIORBD_API_EXPORTS
2 #include "RigidBody/KalmanReconsIMU.h"
3 
4 #include <rbdl/Model.h>
5 #include <rbdl/Kinematics.h>
6 #include "BiorbdModel.h"
7 #include "Utils/Error.h"
8 #include "Utils/Matrix.h"
9 #include "Utils/Rotation.h"
10 #include "RigidBody/GeneralizedCoordinates.h"
11 #include "RigidBody/GeneralizedVelocity.h"
12 #include "RigidBody/GeneralizedAcceleration.h"
13 #include "RigidBody/IMU.h"
14 
16  biorbd::rigidbody::KalmanRecons(),
17  m_PpInitial(std::make_shared<biorbd::utils::Matrix>()),
18  m_firstIteration(std::make_shared<bool>(true))
19 {
20 
21 }
22 
24  biorbd::Model &model,
26  biorbd::rigidbody::KalmanRecons(model, model.nbTechIMUs()*9, params),
27  m_PpInitial(std::make_shared<biorbd::utils::Matrix>()),
28  m_firstIteration(std::make_shared<bool>(true))
29 {
30  // Initialize the filter
31  initialize();
32 }
33 
35 {
37  copy.DeepCopy(*this);
38  return copy;
39 }
40 
42 {
44  *m_PpInitial = *other.m_PpInitial;
45  *m_firstIteration = *other.m_firstIteration;
46 }
47 
49 {
51 
52  // Keep in mind the m_Pp from the start
53  *m_PpInitial = *m_Pp;
54 }
55 
57  biorbd::utils::Matrix &InvTp,
58  biorbd::utils::Vector &measure,
59  const std::vector<unsigned int> &occlusion)
60 {
61  for (unsigned int i = 0; i < occlusion.size(); ++i)
62  for (unsigned int j=occlusion[i] * 9; j< occlusion[i] * 9+9; ++j){
63  InvTp(j,j) = 0; // Artefact due to the fact that m_R has a value at (j:j+2,j:j+2)
64  measure[j] = 0;
65  }
66 }
67 
69 {
70  return *m_firstIteration;
71 }
72 
74  biorbd::Model &m,
75  const std::vector<biorbd::rigidbody::IMU> &IMUobs,
79 {
80  // Separate the IMUobs in a big vector
81  biorbd::utils::Vector T(static_cast<unsigned int>(3*3*IMUobs.size())); // Matrix 3*3 * nbIMU
82  for (unsigned int i=0; i<IMUobs.size(); ++i)
83  for (unsigned int j=0; j<3; ++j)
84  T.block(9*i+3*j, 0, 3, 1) = IMUobs[i].block(0,j,3,1);
85 
86  // Reconstruct the kinematics
87  reconstructFrame(m, T, Q, Qdot, Qddot);
88 }
89 
90 
92  biorbd::Model &model,
93  const biorbd::utils::Vector &IMUobs,
97 {
98  // An iteration of the Kalman filter
99  if (*m_firstIteration){
100  *m_firstIteration = false;
101  for (unsigned int i=0; i<300; ++i){
102  // The first time, call in a recursive manner to have a decent initial position
103  reconstructFrame(model, IMUobs, nullptr, nullptr, nullptr);
104 
105  // we don't need the velocity to get to the initial position
106  // Otherwise, there are risks of overshooting
107  m_xp->block(*m_nbDof, 0, *m_nbDof*2, 1) = biorbd::utils::Vector::Zero(*m_nbDof*2);
108  }
109  }
110 
111  // Projected state
112  const biorbd::utils::Vector& xkm(*m_A * *m_xp);
113  biorbd::rigidbody::GeneralizedCoordinates Q_tp(xkm.topRows(*m_nbDof));
114  model.UpdateKinematicsCustom (&Q_tp, nullptr, nullptr);
115 
116  // Projected markers
117  const std::vector<biorbd::rigidbody::IMU>& zest_tp = model.technicalIMU(Q_tp, false);
118  // Jacobian
119  const std::vector<biorbd::utils::Matrix>& J_tp = model.TechnicalIMUJacobian(Q_tp, false);
120  // Create only one matrix for zest and Jacobian
121  biorbd::utils::Matrix H(biorbd::utils::Matrix::Zero(*m_nMeasure, *m_nbDof*3)); // 3*nCentrales => X,Y,Z ; 3*nbDof => Q, Qdot, Qddot
122  biorbd::utils::Vector zest(biorbd::utils::Vector::Zero(*m_nMeasure));
123  std::vector<unsigned int> occlusionIdx;
124  for (unsigned int i=0; i<*m_nMeasure/9; ++i){
125  biorbd::utils::Scalar sum = 0;
126  for (unsigned int j = 0; j < 9; ++j) // Calculate the norm for the 9 components
127  sum += IMUobs(i*9+j)*IMUobs(i*9+j);
128 #ifdef BIORBD_USE_CASADI_MATH
129  if (true){ // If there is an IMU (no zero or NaN)
130 #else
131  if (sum != 0.0 && !std::isnan(sum)){ // If there is an IMU (no zero or NaN)
132 #endif
133  H.block(i*9,0,9,*m_nbDof) = J_tp[i];
134  const biorbd::utils::Rotation& rot = zest_tp[i].rot();
135  for (unsigned int j = 0; j < 3; ++j)
136  zest.block(i*9+j*3, 0, 3, 1) = rot.block(0, j, 3, 1);
137  }
138  else
139  occlusionIdx.push_back(i);
140  }
141 
142  // Make the filter
143  iteration(IMUobs, zest, H, occlusionIdx);
144 
145  getState(Q, Qdot, Qddot);
146 }
147 
149 {
150  biorbd::utils::Error::raise("Reconstructing kinematics for IMU needs measurements");
151 }
biorbd::utils::Vector
Wrapper of the Eigen VectorXd.
Definition: Vector.h:20
biorbd::rigidbody::KalmanReconsIMU::first
bool first()
Return if the first iteration was done.
Definition: KalmanReconsIMU.cpp:68
biorbd::rigidbody::KalmanReconsIMU::manageOcclusionDuringIteration
virtual void manageOcclusionDuringIteration(biorbd::utils::Matrix &InvTp, biorbd::utils::Vector &measure, const std::vector< unsigned int > &occlusion)
Manage the occlusion during the iteration.
Definition: KalmanReconsIMU.cpp:56
biorbd::rigidbody::KalmanParam
Parameters of the reconstruction.
Definition: KalmanRecons.h:25
biorbd::rigidbody::IMUs::technicalIMU
std::vector< biorbd::rigidbody::IMU > technicalIMU(const biorbd::rigidbody::GeneralizedCoordinates &Q, bool updateKin=true)
Return all the technical inertial measurement units (IMU)
Definition: IMUs.cpp:123
biorbd::rigidbody::GeneralizedCoordinates
Class GeneralizedCoordinates.
Definition: GeneralizedCoordinates.h:15
biorbd::rigidbody::KalmanReconsIMU
Class Kinematic reconstruction algorithm using an Extended Kalman Filter for IMU.
Definition: KalmanReconsIMU.h:19
biorbd::rigidbody::KalmanReconsIMU::reconstructFrame
virtual void reconstructFrame()
This function cannot be used to reconstruct frames.
Definition: KalmanReconsIMU.cpp:148
biorbd::utils::Error::raise
static void raise(const biorbd::utils::String &message)
Throw an error message.
Definition: Error.cpp:4
biorbd::rigidbody::KalmanReconsIMU::DeepCopy
biorbd::rigidbody::KalmanReconsIMU DeepCopy() const
Deep copy of the Kalman reconstruction from inertial measurement units (IMU) data.
Definition: KalmanReconsIMU.cpp:34
biorbd::Model
The actual musculoskeletal model that holds everything in biorbd.
Definition: BiorbdModel.h:78
biorbd::rigidbody::KalmanReconsIMU::KalmanReconsIMU
KalmanReconsIMU()
Initialize the Kalman filter and kalman reconstruction for inertial measurement units (IMU) data.
Definition: KalmanReconsIMU.cpp:15
biorbd::utils::Matrix
A wrapper for the Eigen::MatrixXd.
Definition: Matrix.h:21
biorbd::rigidbody::GeneralizedAcceleration
Class GeneralizedAcceleration.
Definition: GeneralizedAcceleration.h:15
biorbd::rigidbody::KalmanRecons::DeepCopy
void DeepCopy(const biorbd::rigidbody::KalmanRecons &other)
Deep copy of Kalman reconstruction.
Definition: KalmanRecons.cpp:46
biorbd::rigidbody::KalmanRecons::initialize
virtual void initialize()
Initialization of the filter.
Definition: KalmanRecons.cpp:160
biorbd::rigidbody::KalmanRecons
Class Kinematic reconstruction algorithm using an Extended Kalman Filter.
Definition: KalmanRecons.h:63
biorbd::utils::Rotation
Rotation matrix.
Definition: Rotation.h:34
biorbd::rigidbody::IMUs::TechnicalIMUJacobian
std::vector< biorbd::utils::Matrix > TechnicalIMUJacobian(const biorbd::rigidbody::GeneralizedCoordinates &Q, bool updateKin=true)
Return the jacobian of the technical inertial measurement units (IMU)
Definition: IMUs.cpp:209
biorbd::rigidbody::KalmanReconsIMU::m_firstIteration
std::shared_ptr< bool > m_firstIteration
If first iteration was done.
Definition: KalmanReconsIMU.h:110
biorbd::rigidbody::Joints::UpdateKinematicsCustom
void UpdateKinematicsCustom(const biorbd::rigidbody::GeneralizedCoordinates *Q=nullptr, const biorbd::rigidbody::GeneralizedVelocity *Qdot=nullptr, const biorbd::rigidbody::GeneralizedAcceleration *Qddot=nullptr)
Update the kinematic variables such as body velocities and accelerations in the model to reflect the ...
Definition: Joints.cpp:1063
biorbd::rigidbody::GeneralizedVelocity
Class GeneralizedVelocity.
Definition: GeneralizedVelocity.h:15
biorbd::rigidbody::KalmanReconsIMU::m_PpInitial
std::shared_ptr< biorbd::utils::Matrix > m_PpInitial
Initial covariance matrix.
Definition: KalmanReconsIMU.h:109
biorbd::rigidbody::KalmanReconsIMU::initialize
virtual void initialize()
Initialization of the filter.
Definition: KalmanReconsIMU.cpp:48