manual_control.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: 01.02.2013.
00036  *********************************************************************/
00037 #include <labust/control/manual_control.h>
00038 #include <labust/tools/conversions.hpp>
00039 #include <labust/math/NumberManipulation.hpp>
00040 
00041 #include <auv_msgs/BodyForceReq.h>
00042 #include <auv_msgs/BodyVelocityReq.h>
00043 #include <auv_msgs/NavSts.h>
00044 
00045 #include <boost/bind.hpp>
00046 
00047 using namespace labust::control;
00048 
00049 ManualControl::ManualControl():
00050                 nav_valid(false),
00051                 navstate(DOF+1,0),
00052                 mapped(DOF,0)
00053 {
00054         generators.assign(SRequest::DISABLED);
00055         this->onInit();
00056 }
00057 
00058 void ManualControl::onInit()
00059 {
00060         ros::NodeHandle nh, ph("~");
00061 
00062         this->setDefaultConfig();
00063         if (!this->setupConfig())
00064         {
00065                 ROS_ERROR("ManualControl: Wrong configuration. Check all "
00066                                 "vector sizes are %d and sampling size is >0.", DOF);
00067                 this->setDefaultConfig();
00068         }
00069 
00070         //Setup publishers
00071         tauref = nh.advertise<auv_msgs::BodyForceReq>("manual_tau",1);
00072         nuref = nh.advertise<auv_msgs::BodyVelocityReq>("manual_nu",1);
00073         etaref = nh.advertise<auv_msgs::NavSts>("manual_eta",1);
00074         //Setup subscribers
00075         joyin = nh.subscribe(config.topic, 1, &ManualControl::onJoystick, this);
00076         navsts = nh.subscribe("navsts", 1, &ManualControl::onNavSts, this);
00077         //Setup service
00078         config_server = nh.advertiseService("manual_configure", &ManualControl::onConfiguration, this);
00079         select_server = nh.advertiseService("manual_select", &ManualControl::onSelect, this);
00080 }
00081 
00082 bool ManualControl::setupConfig()
00083 {
00084         ros::NodeHandle nh, ph("~");
00085         //Configure remapping
00086         ph.param("axes_map", config.axes_map, config.axes_map);
00087         ph.param("scale_map", config.scale_map, config.scale_map);
00088         ph.param("integrated", config.integrated, config.integrated);
00089         //Configure
00090         ph.param("maximum_effort", config.maximum_effort, config.maximum_effort);
00091         ph.param("maximum_nu", config.maximum_nu, config.maximum_nu);
00092         ph.param("maximum_speed", config.maximum_speed, config.maximum_speed);
00093         std::vector<int> ug(SRequest::DISABLED,0);
00094         ph.param("use_generators", ug, ug);
00095         for (int i=0; i<ug.size(); ++i)
00096         {
00097                 if (i >= generators.size()) break;
00098                 generators[i] = ug[i];
00099         }
00100         //Test first for simulation time, runtime and then the private override
00101         nh.param("simulation/sampling_time", config.sampling_time, config.sampling_time);
00102         nh.param("runtime/sampling_time", config.sampling_time, config.sampling_time);
00103         ph.param("sampling_time", config.sampling_time, config.sampling_time);
00104         bool use_ff(false);
00105         ph.param("use_feedforward", use_ff, use_ff);
00106         config.use_ff = use_ff;
00107 
00108         //Perform some sanity check on the configurations
00109         bool flag(config.sampling_time > 0);
00110         flag = flag && (config.axes_map.size() == DOF);
00111         flag = flag && (config.scale_map.size() == DOF);
00112         flag = flag && (config.maximum_effort.size() == DOF);
00113         flag = flag && (config.maximum_nu.size() == DOF);
00114         flag = flag && (config.maximum_speed.size() == DOF);
00115 
00116         return flag;
00117 }
00118 
00119 void ManualControl::setDefaultConfig()
00120 {
00121         //Set default 1on1 mapping, no scaling
00122         for(int i=0; i<DOF; ++i) config.axes_map.push_back(i);
00123         config.scale_map.resize(6,1);
00124         //By default no axes are integrated.
00125         config.integrated.resize(6,0);
00126 
00127         config.maximum_effort.resize(6,1);
00128 
00129         config.maximum_nu.resize(6,1);
00130 
00131         config.maximum_speed.resize(6,1);
00132         config.sampling_time = 0.1;
00133         config.use_ff = false;
00134 
00135         config.topic = "joy";
00136 }
00137 
00138 bool ManualControl::onConfiguration(CRequest& req, CResponse& resp)
00139 {
00140         boost::mutex::scoped_lock l(cfg_mutex);
00141         navcon_msgs::ManualConfiguration& cfg(req.configuration);
00142         if (cfg.axes_map.size() == DOF)
00143         {
00144                 this->config.axes_map = cfg.axes_map;
00145         }
00146         if (cfg.scale_map.size() == DOF) this->config.scale_map = cfg.scale_map;
00147         if (cfg.integrated.size() == DOF) this->config.integrated = cfg.integrated;
00148         if (cfg.maximum_effort.size() == DOF) this->config.maximum_effort = cfg.maximum_effort;
00149         if (cfg.maximum_nu.size() == DOF) this->config.maximum_nu = cfg.maximum_nu;
00150         if (cfg.maximum_speed.size() == DOF)
00151         {
00152                 this->config.maximum_speed = cfg.maximum_speed;
00153                 this->config.use_ff = cfg.use_ff;
00154                 this->config.sampling_time = cfg.sampling_time;
00155         }
00156 
00157         if (!req.configuration.topic.empty())
00158         {
00159                 this->config.topic = req.configuration.topic;
00160                 ros::NodeHandle nh;
00161                 joyin = nh.subscribe(config.topic, 1, &ManualControl::onJoystick, this);
00162         }
00163 
00164         resp.current_configuration = this->config;
00165         return true;
00166 }
00167 
00168 bool ManualControl::onSelect(SRequest& req, SResponse& resp)
00169 {
00170         boost::mutex::scoped_lock l(cfg_mutex);
00171         for (int i=0; i<req.use_generator.size(); ++i)
00172         {
00173                 if ((req.use_generator[i]>=SRequest::DISABLED) &&
00174                                 (req.use_generator[i]<=SRequest::POSITION))
00175                 {
00176                         this->generators[i] = req.use_generator[i];
00177                 }
00178         }
00179 
00180         return true;
00181 }
00182 
00183 void ManualControl::onJoystick(const sensor_msgs::Joy::ConstPtr& joy)
00184 {
00185         this->remap(joy);
00186 
00187         bool pubEffort(false), pubSpeed(false), pubPos(false);
00188 
00189         std::vector<double> tauv(DOF,0),nuv(DOF,0),etaff(DOF,0);
00190 
00191         boost::mutex::scoped_lock l(cfg_mutex);
00192         for(int i=0; i<DOF; ++i)
00193         {
00194                 if (config.axes_map[i] == CRequest::DISABLED) continue;
00195 
00196                 switch (generators[i])
00197                 {
00198                 case SRequest::EFFORT:
00199                         pubEffort = true;
00200                         tauv[i] = mapped[i] * config.maximum_effort[i];
00201                         break;
00202                 case SRequest::SPEED:
00203                         pubSpeed = true;
00204                         nuv[i] = mapped[i] * config.maximum_speed[i];
00205                         break;
00206                 case SRequest::POSITION:
00207                         if (!nav_valid) continue;
00208                         pubPos = true;
00209                         etaff[i] = mapped[i] * config.maximum_speed[i];
00210                         break;
00211                 }
00212         }
00213         l.unlock();
00214 
00215         if (pubEffort) pubTau(tauv);
00216         if (pubSpeed) pubNu(nuv);
00217         if (pubPos) pubEta(etaff);
00218 };
00219 
00220 void ManualControl::onNavSts(const auv_msgs::NavSts::ConstPtr& state)
00221 {
00222         boost::mutex::scoped_lock l(nav_mutex);
00223         //Copy the data
00224         DataType pos(DOF+1,0);
00225         labust::tools::nedToVector(state->position,pos);
00226         labust::tools::rpyToVector(state->orientation,pos,3);
00227         pos[A] = state->altitude;
00228 
00229         if (nav_valid)
00230         {
00231                 //Update only the data that is not used
00232                 for(int i=0; i<DOF; ++i)
00233                 {
00234                         if (generators[i] != SRequest::POSITION) navstate[i] = pos[i];
00235                 }
00236         }
00237         else
00238         {
00239                 //Copy all for the first time
00240                 navstate = pos;
00241                 nav_valid = true;
00242         }
00243 }
00244 
00245 void ManualControl::pubEta(const DataType& etaff)
00246 {
00247         boost::mutex::scoped_lock l(nav_mutex);
00248         if (!nav_valid) return;
00249 
00250         //Compensate for rotations
00251         Eigen::Vector3d compff, ff;
00252         Eigen::Quaternion<double> quat;
00253         ff<<etaff[X],etaff[Y],etaff[Z];
00254         labust::tools::quaternionFromEulerZYX(navstate[K], navstate[M], navstate[N],quat);
00255         compff = quat.toRotationMatrix()*ff;
00256         //Copy the new X,Y,Z speeds
00257         DataType etadot(DOF,0);
00258         for (int i=X; i<compff.size(); ++i) etadot[i] = compff(i);
00259         for (int i=K; i<DOF; ++i) etadot[i] = etaff[i];
00260 
00261         boost::mutex::scoped_lock lcfg(cfg_mutex);
00262         for (int i=X; i<DOF; ++i)
00263         {
00264                 navstate[i] += etadot[i]*config.sampling_time;
00265                 //Wrap angles
00266                 if (i>(DOF/2-1)) navstate[i] = labust::math::wrapRad(navstate[i]);
00267         }
00268         //Special handling for altitude
00269         navstate[A] += etadot[Z]*config.sampling_time;
00270 
00271         auv_msgs::NavSts eta;
00272         labust::tools::vectorToNED(navstate, eta.position);
00273         labust::tools::vectorToRPY(navstate, eta.orientation, 3);
00274         if (config.use_ff)
00275         {
00276                 labust::tools::vectorToPoint(etaff, eta.body_velocity);
00277                 labust::tools::vectorToRPY(etaff, eta.orientation_rate, 3);
00278         }
00279         lcfg.unlock();
00280         l.unlock();
00281 
00282         eta.header.stamp = ros::Time::now();
00283         eta.header.frame_id = "local";
00284         etaref.publish(eta);
00285 };
00286 
00287 void ManualControl::pubTau(const DataType& tauv)
00288 {
00289         auv_msgs::BodyForceReq tau;
00290         labust::tools::vectorToPoint(tauv, tau.wrench.force);
00291         labust::tools::vectorToPoint(tauv, tau.wrench.torque, 3);
00292         tau.header.stamp = ros::Time::now();
00293         tau.header.frame_id = "base_link";
00294         tauref.publish(tau);
00295 }
00296 
00297 void ManualControl::pubNu(const DataType& nuv)
00298 {
00299         auv_msgs::BodyVelocityReq nu;
00300         labust::tools::vectorToPoint(nuv, nu.twist.linear);
00301         labust::tools::vectorToPoint(nuv, nu.twist.angular, 3);
00302         nu.header.stamp = ros::Time::now();
00303         nu.header.frame_id = "base_link";
00304         nuref.publish(nu);
00305 }
00306 
00307 void ManualControl::remap(const sensor_msgs::Joy::ConstPtr& joy)
00308 {
00309         boost::mutex::scoped_lock l(cfg_mutex);
00310         for (int i=0;i<DOF;++i)
00311         {
00312                 //Track disabling of axes
00313                 if (config.axes_map[i] == CRequest::DISABLED)
00314                 {
00315                         mapped[i] = 0;
00316                         continue;
00317                 }
00318                 //Check if joystick has enough axes
00319                 if (joy->axes.size() <= i) continue;
00320 
00321                 if (config.integrated[i] > 0)
00322                 {
00323                         mapped[i] += joy->axes[config.axes_map[i]]*config.scale_map[i]*config.integrated[i];
00324                         mapped[i] = labust::math::coerce(mapped[i], -1, 1);
00325                 }
00326                 else
00327                 {
00328                         mapped[i] = joy->axes[config.axes_map[i]]*config.scale_map[i];
00329                 }
00330         }
00331 };
00332 
00333 int main(int argc, char* argv[])
00334 {
00335         ros::init(argc,argv,"manual");
00336 
00337         labust::control::ManualControl controller;
00338         ros::spin();
00339 
00340         return 0;
00341 }
00342 
00343 
00344 


labust_control
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:22:42