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
spherical_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 SPHERICAL_POSITION_MEASUREMENTMANAGER_H
18 #define SPHERICAL_POSITION_MEASUREMENTMANAGER_H
19 
20 #include <ros/ros.h>
21 
22 #include <msf_core/msf_core.h>
24 #include "msf_statedef.hpp"
25 #include <msf_updates/spherical_position_sensor/spherical_sensorhandler.h>
26 #include <msf_updates/spherical_position_sensor/spherical_measurement.h>
27 #include <msf_updates/SphericalPositionSensorConfig.h>
28 
29 namespace msf_spherical_position {
30 
31 typedef msf_updates::SphericalPositionSensorConfig Config_T;
32 typedef dynamic_reconfigure::Server<Config_T> ReconfigureServer;
33 typedef boost::shared_ptr<ReconfigureServer> ReconfigureServerPtr;
34 
36  msf_updates::EKFState> {
38  friend class AngleSensorHandler<AngleMeasurement, SensorManager> ;
40  friend class DistanceSensorHandler<DistanceMeasurement, SensorManager> ;
41  public:
45 
47  ros::NodeHandle pnh = ros::NodeHandle("~/spherical_position_sensor")) {
48  angle_handler_.reset(
49  new AngleSensorHandler_T(*this, "", "spherical_position_sensor"));
51  distance_handler_.reset(
52  new DistanceSensorHandler_T(*this, "", "spherical_position_sensor"));
54 
55  reconf_server_.reset(new ReconfigureServer(pnh));
56  ReconfigureServer::CallbackType f = boost::bind(&SensorManager::config,
57  this, _1, _2);
58  reconf_server_->setCallback(f);
59  }
60  virtual ~SensorManager() {
61  }
62 
63  virtual const Config_T& getcfg() const {
64  return config_;
65  }
66 
67  private:
68  boost::shared_ptr<AngleSensorHandler_T> angle_handler_;
69  boost::shared_ptr<DistanceSensorHandler_T> distance_handler_;
70 
73 
77  virtual void config(Config_T &config, uint32_t level) {
78  config_ = config;
79  angle_handler_->setNoises(config.angle_noise_meas);
80  angle_handler_->setDelay(config.angle_delay);
81  distance_handler_->setNoises(config.distance_noise_meas);
82  distance_handler_->setDelay(config.distance_delay);
83 
84  if ((level & msf_updates::SphericalPositionSensor_INIT_FILTER)
85  && config.core_init_filter == true) {
86  init(1.0);
87  config.core_init_filter = false;
88  }
89  }
90 
91  void init(double scale) const {
92  if (scale < 0.001) {
93  ROS_WARN_STREAM("Init scale is " << scale << " correcting to 1.");
94  scale = 1;
95  }
96 
97  Eigen::Matrix<double, 3, 1> p, v, b_w, b_a, g, w_m, a_m, p_ip, p_vc;
98  Eigen::Quaternion<double> q;
100 
101  // Init values.
102  g << 0, 0, 9.81;
103  b_w << 0, 0, 0;
104  b_a << 0, 0, 0;
105 
106  v << 0, 0, 0;
107  w_m << 0, 0, 0;
108  a_m = g;
109 
110  // Set the initial yaw alignment of body to world (the frame in which the
111  // position sensor measures).
112  double yawinit = config_.yaw_init / 180 * M_PI;
113  Eigen::Quaterniond yawq(cos(yawinit / 2), 0, 0, sin(yawinit / 2));
114  yawq.normalize();
115 
116  q = yawq;
117 
118  P.setZero(); // Error state covariance; if zero, a default initialization
119  //in msf_core is used
120 
121  msf_core::Vector2 angles = angle_handler_->getAngleMeasurement();
122  msf_core::Vector1 distance = distance_handler_->getDistanceMeasurement();
123  // Check that angles(0) is theta and angles(1) is phi...
124  p_vc(0, 0) = distance(0) * sin(angles(0)) * cos(angles(1));
125  p_vc(1, 0) = distance(0) * sin(angles(0)) * sin(angles(1));
126  p_vc(2, 0) = distance(0) * cos(angles(0));
127 
128  ROS_INFO_STREAM(
129  "initial measurement pos:[" << p_vc.transpose()<<"] orientation: "
130  <<STREAMQUAT(q));
131 
132  // Check if we have already input from the measurement sensor.
133 if( p_vc.norm() == 0)
134  ROS_WARN_STREAM("No measurements received yet to initialize position - using [0 0 0]");
135 
136  ros::NodeHandle pnh("~");
137  pnh.param("position_sensor/init/p_ip/x", p_ip[0], 0.0);
138  pnh.param("position_sensor/init/p_ip/y", p_ip[1], 0.0);
139  pnh.param("position_sensor/init/p_ip/z", p_ip[2], 0.0);
140 
141  // Calculate initial attitude and position based on sensor measurements.
142  p = p_vc - q.toRotationMatrix() * p_ip;
143 
144  // Prepare init "measurement".
145  boost::shared_ptr < msf_core::MSF_InitMeasurement<EKFState_T>
147 
148  meas->setStateInitValue < StateDefinition_T::p > (p);
149  meas->setStateInitValue < StateDefinition_T::v > (v);
150  meas->setStateInitValue < StateDefinition_T::q > (q);
151  meas->setStateInitValue < StateDefinition_T::b_w > (b_w);
152  meas->setStateInitValue < StateDefinition_T::b_a > (b_a);
153  meas->setStateInitValue < StateDefinition_T::p_ip > (p_ip);
154 
155  setP(meas->get_P()); // Call my set P function.
156  meas->get_w_m() = w_m;
157  meas->get_a_m() = a_m;
158  meas->time = ros::Time::now().toSec();
159 
160  // Call initialization in core.
161  msf_core_->init(meas);
162  }
163 
164  // Prior to this call, all states are initialized to zero/identity.
165  virtual void resetState(EKFState_T& state) const {
166  UNUSED(state);
167  }
168  virtual void initState(EKFState_T& state) const {
169  UNUSED(state);
170  }
171 
172  virtual void calculateQAuxiliaryStates(EKFState_T& state, double dt) const {
173  const msf_core::Vector3 npipv = msf_core::Vector3::Constant(
174  config_.noise_p_ip);
175  // Compute the blockwise Q values and store them with the states,
176  // these then get copied by the core to the correct places in Qd.
178  (dt * npipv.cwiseProduct(npipv)).asDiagonal();
179  }
180 
181  virtual void setP(
182  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime,
184  UNUSED(P);
185  // Nothing, we only use the simulated cov for the core plus diagonal for the rest.
186  }
187 
189  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
190  UNUSED(correction);
191  }
192 
193  virtual void sanityCheckCorrection(
194  EKFState_T& delaystate,
195  const EKFState_T& buffstate,
196  Eigen::Matrix<double, EKFState_T::nErrorStatesAtCompileTime, 1>& correction) const {
197  UNUSED(delaystate);
198  UNUSED(buffstate);
199  UNUSED(correction);
200  }
201 };
202 }
203 #endif /* SPHERICAL_POSITION_MEASUREMENTMANAGER_H */