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
pose_sensormanager.h
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 #ifndef POSE_MEASUREMENTMANAGER_H
18 #define POSE_MEASUREMENTMANAGER_H
19 
20 #include <ros/ros.h>
21 
22 #include <msf_core/msf_core.h>
25 #include "msf_statedef.hpp"
26 #include <msf_updates/pose_sensor_handler/pose_sensorhandler.h>
27 #include <msf_updates/pose_sensor_handler/pose_measurement.h>
28 #include <msf_updates/SinglePoseSensorConfig.h>
29 
30 namespace msf_pose_sensor {
31 
32 typedef msf_updates::SinglePoseSensorConfig Config_T;
33 typedef dynamic_reconfigure::Server<Config_T> ReconfigureServer;
34 typedef shared_ptr<ReconfigureServer> ReconfigureServerPtr;
35 
37  msf_updates::EKFState> {
38  typedef PoseSensorHandler<msf_updates::pose_measurement::PoseMeasurement,
40  friend class PoseSensorHandler<msf_updates::pose_measurement::PoseMeasurement,
42  public:
46 
47  PoseSensorManager(ros::NodeHandle pnh = ros::NodeHandle("~/pose_sensor")) {
48  bool distortmeas = false;
49 
50  imu_handler_.reset(
52  "imu_handler"));
53  pose_handler_.reset(
54  new PoseSensorHandler_T(*this, "", "pose_sensor", distortmeas));
55 
57 
58  reconf_server_.reset(new ReconfigureServer(pnh));
59  ReconfigureServer::CallbackType f = boost::bind(&PoseSensorManager::config,
60  this, _1, _2);
61  reconf_server_->setCallback(f);
62  }
63  virtual ~PoseSensorManager() {
64  }
65 
66  virtual const Config_T& getcfg() {
67  return config_;
68  }
69 
70  private:
71  shared_ptr<msf_core::IMUHandler_ROS<msf_updates::EKFState> > imu_handler_;
72  shared_ptr<PoseSensorHandler_T> pose_handler_;
73 
76 
80  virtual void config(Config_T &config, uint32_t level) {
81  config_ = config;
82  pose_handler_->setNoises(config.pose_noise_meas_p,
83  config.pose_noise_meas_q);
84  pose_handler_->setDelay(config.pose_delay);
85  if ((level & msf_updates::SinglePoseSensor_INIT_FILTER)
86  && config.core_init_filter == true) {
87  init(config.pose_initial_scale);
88  config.core_init_filter = false;
89  }
90  // Init call with "set height" checkbox.
91  if ((level & msf_updates::SinglePoseSensor_SET_HEIGHT)
92  && config.core_set_height == true) {
93  Eigen::Matrix<double, 3, 1> p = pose_handler_->getPositionMeasurement();
94  if (p.norm() == 0) {
96  "No measurements received yet to initialize position. Height init "
97  "not allowed.");
98  return;
99  }
100  double scale = p[2] / config.core_height;
101  init(scale);
102  config.core_set_height = false;
103  }
104  }
105 
106  void init(double scale) const {
107  Eigen::Matrix<double, 3, 1> p, v, b_w, b_a, g, w_m, a_m, p_ic, p_vc, p_wv;
108  Eigen::Quaternion<double> q, q_wv, q_ic, q_cv;
110 
111  // init values
112  g << 0, 0, 9.81;
113  b_w << 0, 0, 0;
114  b_a << 0, 0, 0;
115 
116  v << 0, 0, 0;
117  w_m << 0, 0, 0;
118  a_m = g;
119 
120  q_wv.setIdentity(); // Vision-world rotation drift.
121  p_wv.setZero(); // Vision-world position drift.
122 
123  P.setZero(); // Error state covariance; if zero, a default initialization in msf_core is used
124 
125  p_vc = pose_handler_->getPositionMeasurement();
126  q_cv = pose_handler_->getAttitudeMeasurement();
127 
129  "initial measurement pos:["<<p_vc.transpose()<<"] orientation: "<<STREAMQUAT(q_cv));
130 
131  // Check if we have already input from the measurement sensor.
132  if (p_vc.norm() == 0)
134  "No measurements received yet to initialize position - using [0 0 0]");
135  if (q_cv.w() == 1)
137  "No measurements received yet to initialize attitude - using [1 0 0 0]");
138 
139  ros::NodeHandle pnh("~");
140  pnh.param("pose_sensor/init/p_ic/x", p_ic[0], 0.0);
141  pnh.param("pose_sensor/init/p_ic/y", p_ic[1], 0.0);
142  pnh.param("pose_sensor/init/p_ic/z", p_ic[2], 0.0);
143 
144  pnh.param("pose_sensor/init/q_ic/w", q_ic.w(), 1.0);
145  pnh.param("pose_sensor/init/q_ic/x", q_ic.x(), 0.0);
146  pnh.param("pose_sensor/init/q_ic/y", q_ic.y(), 0.0);
147  pnh.param("pose_sensor/init/q_ic/z", q_ic.z(), 0.0);
148  q_ic.normalize();
149 
150  // Calculate initial attitude and position based on sensor measurements.
151  if (q_cv.w() == 1) { // If there is no pose measurement, only apply q_wv.
152  q = q_wv;
153  } else { // If there is a pose measurement, apply q_ic and q_wv to get initial attitude.
154  q = (q_ic * q_cv.conjugate() * q_wv).conjugate();
155  }
156 
157  q.normalize();
158  p = p_wv + q_wv.conjugate().toRotationMatrix() * p_vc / scale
159  - q.toRotationMatrix() * p_ic;
160 
161  // Prepare init "measurement"
162  // True means that this message contains initial sensor readings.
163  shared_ptr < msf_core::MSF_InitMeasurement<EKFState_T>
165 
166  meas->setStateInitValue<StateDefinition_T::p>(p);
167  meas->setStateInitValue<StateDefinition_T::v>(v);
168  meas->setStateInitValue<StateDefinition_T::q>(q);
169  meas->setStateInitValue<StateDefinition_T::b_w>(b_w);
170  meas->setStateInitValue<StateDefinition_T::b_a>(b_a);
171  meas->setStateInitValue<StateDefinition_T::L>(
172  Eigen::Matrix<double, 1, 1>::Constant(scale));
173  meas->setStateInitValue<StateDefinition_T::q_wv>(q_wv);
174  meas->setStateInitValue<StateDefinition_T::p_wv>(p_wv);
175  meas->setStateInitValue<StateDefinition_T::q_ic>(q_ic);
176  meas->setStateInitValue<StateDefinition_T::p_ic>(p_ic);
177 
178  setP(meas->get_P()); // Call my set P function.
179  meas->get_w_m() = w_m;
180  meas->get_a_m() = a_m;
181  meas->time = ros::Time::now().toSec();
182 
183  // Call initialization in core.
184  msf_core_->init(meas);
185 
186  }
187 
188  // Prior to this call, all states are initialized to zero/identity.
189  virtual void resetState(EKFState_T& state) const {
190  //set scale to 1
191  Eigen::Matrix<double, 1, 1> scale;
192  scale << 1.0;
193  state.set < StateDefinition_T::L > (scale);
194  }
195  virtual void initState(EKFState_T& state) const {
196  UNUSED(state);
197  }
198 
199  virtual void calculateQAuxiliaryStates(EKFState_T& state, double dt) const {
200  const msf_core::Vector3 nqwvv = msf_core::Vector3::Constant(
201  config_.pose_noise_q_wv);
202  const msf_core::Vector3 npwvv = msf_core::Vector3::Constant(
203  config_.pose_noise_p_wv);
204  const msf_core::Vector3 nqicv = msf_core::Vector3::Constant(
205  config_.pose_noise_q_ic);
206  const msf_core::Vector3 npicv = msf_core::Vector3::Constant(
207  config_.pose_noise_p_ic);
208  const msf_core::Vector1 n_L = msf_core::Vector1::Constant(
209  config_.pose_noise_scale);
210 
211  // Compute the blockwise Q values and store them with the states,
212  // these then get copied by the core to the correct places in Qd.
213  state.getQBlock<StateDefinition_T::L>() = (dt * n_L.cwiseProduct(n_L))
214  .asDiagonal();
216  (dt * nqwvv.cwiseProduct(nqwvv)).asDiagonal();
218  (dt * npwvv.cwiseProduct(npwvv)).asDiagonal();
220  (dt * nqicv.cwiseProduct(nqicv)).asDiagonal();
222  (dt * npicv.cwiseProduct(npicv)).asDiagonal();
223  }
224 
225  virtual void setP(
226  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime,
228  UNUSED(P);
229  // Nothing, we only use the simulated cov for the core plus diagonal for the
230  // rest.
231  }
232 
234  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
235  UNUSED(correction);
236  }
237 
238  virtual void sanityCheckCorrection(
239  EKFState_T& delaystate,
240  const EKFState_T& buffstate,
241  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
242  UNUSED(buffstate);
243  UNUSED(correction);
244 
245  const EKFState_T& state = delaystate;
246  if (state.get<StateDefinition_T::L>()(0) < 0) {
248  1, "Negative scale detected: " << state.get<StateDefinition_T::L>()(0)
249  << ". Correcting to 0.1");
250  Eigen::Matrix<double, 1, 1> L_;
251  L_ << 0.1;
252  delaystate.set < StateDefinition_T::L > (L_);
253  }
254  }
255 };
256 
257 }
258 #endif /* POSE_MEASUREMENTMANAGER_H */