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/navigation/KFCore.hpp>
00038 #include <labust/navigation/LDTravModel.hpp>
00039 #include <labust/math/NumberManipulation.hpp>
00040 #include <labust/tools/GeoUtilities.hpp>
00041 #include <labust/tools/MatrixLoader.hpp>
00042 #include <labust/tools/conversions.hpp>
00043 #include <labust/tools/DynamicsLoader.hpp>
00044 #include <labust/simulation/DynamicsParams.hpp>
00045 #include <labust/navigation/KFModelLoader.hpp>
00046
00047
00048 #include <kdl/frames.hpp>
00049 #include <auv_msgs/NavSts.h>
00050 #include <auv_msgs/BodyForceReq.h>
00051 #include <nav_msgs/Odometry.h>
00052 #include <sensor_msgs/NavSatFix.h>
00053 #include <sensor_msgs/Imu.h>
00054 #include <sensor_msgs/FluidPressure.h>
00055 #include <geometry_msgs/TwistStamped.h>
00056
00057 #include <tf/transform_broadcaster.h>
00058 #include <tf/transform_listener.h>
00059
00060 #include <ros/ros.h>
00061
00062 #include <boost/bind.hpp>
00063 #include <sstream>
00064
00065 typedef labust::navigation::KFCore<labust::navigation::LDTravModel> KFNav;
00066 tf::TransformListener* listener;
00067
00068 ros::Time t;
00069 double g_acc(9.81), rho(1025);
00070
00071 void handleTau(KFNav::vector& tauIn, const auv_msgs::BodyForceReq::ConstPtr& tau)
00072 {
00073 tauIn(KFNav::X) = tau->wrench.force.x;
00074 tauIn(KFNav::Y) = tau->wrench.force.y;
00075 tauIn(KFNav::Z) = tau->wrench.force.z;
00076 tauIn(KFNav::N) = tau->wrench.torque.z;
00077 };
00078
00079 void handleGPS(KFNav::vector& measurement, KFNav::vector& newFlag, const sensor_msgs::NavSatFix::ConstPtr& data)
00080 {
00081
00082 tf::StampedTransform transformDeg, transformLocal;
00083 try
00084 {
00085 listener->lookupTransform("local", "gps_frame", ros::Time(0), transformLocal);
00086 listener->lookupTransform("/worldLatLon", "local", ros::Time(0), transformDeg);
00087
00088 std::pair<double,double> posxy =
00089 labust::tools::deg2meter(data->latitude - transformDeg.getOrigin().y(),
00090 data->longitude - transformDeg.getOrigin().x(),
00091 transformDeg.getOrigin().y());
00092
00093
00094 tf::Vector3 pos = tf::Vector3(posxy.first, posxy.second,0);
00095
00096
00097
00098 measurement(KFNav::xp) = posxy.first;
00099 newFlag(KFNav::xp) = 1;
00100 measurement(KFNav::yp) = posxy.second;
00101 newFlag(KFNav::yp) = 1;
00102 }
00103 catch(tf::TransformException& ex)
00104 {
00105 ROS_ERROR("%s",ex.what());
00106 }
00107 };
00108
00109 void handleImu(KFNav::vector& rpy, const sensor_msgs::Imu::ConstPtr& data)
00110 {
00111 enum {r,p,y,newMsg};
00112 double roll,pitch,yaw;
00113 static labust::math::unwrap unwrap;
00114
00115 tf::StampedTransform transform;
00116 try
00117 {
00118 t = data->header.stamp;
00119 listener->lookupTransform("base_link", "imu_frame", ros::Time(0), transform);
00120 tf::Quaternion meas(data->orientation.x,data->orientation.y,
00121 data->orientation.z,data->orientation.w);
00122 tf::Quaternion result = meas*transform.getRotation();
00123
00124 KDL::Rotation::Quaternion(result.x(),result.y(),result.z(),result.w()).GetEulerZYX(yaw,pitch,roll);
00125
00126
00127
00128
00129
00130
00131 rpy(r) = roll;
00132 rpy(p) = pitch;
00133 rpy(y) = unwrap(yaw);
00134 rpy(newMsg) = 1;
00135 }
00136 catch (tf::TransformException& ex)
00137 {
00138 ROS_ERROR("%s",ex.what());
00139 }
00140 };
00141
00142 void handleDvl(KFNav::vector& measurement, KFNav::vector& newFlag,
00143 const geometry_msgs::TwistStamped::ConstPtr& data)
00144 {
00145 measurement(KFNav::u) = data->twist.linear.x;
00146 newFlag(KFNav::u)=1;
00147 measurement(KFNav::v) = data->twist.linear.y;
00148 newFlag(KFNav::v)=1;
00149
00150
00151 };
00152
00153 void handlePressure(KFNav::vector& measurement, KFNav::vector& newFlag,
00154 const std_msgs::Float32::ConstPtr& data)
00155 {
00156 measurement(KFNav::zp) = data->data;
00157 newFlag(KFNav::zp)=1;
00158 };
00159
00160 void configureNav(KFNav& nav, ros::NodeHandle& nh)
00161 {
00162 ROS_INFO("Configure navigation.");
00163
00164 labust::simulation::DynamicsParams params;
00165 labust::tools::loadDynamicsParams(nh, params);
00166
00167 ROS_INFO("Loaded dynamics params.");
00168
00169 KFNav::ModelParams surge,sway,heave,yaw;
00170 surge.alpha = params.m + params.Ma(0,0);
00171 sway.alpha = params.m + params.Ma(1,1);
00172 heave.alpha = params.m + params.Ma(2,2);
00173 yaw.alpha = params.Io(2,2) + params.Ma(5,5);
00174 surge.beta = params.Dlin(0,0);
00175 sway.beta = params.Dlin(1,1);
00176 sway.beta = params.Dlin(2,2);
00177 yaw.beta = params.Dlin(5,5);
00178 surge.betaa = params.Dquad(0,0);
00179 sway.betaa = params.Dquad(1,1);
00180 sway.betaa = params.Dquad(2,2);
00181 yaw.betaa = params.Dquad(5,5);
00182 nav.setParameters(surge,sway,heave,yaw);
00183
00184 g_acc = params.g_acc;
00185 rho = params.rho;
00186
00187 nav.initModel();
00188 labust::navigation::kfModelLoader(nav, nh, "ekfnav");
00189 }
00190
00191
00192 int main(int argc, char* argv[])
00193 {
00194 ros::init(argc,argv,"rov_nav");
00195 ros::NodeHandle nh;
00196 KFNav nav;
00197
00198 configureNav(nav,nh);
00199
00200 double outlierR;
00201 nh.param("outlier_radius",outlierR,1.0);
00202
00203
00204 ros::Publisher stateHat = nh.advertise<auv_msgs::NavSts>("stateHat",1);
00205 ros::Publisher stateMeas = nh.advertise<auv_msgs::NavSts>("meas",1);
00206 ros::Publisher currentTwist = nh.advertise<geometry_msgs::TwistStamped>("currentsHat",1);
00207 ros::Publisher bodyFlowFrame = nh.advertise<geometry_msgs::TwistStamped>("body_flow_frame_twist",1);
00208
00209 KFNav::vector tau(KFNav::vector::Zero(KFNav::inputSize)),
00210 measurements(KFNav::vector::Zero(KFNav::stateNum)),
00211 newMeasFlag(KFNav::vector::Zero(KFNav::stateNum));
00212 KFNav::vector rpy(KFNav::vector::Zero(3+1));
00213
00214 tf::TransformBroadcaster broadcast;
00215 listener = new tf::TransformListener();
00216
00217 ros::Subscriber tauAch = nh.subscribe<auv_msgs::BodyForceReq>("tauAch", 1,
00218 boost::bind(&handleTau,boost::ref(tau),_1));
00219 ros::Subscriber navFix = nh.subscribe<sensor_msgs::NavSatFix>("gps", 1,
00220 boost::bind(&handleGPS,boost::ref(measurements),boost::ref(newMeasFlag),_1));
00221 ros::Subscriber imu = nh.subscribe<sensor_msgs::Imu>("imu", 1,
00222 boost::bind(&handleImu,boost::ref(rpy),_1));
00223 ros::Subscriber dvl = nh.subscribe<geometry_msgs::TwistStamped>("dvl", 1,
00224 boost::bind(&handleDvl,boost::ref(measurements),boost::ref(newMeasFlag),_1));
00225 ros::Subscriber pressure = nh.subscribe<sensor_msgs::FluidPressure>("pressure", 1,
00226 boost::bind(&handlePressure,boost::ref(measurements),boost::ref(newMeasFlag),_1));
00227
00228 ros::Rate rate(10);
00229
00230 nav_msgs::Odometry odom;
00231 auv_msgs::NavSts meas,state;
00232 geometry_msgs::TwistStamped current, flowspeed;
00233 meas.header.frame_id = "local";
00234 state.header.frame_id = "local";
00235 current.header.frame_id = "local";
00236
00237 labust::math::unwrap unwrap;
00238
00239 while (ros::ok())
00240 {
00241 nav.predict(tau);
00242 if (rpy(3))
00243 {
00244 ROS_INFO("Set the yaw.");
00245 double yaw = unwrap(rpy(2));
00246 measurements(KFNav::psi) = yaw;
00247 newMeasFlag(KFNav::psi) = 1;
00248 }
00249
00250 bool anyNew = false;
00251 for (size_t i=0; i<newMeasFlag.size(); ++i) if ((anyNew = (newMeasFlag(i)))) break;
00252
00253 if (anyNew)
00254 {
00255 ROS_INFO("Do update.");
00256 nav.correct(nav.update(measurements, newMeasFlag));
00257 ROS_INFO("Correction step.");
00258 }
00259
00260 meas.orientation.roll = rpy(0);
00261 meas.orientation.pitch = rpy(1);
00262 meas.orientation.yaw = rpy(2);
00263 meas.position.north = measurements(KFNav::xp);
00264 meas.position.east = measurements(KFNav::yp);
00265 meas.position.depth = measurements(KFNav::zp);
00266 meas.body_velocity.x = measurements(KFNav::u);
00267 meas.body_velocity.y = measurements(KFNav::v);
00268 meas.body_velocity.z = measurements(KFNav::w);
00269 stateMeas.publish(meas);
00270
00271 const KFNav::vector& estimate = nav.getState();
00272 state.body_velocity.x = estimate(KFNav::u);
00273 state.body_velocity.y = estimate(KFNav::v);
00274 state.body_velocity.z = estimate(KFNav::w);
00275 state.orientation_rate.yaw = estimate(KFNav::r);
00276 state.position.north = estimate(KFNav::xp);
00277 state.position.east = estimate(KFNav::yp);
00278 state.position.depth = estimate(KFNav::zp);
00279 current.twist.linear.x = estimate(KFNav::xc);
00280 current.twist.linear.y = estimate(KFNav::yc);
00281
00282 const KFNav::matrix& covariance = nav.getStateCovariance();
00283 state.position_variance.north = covariance(KFNav::xp, KFNav::xp);
00284 state.position_variance.east = covariance(KFNav::yp, KFNav::yp);
00285 state.position_variance.depth = covariance(KFNav::zp,KFNav::zp);
00286 state.orientation_variance.yaw = covariance(KFNav::psi, KFNav::psi);
00287
00288 try
00289 {
00290 tf::StampedTransform transformDeg;
00291 listener->lookupTransform("/worldLatLon", "local", ros::Time(0), transformDeg);
00292
00293 std::pair<double, double> diffAngle = labust::tools::meter2deg(state.position.north,
00294 state.position.east,
00295
00296 transformDeg.getOrigin().y());
00297 state.global_position.latitude = transformDeg.getOrigin().y() + diffAngle.first;
00298 state.global_position.longitude = transformDeg.getOrigin().x() + diffAngle.second;
00299 }
00300 catch(tf::TransformException& ex)
00301 {
00302 ROS_WARN("Unable to set global position. %s",ex.what());
00303 }
00304
00305 state.orientation.yaw = labust::math::wrapRad(estimate(KFNav::psi));
00306
00307 tf::StampedTransform transform;
00308 transform.setOrigin(tf::Vector3(estimate(KFNav::xp), estimate(KFNav::yp), 0.0));
00309 Eigen::Quaternion<float> q;
00310 labust::tools::quaternionFromEulerZYX(rpy(0),rpy(1),estimate(KFNav::psi),q);
00311 transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00312 broadcast.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "base_link"));
00313
00314
00315 double xdot,ydot;
00316 nav.getNEDSpeed(xdot,ydot);
00317 labust::tools::quaternionFromEulerZYX(rpy(0),rpy(1),atan2(ydot,xdot),q);
00318 transform.setRotation(tf::Quaternion(q.x(),q.y(),q.z(),q.w()));
00319 broadcast.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "local", "base_link_flow"));
00320
00321 flowspeed.twist.linear.x = xdot;
00322 flowspeed.twist.linear.y = ydot;
00323 bodyFlowFrame.publish(flowspeed);
00324 currentTwist.publish(current);
00325 state.header.stamp = t;
00326 stateHat.publish(state);
00327
00328 rate.sleep();
00329 ros::spinOnce();
00330 }
00331
00332 return 0;
00333 }
00334
00335