Estimator3D.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author : Dula Nad
00035  *  Created: 26.03.2013.
00036  *********************************************************************/
00037 #include <labust/navigation/Estimator3D.hpp>
00038 #include <labust/navigation/LDTravModel.hpp>
00039 #include <labust/tools/GeoUtilities.hpp>
00040 #include <labust/tools/MatrixLoader.hpp>
00041 #include <labust/tools/conversions.hpp>
00042 #include <labust/tools/DynamicsLoader.hpp>
00043 #include <labust/math/NumberManipulation.hpp>
00044 #include <labust/simulation/DynamicsParams.hpp>
00045 #include <labust/navigation/KFModelLoader.hpp>
00046 
00047 
00048 #include <auv_msgs/NavSts.h>
00049 #include <auv_msgs/BodyForceReq.h>
00050 #include <geometry_msgs/TwistStamped.h>
00051 
00052 #include <ros/ros.h>
00053 
00054 #include <boost/bind.hpp>
00055 
00056 using namespace labust::navigation;
00057 
00058 Estimator3D::Estimator3D():
00059                 tauIn(KFNav::vector::Zero(KFNav::inputSize)),
00060                 measurements(KFNav::vector::Zero(KFNav::stateNum)),
00061                 newMeas(KFNav::vector::Zero(KFNav::stateNum)),
00062                 alt(0),
00063                 useYawRate(false),
00064                 dvl_model(0){this->onInit();};
00065 
00066 void Estimator3D::onInit()
00067 {
00068         ros::NodeHandle nh, ph("~");
00069         //Configure the navigation
00070         configureNav(nav,nh);
00071         //Publishers
00072         stateHat = nh.advertise<auv_msgs::NavSts>("stateHat",1);
00073         stateMeas = nh.advertise<auv_msgs::NavSts>("meas",1);
00074         currentsHat = nh.advertise<geometry_msgs::TwistStamped>("currentsHat",1);
00075         //Subscribers
00076         tauAch = nh.subscribe<auv_msgs::BodyForceReq>("tauAch", 1, &Estimator3D::onTau,this);
00077         depth = nh.subscribe<std_msgs::Float32>("depth", 1,     &Estimator3D::onDepth, this);
00078         altitude = nh.subscribe<std_msgs::Float32>("altitude", 1, &Estimator3D::onAltitude, this);
00079         modelUpdate = nh.subscribe<navcon_msgs::ModelParamsUpdate>("model_update", 1, &Estimator3D::onModelUpdate,this);
00080 
00081         //Get DVL model
00082         ph.param("dvl_model",dvl_model, dvl_model);
00083         nav.useDvlModel(dvl_model);
00084         ph.param("imu_with_yaw_rate",useYawRate,useYawRate);
00085 
00086         //Configure handlers.
00087         gps.configure(nh);
00088         dvl.configure(nh);
00089         imu.configure(nh);
00090 }
00091 
00092 void Estimator3D::configureNav(KFNav& nav, ros::NodeHandle& nh)
00093 {
00094         ROS_INFO("Configure navigation.");
00095 
00096         labust::simulation::DynamicsParams params;
00097         labust::tools::loadDynamicsParams(nh, params);
00098 
00099         ROS_INFO("Loaded dynamics params.");
00100 
00101         this->params[X].alpha = params.m + params.Ma(0,0);
00102         this->params[X].beta = params.Dlin(0,0);
00103         this->params[X].betaa = params.Dquad(0,0);
00104 
00105         this->params[Y].alpha = params.m + params.Ma(1,1);
00106         this->params[Y].beta = params.Dlin(1,1);
00107         this->params[Y].betaa = params.Dquad(1,1);
00108 
00109         this->params[Z].alpha = params.m + params.Ma(2,2);
00110         this->params[Z].beta = params.Dlin(2,2);
00111         this->params[Z].betaa = params.Dquad(2,2);
00112 
00113         this->params[N].alpha = params.Io(2,2) + params.Ma(5,5);
00114         this->params[N].beta = params.Dlin(5,5);
00115         this->params[N].betaa = params.Dquad(5,5);
00116 
00117         nav.setParameters(this->params[X],this->params[Y],
00118                         this->params[Z],this->params[N]);
00119 
00120         nav.initModel();
00121         labust::navigation::kfModelLoader(nav, nh, "ekfnav");
00122 }
00123 
00124 void Estimator3D::onModelUpdate(const navcon_msgs::ModelParamsUpdate::ConstPtr& update)
00125 {
00126         ROS_INFO("Updating the model parameters for %d DoF.",update->dof);
00127         params[update->dof].alpha = update->alpha;
00128         if (update->use_linear)
00129         {
00130                 params[update->dof].beta = update->beta;
00131                 params[update->dof].betaa = 0;
00132         }
00133         else
00134         {
00135                 params[update->dof].beta = 0;
00136                 params[update->dof].betaa = update->betaa;
00137         }
00138         nav.setParameters(this->params[X],this->params[Y],
00139                         this->params[Z],this->params[N]);
00140 }
00141 
00142 void Estimator3D::onTau(const auv_msgs::BodyForceReq::ConstPtr& tau)
00143 {
00144         tauIn(KFNav::X) = tau->wrench.force.x;
00145         tauIn(KFNav::Y) = tau->wrench.force.y;
00146         tauIn(KFNav::Z) = tau->wrench.force.z;
00147         tauIn(KFNav::N) = tau->wrench.torque.z;
00148 };
00149 
00150 void Estimator3D::onDepth(const std_msgs::Float32::ConstPtr& data)
00151 {
00152         //measurements(KFNav::zp) = data->data;
00153         //newMeas(KFNav::zp) = 1;
00154 };
00155 
00156 void Estimator3D::onAltitude(const std_msgs::Float32::ConstPtr& data)
00157 {
00158         measurements(KFNav::zp) = data->data;
00159         newMeas(KFNav::zp) = 1;
00160         alt = data->data;
00161 };
00162 
00163 void Estimator3D::processMeasurements()
00164 {
00165         //GPS measurements
00166         if ((newMeas(KFNav::xp) = newMeas(KFNav::yp) = gps.newArrived()))
00167         {
00168                 measurements(KFNav::xp) = gps.position().first;
00169                 measurements(KFNav::yp) = gps.position().second;
00170                 ROS_INFO("Position measurements arrived.");
00171         }
00172         //Imu measurements
00173         if ((newMeas(KFNav::psi) = imu.newArrived()))
00174         {
00175                 measurements(KFNav::psi) = imu.orientation()[ImuHandler::yaw];
00176                 if ((newMeas(KFNav::r) = useYawRate))
00177                 {
00178                         measurements(KFNav::r) = imu.rate()[ImuHandler::r];
00179                 }
00180         }
00181         //DVL measurements
00182         //if ((newMeas(KFNav::u) = newMeas(KFNav::v) = newMeas(KFNav::w) = dvl.NewArrived()))
00183         if ((newMeas(KFNav::u) = newMeas(KFNav::v) = dvl.newArrived()))
00184         {
00185                 double vx = dvl.body_speeds()[DvlHandler::u];
00186                 double vy = dvl.body_speeds()[DvlHandler::v];
00187                 double vxe = nav.getState()(KFNav::u); 
00188                 double vye = nav.getState()(KFNav::v); 
00189 
00190                 double rvx(10),rvy(10);
00191                 //Calculate the measured value
00192                 //This depends on the DVL model actually, but lets assume
00193                 nav.calculateUVInovationVariance(nav.getStateCovariance(), rvx, rvy);
00194 
00195                 double cpsi = cos(nav.getState()(KFNav::psi));
00196                 double spsi = sin(nav.getState()(KFNav::psi));
00197                 double xc = nav.getState()(KFNav::xc);
00198                 double yc = nav.getState()(KFNav::yc);
00199                 switch (dvl_model)
00200                 {
00201                   case 1:
00202                     vxe += xc*cpsi + yc*spsi;
00203                     vye += -xc*spsi + yc*cpsi;
00204                     break;
00205                 default: break;
00206                 }
00207 
00208                 if (fabs((vx - vxe)) > fabs(rvx))
00209                 {
00210                         ROS_INFO("Outlier rejected: meas=%f, est=%f, tolerance=%f", vx, nav.getState()(KFNav::u), fabs(rvx));
00211                         newMeas(KFNav::u) = false;
00212                 }
00213                 measurements(KFNav::u) = vx;
00214 
00215 
00216                 if (fabs((vy - vye)) > fabs(rvy))
00217                 {
00218                         ROS_INFO("Outlier rejected: meas=%f, est=%f, tolerance=%f", vy, nav.getState()(KFNav::v), fabs(rvy));
00219                         newMeas(KFNav::v) = false;
00220                 }
00221                 measurements(KFNav::v) = vy;
00222 
00223                 //measurements(KFNav::w) = dvl.body_speeds()[DvlHandler::w];
00224         }
00225 
00226         //Publish measurements
00227         auv_msgs::NavSts::Ptr meas(new auv_msgs::NavSts());
00228         meas->body_velocity.x = measurements(KFNav::u);
00229         meas->body_velocity.y = measurements(KFNav::v);
00230         meas->body_velocity.z = measurements(KFNav::w);
00231 
00232         meas->position.north = measurements(KFNav::xp);
00233         meas->position.east = measurements(KFNav::yp);
00234         //Altitude hack
00235         //meas->position.depth = measurements(KFNav::zp);
00236         meas->altitude = alt;
00237 
00238         meas->orientation.roll = imu.orientation()[ImuHandler::roll];
00239         meas->orientation.pitch = imu.orientation()[ImuHandler::pitch];
00240         meas->orientation.yaw = labust::math::wrapRad(measurements(KFNav::psi));
00241         if (useYawRate) meas->orientation_rate.yaw = measurements(KFNav::r);
00242 
00243         meas->origin.latitude = gps.origin().first;
00244         meas->origin.longitude = gps.origin().second;
00245         meas->global_position.latitude = gps.latlon().first;
00246         meas->global_position.longitude = gps.latlon().second;
00247 
00248         meas->header.stamp = ros::Time::now();
00249         meas->header.frame_id = "local";
00250         stateMeas.publish(meas);
00251 }
00252 
00253 void Estimator3D::publishState()
00254 {
00255         auv_msgs::NavSts::Ptr state(new auv_msgs::NavSts());
00256         const KFNav::vector& estimate = nav.getState();
00257         state->body_velocity.x = estimate(KFNav::u);
00258         state->body_velocity.y = estimate(KFNav::v);
00259         state->body_velocity.z = estimate(KFNav::w);
00260 
00261         state->orientation_rate.yaw = estimate(KFNav::r);
00262 
00263         state->position.north = estimate(KFNav::xp);
00264         state->position.east = estimate(KFNav::yp);
00265         //state->position.depth = estimate(KFNav::zp);
00266         //The altitude hack
00267         state->altitude = alt;
00268         state->altitude = estimate(KFNav::zp);
00269 
00270         state->orientation.roll = imu.orientation()[ImuHandler::roll];
00271         state->orientation.pitch = imu.orientation()[ImuHandler::pitch];
00272         state->orientation.yaw = labust::math::wrapRad(estimate(KFNav::psi));
00273 
00274         state->origin.latitude = gps.origin().first;
00275     state->origin.longitude = gps.origin().second;
00276         std::pair<double, double> diffAngle = labust::tools::meter2deg(state->position.north,
00277                         state->position.east,
00278                         //The latitude angle
00279                         state->origin.latitude);
00280         state->global_position.latitude = state->origin.latitude + diffAngle.first;
00281         state->global_position.longitude = state->origin.longitude + diffAngle.second;
00282 
00283         const KFNav::matrix& covariance = nav.getStateCovariance();
00284         state->position_variance.north = covariance(KFNav::xp, KFNav::xp);
00285         state->position_variance.east = covariance(KFNav::yp, KFNav::yp);
00286         state->position_variance.depth = covariance(KFNav::zp,KFNav::zp);
00287         state->orientation_variance.yaw =  covariance(KFNav::psi, KFNav::psi);
00288 
00289         state->header.stamp = ros::Time::now();
00290         state->header.frame_id = "local";
00291         stateHat.publish(state);
00292 
00293         geometry_msgs::TwistStamped::Ptr current(new geometry_msgs::TwistStamped());
00294         current->twist.linear.x = estimate(KFNav::xc);
00295         current->twist.linear.y = estimate(KFNav::yc);
00296 
00297         current->header.stamp = ros::Time::now();
00298         current->header.frame_id = "local";
00299         currentsHat.publish(current);
00300 }
00301 
00302 void Estimator3D::start()
00303 {
00304         ros::NodeHandle ph("~");
00305         double Ts(0.1);
00306         ph.param("Ts",Ts,Ts);
00307         ros::Rate rate(1/Ts);
00308         nav.setTs(Ts);
00309 
00310         while (ros::ok())
00311         {
00312                 nav.predict(tauIn);
00313                 dvl.current_r(nav.getState()(KFNav::r));
00314                 processMeasurements();
00315                 bool newArrived(false);
00316                 for(size_t i=0; i<newMeas.size(); ++i)  if ((newArrived = newMeas(i))) break;
00317                 if (newArrived) nav.correct(nav.update(measurements, newMeas));
00318                 //if (newArrived)       nav.correct(measurements, newMeas);
00319 
00320                 publishState();
00321 
00322                 //Send the base-link transform
00323                 tf::StampedTransform transform;
00324                 transform.setOrigin(tf::Vector3(
00325                                 nav.getState()(KFNav::xp),
00326                                 nav.getState()(KFNav::yp),
00327                                 nav.getState()(KFNav::zp)));
00328                 Eigen::Quaternion<float> q;
00329                 labust::tools::quaternionFromEulerZYX(
00330                                 imu.orientation()[ImuHandler::roll],
00331                                 imu.orientation()[ImuHandler::pitch],
00332                                 nav.getState()(KFNav::psi),q);
00333                 transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00334                 broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "base_link"));
00335 
00336                 rate.sleep();
00337                 ros::spinOnce();
00338         }
00339 }
00340 
00341 int main(int argc, char* argv[])
00342 {
00343         ros::init(argc,argv,"nav_3d");
00344         Estimator3D nav;
00345         nav.start();
00346         return 0;
00347 }
00348 
00349 


ldtravocean
Author(s):
autogenerated on Fri Feb 7 2014 11:37:01