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/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
00070 configureNav(nav,nh);
00071
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
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
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
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
00153
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
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
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
00182
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
00192
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
00224 }
00225
00226
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
00235
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
00266
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
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
00319
00320 publishState();
00321
00322
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