go2point.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * go2point.cpp
00003  *
00004  *  Created on: May 26, 2015
00005  *      Author: Filip Mandic
00006  *
00007  ********************************************************************/
00008 
00009 /*********************************************************************
00010  * Software License Agreement (BSD License)
00011  *
00012  *  Copyright (c) 2015, LABUST, UNIZG-FER
00013  *  All rights reserved.
00014  *
00015  *  Redistribution and use in source and binary forms, with or without
00016  *  modification, are permitted provided that the following conditions
00017  *  are met:
00018  *
00019  *   * Redistributions of source code must retain the above copyright
00020  *     notice, this list of conditions and the following disclaimer.
00021  *   * Redistributions in binary form must reproduce the above
00022  *     copyright notice, this list of conditions and the following
00023  *     disclaimer in the documentation and/or other materials provided
00024  *     with the distribution.
00025  *   * Neither the name of the LABUST nor the names of its
00026  *     contributors may be used to endorse or promote products derived
00027  *     from this software without specific prior written permission.
00028  *
00029  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00030  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00031  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00032  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00033  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00034  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00035  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00036  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00037  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00038  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00039  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040  *  POSSIBILITY OF SUCH DAMAGE.
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                  *** Go2Point primitive class
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                                 /*** Initialize controller names ***/
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                                 //Set the flag to avoid disabling controllers on preemption
00100                                 processNewGoal = true;
00101                                 Goal::ConstPtr new_goal = aserver->acceptNewGoal();
00102                                 processNewGoal = false;
00103 
00104                                 // Vidi kakav redoslijed
00105                                 /*** Check primitive subtype ***/
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                                                         //connectTopics();
00119                                                 break;
00120                                 }
00121 
00122 
00123 
00124                                 //Check if course keeping is possible.
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                                         //Save new goal
00140                                         goal = new_goal;
00141                                         //ROS_DEBUG("Change course: %f", new_goal->course);
00142 
00143                                         /*** Calculate new course line ***/
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                                         /*** Update reference ***/
00163                                         stateRef.publish(step(lastState));
00164 
00165 
00166 
00167                                         /*** Enable controllers depending on the primitive subtype ***/
00168                                         if (!underactuated)
00169                                         {
00170                                                 /*** Fully actuated ***/
00171                                                 controllers.state[falf] = true;
00172                                                 controllers.state[hdg] = true;
00173                                         }
00174                                         else
00175                                         {
00176                                                 /*** Under actuated ***/
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                                 //Save new goal
00193 //                              goal = new_goal;
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                                         //ROS_ERROR("New goal processing.");
00210                                 }
00211                                 aserver->setPreempted();
00212                         };
00213 
00214                         void updateControllers()
00215                         {
00216                                 ros::NodeHandle nh;
00217                                 ros::ServiceClient cl;
00218 
00219                                 /*** Enable or disable ualf/falf controller ***/
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                                 /*** Enable or disable hdg controller ***/
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                                 /*** Enable mutex ***/
00239                                 boost::mutex::scoped_lock l(state_mux);
00240 
00241                                 if(aserver->isActive())
00242                                 {
00243                                         /*** Publish reference for high-level controller ***/
00244                                         stateRef.publish(step(*estimate));
00245 
00246                                     /*** Check if goal (victory radius) is achieved ***/
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                                         /*** If goal is completed ***/
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                                         /*** Publish primitive feedback ***/
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                                 /*** Set course frame references ***/
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                                 /*** Calculate bearing to endpoint ***/
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                                 /*** If victory radius is missed change course  ***/
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                                 /*** Check underactuated behaviour ***/
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                                                         /*** Disable hdg and activate ualf ***/
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                                                         /*** Deactivate ualf and activate hdg ***/
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 


labust_primitives
Author(s): Filip Mandic
autogenerated on Fri Aug 28 2015 11:22:51