ethzasl-msf - Modular Sensor Fusion
Time delay compensated single and multi sensor fusion framework based on an EKF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
msf_state_.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2013 Simon Lynen, ASL, ETH Zurich, Switzerland
3  * You can contact the author at <slynen at ethz dot ch>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <msf_core/msf_fwds.h>
18 #include <msf_core/msf_types.hpp>
19 #include <msf_core/msf_tmp.h>
20 #include <Eigen/Dense>
21 #include <Eigen/Geometry>
22 #include <vector>
24 #include <sensor_fusion_comm/ExtState.h>
25 #include <sensor_fusion_comm/DoubleArrayStamped.h>
26 #include <geometry_msgs/PoseWithCovarianceStamped.h>
27 #include <boost/lexical_cast.hpp>
28 
29 namespace msf_core {
30 
31 // Returns the stateVar at position INDEX in the state list, non const version
32 // only for msf_core use you must not make these functions public. Instead
33 // const_cast the state object to const to use the overload.
34 template<typename stateVector_T, typename StateDefinition_T>
35 template<int INDEX>
36 inline typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type GenericState_T<
37  stateVector_T, StateDefinition_T>::getStateVar() {
38 
39  static_assert(
40  (msf_tmp::IsReferenceType<typename boost::fusion::result_of::at_c<stateVector_T, INDEX >::type>::value),
41  "Assumed that boost::fusion would return a reference type here, which is not the case.");
42 
43  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars);
44 }
45 
46 // Returns the state at position INDEX in the state list, non const version
47 // you must not make these functions public. Instead const_cast the state object
48 // to const to use the overload.
49 template<typename stateVector_T, typename StateDefinition_T>
50 template<int INDEX>
51 inline typename msf_tmp::StripReference<
52  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t::value_t&
54 
55  static_assert(
56  (msf_tmp::IsReferenceType<typename boost::fusion::result_of::at_c<stateVector_T, INDEX >::type>::value),
57  "Assumed that boost::fusion would return a reference type here, which is not the case.");
58 
59  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars).state_;
60 }
61 
62 // Apply the correction vector to all state vars.
63 template<typename stateVector_T, typename StateDefinition_T>
65  const Eigen::Matrix<double, nErrorStatesAtCompileTime, 1>& correction) {
66  boost::fusion::for_each(
67  statevars,
69  const Eigen::Matrix<double, nErrorStatesAtCompileTime, 1>,
70  stateVector_T>(correction));
71 }
72 
73 // Returns the Q-block of the state at position INDEX in the state list, not
74 // allowed for core states.
75 template<typename stateVector_T, typename StateDefinition_T>
76 template<int INDEX>
77 inline typename msf_tmp::StripReference<
78  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t::Q_T&
80  typedef typename msf_tmp::StripReference<
81  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t StateVar_T;
82 
83  static_assert(
84  static_cast<int>(StateVar_T::statetype_) != static_cast<int>(
86  static_cast<int>(StateVar_T::statetype_) !=
87  static_cast<int>(msf_core::CoreStateWithoutPropagation),
88  "You requested a non-const reference to a Q-Block for a"
89  "core state of the EKF, but this is not allowed! Use the const version to "
90  "get Q-blocks for core states.");
91 
92  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars).Q;
93 }
94 
95 // Returns the Q-block of the state at position INDEX in the state list, also
96 // possible for core states, since const.
97 template<typename stateVector_T, typename StateDefinition_T>
98 template<int INDEX>
99 inline const typename msf_tmp::StripReference<
100  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t::Q_T&
102  typedef typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type StateVar_T;
103  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars).Q_;
104 }
105 
107 
108 template<typename stateVector_T, typename StateDefinition_T>
110  geometry_msgs::PoseWithCovarianceStamped & pose) {
111  eigen_conversions::vector3dToPoint(get<StateDefinition_T::p>(),
112  pose.pose.pose.position);
113  eigen_conversions::quaternionToMsg(get<StateDefinition_T::q>(),
114  pose.pose.pose.orientation);
115  getPoseCovariance(pose.pose.covariance);
116 }
117 
119 
120 template<typename stateVector_T, typename StateDefinition_T>
122  sensor_fusion_comm::ExtState & state) {
123  eigen_conversions::vector3dToPoint(get<StateDefinition_T::p>(),
124  state.pose.position);
125  eigen_conversions::quaternionToMsg(get<StateDefinition_T::q>(),
126  state.pose.orientation);
127  eigen_conversions::vector3dToPoint(get<StateDefinition_T::v>(),
128  state.velocity);
129 }
130 
132 
133 template<typename stateVector_T, typename StateDefinition_T>
135  sensor_fusion_comm::DoubleArrayStamped & state) {
136  state.data.resize(nStatesAtCompileTime); // Make sure this is correctly sized.
137  boost::fusion::for_each(
138  statevars,
139  msf_tmp::FullStatetoDoubleArray<std::vector<double>, stateVector_T>(
140  state.data));
141 }
142 
144 
145 template<typename stateVector_T, typename StateDefinition_T>
147  sensor_fusion_comm::DoubleArrayStamped & state) {
148  state.data.resize(nCoreStatesAtCompileTime); // Make sure this is correctly sized.
149  boost::fusion::for_each(
150  statevars,
151  msf_tmp::CoreStatetoDoubleArray<std::vector<double>, stateVector_T>(
152  state.data));
153 }
154 
155 template<typename stateVector_T, typename StateDefinition_T>
156 Eigen::Matrix<double,
159  Eigen::Matrix<double,
161  1> data;
162  boost::fusion::for_each(
163  statevars,
165  typename Eigen::Matrix<double,
166  GenericState_T<stateVector_T, StateDefinition_T>::nCoreStatesAtCompileTime,
167  1>, stateVector_T>(data));
168  return data;
169 }
170 
171 //TODO (slynen) Template to container.
172 template<typename stateVector_T, typename StateDefinition_T>
174  std::vector<std::tuple<int, int, int> >& vec) {
175 
176  boost::fusion::for_each(
177  statevars,
178  msf_tmp::GetIndicesInErrorState<std::vector<std::tuple<int, int, int> >,
179  stateVector_T>(vec));
180 }
181 
182 template<typename stateVector_T, typename StateDefinition_T>
184  std::stringstream ss;
185  ss << "--------- State at time " << msf_core::timehuman(time)
186  << "s: ---------" << std::endl;
187  boost::fusion::for_each(
188  statevars,
190  ss << "-------------------------------------------------------";
191  return ss.str();
192 }
193 
194 template<typename stateVector_T, typename StateDefinition_T>
196  Eigen::Matrix<double,
198  1> data;
199  boost::fusion::for_each(
200  statevars,
202  typename Eigen::Matrix<double,
203  GenericState_T<stateVector_T, StateDefinition_T>::nCoreStatesAtCompileTime,
204  1>, stateVector_T>(data));
205 
206  return checkForNumeric(data, "checkStateForNumeric");
207 }
208 
209 // Returns the state at position INDEX in the state list, const version.
210 template<typename stateVector_T, typename StateDefinition_T>
211 template<int INDEX>
212 inline const typename msf_tmp::StripReference<
213  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t::value_t&
215 
216  static_assert(
217  (msf_tmp::IsReferenceType<typename boost::fusion::result_of::at_c<stateVector_T, INDEX >::type>::value),
218  "Assumed that boost::fusion would return a reference type here, which is "
219  "not the case");
220 
221  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars).state_;
222 }
223 
224 template<typename stateVector_T, typename StateDefinition_T>
225 template<int INDEX>
226 inline typename msf_tmp::AddConstReference<
227  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t GenericState_T<
228  stateVector_T, StateDefinition_T>::getStateVar() const {
229 
230  static_assert(
231  (msf_tmp::IsReferenceType<typename boost::fusion::result_of::at_c<stateVector_T, INDEX >::type>::value),
232  "Assumed that boost::fusion would return a reference type here, which is "
233  "not the case");
234 
235  return boost::fusion::at < boost::mpl::int_<INDEX> > (statevars);
236 }
237 
238 template<typename stateVector_T, typename StateDefinition_T>
239 template<int INDEX>
241  const typename msf_tmp::StripConstReference<
242  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t::value_t& newvalue) {
243  typedef typename msf_tmp::StripReference<
244  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t StateVar_T;
245 
246  static_assert(
247  static_cast<int>(StateVar_T::statetype_) !=
248  static_cast<int>(msf_core::CoreStateWithPropagation) ||
249  static_cast<int>(StateVar_T::statetype_) !=
250  static_cast<int>(msf_core::CoreStateWithoutPropagation),
251  "You requested to set a new value for a"
252  "core state of the EKF, but this is not allowed! This is an Error.");
253 
254  boost::fusion::at < boost::mpl::int_<INDEX> > (statevars).state_ = newvalue;
255 }
256 
257 template<typename stateVector_T, typename StateDefinition_T>
258 template<int INDEX>
260  typedef typename msf_tmp::StripReference<
261  typename boost::fusion::result_of::at_c<stateVector_T, INDEX>::type>::result_t StateVar_T;
262 
263  enum {
264  startIdxInState = msf_tmp::getStartIndex<StateSequence_T, StateVar_T,
265  // Index of the data in the correction vector.
266  msf_tmp::CorrectionStateLengthForType>::value,
267  lengthInState = StateVar_T::sizeInCorrection_
268  };
269  // Save covariance block.
270  Eigen::Matrix<double, lengthInState, lengthInState> cov = P
271  .template block<lengthInState, lengthInState>(startIdxInState,
272  startIdxInState);
273  P.template block<lengthInState, nErrorStatesAtCompileTime>(startIdxInState, 0)
274  .setZero();
275  P.template block<nErrorStatesAtCompileTime, lengthInState>(0, startIdxInState)
276  .setZero();
277  // Write back cov block.
278  P.template block<lengthInState, lengthInState>(startIdxInState,
279  startIdxInState) = cov;
280 
281 }
282 
284 
288 template<typename stateVector_T, typename StateDefinition_T>
291 
292  // Reset all states.
293  boost::fusion::for_each(statevars, msf_tmp::resetState());
294 
295  // Reset system inputs.
296  w_m.setZero();
297  a_m.setZero();
298 
299  P.setZero();
300  time = 0;
301 
302  // Now call the user provided function.
303  if (statevisitor)
304  statevisitor->resetState(*this);
305 }
306 
308 template<typename stateVector_T, typename StateDefinition_T>
310  geometry_msgs::PoseWithCovariance::_covariance_type & cov) {
311 
312  typedef typename msf_tmp::getEnumStateType<stateVector_T, StateDefinition_T::p>::value p_type;
313  typedef typename msf_tmp::getEnumStateType<stateVector_T, StateDefinition_T::q>::value q_type;
314 
315  // Get indices of position and attitude in the covariance matrix.
316  static const int idxstartcorr_p = msf_tmp::getStartIndex<stateVector_T,
317  p_type, msf_tmp::CorrectionStateLengthForType>::value;
318  static const int idxstartcorr_q = msf_tmp::getStartIndex<stateVector_T,
319  q_type, msf_tmp::CorrectionStateLengthForType>::value;
320 
321  /* | cov_p_p | cov_p_q |
322  * | | |
323  * cov = |-----------|-----------|
324  * | | |
325  * | cov_q_p | cov_q_q |
326  */
327 
328  for (int i = 0; i < 9; i++)
329  cov[i / 3 * 6 + i % 3] = P(
330  (i / 3 + idxstartcorr_p) * nErrorStatesAtCompileTime + i % 3);
331 
332  for (int i = 0; i < 9; i++)
333  cov[i / 3 * 6 + (i % 3 + 3)] = P(
334  (i / 3 + idxstartcorr_p) * nErrorStatesAtCompileTime + (i % 3 + 6));
335 
336  for (int i = 0; i < 9; i++)
337  cov[(i / 3 + 3) * 6 + i % 3] = P(
338  (i / 3 + idxstartcorr_q) * nErrorStatesAtCompileTime + i % 3);
339 
340  for (int i = 0; i < 9; i++)
341  cov[(i / 3 + 3) * 6 + (i % 3 + 3)] = P(
342  (i / 3 + idxstartcorr_q) * nErrorStatesAtCompileTime + (i % 3 + 6));
343 }
344 
345 }
346 ;