00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
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
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
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
00190 odom->body_velocity.x = state(KFilter::Vv);
00191
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
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
00212 navPub.publish(odom);
00213 rate.sleep();
00214 }
00215 }
00216
00217