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 }