EKF_3D_USBL.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *  EKF_3D_USBL.cpp
00003  *
00004  *  Created on: Mar 26, 2013
00005  *      Author: Dula Nad
00006  *
00007  *   Modified on: Feb 27, 2015
00008  *      Author: Filip Mandic
00009  *
00010  *   Description:
00011  *      6-DOF EKF navigation filter with raw range and bearing measurements
00012  *
00013  *      Relative mode:
00014  *
00015  *      Absolute mode:
00016  *
00017  ********************************************************************/
00018 /*********************************************************************
00019  * Software License Agreement (BSD License)
00020  *
00021  *  Copyright (c) 2015, LABUST, UNIZG-FER
00022  *  All rights reserved.
00023  *
00024  *  Redistribution and use in source and binary forms, with or without
00025  *  modification, are permitted provided that the following conditions
00026  *  are met:
00027  *
00028  *   * Redistributions of source code must retain the above copyright
00029  *     notice, this list of conditions and the following disclaimer.
00030  *   * Redistributions in binary form must reproduce the above
00031  *     copyright notice, this list of conditions and the following
00032  *     disclaimer in the documentation and/or other materials provided
00033  *     with the distribution.
00034  *   * Neither the name of the LABUST nor the names of its
00035  *     contributors may be used to endorse or promote products derived
00036  *     from this software without specific prior written permission.
00037  *
00038  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00039  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00040  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00041  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00042  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00043  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00044  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00045  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00046  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00047  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00048  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00049  *  POSSIBILITY OF SUCH DAMAGE.
00050  *********************************************************************/
00051 #include <labust/navigation/EKF_3D_USBL.hpp>
00052 #include <labust/navigation/EKF_3D_USBLModel.hpp>
00053 #include <labust/tools/GeoUtilities.hpp>
00054 #include <labust/tools/MatrixLoader.hpp>
00055 #include <labust/tools/conversions.hpp>
00056 #include <labust/tools/DynamicsLoader.hpp>
00057 #include <labust/math/NumberManipulation.hpp>
00058 #include <labust/simulation/DynamicsParams.hpp>
00059 #include <labust/navigation/KFModelLoader.hpp>
00060 
00061 #include <auv_msgs/NavSts.h>
00062 #include <auv_msgs/BodyForceReq.h>
00063 #include <geometry_msgs/TwistStamped.h>
00064 #include <geometry_msgs/TransformStamped.h>
00065 #include <std_msgs/Float32.h>
00066 #include <std_msgs/Bool.h>
00067 #include <underwater_msgs/USBLFix.h>
00068 
00069 #include <ros/ros.h>
00070 
00071 #include <boost/bind.hpp>
00072 #include <math.h>
00073 
00074 using namespace labust::navigation;
00075 
00076 
00077 
00078 Estimator3D::Estimator3D():
00079 
00080                 tauIn(KFNav::vector::Zero(KFNav::inputSize)),
00081                 measurements(KFNav::vector::Zero(KFNav::measSize)),
00082                 newMeas(KFNav::vector::Zero(KFNav::measSize)),
00083                 measDelay(KFNav::vector::Zero(KFNav::measSize)),
00084                 alt(0),
00085                 useYawRate(false),
00086                 enableDelay(false),
00087                 enableRange(true),
00088                 enableBearing(true),
00089                 enableElevation(false),
00090                 delayTime(0.0),
00091                 delay_time(0.0),
00092                 dvl_model(0),
00093                 compassVariance(0.3),
00094                 gyroVariance(0.003),
00095                 OR(3,0.95),
00096                 absoluteEKF(false){this->onInit();};
00097 
00098 void Estimator3D::onInit()
00099 {
00100         ros::NodeHandle nh, ph("~");
00101 
00102         /*** Configure the navigation ***/
00103         configureNav(nav,nh);
00104 
00105         /*** Publishers ***/
00106         stateHat = nh.advertise<auv_msgs::NavSts>("stateHat",1);
00107         stateMeas = nh.advertise<auv_msgs::NavSts>("meas",1);
00108         currentsHat = nh.advertise<geometry_msgs::TwistStamped>("currentsHat",1);
00109         buoyancyHat = nh.advertise<std_msgs::Float32>("buoyancy",1);
00110         pubRange = nh.advertise<std_msgs::Float32>("range",1);
00111         pubRangeFiltered = nh.advertise<std_msgs::Float32>("range_filtered",1);
00112         pubwk = nh.advertise<std_msgs::Float32>("w_limit",1);
00113 
00114 
00115 
00116         /*** Subscribers ***/
00117         tauAch = nh.subscribe<auv_msgs::BodyForceReq>("tauAch", 1, &Estimator3D::onTau,this);
00118         depth = nh.subscribe<std_msgs::Float32>("depth", 1,     &Estimator3D::onDepth, this);
00119         altitude = nh.subscribe<std_msgs::Float32>("altitude", 1, &Estimator3D::onAltitude, this);
00120         modelUpdate = nh.subscribe<navcon_msgs::ModelParamsUpdate>("model_update", 1, &Estimator3D::onModelUpdate,this);
00121         resetTopic = nh.subscribe<std_msgs::Bool>("reset_nav_covariance", 1, &Estimator3D::onReset,this);
00122         useGyro = nh.subscribe<std_msgs::Bool>("use_gyro", 1, &Estimator3D::onUseGyro,this);
00123         subUSBL = nh.subscribe<underwater_msgs::USBLFix>("usbl_fix", 1, &Estimator3D::onUSBLfix,this);
00124         sub = nh.subscribe<auv_msgs::NED>("quad_delta_pos", 1, &Estimator3D::deltaPosCallback,this);
00125         subKFmode = nh.subscribe<std_msgs::Bool>("KFmode", 1, &Estimator3D::KFmodeCallback, this);
00126 
00127         KFmode = quadMeasAvailable = false;
00128 
00129         /*** Get DVL model ***/
00130         ph.param("dvl_model",dvl_model, dvl_model);
00131         nav.useDvlModel(dvl_model);
00132         ph.param("imu_with_yaw_rate",useYawRate,useYawRate);
00133         ph.param("compass_variance",compassVariance,compassVariance);
00134         ph.param("gyro_variance",gyroVariance,gyroVariance);
00135 
00136         ph.param("absoluteEKF", absoluteEKF, absoluteEKF);
00137 
00138         /*** Enable USBL measurements ***/
00139         ph.param("delay", enableDelay, enableDelay);
00140         ph.param("delay_time", delay_time, delay_time);
00141         ph.param("range", enableRange, enableRange);
00142         ph.param("bearing", enableBearing, enableBearing);
00143         ph.param("elevation", enableElevation, enableElevation);
00144         //ph.param("delayTime", delayTime, delayTime);
00145 
00146         /*** Configure handlers. ***/
00147         gps.configure(nh);
00148         dvl.configure(nh);
00149         imu.configure(nh);
00150 
00151         /*** Get initial error covariance. ***/
00152     Pstart = nav.getStateCovariance();
00153 }
00154 
00155 void Estimator3D::onReset(const std_msgs::Bool::ConstPtr& reset)
00156 {
00157    if (reset->data)
00158    {
00159       nav.setStateCovariance(10000*KFNav::matrix::Identity(KFNav::stateNum, KFNav::stateNum));
00160    }
00161 }
00162 
00163 void Estimator3D::onUseGyro(const std_msgs::Bool::ConstPtr& use_gyro)
00164 {
00165    if (use_gyro->data)
00166    {
00167       nav.R0(KFNav::psi, KFNav::psi) = gyroVariance;
00168       ROS_INFO("Switch to using gyro measurements.");
00169    }
00170    else
00171    {
00172       nav.R0(KFNav::psi, KFNav::psi) = compassVariance;
00173       ROS_INFO("Switch to using compass measurements.");
00174    }
00175 }
00176 
00177 void Estimator3D::configureNav(KFNav& nav, ros::NodeHandle& nh)
00178 {
00179         ROS_INFO("Configure navigation.");
00180 
00181         labust::simulation::DynamicsParams params;
00182         labust::tools::loadDynamicsParams(nh, params);
00183 
00184         ROS_INFO("Loaded dynamics params.");
00185 
00186         this->params[X].alpha = params.m + params.Ma(0,0);
00187         this->params[X].beta = params.Dlin(0,0);
00188         this->params[X].betaa = params.Dquad(0,0);
00189 
00190         this->params[Y].alpha = params.m + params.Ma(1,1);
00191         this->params[Y].beta = params.Dlin(1,1);
00192         this->params[Y].betaa = params.Dquad(1,1);
00193 
00194         this->params[Z].alpha = params.m + params.Ma(2,2);
00195         this->params[Z].beta = params.Dlin(2,2);
00196         this->params[Z].betaa = params.Dquad(2,2);
00197 
00198         this->params[K].alpha = params.Io(0,0) + params.Ma(3,3);
00199         this->params[K].beta = params.Dlin(3,3);
00200         this->params[K].betaa = params.Dquad(3,3);
00201 
00202         this->params[M].alpha = params.Io(1,1) + params.Ma(4,4);
00203         this->params[M].beta = params.Dlin(4,4);
00204         this->params[M].betaa = params.Dquad(4,4);
00205 
00206         this->params[N].alpha = params.Io(2,2) + params.Ma(5,5);
00207         this->params[N].beta = params.Dlin(5,5);
00208         this->params[N].betaa = params.Dquad(5,5);
00209 
00210         nav.setParameters(this->params[X], this->params[Y],
00211                         this->params[Z], this->params[K],
00212                         this->params[M], this->params[N]);
00213 
00214         nav.initModel();
00215         labust::navigation::kfModelLoader(nav, nh, "ekfnav_usbl");
00216 }
00217 
00218 void Estimator3D::onModelUpdate(const navcon_msgs::ModelParamsUpdate::ConstPtr& update)
00219 {
00220         ROS_INFO("Updating the model parameters for %d DoF.",update->dof);
00221         params[update->dof].alpha = update->alpha;
00222         if (update->use_linear)
00223         {
00224                 params[update->dof].beta = update->beta;
00225                 params[update->dof].betaa = 0;
00226         }
00227         else
00228         {
00229                 params[update->dof].beta = 0;
00230                 params[update->dof].betaa = update->betaa;
00231         }
00232         nav.setParameters(this->params[X],this->params[Y],
00233                         this->params[Z], this->params[K],
00234                         this->params[M],this->params[N]);
00235 }
00236 
00237 void Estimator3D::onTau(const auv_msgs::BodyForceReq::ConstPtr& tau)
00238 {
00239         tauIn(KFNav::X) = tau->wrench.force.x;
00240         tauIn(KFNav::Y) = tau->wrench.force.y;
00241         tauIn(KFNav::Z) = tau->wrench.force.z;
00242         tauIn(KFNav::Kroll) = tau->wrench.torque.x;
00243         tauIn(KFNav::M) = tau->wrench.torque.y;
00244         tauIn(KFNav::N) = tau->wrench.torque.z;
00245 };
00246 
00247 /*********************************************************************
00248  *** Measurement callback
00249  ********************************************************************/
00250 
00251 void Estimator3D::onDepth(const std_msgs::Float32::ConstPtr& data)
00252 {
00253         measurements(KFNav::zp) = data->data;
00254         newMeas(KFNav::zp) = 1;
00255 };
00256 
00257 void Estimator3D::onAltitude(const std_msgs::Float32::ConstPtr& data)
00258 {
00259         measurements(KFNav::altitude) = data->data;
00260         //Dismiss false altitude
00261         if (fabs(data->data-nav.getState()(KFNav::altitude)) < 10*nav.calculateAltInovationVariance(nav.getStateCovariance())) 
00262         {
00263                 newMeas(KFNav::altitude) = 1;
00264                 alt = data->data;
00265                 ROS_DEBUG("Accepted altitude: meas=%f, estimate=%f, variance=%f",
00266                         data->data, nav.getState()(KFNav::altitude), 10* nav.calculateAltInovationVariance(nav.getStateCovariance()));
00267         }
00268         else
00269         {
00270                 ROS_INFO("Dissmissed altitude: meas=%f, estimate=%f, variance=%f",
00271                         data->data, nav.getState()(KFNav::altitude), 10* nav.calculateAltInovationVariance(nav.getStateCovariance()));
00272         }
00273 };
00274 
00275 void Estimator3D::onUSBLfix(const underwater_msgs::USBLFix::ConstPtr& data){
00276 
00277         /*** Calculate measurement delay ***/
00278         //double delay = calculateDelaySteps(data->header.stamp.toSec(), currentTime);
00279         double delay = double(calculateDelaySteps(currentTime-delay_time, currentTime));
00280 
00281         double bear = 360 - data->bearing;
00282         double elev = 180 - data->elevation;
00283 
00284         const KFNav::vector& x = nav.getState();
00285 
00286         //labust::math::wrapRad(measurements(KFNav::psi));
00287 
00288         ROS_ERROR("RANGE: %f, BEARING: %f deg %f rad", data->range, labust::math::wrapRad(bear*M_PI/180), labust::math::wrapRad(bear*M_PI/180+x(KFNav::psi)));
00289         /*** Get USBL measurements ***/
00290         measurements(KFNav::range) = (data->range > 0.1)?data->range:0.1;
00291         newMeas(KFNav::range) = enableRange;
00292         measDelay(KFNav::range) = delay;
00293 
00294         /*Eigen::VectorXd input(Eigen::VectorXd::Zero(3));
00295         //Eigen::VectorXd output(Eigen::VectorXd::Zero(1));
00296 
00297 
00298         input << x(KFNav::xp)-x(KFNav::xb), x(KFNav::yp)-x(KFNav::yb), x(KFNav::zp)-x(KFNav::zb);
00299         //output << measurements(KFNav::range);
00300         double y_filt, sigma, w;
00301         OR.step(input, measurements(KFNav::range), &y_filt, &sigma, &w);
00302         ROS_INFO("Finished outlier rejection");
00303 
00304         std_msgs::Float32 rng_msg;
00305         ROS_ERROR("w: %f",w);
00306 
00307         double w_limit =  0.25*std::sqrt(float(sigma));
00308         w_limit = (w_limit>1.0)?1.0:w_limit;
00309         if(w>w_limit)
00310         {
00311                 rng_msg.data = data->range;
00312                 pubRangeFiltered.publish(rng_msg);
00313         }
00314         //std_msgs::Float32 rng_msg;
00315 
00316         rng_msg.data = w_limit;
00317         pubwk.publish(rng_msg);
00318 
00319         rng_msg.data = data->range;
00320         pubRange.publish(rng_msg);*/
00321 
00322         //measurements(KFNav::bearing) = labust::math::wrapRad(bear*M_PI/180+x(KFNav::psi));
00323         measurements(KFNav::bearing) = labust::math::wrapRad(bear*M_PI/180);
00324         newMeas(KFNav::bearing) = enableBearing;
00325         measDelay(KFNav::bearing) = delay;
00326 
00327         measurements(KFNav::elevation) = elev*M_PI/180;
00328         newMeas(KFNav::elevation) = enableElevation;
00329         measDelay(KFNav::elevation) = delay;
00330 
00331         /*** Get beacon position ***/
00332         measurements(KFNav::xb) =-1.25;
00333         newMeas(KFNav::xb) = 1;
00334         measDelay(KFNav::xb) = delay;
00335 
00336         measurements(KFNav::yb) = 0.5;
00337         newMeas(KFNav::yb) = 1;
00338         measDelay(KFNav::yb) = delay;
00339 
00340         measurements(KFNav::zb) = 2.6;
00341         newMeas(KFNav::zb) = 1;
00342         measDelay(KFNav::zb) = delay;
00343 
00344         // Debug print
00345         //ROS_ERROR("Delay: %f", delay);
00346         //ROS_ERROR("Range: %f, bearing: %f, elevation: %f", measurements(KFNav::range), measurements(KFNav::bearing), measurements(KFNav::elevation));
00347         //ROS_ERROR("ENABLED Range: %d, bearing: %d, elevation: %d", enableRange, enableBearing, enableElevation);
00348 
00349 
00350         // Relativna mjerenja ukljuciti u model mjerenja...
00351 
00352         //measurements(KFNav::xb) = x(KFNav::xp) - data->relative_position.x;
00353         //newMeas(KFNav::xb) = 1;
00354 
00355         //measurements(KFNav::yb) = x(KFNav::yp) - data->relative_position.y;
00356         //newMeas(KFNav::yb) = 1;
00357 
00358         //measurements(KFNav::zb) = x(KFNav::zp) - data->relative_position.z;
00359         //newMeas(KFNav::zb) = 1;
00360 }
00361 
00362 void Estimator3D::deltaPosCallback(const auv_msgs::NED::ConstPtr& msg){
00363 
00364         quadMeasAvailable = true;
00365         deltaXpos = msg->north;
00366         deltaYpos = msg->east;
00367 }
00368 
00369 void Estimator3D::KFmodeCallback(const std_msgs::Bool::ConstPtr& msg){
00370 
00371         if(!absoluteEKF){
00372                 KFmode = msg->data;
00373 
00374                 if(KFmode && (KFmodePast xor KFmode)){
00375 
00376                         KFmodePast = KFmode;
00377                         KFNav::matrix P = nav.getStateCovariance();
00378                         P(KFNav::xp,KFNav::xp) = 10000;
00379                         P(KFNav::yp,KFNav::yp) = 10000;
00380                         nav.setStateCovariance(P);
00381 
00382                         //nav.R0(KFNav::xp,KFNav::xp) = 1;
00383                         //nav.R0(KFNav::xp,KFNav::xp) = 1;
00384                         //nav.R(7,7) = 0.001;
00385 
00386 
00387                 } else if(!KFmode && (KFmodePast xor KFmode)){
00388 
00389                 KFmodePast = KFmode;
00390                         KFNav::matrix P = nav.getStateCovariance();
00391                         P(KFNav::xp,KFNav::xp) = 10000;
00392                         P(KFNav::yp,KFNav::yp) = 10000;
00393                         nav.setStateCovariance(P);
00394 
00395                         //nav.setStateCovariance(Pstart);
00396                         //nav.R0 = Rstart;
00397                         //Rstart(KFNav::xp,KFNav::xp)
00398                 }
00399         }
00400 }
00401 
00402 /*********************************************************************
00403  *** Helper functions
00404  ********************************************************************/
00405 
00406 void Estimator3D::processMeasurements()
00407 {
00408 
00410 
00411         measurements(KFNav::zp) = 0.07;
00412         newMeas(KFNav::zp) = 1;
00413 
00414 
00415         if(KFmode == true && absoluteEKF == false)
00416                 {
00417                         if ((newMeas(KFNav::xp) = newMeas(KFNav::yp) = quadMeasAvailable)){
00418 
00419                                 quadMeasAvailable = false;
00420                                 measurements(KFNav::xp) = deltaXpos;
00421                                 measurements(KFNav::yp) = deltaYpos;
00422                     }
00423                 } else {
00424 
00425                         //GPS measurements
00426                         if ((newMeas(KFNav::xp) = newMeas(KFNav::yp) = gps.newArrived()))
00427                         {
00428                                 measurements(KFNav::xp) = gps.position().first;
00429                                 measurements(KFNav::yp) = gps.position().second;
00430                         }
00431                 }
00432 
00433                 //ROS_ERROR("xp: %4.2f, yp: %4.2f, MODE: %d",measurements(KFNav::xp),measurements(KFNav::yp),KFmode );
00434 
00435         //Imu measurements
00436         if ((newMeas(KFNav::phi) = newMeas(KFNav::theta) = newMeas(KFNav::psi) = imu.newArrived()))
00437         {
00438 
00439                 measurements(KFNav::phi) = imu.orientation()[ImuHandler::roll];
00440                 measurements(KFNav::theta) = imu.orientation()[ImuHandler::pitch];
00441                 measurements(KFNav::psi) = imu.orientation()[ImuHandler::yaw];
00442 
00443                 ROS_DEBUG("NEW IMU: r=%f, p=%f, y=%f", imu.orientation()[ImuHandler::roll],
00444                                 imu.orientation()[ImuHandler::pitch],
00445                                 imu.orientation()[ImuHandler::yaw]);
00446 
00447 
00448                 if ((newMeas(KFNav::r) = useYawRate))
00449                 {
00450                         measurements(KFNav::r) = imu.rate()[ImuHandler::r];
00451                 }
00452         }
00453         //DVL measurements
00454         //if ((newMeas(KFNav::u) = newMeas(KFNav::v) = newMeas(KFNav::w) = dvl.NewArrived()))
00455         if ((newMeas(KFNav::u) = newMeas(KFNav::v) = dvl.newArrived()))
00456         {
00457                 double vx = dvl.body_speeds()[DvlHandler::u];
00458                 double vy = dvl.body_speeds()[DvlHandler::v];
00459                 double vxe = nav.getState()(KFNav::u); 
00460                 double vye = nav.getState()(KFNav::v); 
00461 
00462                 double rvx(10),rvy(10);
00463                 //Calculate the measured value
00464                 //This depends on the DVL model actually, but lets assume
00465                 nav.calculateUVInovationVariance(nav.getStateCovariance(), rvx, rvy);
00466 
00467                 double cpsi = cos(nav.getState()(KFNav::psi));
00468                 double spsi = sin(nav.getState()(KFNav::psi));
00469                 double xc = nav.getState()(KFNav::xc);
00470                 double yc = nav.getState()(KFNav::yc);
00471                 switch (dvl_model)
00472                 {
00473                   case 1:
00474                     vxe += xc*cpsi + yc*spsi;
00475                     vye += -xc*spsi + yc*cpsi;
00476                     break;
00477                 default: break;
00478                 }
00479 
00480                 if (fabs((vx - vxe)) > fabs(rvx))
00481                 {
00482                         ROS_INFO("Outlier rejected: meas=%f, est=%f, tolerance=%f", vx, nav.getState()(KFNav::u), fabs(rvx));
00483                         newMeas(KFNav::u) = false;
00484                 }
00485                 measurements(KFNav::u) = vx;
00486 
00487 
00488                 if (fabs((vy - vye)) > fabs(rvy))
00489                 {
00490                         ROS_INFO("Outlier rejected: meas=%f, est=%f, tolerance=%f", vy, nav.getState()(KFNav::v), fabs(rvy));
00491                         newMeas(KFNav::v) = false;
00492                 }
00493                 measurements(KFNav::v) = vy;
00494 
00495                 //measurements(KFNav::w) = dvl.body_speeds()[DvlHandler::w];
00496         }
00497 
00498         /*** Publish measurements ***/
00499         auv_msgs::NavSts::Ptr meas(new auv_msgs::NavSts());
00500         meas->body_velocity.x = measurements(KFNav::u);
00501         meas->body_velocity.y = measurements(KFNav::v);
00502         meas->body_velocity.z = measurements(KFNav::w);
00503 
00504         meas->position.north = measurements(KFNav::xp);
00505         meas->position.east = measurements(KFNav::yp);
00506         meas->position.depth = measurements(KFNav::zp);
00507         meas->altitude = measurements(KFNav::altitude);
00508 
00509         meas->orientation.roll = measurements(KFNav::phi);
00510         meas->orientation.pitch = measurements(KFNav::theta);
00511         meas->orientation.yaw = labust::math::wrapRad(measurements(KFNav::psi));
00512         if (useYawRate) meas->orientation_rate.yaw = measurements(KFNav::r);
00513 
00514         meas->origin.latitude = gps.origin().first;
00515         meas->origin.longitude = gps.origin().second;
00516         meas->global_position.latitude = gps.latlon().first;
00517         meas->global_position.longitude = gps.latlon().second;
00518 
00519         meas->header.stamp = ros::Time::now();
00520         meas->header.frame_id = "local";
00521         stateMeas.publish(meas);
00522 }
00523 
00524 void Estimator3D::publishState()
00525 {
00526         auv_msgs::NavSts::Ptr state(new auv_msgs::NavSts());
00527         const KFNav::vector& estimate = nav.getState();
00528         state->body_velocity.x = estimate(KFNav::u);
00529         state->body_velocity.y = estimate(KFNav::v);
00530         state->body_velocity.z = estimate(KFNav::w);
00531 
00532         Eigen::Matrix2d R;
00533         double yaw = labust::math::wrapRad(estimate(KFNav::psi));
00534         R<<cos(yaw),-sin(yaw),sin(yaw),cos(yaw);
00535         Eigen::Vector2d in, out;
00536         in << estimate(KFNav::xc), estimate(KFNav::yc);
00537         out = R.transpose()*in;
00538 
00539         state->gbody_velocity.x = estimate(KFNav::u) + out(0);
00540         state->gbody_velocity.y = estimate(KFNav::v) + out(1);
00541         state->gbody_velocity.z = estimate(KFNav::w);
00542 
00543         state->orientation_rate.roll = estimate(KFNav::p);
00544         state->orientation_rate.pitch = estimate(KFNav::q);
00545         state->orientation_rate.yaw = estimate(KFNav::r);
00546 
00547         state->position.north = estimate(KFNav::xp);
00548         state->position.east = estimate(KFNav::yp);
00549         state->position.depth = estimate(KFNav::zp);
00550         state->altitude = estimate(KFNav::altitude);
00551 
00552         state->orientation.roll = estimate(KFNav::phi);
00553         state->orientation.pitch = estimate(KFNav::theta);
00554         state->orientation.yaw = labust::math::wrapRad(estimate(KFNav::psi));
00555 
00556         state->origin.latitude = gps.origin().first;
00557     state->origin.longitude = gps.origin().second;
00558         std::pair<double, double> diffAngle = labust::tools::meter2deg(state->position.north,
00559                         state->position.east,
00560                         //The latitude angle
00561                         state->origin.latitude);
00562         state->global_position.latitude = state->origin.latitude + diffAngle.first;
00563         state->global_position.longitude = state->origin.longitude + diffAngle.second;
00564 
00565         const KFNav::matrix& covariance = nav.getStateCovariance();
00566         state->position_variance.north = covariance(KFNav::xp, KFNav::xp);
00567         state->position_variance.east = covariance(KFNav::yp, KFNav::yp);
00568         state->position_variance.depth = covariance(KFNav::zp,KFNav::zp);
00569         state->orientation_variance.roll =  covariance(KFNav::phi, KFNav::phi);
00570         state->orientation_variance.pitch =  covariance(KFNav::theta, KFNav::theta);
00571         state->orientation_variance.yaw =  covariance(KFNav::psi, KFNav::psi);
00572 
00573         state->header.stamp = ros::Time::now();
00574         state->header.frame_id = "local";
00575         stateHat.publish(state);
00576 
00577         geometry_msgs::TwistStamped::Ptr current(new geometry_msgs::TwistStamped());
00578         current->twist.linear.x = estimate(KFNav::xc);
00579         current->twist.linear.y = estimate(KFNav::yc);
00580         current->header.stamp = ros::Time::now();
00581         current->header.frame_id = "local";
00582         currentsHat.publish(current);
00583 
00584         std_msgs::Float32::Ptr buoyancy(new std_msgs::Float32());
00585         buoyancy->data = estimate(KFNav::buoyancy);
00586         buoyancyHat.publish(buoyancy);
00587 }
00588 
00589 
00590 int Estimator3D::calculateDelaySteps(double measTime, double arrivalTime){
00591                                 return floor((arrivalTime-measTime)/nav.Ts);
00592                         }
00593 
00594 /*********************************************************************
00595  *** Main loop
00596  ********************************************************************/
00597 void Estimator3D::start()
00598 {
00599         ros::NodeHandle ph("~");
00600         double Ts(0.1);
00601         ph.param("Ts",Ts,Ts);
00602         ros::Rate rate(1/Ts);
00603         nav.setTs(Ts);
00604 
00605         /*** Initialize time (for delay calculation) ***/
00606         currentTime = ros::Time::now().toSec();
00607 
00608         while (ros::ok()){
00609 
00610                 /*** Process measurements ***/
00611                 processMeasurements();
00612 
00613                 /*** Store filter data ***/
00614                 FilterState state;
00615                 state.input = tauIn;
00616                 state.meas = measurements;
00617                 state.newMeas = newMeas;
00618 
00619                 /*** Check if there are delayed measurements, and disable them in current step ***/
00620                 bool newDelayed(false);
00621                 for(size_t i=0; i<measDelay.size(); ++i){
00622                         if(measDelay(i)){
00623                                 state.newMeas(i) = 0;
00624                                 newDelayed = true;
00625                         }
00626                 }
00627 
00628                 /*** Store x, P, R data ***/
00629                 state.state = nav.getState();
00630                 state.Pcov = nav.getStateCovariance();
00631                 //state.Rcov = ; // In case of time-varying measurement covariance
00632 
00633                 //ROS_ERROR_STREAM(state.Pcov);
00634                 /*** Limit queue size ***/
00635                 if(pastStates.size()>1000){
00636                         pastStates.pop_front();
00637                         //ROS_ERROR("Pop front");
00638                 }
00639                 pastStates.push_back(state);
00640 
00641                 if(newDelayed && enableDelay)
00642                 {
00643                         /*** Check for maximum delay ***/
00644                         int delaySteps = measDelay.maxCoeff();
00645 
00646                         /*** If delay is bigger then buffer size assume that it is max delay ***/
00647                         if(delaySteps >= pastStates.size())
00648                                 delaySteps = pastStates.size()-1;
00649 
00650                         /*** Position delayed measurements in past states container
00651                              and store past states data in temporary stack ***/
00652                         std::stack<FilterState> tmp_stack;
00653                         for(size_t i=0; i<=delaySteps; i++){
00654 
00655                                 KFNav::vector tmp_cmp;
00656                                 tmp_cmp.setConstant(KFNav::measSize, i);
00657                                 if((measDelay.array() == tmp_cmp.array()).any() && i != 0){
00658                                         FilterState tmp_state = pastStates.back();
00659                                         for(size_t j=0; j<measDelay.size(); ++j){
00660                                                 if(measDelay(j) == i){
00661                                                         tmp_state.newMeas(j) = 1;
00662                                                         tmp_state.meas(j) = measurements(j);
00663 
00667                                                         if(j == KFNav::range)
00668                                                         {
00669                                                                 const KFNav::vector& x = tmp_state.state; 
00670                                                                 double range = measurements(j);
00671 
00672                                                                 Eigen::VectorXd input(Eigen::VectorXd::Zero(3));
00673                                                                         //Eigen::VectorXd output(Eigen::VectorXd::Zero(1));
00674 
00675 
00676                                                                 input << x(KFNav::xp)-x(KFNav::xb), x(KFNav::yp)-x(KFNav::yb), x(KFNav::zp)-x(KFNav::zb);
00677                                                                 //input << x(KFNav::u), x(KFNav::yp)-x(KFNav::yb), x(KFNav::zp)-x(KFNav::zb);
00678 
00679                                                                 //output << measurements(KFNav::range);
00680                                                                 double y_filt, sigma, w;
00681                                                                 OR.step(input, measurements(KFNav::range), &y_filt, &sigma, &w);
00682                                                                 //ROS_INFO("Finished outlier rejection");
00683 
00684                                                                 std_msgs::Float32 rng_msg;
00685                                                                 //ROS_ERROR("w: %f",w);
00686 
00687                                                                 double w_limit =  0.3*std::sqrt(float(sigma));
00688                                                                 w_limit = (w_limit>1.0)?1.0:w_limit;
00689                                                                 if(w>w_limit)
00690                                                                 {
00691                                                                         rng_msg.data = range;
00692                                                                         pubRangeFiltered.publish(rng_msg);
00693                                                                         //pubRangeFiltered.publish(rng_msg);
00694 
00695                                                                 } else {
00696                                                                         tmp_state.newMeas(j) = 0;
00697                                                                 }
00698                                                                 //std_msgs::Float32 rng_msg;
00699 
00700                                                                 rng_msg.data = w_limit;
00701                                                                 pubwk.publish(rng_msg);
00702 
00703                                                                 rng_msg.data = range;
00704                                                                 pubRange.publish(rng_msg);
00705 
00706                                                         }
00707 
00708                                                         if(j == KFNav::bearing && tmp_state.newMeas(j-1) == 0)
00709                                                         {
00710                                                                 tmp_state.newMeas(j) = 0;
00711 
00712                                                         }
00713 
00714 
00715 
00716 
00718 
00719                                                         //ROS_ERROR("Dodano mjerenje. Delay:%d",i);
00720                                                 }
00721                                         }
00722                                         tmp_stack.push(tmp_state);
00723                                 } else {
00724                                         tmp_stack.push(pastStates.back());
00725                                 }
00726                                 pastStates.pop_back();
00727                         }
00728 
00729                         /*** Load past state and covariance for max delay time instant ***/
00730                         FilterState state_p = tmp_stack.top();
00731                         nav.setStateCovariance(state_p.Pcov);
00732                         nav.setState(state_p.state);
00733 
00734                         /*** Pass through stack data and recalculate filter states ***/
00735                         while(!tmp_stack.empty()){
00736                                 state_p = tmp_stack.top();
00737                                 tmp_stack.pop();
00738                                 pastStates.push_back(state_p);
00739 
00740                                 /*** Estimation ***/
00741                                 nav.predict(state_p.input);
00742                                 bool newArrived(false);
00743                                 for(size_t i=0; i<state_p.newMeas.size(); ++i)  if ((newArrived = state_p.newMeas(i))) break;
00744                                 if (newArrived) nav.correct(nav.update(state_p.meas, state_p.newMeas));
00745                         }
00746                 }else{
00747                         /*** Estimation ***/
00748                         nav.predict(tauIn);
00749                         bool newArrived(false);
00750                         for(size_t i=0; i<newMeas.size(); ++i)  if ((newArrived = newMeas(i))) break;
00751                         if (newArrived) nav.correct(nav.update(measurements, newMeas));
00752                 }
00753 
00754                 newMeas.setZero(); // razmisli kako ovo srediti
00755                 measDelay.setZero();
00756                 publishState();
00757 
00758                 //ROS_ERROR_STREAM(nav.getStateCovariance());
00759 
00760                 /*** Send the base-link transform ***/
00761                 geometry_msgs::TransformStamped transform;
00762                 transform.transform.translation.x = nav.getState()(KFNav::xp);
00763                 transform.transform.translation.y = nav.getState()(KFNav::yp);
00764                 transform.transform.translation.z = nav.getState()(KFNav::zp);
00765                 labust::tools::quaternionFromEulerZYX(nav.getState()(KFNav::phi),
00766                                 nav.getState()(KFNav::theta),
00767                                 nav.getState()(KFNav::psi),
00768                                 transform.transform.rotation);
00769                 if(absoluteEKF){
00770                         transform.child_frame_id = "base_link";
00771                 } else{
00772                         transform.child_frame_id = "base_link";
00773                 }
00774                 transform.header.frame_id = "local";
00775                 transform.header.stamp = ros::Time::now();
00776                 broadcaster.sendTransform(transform);
00777 
00778                 rate.sleep();
00779                 /*** Get current time (for delay calculation) ***/
00780                 currentTime = ros::Time::now().toSec();
00781                 ros::spinOnce();
00782         }
00783 }
00784 
00785 int main(int argc, char* argv[])
00786 {
00787         ros::init(argc,argv,"nav_3d");
00788         Estimator3D nav;
00789         nav.start();
00790         return 0;
00791 }
00792 
00793 


labust_navigation
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:23:33