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
position_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 POSITION_POSE_SENSOR_MANAGER_H
18 #define POSITION_POSE_SENSOR_MANAGER_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/position_sensor_handler/position_sensorhandler.h>
29 #include <msf_updates/position_sensor_handler/position_measurement.h>
30 #include <msf_updates/PositionPoseSensorConfig.h>
31 
32 namespace msf_updates {
33 
34 typedef msf_updates::PositionPoseSensorConfig Config_T;
35 typedef dynamic_reconfigure::Server<Config_T> ReconfigureServer;
36 typedef shared_ptr<ReconfigureServer> ReconfigureServerPtr;
37 
39  msf_updates::EKFState> {
41  typedef msf_pose_sensor::PoseSensorHandler<
42  msf_updates::pose_measurement::PoseMeasurement, this_T> PoseSensorHandler_T;
43  friend class msf_pose_sensor::PoseSensorHandler<
44  msf_updates::pose_measurement::PoseMeasurement, this_T>;
45  typedef msf_position_sensor::PositionSensorHandler<
46  msf_updates::position_measurement::PositionMeasurement, this_T> PositionSensorHandler_T;
47  friend class msf_position_sensor::PositionSensorHandler<
48  msf_updates::position_measurement::PositionMeasurement, this_T>;
49  public:
53 
55  ros::NodeHandle pnh = ros::NodeHandle("~/position_pose_sensor")) {
56  imu_handler_.reset(
58  "imu_handler"));
59 
60  bool distortmeas = false;
61 
62  pose_handler_.reset(
63  new PoseSensorHandler_T(*this, "", "pose_sensor", distortmeas));
65 
66  position_handler_.reset(
67  new PositionSensorHandler_T(*this, "", "position_sensor"));
69 
70  reconf_server_.reset(new ReconfigureServer(pnh));
71  ReconfigureServer::CallbackType f = boost::bind(&this_T::config, this, _1,
72  _2);
73  reconf_server_->setCallback(f);
74  }
76  }
77 
78  virtual const Config_T& getcfg() {
79  return config_;
80  }
81 
82  private:
83  shared_ptr<msf_core::IMUHandler_ROS<msf_updates::EKFState> > imu_handler_;
84  shared_ptr<PoseSensorHandler_T> pose_handler_;
85  shared_ptr<PositionSensorHandler_T> position_handler_;
86 
89 
93  virtual void config(Config_T &config, uint32_t level) {
94  config_ = config;
95  pose_handler_->setNoises(config.pose_noise_meas_p,
96  config.pose_noise_meas_q);
97  pose_handler_->setDelay(config.pose_delay);
98 
99  position_handler_->setNoises(config.position_noise_meas);
100  position_handler_->setDelay(config.position_delay);
101 
102  if ((level & msf_updates::PositionPoseSensor_INIT_FILTER)
103  && config.core_init_filter == true) {
104  init(config.pose_initial_scale);
105  config.core_init_filter = false;
106  }
107 
108  // Init call with "set height" checkbox.
109  if ((level & msf_updates::PositionPoseSensor_SET_HEIGHT)
110  && config.core_set_height == true) {
111  Eigen::Matrix<double, 3, 1> p = pose_handler_->getPositionMeasurement();
112  if (p.norm() == 0) {
114  "No measurements received yet to initialize position. Height init "
115  "not allowed.");
116  return;
117  }
118  double scale = p[2] / config.core_height;
119  init(scale);
120  config.core_set_height = false;
121  }
122  }
123 
124  void init(double scale) const {
125  Eigen::Matrix<double, 3, 1> p, v, b_w, b_a, g, w_m, a_m, p_ic, p_vc, p_wv,
126  p_ip, p_pos;
127  Eigen::Quaternion<double> q, q_wv, q_ic, q_vc;
129 
130  // init values
131  g << 0, 0, 9.81;
132  b_w << 0, 0, 0;
133  b_a << 0, 0, 0;
134 
135  v << 0, 0, 0;
136  w_m << 0, 0, 0;
137  a_m = g;
138 
139  q_wv.setIdentity(); // World-vision rotation drift.
140  p_wv.setZero(); // World-vision position drift.
141 
142  P.setZero(); // Error state covariance; if zero, a default initialization in msf_core is used.
143 
144  p_pos = position_handler_->getPositionMeasurement();
145 
146  p_vc = pose_handler_->getPositionMeasurement();
147  q_vc = pose_handler_->getAttitudeMeasurement();
148 
150  "initial measurement vision: pos:["<<p_vc.transpose()<<"] orientation: "
151  <<STREAMQUAT(q_vc));
153  "initial measurement position: pos:["<<p_pos.transpose()<<"]");
154 
155  // Check if we have already input from the measurement sensor.
156  if (p_vc.norm() == 0)
158  "No measurements received yet to initialize vision position - using [0 0 0]");
159  if (p_pos.norm() == 0)
161  "No measurements received yet to initialize absolute position - using [0 0 0]");
162  if (q_vc.w() == 1)
164  "No measurements received yet to initialize attitude - using [1 0 0 0]");
165 
166  ros::NodeHandle pnh("~");
167  pnh.param("pose_sensor/init/p_ic/x", p_ic[0], 0.0);
168  pnh.param("pose_sensor/init/p_ic/y", p_ic[1], 0.0);
169  pnh.param("pose_sensor/init/p_ic/z", p_ic[2], 0.0);
170 
171  pnh.param("pose_sensor/init/q_ic/w", q_ic.w(), 1.0);
172  pnh.param("pose_sensor/init/q_ic/x", q_ic.x(), 0.0);
173  pnh.param("pose_sensor/init/q_ic/y", q_ic.y(), 0.0);
174  pnh.param("pose_sensor/init/q_ic/z", q_ic.z(), 0.0);
175  q_ic.normalize();
176 
177  MSF_INFO_STREAM("p_ic: "<<p_ic.transpose());
178  MSF_INFO_STREAM("q_ic: "<<STREAMQUAT(q_ic));
179 
180  pnh.param("position_sensor/init/p_ip/x", p_ip[0], 0.0);
181  pnh.param("position_sensor/init/p_ip/y", p_ip[1], 0.0);
182  pnh.param("position_sensor/init/p_ip/z", p_ip[2], 0.0);
183 
184  // Calculate initial attitude and position based on sensor measurements
185  // here we take the attitude from the pose sensor and augment it with
186  // global yaw init.
187  double yawinit = config_.position_yaw_init / 180 * M_PI;
188  Eigen::Quaterniond yawq(cos(yawinit / 2), 0, 0, sin(yawinit / 2));
189  yawq.normalize();
190 
191  q = yawq;
192  q_wv = (q * q_ic * q_vc.conjugate()).conjugate();
193 
194  MSF_WARN_STREAM("q "<<STREAMQUAT(q));
195  MSF_WARN_STREAM("q_wv "<<STREAMQUAT(q_wv));
196 
197  Eigen::Matrix<double, 3, 1> p_vision = q_wv.conjugate().toRotationMatrix()
198  * p_vc / scale - q.toRotationMatrix() * p_ic;
199 
200  //TODO (slynen): what if there is no initial position measurement? Then we
201  // have to shift vision-world later on, before applying the first position
202  // measurement.
203  p = p_pos - q.toRotationMatrix() * p_ip;
204  p_wv = p - p_vision; // Shift the vision frame so that it fits the position
205  // measurement
206 
207  //TODO (slynen) Fix this.
208  //we want z from vision (we did scale init), so:
209 // p(2) = p_vision(2);
210 // p_wv(2) = 0;
211 // position_handler_->adjustGPSZReference(p(2));
212 
213  // Prepare init "measurement"
214  // True means that we will also set the initial sensor readings.
215  shared_ptr < msf_core::MSF_InitMeasurement<EKFState_T>
217 
218  meas->setStateInitValue<StateDefinition_T::p> (p);
219  meas->setStateInitValue<StateDefinition_T::v> (v);
220  meas->setStateInitValue<StateDefinition_T::q> (q);
221  meas->setStateInitValue<StateDefinition_T::b_w> (b_w);
222  meas->setStateInitValue<StateDefinition_T::b_a> (b_a);
223  meas->setStateInitValue<StateDefinition_T::L
224  > (Eigen::Matrix<double, 1, 1>::Constant(scale));
225  meas->setStateInitValue<StateDefinition_T::q_wv> (q_wv);
226  meas->setStateInitValue<StateDefinition_T::p_wv> (p_wv);
227  meas->setStateInitValue<StateDefinition_T::q_ic> (q_ic);
228  meas->setStateInitValue<StateDefinition_T::p_ic> (p_ic);
229  meas->setStateInitValue<StateDefinition_T::p_ip> (p_ip);
230 
231  setP(meas->get_P()); // Call my set P function.
232  meas->get_w_m() = w_m;
233  meas->get_a_m() = a_m;
234  meas->time = ros::Time::now().toSec();
235 
236  // Call initialization in core.
237  msf_core_->init(meas);
238  }
239 
240  // Prior to this call, all states are initialized to zero/identity.
241  virtual void resetState(EKFState_T& state) const {
242  // Set scale to 1.
243  Eigen::Matrix<double, 1, 1> scale;
244  scale << 1.0;
245  state.set < StateDefinition_T::L > (scale);
246  }
247  virtual void initState(EKFState_T& state) const {
248  UNUSED(state);
249  }
250 
251  virtual void calculateQAuxiliaryStates(EKFState_T& state, double dt) const {
252  const msf_core::Vector3 nqwvv = msf_core::Vector3::Constant(
253  config_.pose_noise_q_wv);
254  const msf_core::Vector3 npwvv = msf_core::Vector3::Constant(
255  config_.pose_noise_p_wv);
256  const msf_core::Vector3 nqicv = msf_core::Vector3::Constant(
257  config_.pose_noise_q_ic);
258  const msf_core::Vector3 npicv = msf_core::Vector3::Constant(
259  config_.pose_noise_p_ic);
260  const msf_core::Vector1 n_L = msf_core::Vector1::Constant(
261  config_.pose_noise_scale);
262 
263  // Compute the blockwise Q values and store them with the states,
264  // these then get copied by the core to the correct places in Qd.
265  state.getQBlock<StateDefinition_T::L>() = (dt * n_L.cwiseProduct(n_L))
266  .asDiagonal();
268  (dt * nqwvv.cwiseProduct(nqwvv)).asDiagonal();
270  (dt * npwvv.cwiseProduct(npwvv)).asDiagonal();
272  (dt * nqicv.cwiseProduct(nqicv)).asDiagonal();
274  (dt * npicv.cwiseProduct(npicv)).asDiagonal();
275  }
276 
277  virtual void setP(
278  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime,
280  UNUSED(P);
281  // Nothing, we only use the simulated cov for the core plus diagonal for the
282  // rest.
283  }
284 
286  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
287  UNUSED(correction);
288  }
289 
290  virtual void sanityCheckCorrection(
291  EKFState_T& delaystate,
292  const EKFState_T& buffstate,
293  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
294 
295  UNUSED(buffstate);
296  UNUSED(correction);
297 
298  const EKFState_T& state = delaystate;
299  if (state.get<StateDefinition_T::L>()(0) < 0) {
301  1, "Negative scale detected: " << state.get<StateDefinition_T::L>()(0) << ". Correcting to 0.1");
302  Eigen::Matrix<double, 1, 1> L_;
303  L_ << 0.1;
304  delaystate.set < StateDefinition_T::L > (L_);
305  }
306  }
307 };
308 }
309 #endif /* POSITION_POSE_SENSOR_MANAGER_H */