Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] VTOL coordinate FW and MC rate controllers only #9190

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
56412c8
VTOL coordinate FW and MC rate controllers only
dagar Feb 10, 2018
c0569c5
FixedWingAttitudeControl: enable rate controller also for hover
RomanBapst Apr 3, 2018
6898654
tailsitter: removed redundant code after enabling mc & fw rate contro…
RomanBapst Apr 3, 2018
149bc4a
mc_att_control: only control attitude if in multirotor mode
RomanBapst Apr 3, 2018
c1ac573
FixedWingAttitudeControl: make sure rate controller max bodyrates are
RomanBapst Apr 4, 2018
5d7d062
tailsitter: transition improvements
RomanBapst Apr 5, 2018
7b100aa
FixedWingAttitudeControl: small gain scheduling hack for airspeed less
RomanBapst Apr 5, 2018
f863792
msg: update comment about throttle setpoint components
RomanBapst Apr 11, 2018
1b2ed9a
FixedWingAttitudeControl: convert desired bodyrates between mc and fw…
RomanBapst Apr 11, 2018
2567b7b
tailsitter: use mulirotor throttle control during backtransition
RomanBapst Apr 12, 2018
9f1e24a
vtol: moved diff_thrust parameter to vtol class since used for tailsi…
RomanBapst Apr 12, 2018
3d40eaa
tailsitter: transition code cleanup
RomanBapst Apr 12, 2018
50b5845
tailsitter: only use elevons lock parameter in multirotor mode
RomanBapst Apr 12, 2018
f812e44
vtol_att_control cleanup init and default destructors
dagar May 23, 2018
2038477
mc_pos_control: renamed thrust to thrust_z
RomanBapst Aug 9, 2018
f489ba9
FixedWingAttiudeControl: only copy manual control topic if it updated
RomanBapst Aug 9, 2018
1b57bcc
tailsitter.h: include matrix lib
RomanBapst Aug 9, 2018
6c0ab2d
flight_tasks: only run when rotary wing:
RomanBapst Aug 21, 2018
3949ea8
flight tasks: make transitions in altitude control
RomanBapst Aug 21, 2018
f7aaf73
FixedWingAttitudeControl: added parameter to allow airspeed scaling r…
RomanBapst Aug 24, 2018
829c28b
fixed sign of attitude setpoint thrust_z
RomanBapst Sep 14, 2018
1ccfa3d
fw_att_control move static constexpr out of header
dagar Sep 16, 2018
0b29136
vtol mark all virtual functions override
dagar Sep 16, 2018
340df53
uorb graph remove rates_sp_id special case
dagar Sep 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Tools/uorb_graph/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,8 @@ def __init__(self, module_whitelist=[], topic_blacklist=[]):

('mc_pos_control', r'mc_pos_control_main\.cpp$', r'\b_attitude_setpoint_id=([^,)]+)', r'^_attitude_setpoint_id$'),

('mc_att_control', r'mc_att_control_main\.cpp$', r'\b_rates_sp_id=([^,)]+)', r'^_rates_sp_id$'),
('mc_att_control', r'mc_att_control_main\.cpp$', r'\b_actuators_id=([^,)]+)', r'^_actuators_id$'),

('fw_att_control', r'FixedwingAttitudeControl\.cpp$', r'\b_rates_sp_id=([^,)]+)', r'^_rates_sp_id$'),
('fw_att_control', r'FixedwingAttitudeControl\.cpp$', r'\b_actuators_id=([^,)]+)', r'^_actuators_id$'),
('fw_att_control', r'FixedwingAttitudeControl\.cpp$', r'\b_attitude_setpoint_id=([^,)]+)', r'^_attitude_setpoint_id$'),

Expand Down
4 changes: 3 additions & 1 deletion msg/vehicle_attitude_setpoint.msg
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ float32 yaw_sp_move_rate # rad/s (commanded by user)
float32[4] q_d # Desired quaternion for quaternion control
bool q_d_valid # Set to true if quaternion vector is valid

float32 thrust # Thrust in Newton the power system should generate
float32 thrust_x # Throttle command in body x direction [-1,1]
float32 thrust_y # Throttle command in body y direction [-1,1]
float32 thrust_z # Throttle command in body z direction [-1,1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding ", thrust_z is negative for upwards thrust."


