示例#1
0
/// update_velocity_controller_xy - run the velocity controller - should be called at 100hz or higher
///     velocity targets should we set using set_desired_velocity_xy() method
///     callers should use get_roll() and get_pitch() methods and sent to the attitude controller
///     throttle targets will be sent directly to the motors
void AC_PosControl::update_vel_controller_xy(float ekfNavVelGainScaler)
{
    // capture time since last iteration
    uint32_t now = AP_HAL::millis();
    float dt = (now - _last_update_xy_ms)*0.001f;

    // call xy controller
    if (dt >= get_dt_xy()) {
        // sanity check dt
        if (dt >= 0.2f) {
            dt = 0.0f;
        }

        // check for ekf xy position reset
        check_for_ekf_xy_reset();

        // check if xy leash needs to be recalculated
        calc_leash_length_xy();

        // apply desired velocity request to position target
        desired_vel_to_pos(dt);

        // run position controller's position error to desired velocity step
        pos_to_rate_xy(XY_MODE_POS_LIMITED_AND_VEL_FF, dt, ekfNavVelGainScaler);

        // run velocity to acceleration step
        rate_to_accel_xy(dt, ekfNavVelGainScaler);

        // run acceleration to lean angle step
        accel_to_lean_angles(dt, ekfNavVelGainScaler, false);

        // update xy update time
        _last_update_xy_ms = now;
    }
}
示例#2
0
/// update_xy_controller - run the horizontal position controller - should be called at 100hz or higher
void AC_PosControl::update_xy_controller(xy_mode mode, float ekfNavVelGainScaler, bool use_althold_lean_angle)
{
    // compute dt
    uint32_t now = AP_HAL::millis();
    float dt = (now - _last_update_xy_ms)*0.001f;
    _last_update_xy_ms = now;

    // sanity check dt - expect to be called faster than ~5hz
    if (dt > POSCONTROL_ACTIVE_TIMEOUT_MS*1.0e-3f) {
        dt = 0.0f;
    }

    // check for ekf xy position reset
    check_for_ekf_xy_reset();

    // check if xy leash needs to be recalculated
    calc_leash_length_xy();

    // translate any adjustments from pilot to loiter target
    desired_vel_to_pos(dt);

    // run position controller's position error to desired velocity step
    pos_to_rate_xy(mode, dt, ekfNavVelGainScaler);

    // run position controller's velocity to acceleration step
    rate_to_accel_xy(dt, ekfNavVelGainScaler);

    // run position controller's acceleration to lean angle step
    accel_to_lean_angles(dt, ekfNavVelGainScaler, use_althold_lean_angle);
}
示例#3
0
/// update_velocity_controller_xyz - run the velocity controller - should be called at 100hz or higher
///     velocity targets should we set using set_desired_velocity_xyz() method
///     callers should use get_roll() and get_pitch() methods and sent to the attitude controller
///     throttle targets will be sent directly to the motors
void AC_PosControl::update_vel_controller_xyz(float ekfNavVelGainScaler)
{
    // capture time since last iteration
    uint32_t now = hal.scheduler->millis();
    float dt = (now - _last_update_xy_ms) / 1000.0f;

    // sanity check dt - expect to be called faster than ~5hz
    if (dt >= POSCONTROL_ACTIVE_TIMEOUT_MS*1.0e-3f) {
        dt = 0.0f;
    }

    // check if xy leash needs to be recalculated
    calc_leash_length_xy();

    // apply desired velocity request to position target
    desired_vel_to_pos(dt);

    // run position controller's position error to desired velocity step
    pos_to_rate_xy(XY_MODE_POS_LIMITED_AND_VEL_FF, dt, ekfNavVelGainScaler);

    // run velocity to acceleration step
    rate_to_accel_xy(dt, ekfNavVelGainScaler);

    // run acceleration to lean angle step
    accel_to_lean_angles(dt, ekfNavVelGainScaler, false);

    // update altitude target
    set_alt_target_from_climb_rate(_vel_desired.z, dt, false);

    // run z-axis position controller
    update_z_controller();

    // record update time
    _last_update_xy_ms = now;
}
示例#4
0
/// update_xy_controller - run the horizontal position controller - should be called at 100hz or higher
void AC_PosControl::update_xy_controller(bool use_desired_velocity)
{
    // catch if we've just been started
    uint32_t now = hal.scheduler->millis();
    if ((now - _last_update_ms) >= 1000) {
        _last_update_ms = now;
        if (!_flags.keep_xy_I_terms) {
            reset_I_xy();
        }
        _xy_step = 0;
    }
    // reset keep_xy_I_term flag in case it has been set
    _flags.keep_xy_I_terms = false;

    // check if xy leash needs to be recalculated
    calc_leash_length_xy();

    // reset step back to 0 if loiter or waypoint parents have triggered an update and we completed the last full cycle
    if (_flags.force_recalc_xy && _xy_step > 3) {
        _flags.force_recalc_xy = false;
        _xy_step = 0;
    }

    // run loiter steps
    switch (_xy_step) {
        case 0:
            // capture time since last iteration
            _dt_xy = (now - _last_update_ms) / 1000.0f;
            _last_update_ms = now;

            // translate any adjustments from pilot to loiter target
            desired_vel_to_pos(_dt_xy);
            _xy_step++;
            break;
        case 1:
            // run position controller's position error to desired velocity step
            pos_to_rate_xy(use_desired_velocity,_dt_xy);
            _xy_step++;
            break;
        case 2:
            // run position controller's velocity to acceleration step
            rate_to_accel_xy(_dt_xy);
            _xy_step++;
            break;
        case 3:
            // run position controller's acceleration to lean angle step
            accel_to_lean_angles();
            _xy_step++;
            break;
    }
}
示例#5
0
int pos_controller_old::update_controller(float dt)
{
	// if user released stick, or stick moving toward set point.
	// apply a extra braking until velocity decreased to a acceptable value, for at most 1 second.
	bool stick_released = fabs(desired_velocity_earth[0]) < 0.01f && fabs(desired_velocity_earth[1]) < 0.01f;
	if (stick_released)
		release_stick_timer += dt;
	else
		release_stick_timer = 0;

	min_braking_speed = 1.0f * 1.0f;
	float delta[2] = {setpoint[0] - pos[0], setpoint[1] - pos[1]};

	if  (	(velocity[0]*velocity[0] + velocity[1]*velocity[1] > min_braking_speed) &&					// speed fast enough(1m/s)?
			(
			  (stick_released && release_stick_timer < 1.0f)											// released stick? less than 1 second?
			  || (delta[0]*desired_velocity_earth[0] + delta[1]*desired_velocity_earth[1] < 0)			// moving toward set point?
			)
		)
	{
		// braking is based on a 0.05hz low pass filter that move set point toward current position
		float alpha = dt / (dt + 1.0f/(2*PI * 0.05f));
		setpoint[0] = alpha * pos[0] + (1-alpha) * setpoint[0];
		setpoint[1] = alpha * pos[1] + (1-alpha) * setpoint[1];
	}

	move_desire_pos(dt);

	pos_to_rate(dt);

	rate_to_accel(dt);

	accel_to_lean_angles();

#ifdef WIN32
	fprintf(f, "%.3f,%f,%f,%f,%f\r\n", (GetTickCount()-tick)/1000.0f, velocity[0],target_velocity[0], pid[0][0], pid[0][1]);
	fflush(f);
#endif

	return 0;
}
示例#6
0
/// update_velocity_controller_xyz - run the velocity controller - should be called at 100hz or higher
///     velocity targets should we set using set_desired_velocity_xyz() method
///     callers should use get_roll() and get_pitch() methods and sent to the attitude controller
///     throttle targets will be sent directly to the motors
void AC_PosControl::update_vel_controller_xyz()
{
    // capture time since last iteration
    uint32_t now = hal.scheduler->millis();
    float dt_xy = (now - _last_update_vel_xyz_ms) / 1000.0f;

    // check if xy leash needs to be recalculated
    calc_leash_length_xy();

    // we will run the horizontal component every 4th iteration (i.e. 50hz on Pixhawk, 20hz on APM)
    if (dt_xy >= POSCONTROL_VEL_UPDATE_TIME) {

        // record update time
        _last_update_vel_xyz_ms = now;

        // sanity check dt
        if (dt_xy >= POSCONTROL_ACTIVE_TIMEOUT_MS) {
            dt_xy = 0.0f;
        }

        // apply desired velocity request to position target
        desired_vel_to_pos(dt_xy);

        // run position controller's position error to desired velocity step
        pos_to_rate_xy(true, dt_xy);

        // run velocity to acceleration step
        rate_to_accel_xy(dt_xy);

        // run acceleration to lean angle step
        accel_to_lean_angles();
    }

    // update altitude target
    set_alt_target_from_climb_rate(_vel_desired.z, _dt);

    // run z-axis position controller
    update_z_controller();
}
示例#7
0
/// run horizontal position controller correcting position and velocity
///     converts position (_pos_target) to target velocity (_vel_target)
///     desired velocity (_vel_desired) is combined into final target velocity
///     converts desired velocities in lat/lon directions to accelerations in lat/lon frame
///     converts desired accelerations provided in lat/lon frame to roll/pitch angles
void AC_PosControl::run_xy_controller(float dt)
{
    float ekfGndSpdLimit, ekfNavVelGainScaler;
    AP::ahrs_navekf().getEkfControlLimits(ekfGndSpdLimit, ekfNavVelGainScaler);

    Vector3f curr_pos = _inav.get_position();
    float kP = ekfNavVelGainScaler * _p_pos_xy.kP(); // scale gains to compensate for noisy optical flow measurement in the EKF

    // avoid divide by zero
    if (kP <= 0.0f) {
        _vel_target.x = 0.0f;
        _vel_target.y = 0.0f;
    }else{
        // calculate distance error
        _pos_error.x = _pos_target.x - curr_pos.x;
        _pos_error.y = _pos_target.y - curr_pos.y;

        // Constrain _pos_error and target position
        // Constrain the maximum length of _vel_target to the maximum position correction velocity
        // TODO: replace the leash length with a user definable maximum position correction
        if (limit_vector_length(_pos_error.x, _pos_error.y, _leash))
        {
            _pos_target.x = curr_pos.x + _pos_error.x;
            _pos_target.y = curr_pos.y + _pos_error.y;
        }

        _vel_target = sqrt_controller(_pos_error, kP, _accel_cms);
    }

    // add velocity feed-forward
    _vel_target.x += _vel_desired.x;
    _vel_target.y += _vel_desired.y;

    // the following section converts desired velocities in lat/lon directions to accelerations in lat/lon frame

    Vector2f accel_target, vel_xy_p, vel_xy_i, vel_xy_d;

    // check if vehicle velocity is being overridden
    if (_flags.vehicle_horiz_vel_override) {
        _flags.vehicle_horiz_vel_override = false;
    } else {
        _vehicle_horiz_vel.x = _inav.get_velocity().x;
        _vehicle_horiz_vel.y = _inav.get_velocity().y;
    }

    // calculate velocity error
    _vel_error.x = _vel_target.x - _vehicle_horiz_vel.x;
    _vel_error.y = _vel_target.y - _vehicle_horiz_vel.y;
    // TODO: constrain velocity error and velocity target

    // call pi controller
    _pid_vel_xy.set_input(_vel_error);

    // get p
    vel_xy_p = _pid_vel_xy.get_p();

    // update i term if we have not hit the accel or throttle limits OR the i term will reduce
    // TODO: move limit handling into the PI and PID controller
    if (!_limit.accel_xy && !_motors.limit.throttle_upper) {
        vel_xy_i = _pid_vel_xy.get_i();
    } else {
        vel_xy_i = _pid_vel_xy.get_i_shrink();
    }

    // get d
    vel_xy_d = _pid_vel_xy.get_d();

    // acceleration to correct for velocity error and scale PID output to compensate for optical flow measurement induced EKF noise
    accel_target.x = (vel_xy_p.x + vel_xy_i.x + vel_xy_d.x) * ekfNavVelGainScaler;
    accel_target.y = (vel_xy_p.y + vel_xy_i.y + vel_xy_d.y) * ekfNavVelGainScaler;

    // reset accel to current desired acceleration
     if (_flags.reset_accel_to_lean_xy) {
         _accel_target_filter.reset(Vector2f(accel_target.x, accel_target.y));
         _flags.reset_accel_to_lean_xy = false;
     }

    // filter correction acceleration
    _accel_target_filter.set_cutoff_frequency(MIN(_accel_xy_filt_hz, 5.0f*ekfNavVelGainScaler));
    _accel_target_filter.apply(accel_target, dt);

    // pass the correction acceleration to the target acceleration output
    _accel_target.x = _accel_target_filter.get().x;
    _accel_target.y = _accel_target_filter.get().y;

    // Add feed forward into the target acceleration output
    _accel_target.x += _accel_desired.x;
    _accel_target.y += _accel_desired.y;

    // the following section converts desired accelerations provided in lat/lon frame to roll/pitch angles

    // limit acceleration using maximum lean angles
    float angle_max = MIN(_attitude_control.get_althold_lean_angle_max(), get_lean_angle_max_cd());
    float accel_max = MIN(GRAVITY_MSS * 100.0f * tanf(ToRad(angle_max * 0.01f)), POSCONTROL_ACCEL_XY_MAX);
    _limit.accel_xy = limit_vector_length(_accel_target.x, _accel_target.y, accel_max);

    // update angle targets that will be passed to stabilize controller
    accel_to_lean_angles(_accel_target.x, _accel_target.y, _roll_target, _pitch_target);
}