mirror of https://github.com/ArduPilot/ardupilot
Tracker: compensate for tilt while tracking
This adds an earth frame to body frame conversion which is required to convert the earth-frame angles to the target vehicle into body-frame movements of the servos
This commit is contained in:
parent
c6d3f07b5f
commit
a693f9ead6
|
@ -158,6 +158,8 @@ private:
|
|||
float bearing; // bearing to vehicle in centi-degrees
|
||||
float distance; // distance to vehicle in meters
|
||||
float pitch; // pitch to vehicle in degrees (positive means vehicle is above tracker, negative means below)
|
||||
float angle_error_pitch; // angle error between target and current pitch in centi-degrees
|
||||
float angle_error_yaw; // angle error between target and current yaw in centi-degrees
|
||||
float alt_difference_baro; // altitude difference between tracker and vehicle in meters according to the barometer. positive value means vehicle is above tracker
|
||||
float alt_difference_gps; // altitude difference between tracker and vehicle in meters according to the gps. positive value means vehicle is above tracker
|
||||
float altitude_offset; // offset in meters which is added to tracker altitude to align altitude measurements with vehicle's barometer
|
||||
|
@ -166,7 +168,7 @@ private:
|
|||
bool need_altitude_calibration : 1;// true if tracker altitude has not been determined (true after startup)
|
||||
bool scan_reverse_pitch : 1;// controls direction of pitch movement in SCAN mode
|
||||
bool scan_reverse_yaw : 1;// controls direction of yaw movement in SCAN mode
|
||||
} nav_status = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, false, false, true, false, false};
|
||||
} nav_status = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, false, false, true, false, false};
|
||||
|
||||
// setup the var_info table
|
||||
AP_Param param_loader{var_info};
|
||||
|
@ -215,11 +217,11 @@ private:
|
|||
void update_GPS(void);
|
||||
void init_servos();
|
||||
void update_pitch_servo(float pitch);
|
||||
void update_pitch_position_servo(float pitch);
|
||||
void update_pitch_position_servo(void);
|
||||
void update_pitch_cr_servo(float pitch);
|
||||
void update_pitch_onoff_servo(float pitch);
|
||||
void update_yaw_servo(float yaw);
|
||||
void update_yaw_position_servo(float yaw);
|
||||
void update_yaw_position_servo(void);
|
||||
void update_yaw_cr_servo(float yaw);
|
||||
void update_yaw_onoff_servo(float yaw);
|
||||
void init_tracker();
|
||||
|
@ -252,6 +254,8 @@ private:
|
|||
void start_logging();
|
||||
void log_init(void);
|
||||
bool should_log(uint32_t mask);
|
||||
void calc_angle_error(float pitch, float yaw);
|
||||
void calc_body_frame_target(float pitch, float yaw, float& bf_pitch, float& bf_yaw);
|
||||
|
||||
public:
|
||||
void mavlink_snoop(const mavlink_message_t* msg);
|
||||
|
|
|
@ -17,12 +17,44 @@ void Tracker::update_auto(void)
|
|||
return;
|
||||
}
|
||||
|
||||
float yaw = wrap_180_cd((nav_status.bearing+g.yaw_trim)*100) * 0.01f;
|
||||
float pitch = constrain_float(nav_status.pitch+g.pitch_trim, -90, 90);
|
||||
float yaw = wrap_180_cd((nav_status.bearing+g.yaw_trim)*100); // target yaw in centidegrees
|
||||
float pitch = constrain_float(nav_status.pitch+g.pitch_trim, -90, 90) * 100; // target pitch in centidegrees
|
||||
|
||||
calc_angle_error(pitch, yaw);
|
||||
|
||||
float bf_pitch;
|
||||
float bf_yaw;
|
||||
calc_body_frame_target(pitch, yaw, bf_pitch, bf_yaw);
|
||||
|
||||
// only move servos if target is at least distance_min away
|
||||
if ((g.distance_min <= 0) || (nav_status.distance >= g.distance_min)) {
|
||||
update_pitch_servo(pitch);
|
||||
update_yaw_servo(yaw);
|
||||
update_pitch_servo(bf_pitch);
|
||||
update_yaw_servo(bf_yaw);
|
||||
}
|
||||
}
|
||||
void Tracker::calc_angle_error( float pitch, float yaw)
|
||||
{
|
||||
// Pitch angle error in centidegrees
|
||||
// Positive error means the target is above current pitch
|
||||
// Negative error means the target is below current pitch
|
||||
float ahrs_pitch = ahrs.pitch_sensor;
|
||||
nav_status.angle_error_pitch = pitch - ahrs_pitch;
|
||||
|
||||
// Yaw angle error in centidegrees
|
||||
// Positive error means the target is right of current yaw
|
||||
// Negative error means the target is left of current yaw
|
||||
int32_t ahrs_yaw_cd = wrap_180_cd(ahrs.yaw_sensor);
|
||||
nav_status.angle_error_yaw = wrap_180_cd(yaw - ahrs_yaw_cd);
|
||||
|
||||
// earth frame to body frame angle error conversion
|
||||
float bf_pitch_err = ahrs.cos_roll() * nav_status.angle_error_pitch + ahrs.sin_roll() * ahrs.cos_pitch() * nav_status.angle_error_yaw;
|
||||
float bf_yaw_err = -ahrs.sin_roll() * nav_status.angle_error_pitch + ahrs.cos_pitch() * ahrs.cos_roll() * nav_status.angle_error_yaw;
|
||||
nav_status.angle_error_pitch = bf_pitch_err;
|
||||
nav_status.angle_error_yaw = bf_yaw_err;
|
||||
}
|
||||
void Tracker::calc_body_frame_target(float pitch, float yaw, float& bf_pitch, float& bf_yaw)
|
||||
{
|
||||
// earth frame to body frame pitch and yaw conversion
|
||||
bf_pitch = ahrs.cos_roll() * pitch + ahrs.sin_roll() * ahrs.cos_pitch() * yaw;
|
||||
bf_yaw = -ahrs.sin_roll() * pitch + ahrs.cos_pitch() * ahrs.cos_roll() * yaw;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ void Tracker::update_pitch_servo(float pitch)
|
|||
|
||||
case SERVO_TYPE_POSITION:
|
||||
default:
|
||||
update_pitch_position_servo(pitch);
|
||||
update_pitch_position_servo();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,8 @@ void Tracker::update_pitch_servo(float pitch)
|
|||
update the pitch (elevation) servo. The aim is to drive the boards ahrs pitch to the
|
||||
requested pitch, so the board (and therefore the antenna) will be pointing at the target
|
||||
*/
|
||||
void Tracker::update_pitch_position_servo(float pitch)
|
||||
void Tracker::update_pitch_position_servo()
|
||||
{
|
||||
// degrees(ahrs.pitch) is -90 to 90, where 0 is horizontal
|
||||
// pitch argument is -90 to 90, where 0 is horizontal
|
||||
// servo_out is in 100ths of a degree
|
||||
float ahrs_pitch = ahrs.pitch_sensor*0.01f;
|
||||
int32_t angle_err = -(ahrs_pitch - pitch) * 100.0f;
|
||||
int32_t pitch_min_cd = g.pitch_min*100;
|
||||
int32_t pitch_max_cd = g.pitch_max*100;
|
||||
// Need to configure your servo so that increasing servo_out causes increase in pitch/elevation (ie pointing higher into the sky,
|
||||
|
@ -79,7 +74,7 @@ void Tracker::update_pitch_position_servo(float pitch)
|
|||
// PITCH2SRV_IMAX 4000.000000
|
||||
|
||||
// calculate new servo position
|
||||
g.pidPitch2Srv.set_input_filter_all(angle_err);
|
||||
g.pidPitch2Srv.set_input_filter_all(nav_status.angle_error_pitch);
|
||||
int32_t new_servo_out = channel_pitch.get_servo_out() + g.pidPitch2Srv.get_pid();
|
||||
|
||||
// rate limit pitch servo
|
||||
|
@ -115,24 +110,19 @@ void Tracker::update_pitch_position_servo(float pitch)
|
|||
*/
|
||||
void Tracker::update_pitch_onoff_servo(float pitch)
|
||||
{
|
||||
// degrees(ahrs.pitch) is -90 to 90, where 0 is horizontal
|
||||
// pitch argument is -90 to 90, where 0 is horizontal
|
||||
// get_servo_out() is in 100ths of a degree
|
||||
float ahrs_pitch = degrees(ahrs.pitch);
|
||||
float err = ahrs_pitch - pitch;
|
||||
int32_t pitch_min_cd = g.pitch_min*100;
|
||||
int32_t pitch_max_cd = g.pitch_max*100;
|
||||
|
||||
float acceptable_error = g.onoff_pitch_rate * g.onoff_pitch_mintime;
|
||||
if (fabsf(err) < acceptable_error) {
|
||||
if (fabsf(nav_status.angle_error_pitch) < acceptable_error) {
|
||||
channel_pitch.set_servo_out(0);
|
||||
} else if ((err > 0) && (pitch*100>pitch_min_cd)) {
|
||||
// positive error means we are pointing too high, so push the
|
||||
// servo down
|
||||
} else if ((nav_status.angle_error_pitch > 0) && (pitch*100>pitch_min_cd)) {
|
||||
// positive error means we are pointing too low, so push the
|
||||
// servo up
|
||||
channel_pitch.set_servo_out(-9000);
|
||||
} else if (pitch*100<pitch_max_cd){
|
||||
// negative error means we are pointing too low, so push the
|
||||
// servo up
|
||||
// negative error means we are pointing too high, so push the
|
||||
// servo down
|
||||
channel_pitch.set_servo_out(9000);
|
||||
}
|
||||
}
|
||||
|
@ -142,12 +132,10 @@ void Tracker::update_pitch_onoff_servo(float pitch)
|
|||
*/
|
||||
void Tracker::update_pitch_cr_servo(float pitch)
|
||||
{
|
||||
float ahrs_pitch = degrees(ahrs.pitch);
|
||||
float err_cd = (pitch - ahrs_pitch) * 100.0f;
|
||||
int32_t pitch_min_cd = g.pitch_min*100;
|
||||
int32_t pitch_max_cd = g.pitch_max*100;
|
||||
if ((pitch>pitch_min_cd) && (pitch<pitch_max_cd)){
|
||||
g.pidPitch2Srv.set_input_filter_all(err_cd);
|
||||
g.pidPitch2Srv.set_input_filter_all(nav_status.angle_error_pitch);
|
||||
channel_pitch.set_servo_out(g.pidPitch2Srv.get_pid());
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +156,7 @@ void Tracker::update_yaw_servo(float yaw)
|
|||
|
||||
case SERVO_TYPE_POSITION:
|
||||
default:
|
||||
update_yaw_position_servo(yaw);
|
||||
update_yaw_position_servo();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -182,10 +170,8 @@ void Tracker::update_yaw_servo(float yaw)
|
|||
yaw to the requested yaw, so the board (and therefore the antenna)
|
||||
will be pointing at the target
|
||||
*/
|
||||
void Tracker::update_yaw_position_servo(float yaw)
|
||||
void Tracker::update_yaw_position_servo()
|
||||
{
|
||||
int32_t ahrs_yaw_cd = wrap_180_cd(ahrs.yaw_sensor);
|
||||
int32_t yaw_cd = wrap_180_cd(yaw*100);
|
||||
int32_t yaw_limit_cd = g.yaw_range*100/2;
|
||||
const int16_t margin = MAX(500, wrap_360_cd(36000-yaw_limit_cd)/2);
|
||||
|
||||
|
@ -209,11 +195,10 @@ void Tracker::update_yaw_position_servo(float yaw)
|
|||
// param set RC1_MIN 680
|
||||
// According to the specs at https://www.servocity.com/html/hs-645mg_ultra_torque.html,
|
||||
// that should be 600 through 2400, but the azimuth gearing in my antenna pointer is not exactly 2:1
|
||||
int32_t angle_err = wrap_180_cd(ahrs_yaw_cd - yaw_cd);
|
||||
|
||||
/*
|
||||
a positive error means that we need to rotate counter-clockwise
|
||||
a negative error means that we need to rotate clockwise
|
||||
a positive error means that we need to rotate clockwise
|
||||
a negative error means that we need to rotate counter-clockwise
|
||||
|
||||
Use our current yawspeed to determine if we are moving in the
|
||||
right direction
|
||||
|
@ -228,12 +213,12 @@ void Tracker::update_yaw_position_servo(float yaw)
|
|||
if (slew_dir != 0) {
|
||||
making_progress = (-slew_dir * earth_rotation.z >= 0);
|
||||
} else {
|
||||
making_progress = (angle_err * earth_rotation.z >= 0);
|
||||
making_progress = (nav_status.angle_error_yaw * earth_rotation.z <= 0);
|
||||
}
|
||||
|
||||
// handle hitting servo limits
|
||||
if (abs(channel_yaw.get_servo_out()) == 18000 &&
|
||||
labs(angle_err) > margin &&
|
||||
labs(nav_status.angle_error_yaw) > margin &&
|
||||
making_progress &&
|
||||
AP_HAL::millis() - slew_start_ms > g.min_reverse_time*1000) {
|
||||
// we are at the limit of the servo and are not moving in the
|
||||
|
@ -246,14 +231,14 @@ void Tracker::update_yaw_position_servo(float yaw)
|
|||
stop slewing and revert to normal control when normal control
|
||||
should move us in the right direction
|
||||
*/
|
||||
if (slew_dir * angle_err < -margin) {
|
||||
if (slew_dir * nav_status.angle_error_yaw > margin) {
|
||||
new_slew_dir = 0;
|
||||
}
|
||||
|
||||
if (new_slew_dir != slew_dir) {
|
||||
tracker.gcs_send_text_fmt(MAV_SEVERITY_WARNING, "Slew: %d/%d err=%ld servo=%ld ez=%.3f",
|
||||
(int)slew_dir, (int)new_slew_dir,
|
||||
(long)angle_err,
|
||||
(long)nav_status.angle_error_yaw,
|
||||
(long)channel_yaw.get_servo_out(),
|
||||
(double)degrees(ahrs.get_gyro().z));
|
||||
}
|
||||
|
@ -264,10 +249,10 @@ void Tracker::update_yaw_position_servo(float yaw)
|
|||
new_servo_out = slew_dir * 18000;
|
||||
g.pidYaw2Srv.reset_I();
|
||||
} else {
|
||||
g.pidYaw2Srv.set_input_filter_all(angle_err);
|
||||
g.pidYaw2Srv.set_input_filter_all(nav_status.angle_error_yaw);
|
||||
float servo_change = g.pidYaw2Srv.get_pid();
|
||||
servo_change = constrain_float(servo_change, -18000, 18000);
|
||||
new_servo_out = constrain_float(channel_yaw.get_servo_out() - servo_change, -18000, 18000);
|
||||
new_servo_out = constrain_float(channel_yaw.get_servo_out() + servo_change, -18000, 18000);
|
||||
}
|
||||
|
||||
// rate limit yaw servo
|
||||
|
@ -304,22 +289,17 @@ void Tracker::update_yaw_position_servo(float yaw)
|
|||
*/
|
||||
void Tracker::update_yaw_onoff_servo(float yaw)
|
||||
{
|
||||
int32_t ahrs_yaw_cd = wrap_180_cd(ahrs.yaw_sensor);
|
||||
int32_t yaw_cd = wrap_180_cd(yaw*100);
|
||||
int32_t err_cd = wrap_180_cd(ahrs_yaw_cd - yaw_cd);
|
||||
float err = err_cd * 0.01f;
|
||||
|
||||
float acceptable_error = g.onoff_yaw_rate * g.onoff_yaw_mintime;
|
||||
if (fabsf(err) < acceptable_error) {
|
||||
if (fabsf(nav_status.angle_error_yaw * 0.01f) < acceptable_error) {
|
||||
channel_yaw.set_servo_out(0);
|
||||
} else if (err > 0) {
|
||||
// positive error means we are clockwise of the target, so
|
||||
// move anti-clockwise
|
||||
channel_yaw.set_servo_out(-18000);
|
||||
} else {
|
||||
// negative error means we are anti-clockwise of the target, so
|
||||
} else if (nav_status.angle_error_yaw * 0.01f > 0) {
|
||||
// positive error means we are counter-clockwise of the target, so
|
||||
// move clockwise
|
||||
channel_yaw.set_servo_out(18000);
|
||||
} else {
|
||||
// negative error means we are clockwise of the target, so
|
||||
// move counter-clockwise
|
||||
channel_yaw.set_servo_out(-18000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +308,6 @@ void Tracker::update_yaw_onoff_servo(float yaw)
|
|||
*/
|
||||
void Tracker::update_yaw_cr_servo(float yaw)
|
||||
{
|
||||
int32_t ahrs_yaw_cd = wrap_180_cd(ahrs.yaw_sensor);
|
||||
float yaw_cd = wrap_180_cd(yaw*100.0f);
|
||||
float err_cd = wrap_180_cd(yaw_cd - (float)ahrs_yaw_cd);
|
||||
|
||||
g.pidYaw2Srv.set_input_filter_all(err_cd);
|
||||
channel_yaw.set_servo_out(g.pidYaw2Srv.get_pid());
|
||||
g.pidYaw2Srv.set_input_filter_all(nav_status.angle_error_yaw);
|
||||
channel_yaw.set_servo_out(-g.pidYaw2Srv.get_pid());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue