thruster_configuration.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 ARROS paketiE 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: 06.03.2013.
00036  *********************************************************************/
00037 #include <labust/allocation/thruster_configuration.h>
00038 #include <labust/tools/MatrixLoader.hpp>
00039 #include <labust/math/NumberManipulation.hpp>
00040 
00041 using namespace labust::allocation;
00042 
00043 ThrusterConfiguration::ThrusterConfiguration():
00044         Us(1),
00045         Un(1),
00046         adapt(true){}
00047 
00048 bool ThrusterConfiguration::configure(ros::NodeHandle& nh, ros::NodeHandle& ph)
00049 {
00050         //Get the supply voltage
00051         ph.param("Us",Us,Us);
00052         ph.param("Un",Un,Un);
00053         ph.param("adapt_pwm",adapt,adapt);
00054 
00055         //Read thruster gains
00056         std::vector<double> Kp,Kn;
00057         ph.param("K", Kp, Kp);
00058         ph.param("Kp", Kp, Kp);
00059         ph.param("Kn", Kn, Kp);
00060         //Read the allocation matrix
00061         labust::tools::getMatrixParam(ph,"B", _B);
00062 
00063         //Check validity
00064         int sz = Kp.size();
00065         bool valid = (sz != 0);
00066         valid = valid && (sz == Kn.size());
00067         valid = valid && (sz == _B.cols());
00068 
00069         if (!valid)
00070         {
00071                 ROS_ERROR("ThrusterConfigration: Configuration is not valid. Check all vector sizes.");
00072                 return false;
00073         }
00074 
00075         //Calculate the inverse
00076         _Binv = _B.transpose()*(_B*_B.transpose()).inverse();
00077 
00078         //Set mapping defaults
00079         std::vector<double> pwm_max(sz,1.0), pwm_direction(sz,1);
00080         std::vector<int> mapping(sz);
00081         //Add +1 to start calculating from 1
00082         for (int i=0; i<mapping.size(); ++i) mapping[i]=i+1;
00083 
00084         //Read mapping values
00085         ph.param("pwm_mapping", mapping, mapping);
00086         ph.param("pwm_direction", pwm_direction, pwm_direction);
00087         ph.param("pwm_max", pwm_max, pwm_max);
00088         std::vector<double> pwm_min;
00089         for(int i=0; i<pwm_max.size(); ++i) pwm_min.push_back(-pwm_max[i]);
00090         ph.param("pwm_min", pwm_min, pwm_min);
00091 
00092         //Check validity
00093         valid = (sz == mapping.size());
00094         valid = valid && (sz == pwm_direction.size());
00095         valid = valid && (sz == pwm_max.size());
00096         valid = valid && (sz == pwm_min.size());
00097         if (!valid)
00098         {
00099                 ROS_ERROR("ThrusterConfigration: Configuration is not valid. Check all vector sizes.");
00100                 return false;
00101         }
00102         //Sanity check on minimum/maximum
00103         for (int i=0; i<pwm_max.size(); ++i)
00104         {
00105                 if (pwm_max[i] < pwm_min[i])
00106                 {
00107                         ROS_ERROR("Minimum PWM is larger than maximum PWM.");
00108                         return false;
00109                 }
00110         }
00111 
00112         for(int i=0; i<sz; ++i)
00113         {
00114                 //Substract -1 to start calculating from 0
00115                 thrusters.push_back(EThruster(
00116                                 Kp[i], Kn[i], mapping[i]-1,
00117                                 pwm_max[i], pwm_min[i], pwm_direction[i]));
00118         }
00119 
00120         //Setup outputs
00121         pwm_out.resize(sz,0.0);
00122         F_a.resize(sz);
00123         F_max.resize(sz);
00124         F_min.resize(sz);
00125         //Init maximum/minimum to default
00126         this->updateMinMax();
00127 
00128         //Setup subscribers
00129         voltage_sub = nh.subscribe("supply_voltage",1,
00130                         &ThrusterConfiguration::onSupplyVoltage, this);
00131 
00132         return true;
00133 }
00134 
00135 const std::vector<double>& ThrusterConfiguration::pwm(const Eigen::VectorXd& F)
00136 {
00137         bool nofail(false);
00138         //Sanity check
00139         if ((nofail = (F.size() == thrusters.size())))
00140         {
00141                 for(int i=0; i<thrusters.size(); ++i)
00142                 {
00143                         EThruster& t(thrusters[i]);
00144                         //Calculate
00145                         double pwmi = t.pwm(F(i),Us);
00146                         //Limit and correct direction
00147                         pwmi = labust::math::coerce(pwmi, t.pwm_min, t.pwm_max);
00148                         //Assign the achieved force
00149                         F_a(i) = t.F(pwmi, Us);
00150                         //Assign the pwm output
00151                         pwm_out[t.pwm_id] = t.pwm_dir * pwmi;
00152                         //Sanity check
00153                         if (isnan(pwm_out[t.pwm_id]))
00154                         {
00155                                 nofail = false;
00156                                 break;
00157                         }
00158                 }
00159         }
00160 
00161         if (!nofail)
00162         {
00163                 //Zero all
00164                 for(int i=0; i<pwm_out.size(); ++i)
00165                 {
00166                         F_a(i) = 0;
00167                         pwm_out[i]=0;
00168                 }
00169         }
00170 
00171         T_a = _B*F_a;
00172 
00173         return pwm_out;
00174 }
00175 
00176 void ThrusterConfiguration::updateMinMax()
00177 {
00178         //Update the new maximums
00179         for(int i=0; i<thrusters.size(); ++i)
00180         {
00181                 EThruster& t(thrusters[i]);
00182                 if (adapt)
00183                 {
00184                         //Adapt to achieved nominal voltage
00185                         t.pwm_max = labust::math::coerce(Un/Us,-1.0,1.0);
00186                         t.pwm_min = labust::math::coerce(-Un/Us,-1.0,1.0);
00187                 }
00188                 F_max[i] = t.F(t.pwm_max,Us);
00189                 F_min[i] = t.F(t.pwm_min,Us);
00190         };
00191 }


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