bool roll_reset_integral # Reset roll integral part (navigation logic change)
bool pitch_reset_integral # Reset pitch integral part (navigation logic change)
Expand Down
11 changes: 6 additions & 5 deletions msg/vehicle_rates_setpoint.msg
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
uint64 timestamp # time since system start (microseconds)

float32 roll # body angular rates in NED frame
float32 pitch # body angular rates in NED frame
float32 yaw # body angular rates in NED frame
float32 thrust # thrust normalized to 0..1
float32 roll # body angular rates in NED frame
float32 pitch # body angular rates in NED frame
float32 yaw # body angular rates in NED frame

# TOPICS vehicle_rates_setpoint mc_virtual_rates_setpoint fw_virtual_rates_setpoint
float32 thrust_x # Throttle command in body x direction [-1,1]
float32 thrust_y # Throttle command in body y direction [-1,1]
float32 thrust_z # Throttle command in body z direction [-1,1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as in vehicle_attitude_setpoint

2 changes: 1 addition & 1 deletion src/examples/rover_steering_control/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void control_attitude(const struct vehicle_attitude_setpoint_s *att_sp, const st
actuators->control[2] = yaw_err * pp.yaw_p;

/* copy throttle */
actuators->control[3] = att_sp->thrust;
actuators->control[3] = att_sp->thrust_x;

actuators->timestamp = hrt_absolute_time();
}
Expand Down
140 changes: 99 additions & 41 deletions src/modules/fw_att_control/FixedwingAttitudeControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
*/
extern "C" __EXPORT int fw_att_control_main(int argc, char *argv[]);

static constexpr float _airspeed_numerical_min =
0.5f; /**< lowest airspeed we will ever use to prevent numerical problems */

FixedwingAttitudeControl::FixedwingAttitudeControl() :
_airspeed_sub(ORB_ID(airspeed)),

Expand Down Expand Up @@ -116,6 +119,7 @@ FixedwingAttitudeControl::FixedwingAttitudeControl() :

// initialize to invalid VTOL type
_parameters.vtol_type = -1;
_parameters.vtol_airspeed_rule = 0;

/* fetch initial parameter values */
parameters_update();
Expand Down Expand Up @@ -209,6 +213,7 @@ FixedwingAttitudeControl::parameters_update()

if (_vehicle_status.is_vtol) {
param_get(_parameter_handles.vtol_type, &_parameters.vtol_type);
param_get(_parameter_handles.vtol_airspeed_rule, &_parameters.vtol_airspeed_rule);
}

param_get(_parameter_handles.bat_scale_en, &_parameters.bat_scale_en);
Expand Down Expand Up @@ -255,16 +260,18 @@ FixedwingAttitudeControl::vehicle_control_mode_poll()
orb_check(_vcontrol_mode_sub, &vcontrol_mode_updated);

if (vcontrol_mode_updated) {

orb_copy(ORB_ID(vehicle_control_mode), _vcontrol_mode_sub, &_vcontrol_mode);
}
}

