magnetic.cpp
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2011, Johannes Meyer, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Flight Systems and Automatic Control group,
00013 //       TU Darmstadt, nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //=================================================================================================
00028 
00029 #include <hector_pose_estimation/measurements/magnetic.h>
00030 #include <hector_pose_estimation/filter/set_filter.h>
00031 
00032 #include <Eigen/Geometry>
00033 
00034 namespace hector_pose_estimation {
00035 
00036 template class Measurement_<MagneticModel>;
00037 
00038 MagneticModel::MagneticModel()
00039   : declination_(0.0), inclination_(60.0 * M_PI/180.0), magnitude_(0.0)
00040 {
00041   parameters().add("stddev", stddev_, 1.0);
00042   parameters().add("declination", declination_);
00043   parameters().add("inclination", inclination_);
00044   parameters().add("magnitude", magnitude_);
00045 }
00046 
00047 MagneticModel::~MagneticModel() {}
00048 
00049 bool MagneticModel::init(PoseEstimation &estimator, Measurement &measurement, State &state)
00050 {
00051   updateMagneticField();
00052   return true;
00053 }
00054 
00055 void MagneticModel::setReference(const GlobalReference::Heading &reference_heading) {
00056   magnetic_field_reference_.x() = reference_heading.cos * magnetic_field_north_.x() - reference_heading.sin * magnetic_field_north_.y();
00057   magnetic_field_reference_.y() = reference_heading.sin * magnetic_field_north_.x() + reference_heading.cos * magnetic_field_north_.y();
00058   magnetic_field_reference_.z() = magnetic_field_north_.z();
00059 }
00060 
00061 void MagneticModel::getMeasurementNoise(NoiseVariance& R, const State&, bool init)
00062 {
00063   if (init) {
00064     R(0,0) = R(1,1) = R(2,2) = pow(stddev_, 2);
00065   }
00066 }
00067 
00068 void MagneticModel::getExpectedValue(MeasurementVector& y_pred, const State& state)
00069 {
00070   const State::RotationMatrix &R = state.R();
00071   y_pred = R.transpose() * magnetic_field_reference_;
00072 }
00073 
00074 void MagneticModel::getStateJacobian(MeasurementMatrix& C, const State& state, bool)
00075 {
00076   if (state.orientation()) {
00077     const State::RotationMatrix &R = state.R();
00078     state.orientation()->cols(C)(X,Z) = R(0,0) * magnetic_field_reference_.y() - R(1,0) * magnetic_field_reference_.x();
00079     state.orientation()->cols(C)(Y,Z) = R(0,1) * magnetic_field_reference_.y() - R(1,1) * magnetic_field_reference_.x();
00080     state.orientation()->cols(C)(Z,Z) = R(0,2) * magnetic_field_reference_.y() - R(1,2) * magnetic_field_reference_.x();
00081   }
00082 }
00083 
00084 double MagneticModel::getMagneticHeading(const State& state, const MeasurementVector &y) const {
00085   MeasurementVector y_nav;
00086   y_nav = state.R() * y;
00087   return atan2(y_nav.y(), y_nav.x()) - state.getYaw();
00088 }
00089 
00090 double MagneticModel::getTrueHeading(const State& state, const MeasurementVector &y) const {
00091   return getMagneticHeading(state, y) + declination_;
00092 }
00093 
00094 void MagneticModel::updateMagneticField()
00095 {
00096   double cos_inclination, sin_inclination;
00097   sincos(inclination_, &sin_inclination, &cos_inclination);
00098 
00099   double cos_declination, sin_declination;
00100   sincos(declination_, &sin_declination, &cos_declination);
00101 
00102   // return normalized magnetic field if magnitude is zero
00103   double magnitude = magnitude_;
00104   if (magnitude == 0.0) magnitude = 1.0;
00105 
00106   magnetic_field_north_.x() = magnitude * (cos_inclination *   cos_declination);
00107   magnetic_field_north_.y() = magnitude * (cos_inclination * (-sin_declination));
00108   magnetic_field_north_.z() = magnitude * (-sin_inclination);
00109 }
00110 
00111 Magnetic::Magnetic(const std::string &name)
00112   : Measurement_<MagneticModel>(name)
00113   , auto_heading_(true)
00114   , deviation_(3)
00115 {
00116   deviation_.setZero();
00117   parameters().add("auto_heading", auto_heading_);
00118   parameters().add("deviation", deviation_);
00119 }
00120 
00121 void Magnetic::onReset() {
00122   reference_.reset();
00123 }
00124 
00125 const MagneticModel::MeasurementVector& Magnetic::getVector(const Magnetic::Update& update, const State& state) {
00126   y_ = Measurement_<MagneticModel>::getVector(update, state) + deviation_;
00127   if (getModel()->hasMagnitude()) return y_;
00128 
00129   double norm = y_.norm();
00130   if (norm < 1e-5) {
00131     y_.setZero();
00132   } else {
00133     y_ = y_ / norm;
00134   }
00135   return y_;
00136 }
00137 
00138 //const MagneticModel::NoiseVariance& Magnetic::getVariance(const Magnetic::Update& update, const State& state) {
00139 //  if (getModel()->hasMagnitude()) return Measurement_<MagneticModel>::getVariance(update, state);
00140 
00141 //  R_ = Measurement_<MagneticModel>::getVariance(update, state);
00142 //  double norm = Measurement_<MagneticModel>::getVector(update, state).norm();
00143 //  if (norm < 1e-5) {
00144 //    R_ = NoiseVariance(1.0, 1.0, 1.0);
00145 //  } else {
00146 //    R_ =  R_ / (norm*norm);
00147 //  }
00148 //  return R_;
00149 //}
00150 
00151 bool Magnetic::prepareUpdate(State &state, const Update &update) {
00152   // reset reference position if Magnetic has not been updated for a while
00153   if (timedout()) reference_.reset();
00154 
00155   if (reference_ != GlobalReference::Instance()) {
00156     reference_ = GlobalReference::Instance();
00157     if (auto_heading_) reference_->setCurrentHeading(state, getModel()->getTrueHeading(state, update.getVector()));
00158   }
00159 
00160   getModel()->setReference(reference_->heading());
00161   return true;
00162 }
00163 
00164 } // namespace hector_pose_estimation


hector_pose_estimation_core
Author(s): Johannes Meyer
autogenerated on Fri Aug 28 2015 10:59:54