00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
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         
00051         ph.param("Us",Us,Us);
00052         ph.param("Un",Un,Un);
00053         ph.param("adapt_pwm",adapt,adapt);
00054 
00055         
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         
00061         labust::tools::getMatrixParam(ph,"B", _B);
00062 
00063         
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         
00076         _Binv = _B.transpose()*(_B*_B.transpose()).inverse();
00077 
00078         
00079         std::vector<double> pwm_max(sz,1.0), pwm_direction(sz,1);
00080         std::vector<int> mapping(sz);
00081         
00082         for (int i=0; i<mapping.size(); ++i) mapping[i]=i+1;
00083 
00084         
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         
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         
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                 
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         
00121         pwm_out.resize(sz,0.0);
00122         F_a.resize(sz);
00123         F_max.resize(sz);
00124         F_min.resize(sz);
00125         
00126         this->updateMinMax();
00127 
00128         
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         
00139         if ((nofail = (F.size() == thrusters.size())))
00140         {
00141                 for(int i=0; i<thrusters.size(); ++i)
00142                 {
00143                         EThruster& t(thrusters[i]);
00144                         
00145                         double pwmi = t.pwm(F(i),Us);
00146                         
00147                         pwmi = labust::math::coerce(pwmi, t.pwm_min, t.pwm_max);
00148                         
00149                         F_a(i) = t.F(pwmi, Us);
00150                         
00151                         pwm_out[t.pwm_id] = t.pwm_dir * pwmi;
00152                         
00153                         if (isnan(pwm_out[t.pwm_id]))
00154                         {
00155                                 nofail = false;
00156                                 break;
00157                         }
00158                 }
00159         }
00160 
00161         if (!nofail)
00162         {
00163                 
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         
00179         for(int i=0; i<thrusters.size(); ++i)
00180         {
00181                 EThruster& t(thrusters[i]);
00182                 if (adapt)
00183                 {
00184                         
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 }