USBLFilter.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: 02.04.2013.
00036  *********************************************************************/
00037 #include <labust/tritech/USBLFilter.hpp>
00038 #include <labust/tools/GeoUtilities.hpp>
00039 #include <labust/math/uBlasOperations.hpp>
00040 #include <pluginlib/class_list_macros.h>
00041 #include <labust/math/NumberManipulation.hpp>
00042 
00043 #include <geometry_msgs/PointStamped.h>
00044 #include <auv_msgs/NavSts.h>
00045 
00046 PLUGINLIB_DECLARE_CLASS(usbl,USBLFilter,labust::tritech::USBLFilter, nodelet::Nodelet)
00047 
00048 using namespace labust::tritech;
00049 
00050 USBLFilter::USBLFilter():
00051         timeout(150),
00052         iteration(0),
00053         maxSpeed(0.5){};
00054 
00055 USBLFilter::~USBLFilter(){};
00056 
00057 void USBLFilter::onInit()
00058 {
00059         ros::NodeHandle nh = this->getNodeHandle();
00060         usblSub = nh.subscribe<geometry_msgs::PointStamped>("usbl_nav", 1, boost::bind(&USBLFilter::onUsbl,this,_1));
00061         navPub = nh.advertise<auv_msgs::NavSts>("usblFiltered",1);
00062 
00063         filter.initModel();
00064         configureModel(nh);
00065         worker = boost::thread(boost::bind(&USBLFilter::run,this));
00066 }
00067 
00068 void USBLFilter::configureModel(ros::NodeHandle& nh)
00069 {
00070         std::string sQ,sW,sV,sR,sP,sx0;
00071         nh.getParam("usbl_filter/Q", sQ);
00072         nh.getParam("usbl_filter/W", sW);
00073         nh.getParam("usbl_filter/V", sV);
00074         nh.getParam("usbl_filter/R", sR);
00075         nh.getParam("usbl_filter/P", sP);
00076         nh.getParam("usbl_filter/x0", sx0);
00077         try
00078         {
00079                 KFilter::matrix Q,W,V,R,P;
00080                 KFilter::vector x0;
00081 
00082                 boost::numeric::ublas::matrixFromString(sQ,Q);
00083                 boost::numeric::ublas::matrixFromString(sR,R);
00084                 boost::numeric::ublas::matrixFromString(sW,W);
00085                 boost::numeric::ublas::matrixFromString(sV,V);
00086                 boost::numeric::ublas::matrixFromString(sR,R);
00087                 boost::numeric::ublas::matrixFromString(sP,P);
00088                 std::stringstream ss(sx0);
00089                 boost::numeric::ublas::operator >>(ss,x0);
00090 
00091                 double dT(0.1);
00092                 nh.param("sampling_time",dT,dT);
00093                 filter.setTs(dT);
00094                 filter.setStateParameters(W,Q);
00095                 filter.setMeasurementParameters(V,R);
00096                 filter.setStateCovariance(P);
00097                 filter.setState(x0);
00098         }
00099         catch (std::exception& e)
00100         {
00101                 NODELET_ERROR("USBLFilter:: Model configuration failed, %s",
00102                                 e.what());
00103         }
00104 }
00105 
00106 void USBLFilter::onUsbl(const geometry_msgs::PointStamped::ConstPtr& msg)
00107 {
00108         NODELET_DEBUG("New update: %f %f %f\n",msg->point.x, msg->point.y, msg->point.z);
00109 
00110         boost::mutex::scoped_lock lock(dataMux);
00111 
00112         tf::StampedTransform transform;
00113         try
00114         {
00115                 //Take position two seconds from the past
00116                 ros::Time now(ros::Time::now()), desired(now - ros::Duration(0));
00117                 listener.lookupTransform("local", "base_link", ros::Time(0), transform);
00118         }
00119         catch (tf::TransformException& ex)
00120         {
00121                 NODELET_ERROR("%s",ex.what());
00122         }
00123 
00124         KFilter::input_type vec(2);
00125         vec(0) = transform.getOrigin().x() + msg->point.x;
00126         vec(1) = transform.getOrigin().y() + msg->point.y;
00127         depth = transform.getOrigin().z() + (-msg->point.z);
00128 
00129         double inx, iny;
00130         filter.calculateXYInovationVariance(filter.getStateCovariance(),inx,iny);
00131         const KFilter::vector& xy(filter.getState());
00132         double outlierR = 1;
00133         bool outlier = sqrt(pow(xy(KFilter::xp)-vec(0),2) +
00134                         pow(xy(KFilter::yp)-vec(1),2)) > outlierR*sqrt(inx*inx + iny*iny);
00135 
00136         if (!outlier)
00137         {
00138                 filter.correct(vec);
00139 
00140                 //Limit diver speed
00141                 KFilter::vector newState(filter.getState());
00142                 newState(KFilter::Vv) = labust::math::coerce(
00143                                 newState(KFilter::Vv), -maxSpeed, maxSpeed);
00144                 filter.setState(newState);
00145                 iteration = 0;
00146         }
00147         else
00148         {
00149                 NODELET_INFO("Outlier rejected: current: (%f,%f) - measurement: (%f,%f) - inovation: (%f,%f)",
00150                                 xy(KFilter::xp), xy(KFilter::yp),
00151                                 vec(0), vec(1), inx, iny);
00152         }
00153 };
00154 
00155 void USBLFilter::run()
00156 {
00158         ros::Rate rate(10);
00159         timeout = 100;
00160 
00161         while (ros::ok())
00162         {
00163                 boost::mutex::scoped_lock lock(dataMux);
00164 
00165                 if (++iteration > timeout)
00166                 {
00167                         NODELET_INFO("Timeout on USBL measurements. Setting diver speed to zero. Iteration: %d",
00168                                         iteration);
00169                         //Stop the diver speed if lost
00170                         KFilter::vector newState(filter.getState());
00171                         newState(KFilter::Vv) = 0;
00172                         filter.setState(newState);
00173                 }
00174 
00175                 filter.predict();
00176                 const KFilter::vector& state = filter.getState();
00177                 auv_msgs::NavSts::Ptr odom(new auv_msgs::NavSts());
00178                 odom->header.stamp = ros::Time::now();
00179                 odom->header.frame_id = "local";
00180                 odom->position.north = state(KFilter::xp);
00181                 odom->position.east = state(KFilter::yp);
00182                 odom->position.depth = depth;
00183                 odom->orientation.yaw = state(KFilter::psi);
00184                 const KFilter::matrix& variance = filter.getStateCovariance();
00185                 odom->orientation_variance.yaw = variance(KFilter::psi, KFilter::psi);
00186                 odom->position_variance.north = variance(KFilter::xp, KFilter::xp);
00187                 odom->position_variance.east = variance(KFilter::yp, KFilter::yp);
00188 
00189                 //\todo Add covariance data
00190                 odom->body_velocity.x = state(KFilter::Vv);
00191                 //Free the filter lock
00192                 lock.unlock();
00193 
00194                 try
00195                 {
00196                         tf::StampedTransform transformDeg;
00197                         listener.lookupTransform("/worldLatLon", "local", ros::Time(0), transformDeg);
00198 
00199                         std::pair<double, double> diffAngle = labust::tools::meter2deg(state(KFilter::xp),
00200                                         state(KFilter::yp),
00201                                         //The latitude angle
00202                                         transformDeg.getOrigin().y());
00203                         odom->global_position.latitude = transformDeg.getOrigin().y() + diffAngle.first;
00204                         odom->global_position.longitude = transformDeg.getOrigin().x() + diffAngle.second;
00205                 }
00206                 catch(tf::TransformException& ex)
00207                 {
00208                         NODELET_ERROR("%s",ex.what());
00209                 }
00210 
00211                 //\todo Add covariance data
00212                 navPub.publish(odom);
00213                 rate.sleep();
00214         }
00215 }
00216 
00217 


usbl
Author(s): Gyula Nagy
autogenerated on Fri Feb 7 2014 11:36:29