00001
00002
00003
00004
00005
00006
00007
00008 #include "StandardMassEstimator.hpp"
00009
00010 #include <tk_draft_msgs/MassStamped.h>
00011 #include <telekyb_base/ROS.hpp>
00012
00013 #include <pluginlib/class_list_macros.h>
00014
00015 PLUGINLIB_DECLARE_CLASS(tk_param_estimator, StandardMassEstimator, TELEKYB_NAMESPACE::StandardMassEstimator, TELEKYB_NAMESPACE::MassEstimator);
00016
00017 namespace TELEKYB_NAMESPACE {
00018
00019
00020 StandardMassEstimOptions::StandardMassEstimOptions()
00021 : OptionContainer("StandardMassEstim")
00022 {
00023 tInitialMass = addOption<double>("tInitialMass","Mass of UAV in kg", 0.8, false, true);
00024
00025 tAFiltCoeff = addOption<double>("tAFiltCoeff","Mass Estimation: Determines the speed of convergence", 0.2,false,true);
00026 tLambdaZeroGain = addOption<double>("tLambdaZeroGain","Mass Estimation: Lambda Zero gain", 1.0,false,true);
00027 tKappaZeroGain = addOption<double>("tKappaZeroGain","Mass Estimation: Kappa Zero gain", 1.0,false,true);
00028 tSampleTime = addOption<double>("tSampleTime","Mass Estimation: SamplingTime", 0.008,false,true);
00029
00030 tMaxMass = addOption<double>("tMaxMass","Mass Estimation: Maximum mass", 1.8,false,true);
00031 tMinMass = addOption<double>("tMinMass","Mass Estimation: Minimum mass", 0.5,false,true);
00032
00033 tGravity = addOption<double>("tGravity","Mass Estimation: Intial Value for Gravity", 9.81, false, true);
00034
00035 tPublishMass = addOption<bool>("tPublishMass","Specifies if the estimated mass must be published", false, false, true);
00036 tMassTopic = addOption<std::string>("tMassTopic","Specifies the topic for publishing the mass", "EstimatedMass", false, true);
00037
00038 }
00039
00040 StandardMassEstimator::StandardMassEstimator():
00041 nodeHandle( ROSModule::Instance().getMainNodeHandle() )
00042 {
00043
00044 }
00045
00046
00047 void StandardMassEstimator::initialize()
00048 {
00049 if (options.tPublishMass){
00050 massPub = nodeHandle.advertise<tk_draft_msgs::MassStamped>(options.tMassTopic->getValue(), 1);
00051 }
00052
00053 estInvMass = 1.0 / options.tInitialMass->getValue();
00054 estGain = options.tKappaZeroGain->getValue();
00055
00056
00057
00058 integInitialInvMass = estInvMass;
00059 integInitialGain = estGain;
00060
00061
00062
00063 double a = options.tAFiltCoeff->getValue();
00064 double samplTime = options.tSampleTime->getValue();
00065
00066 std::vector<double> num(2);
00067 std::vector<double> den(1);
00068
00069 num[0] = a * samplTime / (2.0 + a * samplTime);
00070 num[1] = a * samplTime / (2.0 + a * samplTime);
00071 den[0] = (a * samplTime - 2.0) / (2.0 + a * samplTime);
00072
00073
00074
00075
00076
00077
00078
00079 thrustFilter = new IIRFilter(num,den);
00080 vertVelFilter = new IIRFilter(num,den);
00081 gravityFilter = new IIRFilter(num,den);
00082
00083 num[0] = 0.5 * samplTime;
00084 num[1] = 0.5 * samplTime;
00085 den[0] = -1.0;
00086
00087
00088
00089
00090
00091 estInvMassIntegrator = new IIRFilter(num,den);
00092 estGainIntegrator = new IIRFilter(num,den);
00093
00094
00095
00096
00097
00098
00099 }
00100
00101 void StandardMassEstimator::destroy()
00102 {
00103 delete thrustFilter;
00104 delete vertVelFilter;
00105 delete gravityFilter;
00106 delete estInvMassIntegrator;
00107 delete estGainIntegrator;
00108 }
00109
00110 std::string StandardMassEstimator::getName() const
00111 {
00112 return "StandardMassEstimator";
00113 }
00114
00115 StandardMassEstimator::~StandardMassEstimator()
00116 {
00117
00118 }
00119
00120 void StandardMassEstimator::run(const MassEstimInput& in,MassEstimOutput& out)
00121 {
00122 double a = options.tAFiltCoeff->getValue();
00123
00124 std::vector<double> input(1);
00125 input[0] = in.thrust * cos(in.roll) * cos(in.pitch);
00126 double filtThrust;
00127 thrustFilter->step(input,filtThrust);
00128
00129
00130
00131
00132 input[0] = in.vertVel;
00133 double filtVertVel;
00134 vertVelFilter->step(input,filtVertVel);
00135
00136
00137
00138
00139 input[0] = options.tGravity->getValue();
00140 double filtGrav;
00141 gravityFilter->step(input,filtGrav);
00142
00143
00144
00145
00146 double w = filtThrust;
00147
00148 double y = a*( in.vertVel - filtVertVel) - filtGrav;
00149
00150 double yHat = w * estInvMass;
00151
00152 double e = y-yHat;
00153
00154 double lambda = options.tLambdaZeroGain->getValue()*(1 - fabs(estGain)/options.tKappaZeroGain->getValue());
00155
00156 input[0] = estGain*w*e;
00157
00158 estInvMassIntegrator->step(input,estInvMass);
00159 estInvMass += integInitialInvMass;
00160
00161
00162 double estMass = 1.0/estInvMass;
00163
00164
00165 if(estMass >= options.tMaxMass->getValue() || estMass <= options.tMinMass->getValue() ){
00166
00167 input[0] = -1.0 * estGain * w * e;
00168 estInvMassIntegrator->step(input,estInvMass);
00169 estInvMass += integInitialInvMass;
00170 }
00171
00172 estMass = std::min( options.tMaxMass->getValue() , std::max(estMass,options.tMinMass->getValue()) );
00173 estInvMass = 1.0/estMass;
00174
00175 input[0] = lambda * estGain - estGain * w * w * estGain;
00176 estGainIntegrator->step(input,estGain);
00177 estGain += integInitialGain;
00178
00179
00180
00181
00182
00183 out.estMass = estMass;
00184 out.estGain = estGain;
00185
00186 if (options.tPublishMass){
00187 tk_draft_msgs::MassStamped msg;
00188 msg.header.stamp = ros::Time::now();
00189 msg.mass = estMass;
00190 massPub.publish(msg);
00191 }
00192
00193 }
00194
00195 double StandardMassEstimator::getInitialMass() const
00196 {
00197 return options.tInitialMass->getValue();
00198 }
00199
00200 }