2023-07-27 02:03:08 -03:00
|
|
|
#include "Blimp.h"
|
|
|
|
|
2024-02-28 08:18:11 -04:00
|
|
|
#include <AC_AttitudeControl/AC_PosControl.h>
|
|
|
|
|
2023-07-27 02:03:08 -03:00
|
|
|
#define MA 0.99
|
|
|
|
#define MO (1-MA)
|
|
|
|
|
|
|
|
void Loiter::run(Vector3f& target_pos, float& target_yaw, Vector4b axes_disabled)
|
|
|
|
{
|
|
|
|
const float dt = blimp.scheduler.get_last_loop_time_s();
|
|
|
|
|
|
|
|
float scaler_xz_n;
|
|
|
|
float xz_out = fabsf(blimp.motors->front_out) + fabsf(blimp.motors->down_out);
|
2023-08-21 08:19:19 -03:00
|
|
|
if (xz_out > 1) {
|
|
|
|
scaler_xz_n = 1 / xz_out;
|
|
|
|
} else {
|
|
|
|
scaler_xz_n = 1;
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
scaler_xz = scaler_xz*MA + scaler_xz_n*MO;
|
|
|
|
|
|
|
|
float scaler_yyaw_n;
|
|
|
|
float yyaw_out = fabsf(blimp.motors->right_out) + fabsf(blimp.motors->yaw_out);
|
2023-08-21 08:19:19 -03:00
|
|
|
if (yyaw_out > 1) {
|
|
|
|
scaler_yyaw_n = 1 / yyaw_out;
|
|
|
|
} else {
|
|
|
|
scaler_yyaw_n = 1;
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
scaler_yyaw = scaler_yyaw*MA + scaler_yyaw_n*MO;
|
|
|
|
|
2024-01-09 23:37:03 -04:00
|
|
|
#if HAL_LOGGING_ENABLED
|
2023-07-27 02:03:08 -03:00
|
|
|
AP::logger().WriteStreaming("BSC", "TimeUS,xz,yyaw,xzn,yyawn",
|
|
|
|
"Qffff",
|
|
|
|
AP_HAL::micros64(),
|
|
|
|
scaler_xz, scaler_yyaw, scaler_xz_n, scaler_yyaw_n);
|
2024-01-09 23:37:03 -04:00
|
|
|
#endif
|
2023-07-27 02:03:08 -03:00
|
|
|
|
|
|
|
float yaw_ef = blimp.ahrs.get_yaw();
|
|
|
|
Vector3f err_xyz = target_pos - blimp.pos_ned;
|
|
|
|
float err_yaw = wrap_PI(target_yaw - yaw_ef);
|
|
|
|
|
|
|
|
Vector4b zero;
|
2023-08-21 08:19:19 -03:00
|
|
|
if ((fabsf(err_xyz.x) < blimp.g.pid_dz) || !blimp.motors->_armed || (blimp.g.dis_mask & (1<<(2-1)))) {
|
|
|
|
zero.x = true;
|
|
|
|
}
|
|
|
|
if ((fabsf(err_xyz.y) < blimp.g.pid_dz) || !blimp.motors->_armed || (blimp.g.dis_mask & (1<<(1-1)))) {
|
|
|
|
zero.y = true;
|
|
|
|
}
|
|
|
|
if ((fabsf(err_xyz.z) < blimp.g.pid_dz) || !blimp.motors->_armed || (blimp.g.dis_mask & (1<<(3-1)))) {
|
|
|
|
zero.z = true;
|
|
|
|
}
|
|
|
|
if ((fabsf(err_yaw) < blimp.g.pid_dz) || !blimp.motors->_armed || (blimp.g.dis_mask & (1<<(4-1)))) {
|
|
|
|
zero.yaw = true;
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
|
|
|
|
//Disabled means "don't update PIDs or output anything at all". Zero means actually output zero thrust. I term is limited in either case."
|
|
|
|
Vector4b limit = zero || axes_disabled;
|
|
|
|
|
|
|
|
Vector3f target_vel_ef;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!axes_disabled.x && !axes_disabled.y) target_vel_ef = {blimp.pid_pos_xy.update_all(target_pos, blimp.pos_ned, dt, {(float)limit.x, (float)limit.y, (float)limit.z}), 0};
|
|
|
|
if (!axes_disabled.z) {
|
|
|
|
target_vel_ef.z = blimp.pid_pos_z.update_all(target_pos.z, blimp.pos_ned.z, dt, limit.z);
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
|
|
|
|
float target_vel_yaw = 0;
|
|
|
|
if (!axes_disabled.yaw) {
|
|
|
|
target_vel_yaw = blimp.pid_pos_yaw.update_error(wrap_PI(target_yaw - yaw_ef), dt, limit.yaw);
|
|
|
|
blimp.pid_pos_yaw.set_target_rate(target_yaw);
|
|
|
|
blimp.pid_pos_yaw.set_actual_rate(yaw_ef);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector3f target_vel_ef_c{constrain_float(target_vel_ef.x, -blimp.g.max_vel_xy, blimp.g.max_vel_xy),
|
|
|
|
constrain_float(target_vel_ef.y, -blimp.g.max_vel_xy, blimp.g.max_vel_xy),
|
|
|
|
constrain_float(target_vel_ef.z, -blimp.g.max_vel_z, blimp.g.max_vel_z)};
|
|
|
|
float target_vel_yaw_c = constrain_float(target_vel_yaw, -blimp.g.max_vel_yaw, blimp.g.max_vel_yaw);
|
|
|
|
|
|
|
|
Vector2f target_vel_ef_c_scaled_xy = {target_vel_ef_c.x * scaler_xz, target_vel_ef_c.y * scaler_yyaw};
|
|
|
|
Vector2f vel_ned_filtd_scaled_xy = {blimp.vel_ned_filtd.x * scaler_xz, blimp.vel_ned_filtd.y * scaler_yyaw};
|
|
|
|
|
|
|
|
Vector2f actuator;
|
|
|
|
if (!axes_disabled.x && !axes_disabled.y) actuator = blimp.pid_vel_xy.update_all(target_vel_ef_c_scaled_xy, vel_ned_filtd_scaled_xy, dt, {(float)limit.x, (float)limit.y});
|
|
|
|
float act_down = 0;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!axes_disabled.z) {
|
|
|
|
act_down = blimp.pid_vel_z.update_all(target_vel_ef_c.z * scaler_xz, blimp.vel_ned_filtd.z * scaler_xz, dt, limit.z);
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
blimp.rotate_NE_to_BF(actuator);
|
|
|
|
float act_yaw = 0;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!axes_disabled.yaw) {
|
|
|
|
act_yaw = blimp.pid_vel_yaw.update_all(target_vel_yaw_c * scaler_yyaw, blimp.vel_yaw_filtd * scaler_yyaw, dt, limit.yaw);
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
|
|
|
|
if (!blimp.motors->armed()) {
|
|
|
|
blimp.pid_pos_xy.set_integrator(Vector2f(0,0));
|
|
|
|
blimp.pid_pos_z.set_integrator(0);
|
|
|
|
blimp.pid_pos_yaw.set_integrator(0);
|
|
|
|
blimp.pid_vel_xy.set_integrator(Vector2f(0,0));
|
|
|
|
blimp.pid_vel_z.set_integrator(0);
|
|
|
|
blimp.pid_vel_yaw.set_integrator(0);
|
|
|
|
target_pos = blimp.pos_ned;
|
|
|
|
target_yaw = blimp.ahrs.get_yaw();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zero.x) {
|
|
|
|
blimp.motors->front_out = 0;
|
|
|
|
} else if (axes_disabled.x);
|
|
|
|
else {
|
|
|
|
blimp.motors->front_out = actuator.x;
|
|
|
|
}
|
|
|
|
if (zero.y) {
|
|
|
|
blimp.motors->right_out = 0;
|
|
|
|
} else if (axes_disabled.y);
|
|
|
|
else {
|
|
|
|
blimp.motors->right_out = actuator.y;
|
|
|
|
}
|
|
|
|
if (zero.z) {
|
|
|
|
blimp.motors->down_out = 0;
|
|
|
|
} else if (axes_disabled.z);
|
|
|
|
else {
|
|
|
|
blimp.motors->down_out = act_down;
|
|
|
|
}
|
|
|
|
if (zero.yaw) {
|
|
|
|
blimp.motors->yaw_out = 0;
|
|
|
|
} else if (axes_disabled.yaw);
|
|
|
|
else {
|
|
|
|
blimp.motors->yaw_out = act_yaw;
|
|
|
|
}
|
|
|
|
|
2024-01-09 23:37:03 -04:00
|
|
|
#if HAL_LOGGING_ENABLED
|
2024-09-28 21:56:51 -03:00
|
|
|
AC_PosControl::Write_PSCN(0.0, target_pos.x * 100.0, blimp.pos_ned.x * 100.0, 0.0, target_vel_ef_c.x * 100.0, blimp.vel_ned_filtd.x * 100.0, 0.0, 0.0, 0.0);
|
|
|
|
AC_PosControl::Write_PSCE(0.0, target_pos.y * 100.0, blimp.pos_ned.y * 100.0, 0.0, target_vel_ef_c.y * 100.0, blimp.vel_ned_filtd.y * 100.0, 0.0, 0.0, 0.0);
|
|
|
|
AC_PosControl::Write_PSCD(0.0, -target_pos.z * 100.0, -blimp.pos_ned.z * 100.0, 0.0, -target_vel_ef_c.z * 100.0, -blimp.vel_ned_filtd.z * 100.0, 0.0, 0.0, 0.0);
|
2024-01-09 23:37:03 -04:00
|
|
|
#endif
|
2023-07-27 02:03:08 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Loiter::run_vel(Vector3f& target_vel_ef, float& target_vel_yaw, Vector4b axes_disabled)
|
|
|
|
{
|
|
|
|
const float dt = blimp.scheduler.get_last_loop_time_s();
|
|
|
|
|
|
|
|
Vector4b zero;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!blimp.motors->_armed || (blimp.g.dis_mask & (1<<(2-1)))) {
|
|
|
|
zero.x = true;
|
|
|
|
}
|
|
|
|
if (!blimp.motors->_armed || (blimp.g.dis_mask & (1<<(1-1)))) {
|
|
|
|
zero.y = true;
|
|
|
|
}
|
|
|
|
if (!blimp.motors->_armed || (blimp.g.dis_mask & (1<<(3-1)))) {
|
|
|
|
zero.z = true;
|
|
|
|
}
|
|
|
|
if (!blimp.motors->_armed || (blimp.g.dis_mask & (1<<(4-1)))) {
|
|
|
|
zero.yaw = true;
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
//Disabled means "don't update PIDs or output anything at all". Zero means actually output zero thrust. I term is limited in either case."
|
|
|
|
Vector4b limit = zero || axes_disabled;
|
|
|
|
|
|
|
|
Vector3f target_vel_ef_c{constrain_float(target_vel_ef.x, -blimp.g.max_vel_xy, blimp.g.max_vel_xy),
|
|
|
|
constrain_float(target_vel_ef.y, -blimp.g.max_vel_xy, blimp.g.max_vel_xy),
|
|
|
|
constrain_float(target_vel_ef.z, -blimp.g.max_vel_z, blimp.g.max_vel_z)};
|
|
|
|
float target_vel_yaw_c = constrain_float(target_vel_yaw, -blimp.g.max_vel_yaw, blimp.g.max_vel_yaw);
|
|
|
|
|
|
|
|
Vector2f target_vel_ef_c_scaled_xy = {target_vel_ef_c.x * scaler_xz, target_vel_ef_c.y * scaler_yyaw};
|
|
|
|
Vector2f vel_ned_filtd_scaled_xy = {blimp.vel_ned_filtd.x * scaler_xz, blimp.vel_ned_filtd.y * scaler_yyaw};
|
|
|
|
|
|
|
|
Vector2f actuator;
|
|
|
|
if (!axes_disabled.x && !axes_disabled.y) actuator = blimp.pid_vel_xy.update_all(target_vel_ef_c_scaled_xy, vel_ned_filtd_scaled_xy, dt, {(float)limit.x, (float)limit.y});
|
|
|
|
float act_down = 0;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!axes_disabled.z) {
|
|
|
|
act_down = blimp.pid_vel_z.update_all(target_vel_ef_c.z * scaler_xz, blimp.vel_ned_filtd.z * scaler_xz, dt, limit.z);
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
blimp.rotate_NE_to_BF(actuator);
|
|
|
|
float act_yaw = 0;
|
2023-08-21 08:19:19 -03:00
|
|
|
if (!axes_disabled.yaw) {
|
|
|
|
act_yaw = blimp.pid_vel_yaw.update_all(target_vel_yaw_c * scaler_yyaw, blimp.vel_yaw_filtd * scaler_yyaw, dt, limit.yaw);
|
|
|
|
}
|
2023-07-27 02:03:08 -03:00
|
|
|
|
|
|
|
if (!blimp.motors->armed()) {
|
|
|
|
blimp.pid_vel_xy.set_integrator(Vector2f(0,0));
|
|
|
|
blimp.pid_vel_z.set_integrator(0);
|
|
|
|
blimp.pid_vel_yaw.set_integrator(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zero.x) {
|
|
|
|
blimp.motors->front_out = 0;
|
|
|
|
} else if (axes_disabled.x);
|
|
|
|
else {
|
|
|
|
blimp.motors->front_out = actuator.x;
|
|
|
|
}
|
|
|
|
if (zero.y) {
|
|
|
|
blimp.motors->right_out = 0;
|
|
|
|
} else if (axes_disabled.y);
|
|
|
|
else {
|
|
|
|
blimp.motors->right_out = actuator.y;
|
|
|
|
}
|
|
|
|
if (zero.z) {
|
|
|
|
blimp.motors->down_out = 0;
|
|
|
|
} else if (axes_disabled.z);
|
|
|
|
else {
|
|
|
|
blimp.motors->down_out = act_down;
|
|
|
|
}
|
|
|
|
if (zero.yaw) {
|
|
|
|
blimp.motors->yaw_out = 0;
|
|
|
|
} else if (axes_disabled.yaw);
|
|
|
|
else {
|
|
|
|
blimp.motors->yaw_out = act_yaw;
|
|
|
|
}
|
|
|
|
|
2024-01-09 23:37:03 -04:00
|
|
|
#if HAL_LOGGING_ENABLED
|
2024-09-28 21:56:51 -03:00
|
|
|
AC_PosControl::Write_PSCN(0.0, 0.0, blimp.pos_ned.x * 100.0, 0.0, target_vel_ef_c.x * 100.0, blimp.vel_ned_filtd.x * 100.0, 0.0, 0.0, 0.0);
|
|
|
|
AC_PosControl::Write_PSCE(0.0, 0.0, blimp.pos_ned.y * 100.0, 0.0, target_vel_ef_c.y * 100.0, blimp.vel_ned_filtd.y * 100.0, 0.0, 0.0, 0.0);
|
|
|
|
AC_PosControl::Write_PSCD(0.0, 0.0, -blimp.pos_ned.z * 100.0, 0.0, -target_vel_ef_c.z * 100.0, -blimp.vel_ned_filtd.z * 100.0, 0.0, 0.0, 0.0);
|
2024-01-09 23:37:03 -04:00
|
|
|
#endif
|
2023-07-27 02:03:08 -03:00
|
|
|
}
|