123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- #include <AP_HAL/AP_HAL.h>
- #include "AP_L1_Control.h"
- extern const AP_HAL::HAL& hal;
- const AP_Param::GroupInfo AP_L1_Control::var_info[] = {
-
-
-
-
-
-
-
- AP_GROUPINFO("PERIOD", 0, AP_L1_Control, _L1_period, 17),
-
-
-
-
-
-
- AP_GROUPINFO("DAMPING", 1, AP_L1_Control, _L1_damping, 0.75f),
-
-
-
-
-
-
- AP_GROUPINFO("XTRACK_I", 2, AP_L1_Control, _L1_xtrack_i_gain, 0.02),
-
-
-
-
-
-
- AP_GROUPINFO_FRAME("LIM_BANK", 3, AP_L1_Control, _loiter_bank_limit, 0.0f, AP_PARAM_FRAME_PLANE),
- AP_GROUPEND
- };
- float AP_L1_Control::get_yaw()
- {
- if (_reverse) {
- return wrap_PI(M_PI + _ahrs.yaw);
- }
- return _ahrs.yaw;
- }
- float AP_L1_Control::get_yaw_sensor()
- {
- if (_reverse) {
- return wrap_180_cd(18000 + _ahrs.yaw_sensor);
- }
- return _ahrs.yaw_sensor;
- }
- int32_t AP_L1_Control::nav_roll_cd(void) const
- {
- float ret;
- ret = cosf(_ahrs.pitch)*degrees(atanf(_latAccDem * 0.101972f) * 100.0f);
- ret = constrain_float(ret, -9000, 9000);
- return ret;
- }
- float AP_L1_Control::lateral_acceleration(void) const
- {
- return _latAccDem;
- }
- int32_t AP_L1_Control::nav_bearing_cd(void) const
- {
- return wrap_180_cd(RadiansToCentiDegrees(_nav_bearing));
- }
- int32_t AP_L1_Control::bearing_error_cd(void) const
- {
- return RadiansToCentiDegrees(_bearing_error);
- }
- int32_t AP_L1_Control::target_bearing_cd(void) const
- {
- return wrap_180_cd(_target_bearing_cd);
- }
- float AP_L1_Control::turn_distance(float wp_radius) const
- {
- wp_radius *= sq(_ahrs.get_EAS2TAS());
- return MIN(wp_radius, _L1_dist);
- }
- float AP_L1_Control::turn_distance(float wp_radius, float turn_angle) const
- {
- float distance_90 = turn_distance(wp_radius);
- turn_angle = fabsf(turn_angle);
- if (turn_angle >= 90) {
- return distance_90;
- }
- return distance_90 * turn_angle / 90.0f;
- }
- float AP_L1_Control::loiter_radius(const float radius) const
- {
-
- float sanitized_bank_limit = constrain_float(_loiter_bank_limit, 0.0f, 89.0f);
- float lateral_accel_sea_level = tanf(radians(sanitized_bank_limit)) * GRAVITY_MSS;
- float nominal_velocity_sea_level;
- if(_spdHgtControl == nullptr) {
- nominal_velocity_sea_level = 0.0f;
- } else {
- nominal_velocity_sea_level = _spdHgtControl->get_target_airspeed();
- }
- float eas2tas_sq = sq(_ahrs.get_EAS2TAS());
- if (is_zero(sanitized_bank_limit) || is_zero(nominal_velocity_sea_level) ||
- is_zero(lateral_accel_sea_level)) {
-
-
-
- return radius * eas2tas_sq;
- } else {
- float sea_level_radius = sq(nominal_velocity_sea_level) / lateral_accel_sea_level;
- if (sea_level_radius > radius) {
-
-
- return radius * eas2tas_sq;
- } else {
-
- return MAX(sea_level_radius * eas2tas_sq, radius);
- }
- }
- }
- bool AP_L1_Control::reached_loiter_target(void)
- {
- return _WPcircle;
- }
- void AP_L1_Control::_prevent_indecision(float &Nu)
- {
- const float Nu_limit = 0.9f*M_PI;
- if (fabsf(Nu) > Nu_limit &&
- fabsf(_last_Nu) > Nu_limit &&
- labs(wrap_180_cd(_target_bearing_cd - get_yaw_sensor())) > 12000 &&
- Nu * _last_Nu < 0.0f) {
-
-
-
-
- Nu = _last_Nu;
- }
- }
- void AP_L1_Control::update_waypoint(const struct Location &prev_WP, const struct Location &next_WP, float dist_min)
- {
- struct Location _current_loc;
- float Nu;
- float xtrackVel;
- float ltrackVel;
- uint32_t now = AP_HAL::micros();
- float dt = (now - _last_update_waypoint_us) * 1.0e-6f;
- if (dt > 0.1) {
- dt = 0.1;
- _L1_xtrack_i = 0.0f;
- }
- _last_update_waypoint_us = now;
-
- float K_L1 = 4.0f * _L1_damping * _L1_damping;
-
- if (_ahrs.get_position(_current_loc) == false) {
-
- _data_is_stale = true;
- return;
- }
- Vector2f _groundspeed_vector = _ahrs.groundspeed_vector();
-
- _target_bearing_cd = _current_loc.get_bearing_to(next_WP);
-
- float groundSpeed = _groundspeed_vector.length();
- if (groundSpeed < 0.1f) {
-
-
- groundSpeed = 0.1f;
- _groundspeed_vector = Vector2f(cosf(get_yaw()), sinf(get_yaw())) * groundSpeed;
- }
-
-
-
- _L1_dist = MAX(0.3183099f * _L1_damping * _L1_period * groundSpeed, dist_min);
-
- Vector2f AB = prev_WP.get_distance_NE(next_WP);
- float AB_length = AB.length();
-
-
- if (AB.length() < 1.0e-6f) {
- AB = _current_loc.get_distance_NE(next_WP);
- if (AB.length() < 1.0e-6f) {
- AB = Vector2f(cosf(get_yaw()), sinf(get_yaw()));
- }
- }
- AB.normalize();
-
- const Vector2f A_air = prev_WP.get_distance_NE(_current_loc);
-
- _crosstrack_error = A_air % AB;
-
-
-
- float WP_A_dist = A_air.length();
- float alongTrackDist = A_air * AB;
- if (WP_A_dist > _L1_dist && alongTrackDist/MAX(WP_A_dist, 1.0f) < -0.7071f)
- {
-
- Vector2f A_air_unit = (A_air).normalized();
- xtrackVel = _groundspeed_vector % (-A_air_unit);
- ltrackVel = _groundspeed_vector * (-A_air_unit);
- Nu = atan2f(xtrackVel,ltrackVel);
- _nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x);
- } else if (alongTrackDist > AB_length + groundSpeed*3) {
-
-
- const Vector2f B_air = next_WP.get_distance_NE(_current_loc);
- Vector2f B_air_unit = (B_air).normalized();
- xtrackVel = _groundspeed_vector % (-B_air_unit);
- ltrackVel = _groundspeed_vector * (-B_air_unit);
- Nu = atan2f(xtrackVel,ltrackVel);
- _nav_bearing = atan2f(-B_air_unit.y , -B_air_unit.x);
- } else {
-
- xtrackVel = _groundspeed_vector % AB;
- ltrackVel = _groundspeed_vector * AB;
- float Nu2 = atan2f(xtrackVel,ltrackVel);
-
- float sine_Nu1 = _crosstrack_error/MAX(_L1_dist, 0.1f);
-
- sine_Nu1 = constrain_float(sine_Nu1, -0.7071f, 0.7071f);
- float Nu1 = asinf(sine_Nu1);
-
-
-
- if (_L1_xtrack_i_gain <= 0 || !is_equal(_L1_xtrack_i_gain.get(), _L1_xtrack_i_gain_prev)) {
- _L1_xtrack_i = 0;
- _L1_xtrack_i_gain_prev = _L1_xtrack_i_gain;
- } else if (fabsf(Nu1) < radians(5)) {
- _L1_xtrack_i += Nu1 * _L1_xtrack_i_gain * dt;
-
- _L1_xtrack_i = constrain_float(_L1_xtrack_i, -0.1f, 0.1f);
- }
-
- Nu1 += _L1_xtrack_i;
- Nu = Nu1 + Nu2;
- _nav_bearing = atan2f(AB.y, AB.x) + Nu1;
- }
- _prevent_indecision(Nu);
- _last_Nu = Nu;
-
- Nu = constrain_float(Nu, -1.5708f, +1.5708f);
- _latAccDem = K_L1 * groundSpeed * groundSpeed / _L1_dist * sinf(Nu);
-
- _WPcircle = false;
- _bearing_error = Nu;
- _data_is_stale = false;
- }
- void AP_L1_Control::update_loiter(const struct Location ¢er_WP, float radius, int8_t loiter_direction)
- {
- struct Location _current_loc;
-
-
- radius = loiter_radius(fabsf(radius));
-
- float omega = (6.2832f / _L1_period);
- float Kx = omega * omega;
- float Kv = 2.0f * _L1_damping * omega;
-
- float K_L1 = 4.0f * _L1_damping * _L1_damping;
-
- if (_ahrs.get_position(_current_loc) == false) {
-
- _data_is_stale = true;
- return;
- }
- Vector2f _groundspeed_vector = _ahrs.groundspeed_vector();
-
- float groundSpeed = MAX(_groundspeed_vector.length() , 1.0f);
-
- _target_bearing_cd = _current_loc.get_bearing_to(center_WP);
-
-
-
- _L1_dist = 0.3183099f * _L1_damping * _L1_period * groundSpeed;
-
- const Vector2f A_air = center_WP.get_distance_NE(_current_loc);
-
-
-
-
- Vector2f A_air_unit;
- if (A_air.length() > 0.1f) {
- A_air_unit = A_air.normalized();
- } else {
- if (_groundspeed_vector.length() < 0.1f) {
- A_air_unit = Vector2f(cosf(_ahrs.yaw), sinf(_ahrs.yaw));
- } else {
- A_air_unit = _groundspeed_vector.normalized();
- }
- }
-
- float xtrackVelCap = A_air_unit % _groundspeed_vector;
- float ltrackVelCap = - (_groundspeed_vector * A_air_unit);
- float Nu = atan2f(xtrackVelCap,ltrackVelCap);
- _prevent_indecision(Nu);
- _last_Nu = Nu;
- Nu = constrain_float(Nu, -M_PI_2, M_PI_2);
-
- float latAccDemCap = K_L1 * groundSpeed * groundSpeed / _L1_dist * sinf(Nu);
-
- float xtrackVelCirc = -ltrackVelCap;
- float xtrackErrCirc = A_air.length() - radius;
-
- _crosstrack_error = xtrackErrCirc;
-
- float latAccDemCircPD = (xtrackErrCirc * Kx + xtrackVelCirc * Kv);
-
- float velTangent = xtrackVelCap * float(loiter_direction);
-
- if (ltrackVelCap < 0.0f && velTangent < 0.0f) {
- latAccDemCircPD = MAX(latAccDemCircPD, 0.0f);
- }
-
- float latAccDemCircCtr = velTangent * velTangent / MAX((0.5f * radius), (radius + xtrackErrCirc));
-
- float latAccDemCirc = loiter_direction * (latAccDemCircPD + latAccDemCircCtr);
-
-
-
- if (xtrackErrCirc > 0.0f && loiter_direction * latAccDemCap < loiter_direction * latAccDemCirc) {
- _latAccDem = latAccDemCap;
- _WPcircle = false;
- _bearing_error = Nu;
- _nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x);
- } else {
- _latAccDem = latAccDemCirc;
- _WPcircle = true;
- _bearing_error = 0.0f;
- _nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x);
- }
- _data_is_stale = false;
- }
- void AP_L1_Control::update_heading_hold(int32_t navigation_heading_cd)
- {
-
- const float omegaA = 4.4428f/_L1_period;
-
- int32_t Nu_cd;
- float Nu;
-
- _target_bearing_cd = wrap_180_cd(navigation_heading_cd);
- _nav_bearing = radians(navigation_heading_cd * 0.01f);
- Nu_cd = _target_bearing_cd - wrap_180_cd(_ahrs.yaw_sensor);
- Nu_cd = wrap_180_cd(Nu_cd);
- Nu = radians(Nu_cd * 0.01f);
- Vector2f _groundspeed_vector = _ahrs.groundspeed_vector();
-
- float groundSpeed = _groundspeed_vector.length();
-
- _L1_dist = groundSpeed / omegaA;
- float VomegaA = groundSpeed * omegaA;
-
- _WPcircle = false;
- _crosstrack_error = 0;
- _bearing_error = Nu;
-
- Nu = constrain_float(Nu, -M_PI_2, M_PI_2);
- _latAccDem = 2.0f*sinf(Nu)*VomegaA;
- _data_is_stale = false;
- }
- void AP_L1_Control::update_level_flight(void)
- {
-
- _target_bearing_cd = _ahrs.yaw_sensor;
- _nav_bearing = _ahrs.yaw;
- _bearing_error = 0;
- _crosstrack_error = 0;
-
- _WPcircle = false;
- _latAccDem = 0;
- _data_is_stale = false;
- }
|