course_keeping.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * course_keeping.cpp
00003  *
00004  *  Created on: Feb 01, 2013
00005  *      Author: Dula Nad
00006  *
00007  ********************************************************************/
00008 
00009 /*********************************************************************
00010  * Software License Agreement (BSD License)
00011  *
00012  *  Copyright (c) 2010, 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 <labust/primitive/PrimitiveBase.hpp>
00043 #include <labust/math/NumberManipulation.hpp>
00044 #include <labust/math/Line.hpp>
00045 #include <labust/tools/conversions.hpp>
00046 
00047 #include <Eigen/Dense>
00048 #include <navcon_msgs/CourseKeepingAction.h>
00049 #include <navcon_msgs/EnableControl.h>
00050 #include <geometry_msgs/Point.h>
00051 #include <geometry_msgs/TransformStamped.h>
00052 #include <tf2_ros/static_transform_broadcaster.h>
00053 #include <ros/ros.h>
00054 
00055 #include <boost/thread/mutex.hpp>
00056 #include <boost/array.hpp>
00057 
00058 namespace labust
00059 {
00060         namespace primitive
00061         {
00066                 struct CourseKeeping : protected ExecutorBase<navcon_msgs::CourseKeepingAction>
00067                 {
00068                         typedef navcon_msgs::CourseKeepingGoal Goal;
00069                         typedef navcon_msgs::CourseKeepingResult Result;
00070 
00071                         enum {ualf=0,falf,hdg, numcnt};
00072                         enum{xp=0,yp,zp};
00073 
00074                         CourseKeeping():
00075                                 ExecutorBase("course_keeping"),
00076                                 underactuated(true),
00077                                 headingEnabled(false),
00078                                 processNewGoal(false){};
00079 
00080                         void init()
00081                         {
00082                                 ros::NodeHandle ph("~");
00083 
00084                                 /*** Initialize controller names ***/
00085                                 controllers.name.resize(numcnt);
00086                                 controllers.state.resize(numcnt, false);
00087 
00088                                 controllers.name[ualf] = "UALF_enable";
00089                                 controllers.name[falf] = "FALF_enable";
00090                                 controllers.name[hdg] = "HDG_enable";
00091                         }
00092 
00093                         void onGoal()
00094                         {
00095                                 boost::mutex::scoped_lock l(state_mux);
00096                                 ROS_DEBUG("On goal.");
00097                                 //Set the flag to avoid disabling controllers on preemption
00098                                 processNewGoal = true;
00099                                 Goal::ConstPtr new_goal = aserver->acceptNewGoal();
00100                                 processNewGoal = false;
00101 
00102                                 switch(new_goal->subtype)
00103                                 {
00104                                         case Goal::COURSE_KEEPING_UA:
00105                                                 underactuated = true;
00106                                                 break;
00107                                         case Goal::COURSE_KEEPING_FA:
00108                                                 underactuated = false;
00109                                                 break;
00110                                         case Goal::COURSE_KEEPING_FA_HDG:
00111                                                 underactuated = false;
00112                                                 if(new_goal->ref_type != Goal::CONSTANT)
00113                                                         //connectTopics();
00114                                                 break;
00115                                 }
00116                                 //Check if course keeping is possible.
00117                                 if (new_goal->speed == 0)
00118                                 {
00119                                         ROS_WARN("Cannot perform course keeping without forward speed.");
00120                                         aserver->setAborted(Result(), "Forward speed is zero.");
00121                                 }
00122 
00123                                 if ((goal == 0) || (new_goal->course != goal->course))
00124                                 {
00125                                         //Save new goal
00126                                         goal = new_goal;
00127                                         ROS_DEBUG("Change course: %f", new_goal->course);
00128                                         //Calculate new line if target changed
00129                                         Eigen::Vector3d T1,T2;
00130                                         T1<<lastState.position.north,
00131                                                         lastState.position.east,
00132                                                         0;
00133                                         T2<<lastState.position.north + 10*cos(new_goal->course),
00134                                                         lastState.position.east + 10*sin(new_goal->course),
00135                                                         0;
00136                                         line.setLine(T1,T2);
00137 
00138 
00139                                         geometry_msgs::TransformStamped transform;
00140                                         transform.transform.translation.x = T1(xp);
00141                                         transform.transform.translation.y = T1(yp);
00142                                         transform.transform.translation.z = T1(zp);
00143                                         labust::tools::quaternionFromEulerZYX(0, 0, line.gamma(),
00144                                                         transform.transform.rotation);
00145                                         transform.child_frame_id = "course_frame";
00146                                         transform.header.frame_id = "local";
00147                                         transform.header.stamp = ros::Time::now();
00148                                         broadcaster.sendTransform(transform);
00149 
00150                                         //Update reference
00151                                         //The underactuated controller will auto-enable itself
00152                                         stateRef.publish(step(lastState));
00153 
00154                                         //Enable overactuated controllers
00155                                         if (!underactuated)
00156                                         {
00157                                                 controllers.state[falf] = true;
00158                                                 controllers.state[hdg] = true;
00159                                         }
00160                                         else
00161                                         {
00162                                                 double delta = labust::math::wrapRad(lastState.orientation.yaw - line.gamma());
00163                                                 ROS_DEBUG("Delta: %f",delta);
00164                                                 if (std::abs(delta) < M_PI_2)
00165                                                 {
00166                                                         controllers.state[ualf] = true;
00167                                                         controllers.state[hdg] = false;
00168                                                 }
00169                                         }
00170                                         this->updateControllers();
00171                                 }
00172 
00173                                 //Save new goal
00174                                 goal = new_goal;
00175                         }
00176 
00177                         void onPreempt()
00178                         {
00179                                 ROS_ERROR("Preempted.");
00180                                 if (!processNewGoal)
00181                                 {
00182                                         //ROS_ERROR("Stopping controllers.");
00183                                         //controllers.state.assign(numcnt, false);
00184                                         //this->updateControllers();
00185                                 }
00186                                 else
00187                                 {
00188                                         //ROS_ERROR("New goal processing.");
00189                                 }
00190                                 aserver->setPreempted();
00191                         };
00192 
00193                         void updateControllers()
00194                         {
00195                                 ros::NodeHandle nh;
00196                                 ros::ServiceClient cl;
00197 
00198                                 /*** Enable or disable ualf/falf controller ***/
00199                                 if(underactuated)
00200                                         cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[ualf]));
00201                                 else
00202                                         cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[falf]));
00203 
00204                                 navcon_msgs::EnableControl a;
00205                                 a.request.enable = controllers.state[ualf] || controllers.state[falf];
00206                                 cl.call(a);
00207 
00208                                 /*** Enable or disable hdg controller ***/
00209                                 cl = nh.serviceClient<navcon_msgs::EnableControl>(std::string(controllers.name[hdg]));
00210                                 a.request.enable = controllers.state[hdg];
00211                                 cl.call(a);
00212                         }
00213 
00214                         void onStateHat(const auv_msgs::NavSts::ConstPtr& estimate)
00215                         {
00216                                 boost::mutex::scoped_lock l(state_mux);
00217                                 if (aserver->isActive())
00218                                 {
00219                                         stateRef.publish(step(*estimate));
00220                                 }
00221                                 else if (goal != 0)
00222                                 {
00223                                                 goal.reset();
00224                                                 ROS_INFO("Stopping controllers.");
00225                                                 controllers.state.assign(numcnt, false);
00226                                                 this->updateControllers();
00227                                 }
00228 
00229                                 lastState = *estimate;
00230                         }
00231 
00232                         auv_msgs::NavStsPtr step(const auv_msgs::NavSts& state)
00233                         {
00234                                 auv_msgs::NavStsPtr ref(new auv_msgs::NavSts());
00235 
00236                                 ref->position.east = 0;
00237                                 ref->body_velocity.x = goal->speed;
00238                                 ref->orientation.yaw = goal->yaw;
00239                                 ref->header.frame_id = "course_frame";
00240 
00241                                 //Check underactuated behaviour
00242                                 if (underactuated)
00243                                 {
00244                                         ref->orientation.yaw = line.gamma();
00245                                         double delta = labust::math::wrapRad(state.orientation.yaw - line.gamma());
00246                                         ROS_DEBUG("Delta, gamma: %f, %f",delta, line.gamma());
00247                                         if (controllers.state[hdg] && (std::abs(delta) < M_PI/3))
00248                                         {
00249                                                         //disable heading and activate ualf
00250                                                         controllers.state[hdg] = false;
00251                                                         controllers.state[ualf] = true;
00252                                                         this->updateControllers();
00253                                                         ref->header.frame_id = "course_frame";
00254                                         }
00255                                         else if (std::abs(delta) >= M_PI/2)
00256                                         {
00257                                                         //deactivate ualf and activate heading
00258                                                         controllers.state[hdg] = true;
00259                                                         controllers.state[ualf] = false;
00260                                                         this->updateControllers();
00261                                                         ref->header.frame_id = "local";
00262                                         }
00263                                 }
00264 
00265                                 ref->header.stamp = ros::Time::now();
00266                                 return ref;
00267                         }
00268 
00269                 private:
00270                         geometry_msgs::Point lastPosition;
00271                         labust::math::Line line;
00272                         tf2_ros::StaticTransformBroadcaster broadcaster;
00273                         bool underactuated;
00274                         bool headingEnabled;
00275                         bool processNewGoal;
00276                         Goal::ConstPtr goal;
00277                         auv_msgs::NavSts lastState;
00278                         boost::mutex state_mux;
00279                         navcon_msgs::ControllerSelectRequest controllers;
00280                 };
00281         }
00282 }
00283 
00284 int main(int argc, char* argv[])
00285 {
00286     ros::init(argc,argv,"course_keeping");
00287 
00288         labust::primitive::PrimitiveBase<labust::primitive::CourseKeeping> primitive;
00289         ros::spin();
00290 
00291         return 0;
00292 }
00293 
00294 
00295 
00296 
00297 
00298 


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