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