@@ -44,6 +44,7 @@ LQRController::LQRController(BiasEstimator &b) : nh_(),
44
44
( " /rpyt_command" , 1 , true );
45
45
controller_debug_pub_ = nh_.advertise <freyja_msgs::ControllerDebug>
46
46
( " /controller_debug" , 1 , true );
47
+ est_mass_pub_ = nh_.advertise <std_msgs::Float32>( " /freyja_estimated_mass" , 1 , true );
47
48
48
49
/* Timer to run the LQR controller perdiodically */
49
50
float controller_period = 1.0 /controller_rate_;
@@ -56,9 +57,25 @@ LQRController::LQRController(BiasEstimator &b) : nh_(),
56
57
have_reference_update_ = false ;
57
58
58
59
/* Bias compensation parameters */
59
- bool _bcomp = true ;
60
- priv_nh_.param ( " bias_compensation" , bias_compensation_req_, _bcomp );
60
+ std::string _bcomp = " auto" ;
61
+ priv_nh_.param ( " bias_compensation" , _bcomp, _bcomp );
62
+ if ( _bcomp == " on" )
63
+ bias_compensation_req_ = true ; // always on (be careful!!)
64
+ else if ( _bcomp == " auto" || _bcomp == " off" )
65
+ bias_compensation_req_ = false ; // off, or on by service call
66
+
61
67
f_biases_ << 0.0 , 0.0 , 0.0 ;
68
+
69
+
70
+ /* Mass estimation */
71
+ enable_dyn_mass_correction_ = false ;
72
+ priv_nh_.param ( " mass_correction" , enable_dyn_mass_correction_, bool (false ) );
73
+ priv_nh_.param ( " mass_estimation" , enable_dyn_mass_estimation_, bool (true ) );
74
+ if ( enable_dyn_mass_correction_ )
75
+ {
76
+ enable_dyn_mass_estimation_ = true ;
77
+ ROS_WARN ( " LQR: Mass correction active at init! This is discouraged." );
78
+ }
62
79
}
63
80
64
81
void LQRController::initLqrSystem ()
@@ -240,6 +257,43 @@ void LQRController::computeFeedback( const ros::TimerEvent &event )
240
257
/* Tell bias estimator about new control input */
241
258
if ( bias_compensation_req_ )
242
259
bias_est_.setControlInput ( control_input );
260
+
261
+ /* Update the total flying mass if requested */
262
+ if ( enable_dyn_mass_estimation_ )
263
+ estimateMass ( control_input, tnow );
264
+ }
265
+
266
+ void LQRController::estimateMass ( const Eigen::Matrix<double , 4 , 1 > &c, ros::Time &t )
267
+ {
268
+ /* Experimental module that estimates the true mass of the system in air.
269
+ It uses the provided mass and observes the deviation from expected output
270
+ of the controller - and attributes *all* of that error to an incorrect
271
+ mass parameter. This is recommended only if mass may be off by ~200-300g.
272
+ Errors larger than that can induce major second-order oscillations, and are
273
+ usually better addressed elsewhere in the architecture (or get a better scale).
274
+ */
275
+ static float prev_estimated_mass = total_mass_;
276
+ static std_msgs::Float32 estmass;
277
+ static ros::Time t_last = ros::Time::now ();
278
+
279
+ if ( (t-t_last).toSec () < 3.0 )
280
+ return ;
281
+
282
+ float ctrl_effort = c (2 ) + 9.81 ;
283
+ float estimated_mass = total_mass_*(9.81 - ctrl_effort)/9.81 ;
284
+ // basic low-pass filter to prevent wild jitter
285
+ estimated_mass = (prev_estimated_mass + estimated_mass)/2.0 ;
286
+
287
+ estmass.data = estimated_mass;
288
+ est_mass_pub_.publish ( estmass );
289
+
290
+ /* if correction is allowed- clip between min and max */
291
+ if ( enable_dyn_mass_correction_ )
292
+ total_mass_ = std::min ( 2 .0f , std::max ( 0 .8f , estimated_mass ) );
293
+
294
+ // book-keeping
295
+ t_last = t;
296
+ prev_estimated_mass = estimated_mass;
243
297
}
244
298
245
299
int main ( int argc, char ** argv )
0 commit comments