void
FixedwingAttitudeControl::vehicle_manual_poll()
{
bool manual_updated;
orb_check(_manual_sub, &manual_updated);

// only update manual if in a manual mode
if (_vcontrol_mode.flag_control_manual_enabled) {
if (_vcontrol_mode.flag_control_manual_enabled && manual_updated && !_vehicle_status.is_rotary_wing) {

// Always copy the new manual setpoint, even if it wasn't updated, to fill the _actuators with valid values
if (orb_copy(ORB_ID(manual_control_setpoint), _manual_sub, &_manual) == PX4_OK) {
Expand All @@ -287,7 +294,7 @@ FixedwingAttitudeControl::vehicle_manual_poll()
_att_sp.pitch_body = -_manual.x * _parameters.man_pitch_max + _parameters.pitchsp_offset_rad;
_att_sp.pitch_body = math::constrain(_att_sp.pitch_body, -_parameters.man_pitch_max, _parameters.man_pitch_max);
_att_sp.yaw_body = 0.0f;
_att_sp.thrust = _manual.z;
_att_sp.thrust_x = _manual.z;

Quatf q(Eulerf(_att_sp.roll_body, _att_sp.pitch_body, _att_sp.yaw_body));
q.copyTo(_att_sp.q_d);
Expand All @@ -310,15 +317,15 @@ FixedwingAttitudeControl::vehicle_manual_poll()
_rates_sp.roll = _manual.y * _parameters.acro_max_x_rate_rad;
_rates_sp.pitch = -_manual.x * _parameters.acro_max_y_rate_rad;
_rates_sp.yaw = _manual.r * _parameters.acro_max_z_rate_rad;
_rates_sp.thrust = _manual.z;
_rates_sp.thrust_x = _manual.z;

if (_rate_sp_pub != nullptr) {
/* publish the attitude rates setpoint */
orb_publish(_rates_sp_id, _rate_sp_pub, &_rates_sp);
orb_publish(ORB_ID(vehicle_rates_setpoint), _rate_sp_pub, &_rates_sp);

} else if (_rates_sp_id) {
} else {
/* advertise the attitude rates setpoint */
_rate_sp_pub = orb_advertise(_rates_sp_id, &_rates_sp);
_rate_sp_pub = orb_advertise(ORB_ID(vehicle_rates_setpoint), &_rates_sp);
}

} else {
Expand All @@ -335,14 +342,38 @@ FixedwingAttitudeControl::vehicle_manual_poll()
}

void
FixedwingAttitudeControl::vehicle_setpoint_poll()
FixedwingAttitudeControl::vehicle_attitude_setpoint_poll()
{
/* check if there is a new setpoint */
bool att_sp_updated;
orb_check(_att_sp_sub, &att_sp_updated);

if (att_sp_updated) {
orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
if (orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp)) {
_rates_sp.thrust_x = _att_sp.thrust_x;
_rates_sp.thrust_y = _att_sp.thrust_y;
_rates_sp.thrust_z = _att_sp.thrust_z;
}
}
}

void
FixedwingAttitudeControl::vehicle_rates_setpoint_poll()
{
/* check if there is a new setpoint */
bool rates_sp_updated = false;
orb_check(_rates_sp_sub, &rates_sp_updated);

if (rates_sp_updated) {
orb_copy(ORB_ID(vehicle_rates_setpoint), _rates_sp_sub, &_rates_sp);

if (_parameters.vtol_type == vtol_type::TAILSITTER) {
float tmp = _rates_sp.roll;
_rates_sp.roll = -_rates_sp.yaw;
_rates_sp.yaw = tmp;
}


}
}

Expand All @@ -368,19 +399,26 @@ FixedwingAttitudeControl::vehicle_status_poll()
if (vehicle_status_updated) {
orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);

// if VTOL listen to rate setpoints only
if (_vehicle_status.is_vtol) {
if (_vehicle_status.is_rotary_wing) {
_vcontrol_mode.flag_control_attitude_enabled = false;
_vcontrol_mode.flag_control_manual_enabled = false;
}
}

/* set correct uORB ID, depending on if vehicle is VTOL or not */
if (!_rates_sp_id) {
if (!_actuators_id) {
if (_vehicle_status.is_vtol) {
_rates_sp_id = ORB_ID(fw_virtual_rates_setpoint);
_actuators_id = ORB_ID(actuator_controls_virtual_fw);
_attitude_setpoint_id = ORB_ID(fw_virtual_attitude_setpoint);

_parameter_handles.vtol_type = param_find("VT_TYPE");
_parameter_handles.vtol_airspeed_rule = param_find("VT_AIRSPD_RULE");

parameters_update();

} else {
_rates_sp_id = ORB_ID(vehicle_rates_setpoint);
_actuators_id = ORB_ID(actuator_controls_0);
_attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
}
Expand All @@ -404,6 +442,29 @@ FixedwingAttitudeControl::vehicle_land_detected_poll()
}
}

float FixedwingAttitudeControl::get_airspeed_scaling(float airspeed)
{
// check if we have special airspeed rules for vtol
if (_vehicle_status.is_vtol && _parameters.vtol_airspeed_rule > 0) {

// always use minimum airspeed during hover
if (_parameters.vtol_airspeed_rule == 1 && _vehicle_status.is_rotary_wing &&
!_vehicle_status.in_transition_mode) {
airspeed = _airspeed_numerical_min;
}
}

/*
* For scaling our actuators using anything less than the min (close to stall)
* speed doesn't make any sense - its the strongest reasonable deflection we
* want to do in flight and its the baseline a human pilot would choose.
*
* Forcing the scaling to this value allows reasonable handheld tests.
*/
return _parameters.airspeed_trim / ((airspeed < _parameters.airspeed_min) ? _parameters.airspeed_min :
airspeed);
}

void FixedwingAttitudeControl::run()
{
/*
Expand All @@ -418,16 +479,23 @@ void FixedwingAttitudeControl::run()
_vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
_vehicle_land_detected_sub = orb_subscribe(ORB_ID(vehicle_land_detected));
_battery_status_sub = orb_subscribe(ORB_ID(battery_status));
_rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));

parameters_update();

/* get an initial update for all sensor and status data */
vehicle_setpoint_poll();
vehicle_attitude_setpoint_poll();
vehicle_control_mode_poll();
vehicle_manual_poll();
vehicle_status_poll();
vehicle_land_detected_poll();

// set initial maximum body rate setpoints
_roll_ctrl.set_max_rate(_parameters.acro_max_x_rate_rad);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing set_max_rate() update code below doesn't handle this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dagar Nope, it does not. The problem is that for VTOL the condition
_vcontrol_mode.flag_control_attitude_enabled != _flag_control_attitude_enabled_last
does not hold because since the mc attitude controller is in charge _vcontrol_mode.flag_control_attitude_enabled is false in the beginning.
So you either have to switch to fw mode first of you have to change a parameter.
Without this change all of the max rates of the rate controller were set to zero, so it essentially did nothing.

_pitch_ctrl.set_max_rate_pos(_parameters.acro_max_y_rate_rad);
_pitch_ctrl.set_max_rate_neg(_parameters.acro_max_y_rate_rad);
_yaw_ctrl.set_max_rate(_parameters.acro_max_z_rate_rad);

/* wakeup source */
px4_pollfd_struct_t fds[1];

Expand Down Expand Up @@ -529,7 +597,7 @@ void FixedwingAttitudeControl::run()
matrix::Eulerf euler_angles(R);

_airspeed_sub.update();
vehicle_setpoint_poll();
vehicle_attitude_setpoint_poll();
vehicle_control_mode_poll();
vehicle_manual_poll();
global_pos_poll();
Expand Down Expand Up @@ -560,6 +628,7 @@ void FixedwingAttitudeControl::run()

/* decide if in stabilized or full manual control */
if (_vcontrol_mode.flag_control_rates_enabled) {

/* scale around tuning airspeed */
float airspeed;

Expand All @@ -570,7 +639,7 @@ void FixedwingAttitudeControl::run()

if (!_parameters.airspeed_disabled && airspeed_valid) {
/* prevent numerical drama by requiring 0.5 m/s minimal speed */
airspeed = math::max(0.5f, _airspeed_sub.get().indicated_airspeed_m_s);
airspeed = math::max(_airspeed_numerical_min, _airspeed_sub.get().indicated_airspeed_m_s);

} else {
airspeed = _parameters.airspeed_trim;
Expand All @@ -580,15 +649,7 @@ void FixedwingAttitudeControl::run()
}
}

/*
* For scaling our actuators using anything less than the min (close to stall)
* speed doesn't make any sense - its the strongest reasonable deflection we
* want to do in flight and its the baseline a human pilot would choose.
*
* Forcing the scaling to this value allows reasonable handheld tests.
*/
float airspeed_scaling = _parameters.airspeed_trim / ((airspeed < _parameters.airspeed_min) ? _parameters.airspeed_min :
airspeed);
float airspeed_scaling = get_airspeed_scaling(airspeed);

/* Use min airspeed to calculate ground speed scaling region.
* Don't scale below gspd_scaling_trim
Expand Down Expand Up @@ -624,10 +685,6 @@ void FixedwingAttitudeControl::run()
_wheel_ctrl.reset_integrator();
}

float roll_sp = _att_sp.roll_body;
float pitch_sp = _att_sp.pitch_body;
float yaw_sp = _att_sp.yaw_body;

/* Prepare data for attitude controllers */
struct ECL_ControlData control_input = {};
control_input.roll = euler_angles.phi();
Expand All @@ -636,9 +693,9 @@ void FixedwingAttitudeControl::run()
control_input.body_x_rate = _att.rollspeed;
control_input.body_y_rate = _att.pitchspeed;
control_input.body_z_rate = _att.yawspeed;
control_input.roll_setpoint = roll_sp;
control_input.pitch_setpoint = pitch_sp;
control_input.yaw_setpoint = yaw_sp;
control_input.roll_setpoint = _att_sp.roll_body;
control_input.pitch_setpoint = _att_sp.pitch_body;
control_input.yaw_setpoint = _att_sp.yaw_body;
control_input.airspeed_min = _parameters.airspeed_min;
control_input.airspeed_max = _parameters.airspeed_max;
control_input.airspeed = airspeed;
Expand All @@ -649,7 +706,7 @@ void FixedwingAttitudeControl::run()

/* reset body angular rate limits on mode change */
if ((_vcontrol_mode.flag_control_attitude_enabled != _flag_control_attitude_enabled_last) || params_updated) {
if (_vcontrol_mode.flag_control_attitude_enabled) {
if (_vcontrol_mode.flag_control_attitude_enabled || _vehicle_status.is_rotary_wing) {
_roll_ctrl.set_max_rate(math::radians(_parameters.r_rmax));
_pitch_ctrl.set_max_rate_pos(math::radians(_parameters.p_rmax_pos));
_pitch_ctrl.set_max_rate_neg(math::radians(_parameters.p_rmax_neg));
Expand Down Expand Up @@ -693,7 +750,7 @@ void FixedwingAttitudeControl::run()

/* Run attitude controllers */
if (_vcontrol_mode.flag_control_attitude_enabled) {
if (PX4_ISFINITE(roll_sp) && PX4_ISFINITE(pitch_sp)) {
if (PX4_ISFINITE(_att_sp.roll_body) && PX4_ISFINITE(_att_sp.pitch_body)) {
_roll_ctrl.control_attitude(control_input);
_pitch_ctrl.control_attitude(control_input);
_yaw_ctrl.control_attitude(control_input); //runs last, because is depending on output of roll and pitch attitude
Expand Down Expand Up @@ -744,8 +801,8 @@ void FixedwingAttitudeControl::run()
}

/* throttle passed through if it is finite and if no engine failure was detected */
_actuators.control[actuator_controls_s::INDEX_THROTTLE] = (PX4_ISFINITE(_att_sp.thrust)
&& !_vehicle_status.engine_failure) ? _att_sp.thrust : 0.0f;
_actuators.control[actuator_controls_s::INDEX_THROTTLE] = (PX4_ISFINITE(_att_sp.thrust_x)
&& !_vehicle_status.engine_failure) ? _att_sp.thrust_x : 0.0f;

/* scale effort by battery status */
if (_parameters.bat_scale_en &&
Expand Down Expand Up @@ -783,18 +840,19 @@ void FixedwingAttitudeControl::run()

if (_rate_sp_pub != nullptr) {
/* publish the attitude rates setpoint */
orb_publish(_rates_sp_id, _rate_sp_pub, &_rates_sp);
orb_publish(ORB_ID(vehicle_rates_setpoint), _rate_sp_pub, &_rates_sp);

} else if (_rates_sp_id) {
} else {
/* advertise the attitude rates setpoint */
_rate_sp_pub = orb_advertise(_rates_sp_id, &_rates_sp);
_rate_sp_pub = orb_advertise(ORB_ID(vehicle_rates_setpoint), &_rates_sp);
}

} else {
// pure rate control
vehicle_rates_setpoint_poll();

_roll_ctrl.set_bodyrate_setpoint(_rates_sp.roll);
_pitch_ctrl.set_bodyrate_setpoint(_rates_sp.pitch);
_yaw_ctrl.set_bodyrate_setpoint(_rates_sp.yaw);
_pitch_ctrl.set_bodyrate_setpoint(_rates_sp.pitch);

float roll_u = _roll_ctrl.control_bodyrate(control_input);
_actuators.control[actuator_controls_s::INDEX_ROLL] = (PX4_ISFINITE(roll_u)) ? roll_u + trim_roll : trim_roll;
Expand All @@ -805,7 +863,7 @@ void FixedwingAttitudeControl::run()
float yaw_u = _yaw_ctrl.control_bodyrate(control_input);
_actuators.control[actuator_controls_s::INDEX_YAW] = (PX4_ISFINITE(yaw_u)) ? yaw_u + trim_yaw : trim_yaw;

_actuators.control[actuator_controls_s::INDEX_THROTTLE] = PX4_ISFINITE(_rates_sp.thrust) ? _rates_sp.thrust : 0.0f;
_actuators.control[actuator_controls_s::INDEX_THROTTLE] = PX4_ISFINITE(_rates_sp.thrust_x) ? _rates_sp.thrust_x : 0.0f;
}

rate_ctrl_status_s rate_ctrl_status;
Expand Down
Loading