123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- #include <AP_HAL/AP_HAL.h>
- #include "AC_Circle.h"
- #include <AP_Math/AP_Math.h>
- extern const AP_HAL::HAL& hal;
- const AP_Param::GroupInfo AC_Circle::var_info[] = {
-
-
-
-
-
-
-
- AP_GROUPINFO("RADIUS", 0, AC_Circle, _radius, AC_CIRCLE_RADIUS_DEFAULT),
-
-
-
-
-
-
-
- AP_GROUPINFO("RATE", 1, AC_Circle, _rate, AC_CIRCLE_RATE_DEFAULT),
- AP_GROUPEND
- };
- AC_Circle::AC_Circle(const AP_InertialNav& inav, const AP_AHRS_View& ahrs, AC_PosControl& pos_control) :
- _inav(inav),
- _ahrs(ahrs),
- _pos_control(pos_control),
- _yaw(0.0f),
- _angle(0.0f),
- _angle_total(0.0f),
- _angular_vel(0.0f),
- _angular_vel_max(0.0f),
- _angular_accel(0.0f)
- {
- AP_Param::setup_object_defaults(this, var_info);
-
- _flags.panorama = false;
- }
- void AC_Circle::init(const Vector3f& center)
- {
- _center = center;
-
- _pos_control.set_desired_accel_xy(0.0f,0.0f);
- _pos_control.set_desired_velocity_xy(0.0f,0.0f);
- _pos_control.init_xy_controller();
-
- _pos_control.set_target_to_stopping_point_xy();
- _pos_control.set_target_to_stopping_point_z();
-
- calc_velocities(true);
-
- init_start_angle(false);
- }
- void AC_Circle::init()
- {
-
- _pos_control.set_desired_accel_xy(0.0f,0.0f);
- _pos_control.set_desired_velocity_xy(0.0f,0.0f);
- _pos_control.init_xy_controller();
-
- _pos_control.set_target_to_stopping_point_xy();
- _pos_control.set_target_to_stopping_point_z();
-
- const Vector3f& stopping_point = _pos_control.get_pos_target();
-
- _center.x = stopping_point.x + _radius * _ahrs.cos_yaw();
- _center.y = stopping_point.y + _radius * _ahrs.sin_yaw();
- _center.z = stopping_point.z;
-
- calc_velocities(true);
-
- init_start_angle(true);
- }
- void AC_Circle::set_rate(float deg_per_sec)
- {
- if (!is_equal(deg_per_sec, _rate.get())) {
- _rate = deg_per_sec;
- calc_velocities(false);
- }
- }
- void AC_Circle::update()
- {
-
- float dt = _pos_control.time_since_last_xy_update();
- if (dt >= 0.2f) {
- dt = 0.0f;
- }
-
- if (_angular_vel < _angular_vel_max) {
- _angular_vel += fabsf(_angular_accel) * dt;
- _angular_vel = MIN(_angular_vel, _angular_vel_max);
- }
- if (_angular_vel > _angular_vel_max) {
- _angular_vel -= fabsf(_angular_accel) * dt;
- _angular_vel = MAX(_angular_vel, _angular_vel_max);
- }
-
- float angle_change = _angular_vel * dt;
- _angle += angle_change;
- _angle = wrap_PI(_angle);
- _angle_total += angle_change;
-
- if (!is_zero(_radius)) {
-
- Vector3f target;
- target.x = _center.x + _radius * cosf(-_angle);
- target.y = _center.y - _radius * sinf(-_angle);
- target.z = _pos_control.get_alt_target();
-
- _pos_control.set_xy_target(target.x, target.y);
-
- _yaw = get_bearing_cd(_inav.get_position(), _center);
- } else {
-
- Vector3f target;
- target.x = _center.x;
- target.y = _center.y;
- target.z = _pos_control.get_alt_target();
-
- _pos_control.set_xy_target(target.x, target.y);
-
- _yaw = _angle * DEGX100;
- }
-
- _pos_control.update_xy_controller();
- }
- void AC_Circle::get_closest_point_on_circle(Vector3f &result)
- {
-
- if (_radius <= 0) {
- result = _center;
- return;
- }
-
- Vector3f stopping_point;
- _pos_control.get_stopping_point_xy(stopping_point);
-
- Vector2f vec;
- vec.x = (stopping_point.x - _center.x);
- vec.y = (stopping_point.y - _center.y);
- float dist = norm(vec.x, vec.y);
-
- if (is_zero(dist)) {
- result.x = _center.x - _radius * _ahrs.cos_yaw();
- result.y = _center.y - _radius * _ahrs.sin_yaw();
- result.z = _center.z;
- return;
- }
-
- result.x = _center.x + vec.x / dist * _radius;
- result.y = _center.y + vec.y / dist * _radius;
- result.z = _center.z;
- }
- void AC_Circle::calc_velocities(bool init_velocity)
- {
-
- if (_radius <= 0) {
- _angular_vel_max = ToRad(_rate);
- _angular_accel = MAX(fabsf(_angular_vel_max),ToRad(AC_CIRCLE_ANGULAR_ACCEL_MIN));
- }else{
-
- float velocity_max = MIN(_pos_control.get_max_speed_xy(), safe_sqrt(0.5f*_pos_control.get_max_accel_xy()*_radius));
-
- _angular_vel_max = velocity_max/_radius;
- _angular_vel_max = constrain_float(ToRad(_rate),-_angular_vel_max,_angular_vel_max);
-
- _angular_accel = MAX(_pos_control.get_max_accel_xy()/_radius, ToRad(AC_CIRCLE_ANGULAR_ACCEL_MIN));
- }
-
- if (init_velocity) {
- _angular_vel = 0;
- }
- }
- void AC_Circle::init_start_angle(bool use_heading)
- {
-
- _angle_total = 0;
-
- if (_radius <= 0) {
- _angle = _ahrs.yaw;
- return;
- }
-
- if (use_heading) {
- _angle = wrap_PI(_ahrs.yaw-M_PI);
- } else {
-
- const Vector3f &curr_pos = _inav.get_position();
- if (is_equal(curr_pos.x,_center.x) && is_equal(curr_pos.y,_center.y)) {
- _angle = wrap_PI(_ahrs.yaw-M_PI);
- } else {
-
- float bearing_rad = atan2f(curr_pos.y-_center.y,curr_pos.x-_center.x);
- _angle = wrap_PI(bearing_rad);
- }
- }
- }
|