IdentificationNode.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: 30.10.2013.
00036  *********************************************************************/
00037 #include <labust/control/IdentificationNode.hpp>
00038 #include <labust/math/NumberManipulation.hpp>
00039 #include <labust/tools/conversions.hpp>
00040 
00041 #include <auv_msgs/BodyForceReq.h>
00042 
00043 #include <boost/bind.hpp>
00044 
00045 using namespace labust::control;
00046 
00047 const char dofNames[]={'X','Y','Z','K','M','N','A'};
00048 
00049 IdentificationNode::IdentificationNode():
00050                                 measurements(MeasVec::Zero()),
00051                                 integrateUV(true),
00052                                 useUV(false),
00053                                 useW(false)
00054 {
00055         this->onInit();
00056 }
00057 
00058 void IdentificationNode::onInit()
00059 {
00060         ros::NodeHandle nh,ph("~");
00061         aserver.reset(new ActionServer(nh,
00062                         "Identification",
00063                         boost::bind(&IdentificationNode::doIdentification, this, _1),
00064                         false));
00065         aserver->start();
00066 
00067         tauOut = nh.advertise<auv_msgs::BodyForceReq>("tauOut", 1);
00068         stateOut = nh.advertise<auv_msgs::NavSts>("identState", 1);
00069         meas = nh.subscribe<auv_msgs::NavSts>("meas", 1,
00070                         &IdentificationNode::onMeasurement,this);
00071 
00072         ph.param("integrateUV",integrateUV, true);
00073         ph.param("useUV",useUV, false);
00074         ph.param("useW",useW, false);
00075 }
00076 
00077 void IdentificationNode::onMeasurement(const auv_msgs::NavSts::ConstPtr& meas)
00078 {
00079         static ros::Time lastSampleTime=ros::Time::now();
00080 
00081         if (integrateUV)
00082         {
00083                 boost::mutex::scoped_lock l(measmux);
00084                 double dT = (ros::Time::now() - lastSampleTime).toSec();
00085                 lastSampleTime = ros::Time::now();
00086                 //ROS_INFO("Estimated rate: %f",dT);
00087                 measurements(x) += meas->body_velocity.x*dT;
00088                 measurements(y) += meas->body_velocity.y*dT;
00089                 ROS_DEBUG("Estimated pos: Ts=%f, x=%f, y=%f",dT, measurements(x), measurements(y));
00090         }
00091         else
00092         {
00093                 boost::mutex::scoped_lock l(measmux);
00094                 measurements(x) = meas->position.north;
00095                 measurements(y) = meas->position.east;
00096         }
00097         measurements(z) = meas->position.depth;
00098         measurements(roll) = meas->orientation.roll;
00099         measurements(pitch) = meas->orientation.pitch;
00100         measurements(yaw) = meas->orientation.yaw;
00101 
00102         measurements(altitude) = meas->altitude;
00103         measurements(u) = meas->body_velocity.x;
00104         measurements(v) = meas->body_velocity.y;
00105         measurements(w) = meas->body_velocity.z;
00106 }
00107 
00108 void IdentificationNode::doIdentification(const Goal::ConstPtr& goal)
00109 {
00110         ROS_INFO("Recevied goal.");
00111 
00112         //Some run-time sanity checking.
00113         if ((goal->sampling_rate <= 0) ||
00114                         (goal->command == 0) ||
00115                         (goal->hysteresis == 0) ||
00116                         (goal->dof < Goal::Surge) || (goal->dof > Goal::Altitude))
00117         {
00118                 ROS_ERROR("Some identification criteria are faulty: "
00119                                 "command: (%f != 0), "
00120                                 "hysteresis: (%f != 0), "
00121                                 "dof: (abs(%d) < 6), "
00122                                 "(sampling_rate: (%f >=0)", goal->command,
00123                                 goal->hysteresis, goal->dof, goal->sampling_rate);
00124                 return;
00125         }
00126 
00127         ros::Rate rate(goal->sampling_rate);
00128         int oscnum(0);
00129 
00130         SOIdentification ident;
00131         ident.setRelay(goal->command,goal->hysteresis);
00132         ident.Ref(goal->reference);
00133 
00134         ROS_INFO("Started identification of %c DOF.",dofNames[goal->dof]);
00135 
00136         //Reset the integrals
00137         if (integrateUV)
00138         {
00139                 boost::mutex::scoped_lock l(measmux);
00140                 measurements(x)=0;
00141                 measurements(y)=0;
00142         }
00143 
00144         //Reset the cumulative error
00145         if (useUV)
00146         {
00147                 cumulative_error = 0;
00148         }
00149 
00150         while (!ident.isFinished())
00151         {
00152                 double error = goal->reference - measurements(goal->dof);
00153 
00154                 if (((goal->dof <= Goal::Sway) && useUV) || ((goal->dof == Goal::Heave) && useW))
00155                 {
00156                         enum {stateDiff = 7};
00157                         //This takes "u,v,w" when "x,y,z" is identified
00158                         error = goal->reference - measurements(goal->dof + stateDiff);
00159                         cumulative_error += error/goal->sampling_rate;
00160                         error = cumulative_error;
00161                 }
00162 
00163                 //Handle angular values
00164                 if ((goal->dof >= Goal::Roll) && (goal->dof <=Goal::Yaw))
00165                 {
00166                         error = labust::math::wrapRad(
00167                                         labust::math::wrapRad(goal->reference) -
00168                                         labust::math::wrapRad(measurements(goal->dof)));
00169                 }
00170                 //Perform one step
00171                 if ((goal->dof >= Goal::Surge) && (goal->dof <= Goal::Yaw))
00172                 {
00173                         this->setTau(goal->dof, ident.step(error, 1/goal->sampling_rate));
00174                 }
00175                 else if (goal->dof == Goal::Altitude)
00176                 {
00177                         ROS_INFO("Doing identification: %f %f %f.",goal->reference, measurements[goal->dof], error);
00178                         this->setTau(Goal::Heave, -ident.step(error, 1/goal->sampling_rate));
00179                 }
00180 
00181                 //Check for preemption
00182                 if (aserver->isPreemptRequested() || !ros::ok())
00183                 {
00184                         ROS_INFO("DOFIdentification for %d: Preempted", goal->dof);
00185                         //Set output to zero
00186                         this->setTau(0, 0.0);
00187                         // set the action state to preempted
00188                         aserver->setPreempted();
00189                         return;
00190                 }
00191 
00192                 //Send feedback about progress
00193                 if (ident.hasSwitched())
00194                 {
00195                         navcon_msgs::DOFIdentificationFeedback feedback;
00196                         feedback.dof = goal->dof;
00197                         feedback.error = ident.avgError();
00198                         feedback.oscillation_num = ++oscnum/2;
00199                         aserver->publishFeedback(feedback);
00200                 }
00201 
00202                 auv_msgs::NavSts::Ptr outsts(new auv_msgs::NavSts);
00203                 outsts->position.north = measurements(x);
00204                 outsts->position.east = measurements(y);
00205                 outsts->position.depth = measurements(z);
00206                 outsts->orientation.roll = measurements(roll);
00207                 outsts->orientation.pitch = measurements(pitch);
00208                 outsts->orientation.yaw = measurements(yaw);
00209                 stateOut.publish(outsts);
00210 
00211                 //Set the feedback value
00212                 rate.sleep();
00213         }
00214 
00215         //Stop the vessel
00216         this->setTau(0, 0.0);
00217 
00218         if (ident.isFinished())
00219         {
00220                 const std::vector<double>& params = ident.parameters();
00221                 Result result;
00222                 result.dof = goal->dof;
00223                 result.alpha = params[SOIdentification::alpha];
00224                 result.beta = params[SOIdentification::kx];
00225                 result.betaa = params[SOIdentification::kxx];
00226                 result.delta = params[SOIdentification::delta];
00227                 result.wn = params[SOIdentification::wn];
00228 
00229                 ROS_INFO("Identified parameters: %f %f %f %f",
00230                                 params[SOIdentification::alpha],
00231                                 params[SOIdentification::kx],
00232                                 params[SOIdentification::kxx],
00233                                 params[SOIdentification::delta],
00234                                 params[SOIdentification::wn]);
00235 
00236                 // set the action state to succeeded
00237                 aserver->setSucceeded(result);
00238         }
00239 }
00240 
00241 void IdentificationNode::setTau(int elem, double value)
00242 {
00243         labust::simulation::vector tauvec = labust::simulation::vector::Zero();
00244         tauvec(elem) = value;
00245         std::ostringstream out;
00246         out<<"ident_"<<dofNames[elem];
00247         auv_msgs::BodyForceReqPtr tau(new auv_msgs::BodyForceReq());
00248         tau->header.stamp = ros::Time::now();
00249         tau->goal.requester = out.str();
00250         labust::tools::vectorToPoint(tauvec,tau->wrench.force);
00251         labust::tools::vectorToPoint(tauvec,tau->wrench.torque,3);
00252         tauOut.publish(tau);
00253 }
00254 
00255 int main(int argc, char* argv[])
00256 {
00257         ros::init(argc,argv,"ident_node");
00258         labust::control::IdentificationNode ident;
00259         ros::spin();
00260         return 0;
00261 }


ident_so
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:23:43