global_reference.cpp
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2012, 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/global_reference.h>
00030 #include <hector_pose_estimation/pose_estimation.h>
00031 #include <cmath>
00032 
00033 using namespace std;
00034 
00035 namespace hector_pose_estimation {
00036 
00037 GlobalReference::GlobalReference()
00038 {
00039   parameters().add("reference_latitude",  position_.latitude);
00040   parameters().add("reference_longitude", position_.longitude);
00041   parameters().add("reference_altitude",  position_.altitude);
00042   parameters().add("reference_heading",   heading_.value);
00043 
00044   reset();
00045 }
00046 
00047 void GlobalReference::reset()
00048 {
00049   position_ = Position();
00050   heading_ = Heading();
00051 
00052   has_position_ = false;
00053   has_heading_ = false;
00054   has_altitude_ = false;
00055 
00056   updated();
00057 }
00058 
00059 ParameterList& GlobalReference::parameters() {
00060   return parameters_;
00061 }
00062 
00063 void GlobalReference::updated() {
00064   // check if a non-default reference has been set
00065   if (position_.latitude  != Position().latitude)  has_position_ = true;
00066   if (position_.longitude != Position().longitude) has_position_ = true;
00067   if (position_.altitude  != Position().altitude)  has_altitude_ = true;
00068   if (heading_.value      != Heading().value)      has_heading_  = true;
00069 
00070   // WGS84 constants
00071   static const double equatorial_radius = 6378137.0;
00072   static const double flattening = 1.0/298.257223563;
00073   static const double excentrity2 = 2*flattening - flattening*flattening;
00074 
00075   // calculate earth radii
00076   double temp = 1.0 / (1.0 - excentrity2 * sin(position_.latitude) * sin(position_.latitude));
00077   double prime_vertical_radius = equatorial_radius * sqrt(temp);
00078   radius_.north = prime_vertical_radius * (1 - excentrity2) * temp;
00079   radius_.east  = prime_vertical_radius * cos(position_.latitude);
00080 
00081   // calculate sin and cos of the heading reference
00082   sincos(heading_.value, &heading_.sin, &heading_.cos);
00083 }
00084 
00085 void GlobalReference::fromWGS84(double latitude, double longitude, double &x, double &y) {
00086   double north = radius_.north * (latitude  - position_.latitude);
00087   double east  = radius_.east  * (longitude - position_.longitude);
00088   fromNorthEast(north, east, x, y);
00089 }
00090 
00091 void GlobalReference::toWGS84(double x, double y, double &latitude, double &longitude) {
00092   if (radius_.north == 0.0 || radius_.east == 0.0) {
00093     latitude  = 0.0;
00094     longitude = 0.0;
00095     return;
00096   }
00097 
00098   double north, east;
00099   toNorthEast(x, y, north, east);
00100   latitude  = position_.latitude  + north / radius_.north;
00101   longitude = position_.longitude + east  / radius_.east;
00102 }
00103 
00104 void GlobalReference::fromNorthEast(double north, double east, double &x, double &y) {
00105   x = north * heading_.cos + east * heading_.sin;
00106   y = north * heading_.sin - east * heading_.cos;
00107 }
00108 
00109 void GlobalReference::toNorthEast(double x, double y, double &north, double &east) {
00110   north = x * heading_.cos + y * heading_.sin;
00111   east  = x * heading_.sin - y * heading_.cos;
00112 }
00113 
00114 GlobalReference& GlobalReference::setPosition(double latitude, double longitude, bool quiet /* = false */) {
00115   position_.latitude = latitude;
00116   position_.longitude = longitude;
00117   has_position_ = true;
00118   updated();
00119   if (!quiet) ROS_INFO("Set new reference position to %f deg N / %f deg E", this->position().latitude * 180.0/M_PI, this->position().longitude * 180.0/M_PI);
00120   return *this;
00121 }
00122 
00123 GlobalReference& GlobalReference::setHeading(double heading, bool quiet /* = false */) {
00124   heading_.value = heading;
00125   has_heading_ = true;
00126   updated();
00127   if (!quiet) ROS_INFO("Set new reference heading to %.1f degress", this->heading() * 180.0 / M_PI);
00128   return *this;
00129 }
00130 
00131 GlobalReference& GlobalReference::setAltitude(double altitude, bool quiet /* = false */) {
00132   position_.altitude = altitude;
00133   has_altitude_ = true;
00134   updated();
00135   if (!quiet) ROS_INFO("Set new reference altitude to %.2f m", this->position().altitude);
00136   return *this;
00137 }
00138 
00139 GlobalReference& GlobalReference::setCurrentPosition(PoseEstimation& estimator, double new_latitude, double new_longitude) {
00140   const StateVector& state = estimator.getState();
00141 
00142   // set reference to new latitude/longitude first (intermediate reference)
00143   setPosition(new_latitude, new_longitude, true);
00144 
00145   // convert current position back to WGS84 using the new reference position
00146   // and reset the reference position so that current position in x/y coordinates remains the same
00147   // This will work unless the radii at the origin and the x/y position of the robot differ too much
00148   toWGS84(-state(POSITION_X), -state(POSITION_Y), new_latitude, new_longitude);
00149   setPosition(new_latitude, new_longitude);
00150 
00151   return *this;
00152 }
00153 
00154 GlobalReference& GlobalReference::setCurrentHeading(PoseEstimation& estimator, double new_heading) {
00155   // get current yaw angle
00156   double current_yaw, temp;
00157   estimator.getOrientation(current_yaw, temp, temp);
00158 
00159   // get current position in WGS84
00160   const StateVector& state = estimator.getState();
00161   double current_latitude, current_longitude;
00162   if (hasPosition()) {
00163     toWGS84(state(POSITION_X), state(POSITION_Y), current_latitude, current_longitude);
00164   }
00165 
00166   // set the new reference heading
00167   setHeading(new_heading - (-current_yaw));
00168 
00169   // set the new reference position so that current position in WGS84 coordinates remains the same as before
00170   if (hasPosition()) {
00171     setCurrentPosition(estimator, current_latitude, current_longitude);
00172   }
00173 
00174   return *this;
00175 }
00176 
00177 GlobalReference& GlobalReference::setCurrentAltitude(PoseEstimation& estimator, double new_altitude) {
00178   const StateVector& state = estimator.getState();
00179   setAltitude(new_altitude - state(POSITION_Z));
00180   return *this;
00181 }
00182 
00183 } // namespace hector_pose_estimation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


hector_pose_estimation_core
Author(s): Johannes Meyer
autogenerated on Mon Jul 15 2013 16:48:43