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
00038
00039
00040
00041
00042 #include <Eigen/Dense>
00043 #include <boost/thread/mutex.hpp>
00044 #include <boost/array.hpp>
00045
00046 #include <labust/primitive/PrimitiveBase.hpp>
00047 #include <labust/math/NumberManipulation.hpp>
00048 #include <labust/math/Line.hpp>
00049 #include <labust/tools/conversions.hpp>
00050
00051 #include <ros/ros.h>
00052 #include <navcon_msgs/GoToPointAction.h>
00053 #include <navcon_msgs/EnableControl.h>
00054 #include <geometry_msgs/Point.h>
00055 #include <geometry_msgs/TransformStamped.h>
00056 #include <tf2_ros/static_transform_broadcaster.h>
00057
00058 namespace labust
00059 {
00060 namespace primitive
00061 {
00062
00063
00064
00065
00066 struct GoToPoint : protected ExecutorBase<navcon_msgs::GoToPointAction>
00067 {
00068 typedef navcon_msgs::GoToPointGoal Goal;
00069 typedef navcon_msgs::GoToPointResult Result;
00070 typedef navcon_msgs::GoToPointFeedback Feedback;
00071
00072 enum {ualf = 0, falf, hdg, fadp, numcnt};
00073 enum {xp = 0, yp, zp};
00074
00075 GoToPoint():ExecutorBase("go2point"),
00076 underactuated(true),
00077 processNewGoal(false),
00078 lastDistance(0.0),
00079 distVictory(0.0),
00080 Ddistance(0.0){};
00081
00082 void init()
00083 {
00084 ros::NodeHandle ph("~");
00085
00086
00087 controllers.name.resize(numcnt);
00088 controllers.state.resize(numcnt, false);
00089
00090 controllers.name[ualf] = "UALF_enable";
00091 controllers.name[falf] = "FALF_enable";
00092 controllers.name[hdg] = "HDG_enable";
00093 }
00094
00095 void onGoal()
00096 {
00097 boost::mutex::scoped_lock l(state_mux);
00098 ROS_DEBUG("On goal.");
00099
00100 processNewGoal = true;
00101 Goal::ConstPtr new_goal = aserver->acceptNewGoal();
00102 processNewGoal = false;
00103
00104
00105
00106
00107 switch(new_goal->subtype)
00108 {
00109 case Goal::GO2POINT_UA:
00110 underactuated = true;
00111 break;
00112 case Goal::GO2POINT_FA:
00113 underactuated = false;
00114 break;
00115 case Goal::GO2POINT_FA_HDG:
00116 underactuated = false;
00117 if(new_goal->ref_type != Goal::CONSTANT)
00118
00119 break;
00120 }
00121
00122
00123
00124
00125 if (new_goal->speed == 0)
00126 {
00127 ROS_WARN("Cannot perform course keeping without forward speed.");
00128 aserver->setAborted(Result(), "Forward speed is zero.");
00129 }
00130
00131 if ((goal == 0) || (new_goal->T1.point.x != goal->T1.point.x)
00132 || (new_goal->T1.point.y != goal->T1.point.y)
00133 || (new_goal->T2.point.x != goal->T2.point.x)
00134 || (new_goal->T2.point.y != goal->T2.point.y)
00135 || (new_goal->heading != goal->heading)
00136 || (new_goal->speed != goal->speed))
00137 {
00138
00139
00140 goal = new_goal;
00141
00142
00143
00144 Eigen::Vector3d T1,T2;
00145 T1 << new_goal->T1.point.x, new_goal->T1.point.y, 0;
00146 T2 << new_goal->T2.point.x, new_goal->T2.point.y, 0;
00147 line.setLine(T1,T2);
00148
00149
00150 geometry_msgs::TransformStamped transform;
00151 transform.transform.translation.x = T1(xp);
00152 transform.transform.translation.y = T1(yp);
00153 transform.transform.translation.z = T1(zp);
00154 labust::tools::quaternionFromEulerZYX(0, 0, line.gamma(),
00155 transform.transform.rotation);
00156 transform.child_frame_id = "course_frame";
00157 transform.header.frame_id = "local";
00158 transform.header.stamp = ros::Time::now();
00159 broadcaster.sendTransform(transform);
00160
00161
00162
00163 stateRef.publish(step(lastState));
00164
00165
00166
00167
00168 if (!underactuated)
00169 {
00170
00171 controllers.state[falf] = true;
00172 controllers.state[hdg] = true;
00173 }
00174 else
00175 {
00176
00177 double delta = labust::math::wrapRad(lastState.orientation.yaw - line.gamma());
00178 ROS_DEBUG("Delta: %f",delta);
00179 if (std::abs(delta) < M_PI_2)
00180 {
00181 controllers.state[ualf] = true;
00182 controllers.state[hdg] = false;
00183 }
00184 }
00185
00186
00187 this->updateControllers();
00188
00189
00190 }
00191
00192
00193
00194
00195
00196 }
00197
00198 void onPreempt()
00199 {
00200 ROS_ERROR("Preempted.");
00201 if (!processNewGoal)
00202 {
00203 ROS_ERROR("Stopping controllers.");
00204 controllers.state.assign(numcnt, false);
00205 this->updateControllers();
00206 }
00207 else
00208 {
00209
00210 }
00211 aserver->setPreempted();
00212 };
00213
00214 void updateControllers()
00215 {
00216 ros::NodeHandle nh;
00217 ros::ServiceClient cl;
00218
00219
00220 if(underactuated)
00221 cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[ualf]).c_str());
00222 else
00223 cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[falf]).c_str());
00224
00225 navcon_msgs::EnableControl a;
00226 a.request.enable = controllers.state[ualf] || controllers.state[falf];
00227 cl.call(a);
00228
00229
00230 cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[hdg]).c_str());
00231 a.request.enable = controllers.state[hdg];
00232 cl.call(a);
00233
00234 }
00235
00236 void onStateHat(const auv_msgs::NavSts::ConstPtr& estimate)
00237 {
00238
00239 boost::mutex::scoped_lock l(state_mux);
00240
00241 if(aserver->isActive())
00242 {
00243
00244 stateRef.publish(step(*estimate));
00245
00246
00247 Eigen::Vector3d deltaVictory;
00248 deltaVictory<<goal->T2.point.x-estimate->position.north, goal->T2.point.y-estimate->position.east, 0;
00249
00250 distVictory = deltaVictory.norm();
00251 Ddistance = distVictory - lastDistance;
00252 lastDistance = distVictory;
00253
00254
00255 if(distVictory < goal->victory_radius)
00256 {
00257 result.position.point.x = estimate->position.north;
00258 result.position.point.y = estimate->position.east;
00259 result.distance = distVictory;
00260 result.bearing = bearing_to_endpoint.gamma();
00261 aserver->setSucceeded(result);
00262 return;
00263 }
00264
00265
00266 Feedback feedback;
00267 feedback.distance = distVictory;
00268 feedback.bearing = bearing_to_endpoint.gamma();
00269 aserver->publishFeedback(feedback);
00270 }
00271 else if (goal != 0)
00272 {
00273 goal.reset();
00274 ROS_INFO("Stopping controllers.");
00275 controllers.state.assign(numcnt, false);
00276 this->updateControllers();
00277 }
00278
00279 lastState = *estimate;
00280 }
00281
00282 auv_msgs::NavStsPtr step(const auv_msgs::NavSts& state)
00283 {
00284 auv_msgs::NavStsPtr ref(new auv_msgs::NavSts());
00285
00286
00287 ref->position.east = 0;
00288 ref->body_velocity.x = goal->speed;
00289 ref->orientation.yaw = goal->heading;
00290 ref->header.frame_id = "course_frame";
00291
00292
00293 Eigen::Vector3d T1,T2;
00294 T1 << state.position.north, state.position.east, 0;
00295 T2 << goal->T2.point.x, goal->T2.point.y, 0;
00296 bearing_to_endpoint.setLine(T1,T2);
00297
00298
00299 if(std::abs(labust::math::wrapRad(bearing_to_endpoint.gamma() - line.gamma())) > 60*M_PI/180 && Ddistance > 0)
00300 {
00301
00302 ROS_ERROR("Changing course");
00303 line = bearing_to_endpoint;
00304
00305 geometry_msgs::TransformStamped transform;
00306 transform.transform.translation.x = T1(xp);
00307 transform.transform.translation.y = T1(yp);
00308 transform.transform.translation.z = T1(zp);
00309 labust::tools::quaternionFromEulerZYX(0, 0, line.gamma(),
00310 transform.transform.rotation);
00311 transform.child_frame_id = "course_frame";
00312 transform.header.frame_id = "local";
00313 transform.header.stamp = ros::Time::now();
00314 broadcaster.sendTransform(transform);
00315 }
00316
00317
00318 if (underactuated)
00319 {
00320 ref->orientation.yaw = line.gamma();
00321 double delta = labust::math::wrapRad(state.orientation.yaw - line.gamma());
00322 ROS_DEBUG("Delta, gamma: %f, %f",delta, line.gamma());
00323
00324
00325 if (controllers.state[hdg] && (std::abs(delta) < M_PI/3))
00326 {
00327
00328 controllers.state[hdg] = false;
00329 controllers.state[ualf] = true;
00330 this->updateControllers();
00331 ref->header.frame_id = "course_frame";
00332 }
00333 else if (std::abs(delta) >= M_PI/2)
00334 {
00335
00336 controllers.state[hdg] = true;
00337 controllers.state[ualf] = false;
00338 this->updateControllers();
00339 ref->header.frame_id = "local";
00340 }
00341
00342 }
00343
00344 ref->header.stamp = ros::Time::now();
00345 return ref;
00346 }
00347
00348 Result result;
00349
00350 private:
00351
00352 geometry_msgs::Point lastPosition;
00353 labust::math::Line line, bearing_to_endpoint;
00354 tf2_ros::StaticTransformBroadcaster broadcaster;
00355 Goal::ConstPtr goal;
00356 auv_msgs::NavSts lastState;
00357 boost::mutex state_mux;
00358 navcon_msgs::ControllerSelectRequest controllers;
00359 double distVictory, lastDistance, Ddistance;
00360 bool processNewGoal, underactuated;
00361 };
00362 }
00363 }
00364
00365 int main(int argc, char* argv[])
00366 {
00367 ros::init(argc,argv,"go2point");
00368 labust::primitive::PrimitiveBase<labust::primitive::GoToPoint> primitive;
00369 ros::spin();
00370 return 0;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379