VirtualTarget.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author: Dula Nad
00035  *  Created: 03.05.2013.
00036  *********************************************************************/
00037 #include <labust/control/VirtualTarget.hpp>
00038 #include <labust/tools/MatrixLoader.hpp>
00039 
00040 #include <auv_msgs/BodyVelocityReq.h>
00041 #include <kdl/frames.hpp>
00042 #include <boost/bind.hpp>
00043 
00044 #include <cmath>
00045 #include <vector>
00046 #include <string>
00047 
00048 using labust::control::VirtualTarget;
00049 
00050 VirtualTarget::VirtualTarget():
00051                 nh(ros::NodeHandle()),
00052                 ph(ros::NodeHandle("~")),
00053                 lastEst(ros::Time::now()),
00054                 timeout(0.5),
00055                 Ts(0.1),
00056                 safetyRadius(0.5),
00057                 surge(1),
00058                 flowSurgeEstimate(0),
00059                 K1(0.2),
00060                 K2(1),
00061                 gammaARad(45),
00062                 enable(false),
00063                 use_flow_frame(false)
00064 {this->onInit();}
00065 
00066 void VirtualTarget::onInit()
00067 {
00068         //Initialize publishers
00069         nuRef = nh.advertise<auv_msgs::BodyVelocityReq>("nuRef", 1);
00070         vtTwist = nh.advertise<geometry_msgs::TwistStamped>("virtual_target_twist", 1);
00071 
00072         //Initialze subscribers
00073         stateHat = nh.subscribe<auv_msgs::NavSts>("stateHat", 1,
00074                         &VirtualTarget::onEstimate,this);
00075         flowTwist = nh.subscribe<geometry_msgs::TwistStamped>("body_flow_frame_twist", 1,
00076                         &VirtualTarget::onFlowTwist,this);
00077         //      refPoint = nh.subscribe<geometry_msgs::PointStamped>("LFPoint", 1,
00078         //                      &VirtualTarget::onNewPoint,this);
00079         //      refTrack = nh.subscribe<auv_msgs::NavSts>("TrackPoint", 1,
00080         //                      &VirtualTarget::onTrackPoint,this);
00081         windup = nh.subscribe<auv_msgs::BodyForceReq>("tauAch", 1,
00082                         &VirtualTarget::onWindup,this);
00083         openLoopSurge = nh.subscribe<std_msgs::Float32>("open_loop_surge", 1,
00084                         &VirtualTarget::onOpenLoopSurge,this);
00085         enableControl = nh.advertiseService("VT_enable",
00086                         &VirtualTarget::onEnableControl, this);
00087 
00088         nh.param("virtual_target/timeout",timeout,timeout);
00089         nh.param("virtual_target/use_flow_frame",use_flow_frame,use_flow_frame);
00090 
00091         //Configure the dynamic reconfigure server
00092         //server.setCallback(boost::bind(&VelocityControl::dynrec_cb, this, _1, _2));
00093 
00094         initialize_controller();
00095         //config.__fromServer__(ph);
00096         //server.setConfigDefault(config);
00097         //this->updateDynRecConfig();
00098 }
00099 
00100 //void VirtualTarget::updateDynRecConfig()
00101 //{
00102 //      ROS_INFO("Updating the dynamic reconfigure parameters.");
00103 //
00104 //      config.__fromServer__(ph);
00105 //      config.Surge_mode = axis_control[u];
00106 //      config.Sway_mode = axis_control[v];
00107 //      config.Heave_mode = axis_control[w];
00108 //      config.Roll_mode = axis_control[p];
00109 //      config.Pitch_mode = axis_control[q];
00110 //      config.Yaw_mode = axis_control[r];
00111 //
00112 //      config.High_level_controller="0 - None\n 1 - DP";
00113 //
00114 //      server.updateConfig(config);
00115 //}
00116 
00117 //void VirtualTarget::dynrec_cb(labust_uvapp::VelConConfig& config, uint32_t level)
00118 //{
00119 //      this->config = config;
00120 //
00121 //      for(size_t i=u; i<=r; ++i)
00122 //      {
00123 //              int newMode(0);
00124 //              ph.getParam(dofName[i]+"_mode", newMode);
00125 //              //Stop the identification if it was aborted remotely.
00126 //              if ((axis_control[i] == identAxis) &&
00127 //                              (newMode != identAxis) &&
00128 //                              (ident[i] != 0)) ident[i].reset();
00129 //
00130 //              axis_control[i] = newMode;
00131 //      }
00132 //}
00133 
00134 //void VirtualTarget::onNewPoint(const geometry_msgs::PointStamped::ConstPtr& point)
00135 //{
00136 //      trackPoint.position.north = point->point.x;
00137 //      trackPoint.position.east = point->point.y;
00138 //      trackPoint.position.depth = point->point.z;
00139 //};
00140 
00141 bool VirtualTarget::onEnableControl(labust_uvapp::EnableControl::Request& req,
00142                 labust_uvapp::EnableControl::Response& resp)
00143 {
00144         this->enable = req.enable;
00145         return true;
00146 }
00147 
00148 void VirtualTarget::onOpenLoopSurge(const std_msgs::Float32::ConstPtr& surge)
00149 {
00150         this->surge = surge->data;
00151 }
00152 
00153 void VirtualTarget::onFlowTwist(const geometry_msgs::TwistStamped::ConstPtr& flowtwist)
00154 {
00155         boost::mutex::scoped_lock l(dataMux);
00156         flowSurgeEstimate = flowtwist->twist.linear.x*flowtwist->twist.linear.x;
00157         flowSurgeEstimate += flowtwist->twist.linear.y*flowtwist->twist.linear.y;
00158         flowSurgeEstimate = sqrt(flowSurgeEstimate);
00159 }
00160 
00161 void VirtualTarget::onEstimate(const auv_msgs::NavSts::ConstPtr& estimate)
00162 {
00163         //Copy into controller
00164         state = *estimate;
00165         lastEst = ros::Time::now();
00166         if (enable) this->step();
00167 };
00168 
00169 //void VirtualTarget::onTrackPoint(const auv_msgs::NavSts::ConstPtr& ref)
00170 //{
00171 //      //Copy into controller
00172 //      trackPoint = *ref;
00173 //};
00174 
00175 void VirtualTarget::onWindup(const auv_msgs::BodyForceReq::ConstPtr& tauAch)
00176 {
00177         //Copy into controller
00178         headingController.windup = tauAch->disable_axis.yaw;
00179 };
00180 
00181 //void VirtualTarget::safetyTest()
00182 //{
00183 //      bool refTimeout = (ros::Time::now() - lastRef).toSec() > timeout;
00184 //      bool estTimeout = (ros::Time::now() - lastEst).toSec() > timeout;
00185 //      bool manTimeout = (ros::Time::now() - lastMan).toSec() > timeout;
00186 //      bool measTimeout = (ros::Time::now() - lastMeas).toSec() > timeout;
00187 //      bool changed = false;
00188 //
00189 //      for (int i=u; i<=r;++i)
00190 //      {
00191 //              bool cntChannel = (refT*imeout || estTimeout) && (axis_control[i] == controlAxis);
00192 //              if (cntChannel) ROS_WARN("Timeout on the control channel. Controlled axes will be disabled.");
00193 //              bool measChannel = measTimeout && (axis_control[i] == identAxis);
00194 //              if (measChannel) ROS_WARN("Timeout on the measurement channel. Stopping identifications in progress.");
00195 //              bool manChannel = manTimeout && (axis_control[i] == manualAxis);
00196 //              if (manChannel) ROS_WARN("Timeout on the manual channel. Manual axes will be disabled.");
00197 //
00198 //              suspend_axis[i] = (cntChannel || measChannel || manChannel);
00199 //      }
00200 //
00201 //      //Update only on change.
00202 //      //if (changed) this->updateDynRecConfig();
00203 //}
00204 
00205 void VirtualTarget::step()
00206 {
00207         if (!enable) return;
00208         //this->safetyTest();
00209 
00210         tf::StampedTransform sfTransform, sfLocal, flowLocal;
00211         try
00212         {
00213                 listener.lookupTransform("serret_frenet_frame", "base_link_flow", ros::Time(0), sfTransform);
00214                 listener.lookupTransform("local", "base_link_flow", ros::Time(0), flowLocal);
00215                 listener.lookupTransform("local", "serret_frenet_frame", ros::Time(0), sfLocal);
00216                 tf::Quaternion q = sfTransform.getRotation();
00217                 double gamma,gammaRabbit,flow_yaw,pitch,roll;
00218                 KDL::Rotation::Quaternion(q.x(),q.y(),q.z(),q.w()).GetEulerZYX(gamma,pitch,roll);
00219                 q = sfLocal.getRotation();
00220                 KDL::Rotation::Quaternion(q.x(),q.y(),q.z(),q.w()).GetEulerZYX(gammaRabbit,pitch,roll);
00221                 q = flowLocal.getRotation();
00222                 KDL::Rotation::Quaternion(q.x(),q.y(),q.z(),q.w()).GetEulerZYX(flow_yaw,pitch,roll);
00223 
00224                 //double UvecYaw = state.orientation.yaw;
00225                 //For slow movements prefer the body frame instead of the flow frame.
00226                 boost::mutex::scoped_lock l(dataMux);
00227                 if (!use_flow_frame || (flowSurgeEstimate < (surge/10)))
00228                 {
00229                         gamma = labust::math::wrapRad(state.orientation.yaw-gammaRabbit);
00230                         flowSurgeEstimate = state.body_velocity.x;
00231                         headingController.state = labust::math::wrapRad(state.orientation.yaw);
00232                 }
00233                 else
00234                 {
00235                         headingController.state = labust::math::wrapRad(flow_yaw);
00236                 }
00237                 l.unlock();
00238 
00239                 gamma=labust::math::wrapRad(gamma);
00240 
00241                 double distance(pow(sfTransform.getOrigin().y(),2) + pow(sfTransform.getOrigin().x(),2));
00242                 double angleDiff(atan2(sfTransform.getOrigin().y(),sfTransform.getOrigin().x()));
00243                 if (false && distance > 0.5 && fabs(angleDiff) > M_PI/2)
00244                 {
00245                         headingController.desired = angleDiff;
00246                 }
00247                 else
00248                 {
00249                         //Just for readability
00250                         double s1(sfTransform.getOrigin().x()),y1(sfTransform.getOrigin().y());
00251 
00252                         geometry_msgs::TwistStamped sTwist;
00253                         //double flowSurgeEstimate = state.body_velocity.x;
00254                         //sDot
00255                         boost::mutex::scoped_lock l(dataMux);
00256                         sTwist.twist.linear.x = flowSurgeEstimate*cos(gamma) + K1*s1;
00257                         //sTwist.twist.linear.y = flowSurgeEstimate;
00258                         l.unlock();
00259                         vtTwist.publish(sTwist);
00260 
00261                         double gammaRef=-gammaARad*tanh(K2*y1);
00262 
00263                         headingController.desired = labust::math::wrapRad(gammaRabbit+gammaRef);
00264                 }
00265 
00266                 float errorWrap = labust::math::wrapRad(headingController.desired - headingController.state);
00267                 PIFFExtController_stepWrap(&headingController,Ts, errorWrap);
00268 
00269                 auv_msgs::BodyVelocityReq nu;
00270                 nu.header.stamp = ros::Time::now();
00271                 nu.goal.requester = "virtual_target";
00272                 nu.twist.angular.z = headingController.output;
00273                 nu.twist.linear.x = surge;
00274 
00275                 nuRef.publish(nu);
00276         }
00277         catch (tf::TransformException& ex)
00278         {
00279                 ROS_ERROR("%s",ex.what());
00280         }
00281 }
00282 
00283 void VirtualTarget::start()
00284 {
00285         ros::spin();
00286 }
00287 
00288 void VirtualTarget::initialize_controller()
00289 {
00290         ROS_INFO("Initializing dynamic positioning controller...");
00291 
00292         double w(1);
00293         nh.param("virtual_target/heading_closed_loop_freq", w,w);
00294         nh.param("virtual_target/sampling",Ts,Ts);
00295         nh.param("virtual_target/approach_angle",gammaARad,gammaARad);
00296         nh.param("virtual_target/openLoopSurge",surge,surge);
00297         gammaARad = gammaARad*M_PI/180;
00298         Eigen::Vector2d gains(Eigen::Vector2d::Ones());
00299         labust::tools::getMatrixParam(nh,"virtual_target/outer_loop_gains", gains);
00300         K1 = gains(0);
00301         K2 = gains(1);
00302 
00303         enum {Kp=0, Ki, Kd, Kt};
00304         PIDController_init(&headingController);
00305         headingController.gains[Kp] = 2*w;
00306         headingController.gains[Ki] = w*w;
00307         headingController.autoTracking = 0;
00308 
00309         ROS_INFO("Line following controller initialized.");
00310 }


labust_uvapp
Author(s): Dula Nad
autogenerated on Fri Feb 7 2014 11:36:37