Skip to content

Commit 09813f0

Browse files
committed
add dynamic mass correction, support automatic bias estimation
*mass estimation is enabled, correction is off by default *bias estimation param type change to string: "auto" default *add parameters to launch file
1 parent 378c86b commit 09813f0

File tree

3 files changed

+82
-17
lines changed

3 files changed

+82
-17
lines changed

freyja_controller.launch

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@
99

1010
<!-- allowed autopilots: "asctec" or "arducopter" -->
1111
<!-- must provide vicon_topic -->
12-
<arg name="autopilot" default="arducopter"/>
12+
<arg name="autopilot" default="arducopter"/>
1313
<arg name="vicon_topic"/>
1414
<!-- use "device:baudrate" for apm, "device" for asctec -->
15-
<arg name="comm_port" default="/dev/ttyUSB0:57600"/>
16-
<arg name="total_mass" default="0.95"/>
17-
<arg name="thrust_scaler" default="200.0"/>
15+
<arg name="comm_port" default="/dev/ttyUSB0:57600"/>
16+
<arg name="total_mass" default="0.95"/>
17+
<arg name="thrust_scaler" default="200.0"/>
1818

1919
<!-- true if providing your own trajectory source -->
2020
<arg name="use_external_trajectory" default="false"/>
2121
<arg name="use_velctrl_only" default="false"/>
22-
<arg name="bias_compensation" default="false" />
22+
<arg name="bias_compensation" default="auto" />
2323
<arg name="start_rosbag" default="false"/>
2424

2525

2626
<!-- state source can be: "apm", "asctec", "vicon" or "onboard_camera" -->
2727
<!-- implemented filters: "median", "gauss" and "lwma" -->
2828
<node name="state_manager" pkg="state_manager" type="state_manager_node">
29-
<param name="state_source" type="string" value="vicon" />
30-
<param name="filter_type" type="string" value="median" />
31-
<param name="vicon_topic" type="string" value="$(arg vicon_topic)" />
29+
<param name="state_source" type="string" value="vicon" />
30+
<param name="filter_type" type="string" value="median" />
31+
<param name="vicon_topic" type="string" value="$(arg vicon_topic)" />
3232
</node>
3333

3434
<!-- an example trajectory node for reference -->
@@ -41,17 +41,19 @@
4141
<!-- control node (see velctrl flag above) -->
4242
<node name="lqg_controller" pkg="lqg_control" type="lqg_control_node"
4343
output="screen" if="$(eval not use_velctrl_only)">
44-
<param name="controller_rate" type="int" value="45" />
45-
<param name="total_mass" type="double" value="$(arg total_mass)"/>
46-
<param name="use_stricter_gains" type="bool" value="false" />
47-
<param name="estimator_rate" type="int" value="70" />
48-
<param name="bias_compensation" type="bool" value="$(arg bias_compensation)" />
44+
<param name="controller_rate" type="int" value="45" />
45+
<param name="total_mass" type="double" value="$(arg total_mass)"/>
46+
<param name="use_stricter_gains" type="bool" value="false" />
47+
<param name="estimator_rate" type="int" value="10" />
48+
<param name="bias_compensation" type="string" value="$(arg bias_compensation)" />
49+
<param name="mass_estimation" type="bool" value="true" />
50+
<param name="mass_correction" type="bool" value="false" />
4951
</node>
5052

5153
<node name="lqr_vel_controller" pkg="lqr_control" type="lqr_vel_ctrl_node"
5254
if="$(eval use_velctrl_only)">
53-
<param name="controller_rate" type="int" value="30" />
54-
<param name="total_mass" type="double" value="$(arg total_mass)" />
55+
<param name="controller_rate" type="int" value="30" />
56+
<param name="total_mass" type="double" value="$(arg total_mass)" />
5557
</node>
5658

5759
<!-- autopilot communication node -->

lqg_controller/include/lqr_control_bias.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <ros/ros.h>
1818
#include <geometry_msgs/TransformStamped.h>
1919
#include <std_srvs/SetBool.h>
20+
#include <std_msgs/Float32.h>
2021

2122
#include <freyja_msgs/CurrentState.h>
2223
#include <freyja_msgs/CtrlCommand.h>
@@ -70,6 +71,10 @@ class LQRController
7071
Eigen::Matrix<double, 3, 1> f_biases_;
7172
std::thread bias_handler_thread_;
7273

74+
/*Dynamic mass estimation and compensation */
75+
bool enable_dyn_mass_correction_;
76+
bool enable_dyn_mass_estimation_;
77+
7378
public:
7479
LQRController( BiasEstimator & );
7580
void initLqrSystem();
@@ -91,4 +96,8 @@ class LQRController
9196

9297
/* helper function to calculate yaw error */
9398
inline double calcYawError( const double&, const double& ) __attribute__((always_inline));
99+
100+
/* estimate actual mass in flight */
101+
void estimateMass( const Eigen::Matrix<double, 4, 1> &, ros::Time & );
102+
ros::Publisher est_mass_pub_;
94103
};

lqg_controller/src/lqr_control_bias.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ LQRController::LQRController(BiasEstimator &b) : nh_(),
4444
( "/rpyt_command", 1, true );
4545
controller_debug_pub_ = nh_.advertise <freyja_msgs::ControllerDebug>
4646
( "/controller_debug", 1, true );
47+
est_mass_pub_ = nh_.advertise<std_msgs::Float32>( "/freyja_estimated_mass", 1, true );
4748

4849
/* Timer to run the LQR controller perdiodically */
4950
float controller_period = 1.0/controller_rate_;
@@ -56,9 +57,25 @@ LQRController::LQRController(BiasEstimator &b) : nh_(),
5657
have_reference_update_ = false;
5758

5859
/* 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+
6167
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+
}
6279
}
6380

6481
void LQRController::initLqrSystem()
@@ -240,6 +257,43 @@ void LQRController::computeFeedback( const ros::TimerEvent &event )
240257
/* Tell bias estimator about new control input */
241258
if( bias_compensation_req_ )
242259
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;
243297
}
244298

245299
int main( int argc, char** argv )

0 commit comments

Comments
 (0)