void ModeSmartRTL::update()
{
    switch (smart_rtl_state) {
        case SmartRTL_WaitForPathCleanup:
            // check if return path is computed and if yes, begin journey home
            if (g2.smart_rtl.request_thorough_cleanup()) {
                smart_rtl_state = SmartRTL_PathFollow;
                _load_point = true;
            }
            // Note: this may lead to an unnecessary 20ms slow down of the vehicle (but it is unlikely)
            stop_vehicle();
            break;

        case SmartRTL_PathFollow:
            // load point if required
            if (_load_point) {
                Vector3f next_point;
                if (!g2.smart_rtl.pop_point(next_point)) {
                    // if not more points, we have reached home
                    gcs().send_text(MAV_SEVERITY_INFO, "Reached destination");
                    smart_rtl_state = SmartRTL_StopAtHome;
                    break;
                }
                _load_point = false;
                // set target destination to new point
                if (!set_desired_location_NED(next_point)) {
                    // this failure should never happen but we add it just in case
                    gcs().send_text(MAV_SEVERITY_INFO, "SmartRTL: failed to set destination");
                    smart_rtl_state = SmartRTL_Failure;
                }
            }
            // check if we've reached the next point
            _distance_to_destination = get_distance(rover.current_loc, _destination);
            if (_distance_to_destination <= rover.g.waypoint_radius || location_passed_point(rover.current_loc, _origin, _destination)) {
                _load_point = true;
            }
            // continue driving towards destination
            calc_steering_to_waypoint(_origin, _destination);
            calc_throttle(calc_reduced_speed_for_turn_or_distance(_desired_speed), true);
            break;

        case SmartRTL_StopAtHome:
        case SmartRTL_Failure:
            _reached_destination = true;
            if (rover.is_boat()) {
                // boats attempt to hold position at home
                calc_steering_to_waypoint(rover.current_loc, _destination);
                calc_throttle(calc_reduced_speed_for_turn_or_distance(_desired_speed), true);
            } else {
                // rovers stop
                stop_vehicle();
            }
            break;
    }
}
Example #2
0
/*
  main handling for AUTO mode
 */
void Plane::handle_auto_mode(void)
{
    uint16_t nav_cmd_id;

    if (mission.state() != AP_Mission::MISSION_RUNNING) {
        // this should never be reached
        set_mode(RTL);
        GCS_MAVLINK::send_statustext_all(MAV_SEVERITY_INFO, "Aircraft in auto without a running mission");
        return;
    }

    nav_cmd_id = mission.get_current_nav_cmd().id;

    if (quadplane.in_vtol_auto()) {
        quadplane.control_auto(next_WP_loc);
    } else if (nav_cmd_id == MAV_CMD_NAV_TAKEOFF ||
        (nav_cmd_id == MAV_CMD_NAV_LAND && flight_stage == AP_SpdHgtControl::FLIGHT_LAND_ABORT)) {
        takeoff_calc_roll();
        takeoff_calc_pitch();
        calc_throttle();
    } else if (nav_cmd_id == MAV_CMD_NAV_LAND) {
        calc_nav_roll();
        calc_nav_pitch();
        
        if (auto_state.land_complete) {
            // during final approach constrain roll to the range
            // allowed for level flight
            nav_roll_cd = constrain_int32(nav_roll_cd, -g.level_roll_limit*100UL, g.level_roll_limit*100UL);
        }
        calc_throttle();
        
        if (auto_state.land_complete) {
            // we are in the final stage of a landing - force
            // zero throttle
            channel_throttle->set_servo_out(0);
        }
    } else {
        // we are doing normal AUTO flight, the special cases
        // are for takeoff and landing
        if (nav_cmd_id != MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT) {
            steer_state.hold_course_cd = -1;
        }
        auto_state.land_complete = false;
        auto_state.land_pre_flare = false;
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
    }
}
Example #3
0
/*
  main handling for AUTO mode
 */
void Plane::handle_auto_mode(void)
{
    uint8_t nav_cmd_id;

    // we should be either running a mission or RTLing home
    if (mission.state() == AP_Mission::MISSION_RUNNING) {
        nav_cmd_id = mission.get_current_nav_cmd().id;
    }else{
        nav_cmd_id = auto_rtl_command.id;
    }

    switch(nav_cmd_id) {
    case MAV_CMD_NAV_TAKEOFF:
        takeoff_calc_roll();
        takeoff_calc_pitch();
        calc_throttle();

        break;

    case MAV_CMD_NAV_LAND:
        calc_nav_roll();
        calc_nav_pitch();
        
        if (auto_state.land_complete) {
            // during final approach constrain roll to the range
            // allowed for level flight
            nav_roll_cd = constrain_int32(nav_roll_cd, -g.level_roll_limit*100UL, g.level_roll_limit*100UL);
        }
        calc_throttle();
        
        if (auto_state.land_complete) {
            // we are in the final stage of a landing - force
            // zero throttle
            channel_throttle->servo_out = 0;
        }
        break;
        
    default:
        // we are doing normal AUTO flight, the special cases
        // are for takeoff and landing
        steer_state.hold_course_cd = -1;
        auto_state.land_complete = false;
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
        break;
    }
}
Example #4
0
void ModeLoiter::update()
{
    // get distance (in meters) to destination
    _distance_to_destination = get_distance(rover.current_loc, _destination);

    // if within waypoint radius slew desired speed towards zero and use existing desired heading
    if (_distance_to_destination <= g.waypoint_radius) {
        _desired_speed = attitude_control.get_desired_speed_accel_limited(0.0f, rover.G_Dt);
        _yaw_error_cd = 0.0f;
    } else {
        // P controller with hard-coded gain to convert distance to desired speed
        // To-Do: make gain configurable or calculate from attitude controller's maximum accelearation
        _desired_speed = MIN((_distance_to_destination - g.waypoint_radius) * 0.5f, g.speed_cruise);

        // calculate bearing to destination
        _desired_yaw_cd = get_bearing_cd(rover.current_loc, _destination);
        _yaw_error_cd = wrap_180_cd(_desired_yaw_cd - ahrs.yaw_sensor);
        // if destination is behind vehicle, reverse towards it
        if (fabsf(_yaw_error_cd) > 9000 && g2.loit_type == 0) {
            _desired_yaw_cd = wrap_180_cd(_desired_yaw_cd + 18000);
            _yaw_error_cd = wrap_180_cd(_desired_yaw_cd - ahrs.yaw_sensor);
            _desired_speed = -_desired_speed;
        }

        // reduce desired speed if yaw_error is large
        // 45deg of error reduces speed to 75%, 90deg of error reduces speed to 50%
        float yaw_error_ratio = 1.0f - constrain_float(fabsf(_yaw_error_cd / 9000.0f), 0.0f, 1.0f) * 0.5f;
        _desired_speed *= yaw_error_ratio;
    }

    // run steering and throttle controllers
    calc_steering_to_heading(_desired_yaw_cd);
    calc_throttle(_desired_speed, false, true);
}
Example #5
0
/*
  handle speed and height control in FBWB or CRUISE mode. 
  In this mode the elevator is used to change target altitude. The
  throttle is used to change target airspeed or throttle
 */
void Plane::update_fbwb_speed_height(void)
{
    static float last_elevator_input;
    float elevator_input;
    elevator_input = channel_pitch->control_in / 4500.0f;
    
    if (g.flybywire_elev_reverse) {
        elevator_input = -elevator_input;
    }
    
    change_target_altitude(g.flybywire_climb_rate * elevator_input * delta_us_fast_loop * 0.0001f);
    
    if (is_zero(elevator_input) && !is_zero(last_elevator_input)) {
        // the user has just released the elevator, lock in
        // the current altitude
        set_target_altitude_current();
    }

    // check for FBWB altitude limit
    check_minimum_altitude();

    altitude_error_cm = calc_altitude_error_cm();
    
    last_elevator_input = elevator_input;
    
    calc_throttle();
    calc_nav_pitch();
}
Example #6
0
// output_armed - sends commands to the motors
void AP_MotorsVtol::output_armed()
{
    int16_t motor_out[VTOL_NUMBERS_OF_MOTORS + VTOL_NUMBERS_OF_SERVOS];
    float transition_factor = get_transition_progress();

    for (uint8_t i = 0; i < VTOL_NUMBERS_OF_MOTORS + VTOL_NUMBERS_OF_SERVOS; i++)
    {
        motor_out[i] = 0;
    }

    set_throttle_limits();

    // capture desired roll, pitch, yaw and throttle from receiver
    _rc_roll.calc_pwm();
    _rc_pitch.calc_pwm();
    _rc_yaw.calc_pwm();
    _rc_throttle.calc_pwm();

    calc_throttle(motor_out);
    calc_vertical_roll_pitch(motor_out, transition_factor);
    calc_horizontal_roll_pitch(motor_out, transition_factor);
    calc_yaw_and_transition(motor_out, transition_factor);

    output_motors(motor_out);
}
Example #7
0
void Rover::do_yaw(const AP_Mission::Mission_Command& cmd)
{
    // Only support target yaw for now
    condition_start = condition_value;  // save condition_value from current navigation wp loaded
    // get final angle, 1 = Relative, 0 = Absolute
    if (cmd.content.yaw.relative_angle == 0) {
        // absolute angle
        condition_value = cmd.content.yaw.angle_deg * 100;
    } else {
        // relative angle
        condition_value = cmd.content.yaw.angle_deg * 100;
        if (cmd.content.yaw.direction < 0) {
            condition_value = -condition_value;
        }

        condition_value = condition_value + ahrs.yaw_sensor;
    }

    // absolute angle error
    const int32_t error_to_target_yaw = abs((condition_value - ahrs.yaw_sensor));

    // Calculate the steering to apply base on error calculated
    const int32_t steering = steerController.get_steering_out_angle_error(error_to_target_yaw);
    SRV_Channels::set_output_scaled(SRV_Channel::k_steering, steering);
    next_navigation_leg_cd = condition_value;
    calc_throttle(g.speed_cruise);

    do_auto_rotation = true;
}
Example #8
0
void Rover::nav_set_speed()
{
    // if we haven't received a MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED message within the last 3 seconds bring the rover to a halt
    if ((millis() - guided_control.msg_time_ms) > 3000) {
        gcs_send_text(MAV_SEVERITY_WARNING, "SET_VELOCITY not recvd last 3secs, stopping");
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, g.throttle_min.get());
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, 0);
        lateral_acceleration = 0.0f;
        prev_WP = current_loc;
        next_WP = current_loc;
        set_guided_WP(current_loc);  // exit Guided_Velocity to prevent spam
        return;
    }
    prev_WP = current_loc;
    next_WP = current_loc;

    const int32_t steer_value = steerController.get_steering_out_rate(guided_control.target_steer_speed);
    location_update(next_WP, (steer_value + ahrs.yaw_sensor) * 0.01f, 4.0f);  // put the next wp at 4m forward at steer direction
    nav_controller->update_waypoint(current_loc, next_WP);

    SRV_Channels::set_output_scaled(SRV_Channel::k_steering, steer_value);
    calc_throttle(guided_control.target_speed);

    Log_Write_GuidedTarget(guided_mode, Vector3f(steer_value, 0.0f, 0.0f), Vector3f(guided_control.target_speed, 0.0f, 0.0f));
}
Example #9
0
/*
  main handling for AUTO mode
 */
void Plane::handle_auto_mode(void)
{
    uint16_t nav_cmd_id;

    if (mission.state() != AP_Mission::MISSION_RUNNING) {
        // this could happen if AP_Landing::restart_landing_sequence() returns false which would only happen if:
        // restart_landing_sequence() is called when not executing a NAV_LAND or there is no previous nav point
        set_mode(RTL, MODE_REASON_MISSION_END);
        GCS_MAVLINK::send_statustext_all(MAV_SEVERITY_INFO, "Aircraft in auto without a running mission");
        return;
    }

    nav_cmd_id = mission.get_current_nav_cmd().id;

    if (quadplane.in_vtol_auto()) {
        quadplane.control_auto(next_WP_loc);
    } else if (nav_cmd_id == MAV_CMD_NAV_TAKEOFF ||
        (nav_cmd_id == MAV_CMD_NAV_LAND && flight_stage == AP_SpdHgtControl::FLIGHT_LAND_ABORT)) {
        takeoff_calc_roll();
        takeoff_calc_pitch();
        calc_throttle();
    } else if (nav_cmd_id == MAV_CMD_NAV_LAND) {
        calc_nav_roll();
        calc_nav_pitch();
        
        if (landing.is_complete()) {
            // during final approach constrain roll to the range
            // allowed for level flight
            nav_roll_cd = constrain_int32(nav_roll_cd, -g.level_roll_limit*100UL, g.level_roll_limit*100UL);

            // we are in the final stage of a landing - force
            // zero throttle
            channel_throttle->set_servo_out(0);
        } else {
            calc_throttle();
        }
    } else {
        // we are doing normal AUTO flight, the special cases
        // are for takeoff and landing
        if (nav_cmd_id != MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT) {
            steer_state.hold_course_cd = -1;
        }
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
    }
}
Example #10
0
/*
  main handling for AUTO mode
 */
void Plane::handle_auto_mode(void)
{
    uint16_t nav_cmd_id;

    // we should be either running a mission or RTLing home
    if (mission.state() == AP_Mission::MISSION_RUNNING) {
        nav_cmd_id = mission.get_current_nav_cmd().id;
    }else{
        nav_cmd_id = auto_rtl_command.id;
    }

    if (quadplane.in_vtol_auto()) {
        quadplane.control_auto(next_WP_loc);
    } else if (nav_cmd_id == MAV_CMD_NAV_TAKEOFF ||
        (nav_cmd_id == MAV_CMD_NAV_LAND && flight_stage == AP_SpdHgtControl::FLIGHT_LAND_ABORT)) {
        takeoff_calc_roll();
        takeoff_calc_pitch();
        calc_throttle();
    } else if (nav_cmd_id == MAV_CMD_NAV_LAND) {
        calc_nav_roll();
        calc_nav_pitch();
        
        if (auto_state.land_complete) {
            // during final approach constrain roll to the range
            // allowed for level flight
            nav_roll_cd = constrain_int32(nav_roll_cd, -g.level_roll_limit*100UL, g.level_roll_limit*100UL);
        }
        calc_throttle();
        
        if (auto_state.land_complete) {
            // we are in the final stage of a landing - force
            // zero throttle
            channel_throttle->servo_out = 0;
        }
    } else {
        // we are doing normal AUTO flight, the special cases
        // are for takeoff and landing
        if (nav_cmd_id != MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT) {
            steer_state.hold_course_cd = -1;
        }
        auto_state.land_complete = false;
        auto_state.land_pre_flare = false;
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
    }
}
Example #11
0
/*
  main handling for AUTO mode
 */
void Plane::handle_auto_mode(void)
{
    uint16_t nav_cmd_id;

    if (mission.state() != AP_Mission::MISSION_RUNNING) {
        // this could happen if AP_Landing::restart_landing_sequence() returns false which would only happen if:
        // restart_landing_sequence() is called when not executing a NAV_LAND or there is no previous nav point
        set_mode(RTL, MODE_REASON_MISSION_END);
        gcs().send_text(MAV_SEVERITY_INFO, "Aircraft in auto without a running mission");
        return;
    }

    nav_cmd_id = mission.get_current_nav_cmd().id;

    if (quadplane.in_vtol_auto()) {
        quadplane.control_auto(next_WP_loc);
    } else if (nav_cmd_id == MAV_CMD_NAV_TAKEOFF ||
        (nav_cmd_id == MAV_CMD_NAV_LAND && flight_stage == AP_Vehicle::FixedWing::FLIGHT_ABORT_LAND)) {
        takeoff_calc_roll();
        takeoff_calc_pitch();
        calc_throttle();
    } else if (nav_cmd_id == MAV_CMD_NAV_LAND) {
        calc_nav_roll();
        calc_nav_pitch();
        
        // allow landing to restrict the roll limits
        nav_roll_cd = landing.constrain_roll(nav_roll_cd, g.level_roll_limit*100UL);

        if (landing.is_throttle_suppressed()) {
            // if landing is considered complete throttle is never allowed, regardless of landing type
            SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 0);
        } else {
            calc_throttle();
        }
    } else {
        // we are doing normal AUTO flight, the special cases
        // are for takeoff and landing
        if (nav_cmd_id != MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT) {
            steer_state.hold_course_cd = -1;
        }
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
    }
}
Example #12
0
void ModeSteering::update()
{
    float desired_steering, desired_throttle;
    get_pilot_desired_steering_and_throttle(desired_steering, desired_throttle);

    // convert pilot throttle input to desired speed (up to twice the cruise speed)
    const float target_speed = desired_throttle * 0.01f * calc_speed_max(g.speed_cruise, g.throttle_cruise * 0.01f);

    // get speed forward
    float speed;
    if (!attitude_control.get_forward_speed(speed)) {
        // no valid speed so stop
        g2.motors.set_throttle(0.0f);
        g2.motors.set_steering(0.0f);
        _desired_lat_accel = 0.0f;
        return;
    }

    // determine if pilot is requesting pivot turn
    bool is_pivot_turning = g2.motors.have_skid_steering() && is_zero(target_speed) && (!is_zero(desired_steering));

    // In steering mode we control lateral acceleration directly.
    // For pivot steering vehicles we use the TURN_MAX_G parameter
    // For regular steering vehicles we use the maximum lateral acceleration at full steering lock for this speed: V^2/R where R is the radius of turn.
    float max_g_force;
    if (is_pivot_turning) {
        max_g_force = g.turn_max_g * GRAVITY_MSS;
    } else {
        max_g_force = speed * speed / MAX(g2.turn_radius, 0.1f);
    }

    // constrain to user set TURN_MAX_G
    max_g_force = constrain_float(max_g_force, 0.1f, g.turn_max_g * GRAVITY_MSS);

    // convert pilot steering input to desired lateral acceleration
    _desired_lat_accel = max_g_force * (desired_steering / 4500.0f);

    // reverse target lateral acceleration if backing up
    bool reversed = false;
    if (is_negative(target_speed)) {
        reversed = true;
        _desired_lat_accel = -_desired_lat_accel;
    }

    // mark us as in_reverse when using a negative throttle
    rover.set_reverse(reversed);

    // run speed to throttle output controller
    if (is_zero(target_speed) && !is_pivot_turning) {
        stop_vehicle();
    } else {
        // run lateral acceleration to steering controller
        calc_steering_from_lateral_acceleration(false);
        calc_throttle(target_speed, false);
    }
}
Example #13
0
void ModeAcro::update()
{
    // get speed forward
    float speed, desired_steering;
    if (!attitude_control.get_forward_speed(speed)) {
        float desired_throttle;
        // convert pilot stick input into desired steering and throttle
        get_pilot_desired_steering_and_throttle(desired_steering, desired_throttle);
        // no valid speed, just use the provided throttle
        g2.motors.set_throttle(desired_throttle);
    } else {
        float desired_speed;
        // convert pilot stick input into desired steering and speed
        get_pilot_desired_steering_and_speed(desired_steering, desired_speed);
        calc_throttle(desired_speed, true);
    }

    float steering_out;

    // handle sailboats
    if (!is_zero(desired_steering)) {
        // steering input return control to user
        rover.sailboat_clear_tack();
    }
    if (g2.motors.has_sail() && rover.sailboat_tacking()) {
        // call heading controller during tacking
        steering_out = attitude_control.get_steering_out_heading(rover.sailboat_get_tack_heading_rad(),
                                                                 g2.wp_nav.get_pivot_rate(),
                                                                 g2.motors.limit.steer_left,
                                                                 g2.motors.limit.steer_right,
                                                                 rover.G_Dt);
    } else {
        // convert pilot steering input to desired turn rate in radians/sec
        const float target_turn_rate = (desired_steering / 4500.0f) * radians(g2.acro_turn_rate);

        // run steering turn rate controller and throttle controller
        steering_out = attitude_control.get_steering_out_rate(target_turn_rate,
                                                              g2.motors.limit.steer_left,
                                                              g2.motors.limit.steer_right,
                                                              rover.G_Dt);
    }

    set_steering(steering_out * 4500.0f);
}
Example #14
0
void ModeSteering::update()
{
    // convert pilot throttle input to desired speed (up to twice the cruise speed)
    float target_speed = channel_throttle->get_control_in() * 0.01f * calc_speed_max(g.speed_cruise, g.throttle_cruise * 0.01f);

    // get speed forward
    float speed;
    if (!attitude_control.get_forward_speed(speed)) {
        // no valid speed so stop
        g2.motors.set_throttle(0.0f);
        g2.motors.set_steering(0.0f);
        lateral_acceleration = 0.0f;
        return;
    }

    // in steering mode we control lateral acceleration directly. We first calculate the maximum lateral
    // acceleration at full steering lock for this speed. That is V^2/R where R is the radius of turn.
    float max_g_force = speed * speed / MAX(g2.turn_radius, 0.1f);

    // constrain to user set TURN_MAX_G
    max_g_force = constrain_float(max_g_force, 0.1f, g.turn_max_g * GRAVITY_MSS);

    // convert pilot steering input to desired lateral acceleration
    lateral_acceleration = max_g_force * (channel_steer->get_control_in() / 4500.0f);

    // reverse target lateral acceleration if backing up
    bool reversed = false;
    if (is_negative(target_speed)) {
        reversed = true;
        lateral_acceleration = -lateral_acceleration;
    }

    // mark us as in_reverse when using a negative throttle
    rover.set_reverse(reversed);

    // run speed to throttle output controller
    if (is_zero(target_speed)) {
        stop_vehicle();
    } else {
        // run steering controller
        calc_nav_steer(reversed);
        calc_throttle(target_speed, false);
    }
}
Example #15
0
void ModeLoiter::update()
{
    // get distance (in meters) to destination
    _distance_to_destination = get_distance(rover.current_loc, _destination);

    // if within waypoint radius slew desired speed towards zero and use existing desired heading
    if (_distance_to_destination <= g.waypoint_radius) {
        if (is_negative(_desired_speed)) {
            _desired_speed = MIN(_desired_speed + attitude_control.get_accel_max() * rover.G_Dt, 0.0f);
        } else {
            _desired_speed = MAX(_desired_speed - attitude_control.get_accel_max() * rover.G_Dt, 0.0f);
        }
        _yaw_error_cd = 0.0f;
    } else {
        // P controller with hard-coded gain to convert distance to desired speed
        // To-Do: make gain configurable or calculate from attitude controller's maximum accelearation
        _desired_speed = MIN((_distance_to_destination - g.waypoint_radius) * 0.5f, g.speed_cruise);

        // calculate bearing to destination
        _desired_yaw_cd = get_bearing_cd(rover.current_loc, _destination);
        _yaw_error_cd = wrap_180_cd(_desired_yaw_cd - ahrs.yaw_sensor);
        // if destination is behind vehicle, reverse towards it
        if (fabsf(_yaw_error_cd) > 9000) {
            _desired_yaw_cd = wrap_180_cd(_desired_yaw_cd + 18000);
            _yaw_error_cd = wrap_180_cd(_desired_yaw_cd - ahrs.yaw_sensor);
            _desired_speed = -_desired_speed;
        }

        // reduce desired speed if yaw_error is large
        // note: copied from calc_reduced_speed_for_turn_or_distance
        float yaw_error_ratio = 1.0f - constrain_float(fabsf(_yaw_error_cd / 9000.0f), 0.0f, 1.0f) * ((100.0f - g.speed_turn_gain) * 0.01f);
        _desired_speed *= yaw_error_ratio;
    }

    // run steering and throttle controllers
    calc_steering_to_heading(_desired_yaw_cd, _desired_speed < 0);
    calc_throttle(_desired_speed, false, true);

    // mark us as in_reverse when using a negative throttle
    // To-Do: only in reverse if vehicle is actually travelling backwards?
    rover.set_reverse(_desired_speed < 0);
}
Example #16
0
void ModeRTL::update()
{
    if (!_reached_destination || rover.is_boat()) {
        // calculate distance to home
        _distance_to_destination = get_distance(rover.current_loc, _destination);
        // check if we've reached the destination
        if (!_reached_destination && (_distance_to_destination <= rover.g.waypoint_radius || location_passed_point(rover.current_loc, _origin, _destination))) {
            // trigger reached
            _reached_destination = true;
            gcs().send_text(MAV_SEVERITY_INFO, "Reached destination");
        }
        // continue driving towards destination
        calc_steering_to_waypoint(_reached_destination ? rover.current_loc :_origin, _destination);
        calc_throttle(calc_reduced_speed_for_turn_or_distance(_desired_speed), true);
    } else {
        // we've reached destination so stop
        stop_vehicle();
        _desired_lat_accel = 0.0f;
    }
}
Example #17
0
void ModeRTL::update()
{
    // calculate distance to home
    _distance_to_destination = rover.current_loc.get_distance(_destination);
    const bool near_wp = _distance_to_destination <= rover.g.waypoint_radius;
    // check if we've reached the destination
    if (!_reached_destination && (near_wp || location_passed_point(rover.current_loc, _origin, _destination))) {
        // trigger reached
        _reached_destination = true;
        gcs().send_text(MAV_SEVERITY_INFO, "Reached destination");
    }
    // determine if we should keep navigating
    if (!_reached_destination || (rover.is_boat() && !near_wp)) {
        // continue driving towards destination
        calc_steering_to_waypoint(_reached_destination ? rover.current_loc :_origin, _destination, _reversed);
        calc_throttle(calc_reduced_speed_for_turn_or_distance(_reversed ? -_desired_speed : _desired_speed), true, true);
    } else {
        // we've reached destination so stop
        stop_vehicle();
    }
}
Example #18
0
void Rover::nav_set_yaw_speed()
{
    // if we haven't received a MAV_CMD_NAV_SET_YAW_SPEED message within the last 3 seconds bring the rover to a halt
    if ((millis() - guided_control.msg_time_ms) > 3000) {
        gcs_send_text(MAV_SEVERITY_WARNING, "NAV_SET_YAW_SPEED not recvd last 3secs, stopping");
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, g.throttle_min.get());
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, 0);
        lateral_acceleration = 0.0f;
        return;
    }

    const int32_t steering = steerController.get_steering_out_angle_error(guided_control.turn_angle);
    SRV_Channels::set_output_scaled(SRV_Channel::k_steering, steering);

    // speed param in the message gives speed as a proportion of cruise speed.
    // 0.5 would set speed to the cruise speed
    // 1 is double the cruise speed.
    const float target_speed = g.speed_cruise * guided_control.target_speed * 2.0f;
    calc_throttle(target_speed);

    Log_Write_GuidedTarget(guided_mode, Vector3f(steering, 0.0f, 0.0f), Vector3f(target_speed, 0.0f, 0.0f));
}
Example #19
0
bool Rover::do_yaw_rotation()
{
    // absolute angle error
    const int32_t error_to_target_yaw = abs(condition_value - ahrs.yaw_sensor);

    // check if we are within 5 degrees of the target heading
    if (error_to_target_yaw <= 500) {
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, 0);  // stop the current rotation
        condition_value = condition_start;  // reset the condition value to its previous value
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 0);
        next_navigation_leg_cd = mission.get_next_ground_course_cd(0);
        do_auto_rotation = false;
        return true;
    } else {
        // Calculate the steering to apply base on error calculated
        const int32_t steering = steerController.get_steering_out_angle_error(error_to_target_yaw);
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, steering);
        calc_throttle(g.speed_cruise);
        do_auto_rotation = true;
        return false;
    }
}
void Rover::nav_set_yaw_speed()
{
    // if we haven't received a MAV_CMD_NAV_SET_YAW_SPEED message within the last 3 seconds bring the rover to a halt
    if ((millis() - guided_yaw_speed.msg_time_ms) > 3000)
    {
        gcs_send_text(MAV_SEVERITY_WARNING, "NAV_SET_YAW_SPEED not recvd last 3secs, stopping");
        channel_throttle->set_servo_out(g.throttle_min.get());
        channel_steer->set_servo_out(0);
        lateral_acceleration = 0;
        return;
    }

    channel_steer->set_servo_out(steerController.get_steering_out_angle_error(guided_yaw_speed.turn_angle));

    // speed param in the message gives speed as a proportion of cruise speed.
    // 0.5 would set speed to the cruise speed
    // 1 is double the cruise speed.
    float target_speed = g.speed_cruise * guided_yaw_speed.target_speed * 2;
    calc_throttle(target_speed);

    return;
}
Example #21
0
void ModeSimple::update()
{
    float desired_heading_cd, desired_speed;

    // get pilot input
    get_pilot_desired_heading_and_speed(desired_heading_cd, desired_speed);

    // rotate heading around based on initial heading
    if (g2.simple_type == Simple_InitialHeading) {
        desired_heading_cd = wrap_360_cd(_initial_heading_cd + desired_heading_cd);
    }

    // if sticks in middle, use previous desired heading (important when vehicle is slowing down)
    if (!is_positive(desired_speed)) {
        desired_heading_cd = _desired_heading_cd;
    } else {
        // record desired heading for next iteration
        _desired_heading_cd = desired_heading_cd;
    }

    // run throttle and steering controllers
    calc_steering_to_heading(desired_heading_cd);
    calc_throttle(desired_speed, true);
}
Example #22
0
/*
  handle speed and height control in FBWB or CRUISE mode. 
  In this mode the elevator is used to change target altitude. The
  throttle is used to change target airspeed or throttle
 */
void Plane::update_fbwb_speed_height(void)
{
    uint32_t now = micros();
    if (now - target_altitude.last_elev_check_us >= 100000) {
        // we don't run this on every loop as it would give too small granularity on quadplanes at 300Hz, and
        // give below 1cm altitude change, which would result in no climb or descent
        float dt = (now - target_altitude.last_elev_check_us) * 1.0e-6;
        dt = constrain_float(dt, 0.1, 0.15);

        target_altitude.last_elev_check_us = now;
        
        float elevator_input = channel_pitch->get_control_in() / 4500.0f;
    
        if (g.flybywire_elev_reverse) {
            elevator_input = -elevator_input;
        }

        int32_t alt_change_cm = g.flybywire_climb_rate * elevator_input * dt * 100;
        change_target_altitude(alt_change_cm);
        
        if (is_zero(elevator_input) && !is_zero(target_altitude.last_elevator_input)) {
            // the user has just released the elevator, lock in
            // the current altitude
            set_target_altitude_current();
        }
        
        target_altitude.last_elevator_input = elevator_input;
    }
    
    check_fbwb_minimum_altitude();

    altitude_error_cm = calc_altitude_error_cm();
    
    calc_throttle();
    calc_nav_pitch();
}
Example #23
0
/*
  main flight mode dependent update code 
 */
void Plane::update_flight_mode(void)
{
    enum FlightMode effective_mode = control_mode;
    if (control_mode == AUTO && g.auto_fbw_steer == 42) {
        effective_mode = FLY_BY_WIRE_A;
    }

    if (effective_mode != AUTO) {
        // hold_course is only used in takeoff and landing
        steer_state.hold_course_cd = -1;
    }

    // ensure we are fly-forward when we are flying as a pure fixed
    // wing aircraft. This helps the EKF produce better state
    // estimates as it can make stronger assumptions
    if (quadplane.in_vtol_mode() ||
        quadplane.in_assisted_flight()) {
        ahrs.set_fly_forward(false);
    } else if (flight_stage == AP_Vehicle::FixedWing::FLIGHT_LAND) {
        ahrs.set_fly_forward(landing.is_flying_forward());
    } else {
        ahrs.set_fly_forward(true);
    }

    switch (effective_mode) 
    {
    case AUTO:
        handle_auto_mode();
        break;

    case AVOID_ADSB:
    case GUIDED:
        if (auto_state.vtol_loiter && quadplane.available()) {
            quadplane.guided_update();
            break;
        }
        FALLTHROUGH;

    case RTL:
    case LOITER:
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
        break;
        
    case TRAINING: {
        training_manual_roll = false;
        training_manual_pitch = false;
        update_load_factor();
        
        // if the roll is past the set roll limit, then
        // we set target roll to the limit
        if (ahrs.roll_sensor >= roll_limit_cd) {
            nav_roll_cd = roll_limit_cd;
        } else if (ahrs.roll_sensor <= -roll_limit_cd) {
            nav_roll_cd = -roll_limit_cd;                
        } else {
            training_manual_roll = true;
            nav_roll_cd = 0;
        }
        
        // if the pitch is past the set pitch limits, then
        // we set target pitch to the limit
        if (ahrs.pitch_sensor >= aparm.pitch_limit_max_cd) {
            nav_pitch_cd = aparm.pitch_limit_max_cd;
        } else if (ahrs.pitch_sensor <= pitch_limit_min_cd) {
            nav_pitch_cd = pitch_limit_min_cd;
        } else {
            training_manual_pitch = true;
            nav_pitch_cd = 0;
        }
        if (fly_inverted()) {
            nav_pitch_cd = -nav_pitch_cd;
        }
        break;
    }

    case ACRO: {
        // handle locked/unlocked control
        if (acro_state.locked_roll) {
            nav_roll_cd = acro_state.locked_roll_err;
        } else {
            nav_roll_cd = ahrs.roll_sensor;
        }
        if (acro_state.locked_pitch) {
            nav_pitch_cd = acro_state.locked_pitch_cd;
        } else {
            nav_pitch_cd = ahrs.pitch_sensor;
        }
        break;
    }

    case AUTOTUNE:
    case FLY_BY_WIRE_A: {
        // set nav_roll and nav_pitch using sticks
        nav_roll_cd  = channel_roll->norm_input() * roll_limit_cd;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
        update_load_factor();
        float pitch_input = channel_pitch->norm_input();
        if (pitch_input > 0) {
            nav_pitch_cd = pitch_input * aparm.pitch_limit_max_cd;
        } else {
            nav_pitch_cd = -(pitch_input * pitch_limit_min_cd);
        }
        adjust_nav_pitch_throttle();
        nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
        if (fly_inverted()) {
            nav_pitch_cd = -nav_pitch_cd;
        }
        if (failsafe.rc_failsafe && g.fs_action_short == FS_ACTION_SHORT_FBWA) {
            // FBWA failsafe glide
            nav_roll_cd = 0;
            nav_pitch_cd = 0;
            SRV_Channels::set_output_limit(SRV_Channel::k_throttle, SRV_Channel::SRV_CHANNEL_LIMIT_MIN);
        }
        if (g.fbwa_tdrag_chan > 0) {
            // check for the user enabling FBWA taildrag takeoff mode
            bool tdrag_mode = (RC_Channels::get_radio_in(g.fbwa_tdrag_chan-1) > 1700);
            if (tdrag_mode && !auto_state.fbwa_tdrag_takeoff_mode) {
                if (auto_state.highest_airspeed < g.takeoff_tdrag_speed1) {
                    auto_state.fbwa_tdrag_takeoff_mode = true;
                    gcs().send_text(MAV_SEVERITY_WARNING, "FBWA tdrag mode");
                }
            }
        }
        break;
    }

    case FLY_BY_WIRE_B:
        // Thanks to Yury MonZon for the altitude limit code!
        nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
        update_load_factor();
        update_fbwb_speed_height();
        break;
        
    case CRUISE:
        /*
          in CRUISE mode we use the navigation code to control
          roll when heading is locked. Heading becomes unlocked on
          any aileron or rudder input
        */
        if (channel_roll->get_control_in() != 0 || channel_rudder->get_control_in() != 0) {
            cruise_state.locked_heading = false;
            cruise_state.lock_timer_ms = 0;
        }                 
        
        if (!cruise_state.locked_heading) {
            nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
            nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
            update_load_factor();
        } else {
            calc_nav_roll();
        }
        update_fbwb_speed_height();
        break;
        
    case STABILIZE:
        nav_roll_cd        = 0;
        nav_pitch_cd       = 0;
        // throttle is passthrough
        break;
        
    case CIRCLE:
        // we have no GPS installed and have lost radio contact
        // or we just want to fly around in a gentle circle w/o GPS,
        // holding altitude at the altitude we set when we
        // switched into the mode
        nav_roll_cd  = roll_limit_cd / 3;
        update_load_factor();
        calc_nav_pitch();
        calc_throttle();
        break;

    case MANUAL:
        SRV_Channels::set_output_scaled(SRV_Channel::k_aileron, channel_roll->get_control_in_zero_dz());
        SRV_Channels::set_output_scaled(SRV_Channel::k_elevator, channel_pitch->get_control_in_zero_dz());
        steering_control.steering = steering_control.rudder = channel_rudder->get_control_in_zero_dz();
        break;

    case QSTABILIZE:
    case QHOVER:
    case QLOITER:
    case QLAND:
    case QRTL: {
        // set nav_roll and nav_pitch using sticks
        int16_t roll_limit = MIN(roll_limit_cd, quadplane.aparm.angle_max);
        float pitch_input = channel_pitch->norm_input();

        // Scale from normalized input [-1,1] to centidegrees
        if (quadplane.tailsitter_active()) {
            // separate limit for tailsitter roll, if set
            if (quadplane.tailsitter.max_roll_angle > 0) {
                roll_limit = quadplane.tailsitter.max_roll_angle * 100.0f;
            }

            // angle max for tailsitter pitch
            nav_pitch_cd = pitch_input * quadplane.aparm.angle_max;
        } else {
            // pitch is further constrained by LIM_PITCH_MIN/MAX which may impose
            // tighter (possibly asymmetrical) limits than Q_ANGLE_MAX
            if (pitch_input > 0) {
                nav_pitch_cd = pitch_input * MIN(aparm.pitch_limit_max_cd, quadplane.aparm.angle_max);
            } else {
                nav_pitch_cd = pitch_input * MIN(-pitch_limit_min_cd, quadplane.aparm.angle_max);
            }
            nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
        }

        nav_roll_cd  = (channel_roll->get_control_in() / 4500.0) * roll_limit;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit, roll_limit);

        break;
    }
        
    case INITIALISING:
        // handled elsewhere
        break;
    }
}
static void *control_loop(void *arg)
{
	// Set thread name
	prctl(1, "fixedwing_control attitude", getpid());

	control_outputs.mode = HIL_MODE + 16;
	control_outputs.nav_mode = 0;

	while (1) {

		/************************************
		 * Read global data structures here
		 ************************************/

		// Get parameters
		get_parameters();

#define MUTE
#ifndef MUTE
		///// DEBUG OUTPUT ////////

//		printf("Throttle: \tChannel %i\t Value %i\n", global_data_rc_channels->function[THROTTLE], global_data_rc_channels->chan[global_data_rc_channels->function[THROTTLE]].scale);
//		printf("Throttle_correct: \tChannel %i\t Value %i\n", THROTTLE, global_data_rc_channels->chan[THROTTLE].scale);
//		printf("Override: Channel %i\t Value %i\n", global_data_rc_channels->function[OVERRIDE], global_data_rc_channels->chan[global_data_rc_channels->function[OVERRIDE]].scale);
//		printf("Override_correct: \tChannel %i\t Value %i\n", OVERRIDE, global_data_rc_channels->chan[OVERRIDE].scale);

		printf("Parameter: %i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i \n", (int)plane_data.Kp_att, (int)plane_data.Ki_att,
		       (int)plane_data.Kd_att, (int)plane_data.intmax_att, (int)plane_data.Kp_pos, (int)plane_data.Ki_pos,
		       (int)plane_data.Kd_pos, (int)plane_data.intmax_pos, (int)plane_data.airspeed,
		       (int)plane_data.wp_x, (int)plane_data.wp_y, (int)plane_data.wp_z);

//		printf("PITCH SETPOINT: %i\n", (int)plane_data.pitch_setpoint);
//		printf("ROLL SETPOINT: %i\n", (int)plane_data.roll_setpoint);
//		printf("THROTTLE SETPOINT: %i\n", (int)calc_throttle_setpoint());

		printf("\n\nVx: %i\t Vy: %i\t Current speed:%i\n\n", (int)plane_data.vx, (int)plane_data.vy, (int)(calc_gnd_speed()));

		printf("Current Altitude: %i\n\n", (int)plane_data.alt);

		printf("\nAttitude values: \n R:%i \n P: %i \n Y: %i \n\n RS: %i \n PS: %i \n YS: %i \n ",
		       (int)(1000 * plane_data.roll), (int)(1000 * plane_data.pitch), (int)(1000 * plane_data.yaw),
		       (int)(1000 * plane_data.rollspeed), (int)(1000 * plane_data.pitchspeed), (int)(1000 * plane_data.yawspeed));

		printf("\nBody Rates: \n P: %i \n Q: %i \n R: %i \n",
		       (int)(10000 * plane_data.p), (int)(10000 * plane_data.q), (int)(10000 * plane_data.r));

		printf("\nCalculated outputs: \n R: %i\n P: %i\n Y: %i\n T: %i \n",
		       (int)(10000 * control_outputs.roll_ailerons), (int)(10000 * control_outputs.pitch_elevator),
		       (int)(10000 * control_outputs.yaw_rudder), (int)(10000 * control_outputs.throttle));

//		printf("\nGlobal attitude outputs \n, %i\n%i\n%i\n", global_data_fixedwing_control->attitude_control_output[ROLL],
//			global_data_fixedwing_control->attitude_control_output[PITCH], global_data_fixedwing_control->attitude_control_output[THROTTLE]);

		///////////////////////////

#endif

		// position values

		if (global_data_trylock(&global_pos.access_conf) == 0) {
			plane_data.lat = global_pos.lat / 10000000;
			plane_data.lon = global_pos.lon / 10000000;
			plane_data.alt = global_pos.alt / 1000;
			plane_data.vx = global_pos.vx / 100;
			plane_data.vy = global_pos.vy / 100;
			plane_data.vz = global_pos.vz / 100;
		}

		global_data_unlock(&global_pos.access_conf);

		// attitude values

		if (global_data_trylock(&att.access_conf) == 0) {
			plane_data.roll = att.roll;
			plane_data.pitch = att.pitch;
			plane_data.yaw = att.yaw;
			plane_data.hdg = att.yaw - 180;
			plane_data.rollspeed = att.rollspeed;
			plane_data.pitchspeed = att.pitchspeed;
			plane_data.yawspeed = att.yawspeed;
		}

		global_data_unlock(&att.access_conf);

		// Set plane mode
		set_plane_mode();

		// Calculate the P,Q,R body rates of the aircraft
		calc_body_angular_rates(plane_data.roll / RAD2DEG, plane_data.pitch / RAD2DEG, plane_data.yaw / RAD2DEG,
					plane_data.rollspeed, plane_data.pitchspeed, plane_data.yawspeed);

		// Calculate the body frame angles of the aircraft
		//calc_bodyframe_angles(plane_data.roll/RAD2DEG,plane_data.pitch/RAD2DEG,plane_data.yaw/RAD2DEG);

		// Calculate the output values
		control_outputs.roll_ailerons = calc_roll_ail();
		control_outputs.pitch_elevator = calc_pitch_elev();
		//control_outputs.yaw_rudder = calc_yaw_rudder();
		control_outputs.throttle = calc_throttle();


		/*******************************************
		 * Send data to global data structure
		 ******************************************/

		if (global_data_rc_channels->chan[global_data_rc_channels->function[OVERRIDE]].scale < MANUAL) { // if we're flying in automated mode

			if (plane_data.mode == TAKEOFF) {
				global_data_fixedwing_control->attitude_control_output[ROLL] = 0;
				global_data_fixedwing_control->attitude_control_output[PITCH] = 5000;
				global_data_fixedwing_control->attitude_control_output[THROTTLE] = 10000;
				//global_data_fixedwing_control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder);
			}

			if (plane_data.mode == CRUISE) {
				global_data_fixedwing_control->attitude_control_output[ROLL] = (int16_t)(10000 * control_outputs.roll_ailerons);
				global_data_fixedwing_control->attitude_control_output[PITCH] = (int16_t)(10000 * control_outputs.pitch_elevator);
				global_data_fixedwing_control->attitude_control_output[THROTTLE] = (int16_t)(10000 * control_outputs.throttle);
				//global_data_fixedwing_control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder);
			}

			global_data_fixedwing_control->counter++;
			global_data_fixedwing_control->timestamp = hrt_absolute_time();

#error Either publish here or above, not at two locations
			orb_publish()
		}

		// 20 Hz loop
		usleep(100000);
	}

	return NULL;
}
int fixedwing_control_main(int argc, char *argv[])
{
    /* default values for arguments */
    char *fixedwing_uart_name = "/dev/ttyS1";
    char *commandline_usage = "\tusage: %s -d fixedwing-devicename\n";

    /* read arguments */
    bool verbose = false;

    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) {
            if (argc > i + 1) {
                fixedwing_uart_name = argv[i + 1];

            } else {
                printf(commandline_usage, argv[0]);
                return 0;
            }
        }
        if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
            verbose = true;
        }
    }

    /* welcome user */
    printf("[fixedwing control] started\n");

    /* Set up to publish fixed wing control messages */
    struct fixedwing_control_s control;
    int fixedwing_control_pub = orb_advertise(ORB_ID(fixedwing_control), &control);

    /* Subscribe to global position, attitude and rc */
    struct vehicle_global_position_s global_pos;
    int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
    struct vehicle_attitude_s att;
    int attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
    struct rc_channels_s rc;
    int rc_sub = orb_subscribe(ORB_ID(rc_channels));
    struct vehicle_global_position_setpoint_s global_setpoint;
    int global_setpoint_sub = orb_subscribe(ORB_ID(vehicle_global_position_setpoint));

    /* Mainloop setup */
    unsigned int loopcounter = 0;
    unsigned int failcounter = 0;

    /* Control constants */
    control_outputs.mode = HIL_MODE;
    control_outputs.nav_mode = 0;

    /* Servo setup */

    int fd;
    servo_position_t data[PWM_OUTPUT_MAX_CHANNELS];

    fd = open("/dev/pwm_servo", O_RDWR);

    if (fd < 0) {
        printf("[fixedwing control] Failed opening /dev/pwm_servo\n");
    }

    ioctl(fd, PWM_SERVO_ARM, 0);

    int16_t buffer_rc[3];
    int16_t buffer_servo[3];
    mixer_data_t mixer_buffer;
    mixer_buffer.input  = buffer_rc;
    mixer_buffer.output = buffer_servo;

    mixer_conf_t mixers[3];

    mixers[0].source = PITCH;
    mixers[0].nr_actuators = 2;
    mixers[0].dest[0] = AIL_1;
    mixers[0].dest[1] = AIL_2;
    mixers[0].dual_rate[0] = 1;
    mixers[0].dual_rate[1] = 1;

    mixers[1].source = ROLL;
    mixers[1].nr_actuators = 2;
    mixers[1].dest[0] = AIL_1;
    mixers[1].dest[1] = AIL_2;
    mixers[1].dual_rate[0] = 1;
    mixers[1].dual_rate[1] = -1;

    mixers[2].source = THROTTLE;
    mixers[2].nr_actuators = 1;
    mixers[2].dest[0] = MOT;
    mixers[2].dual_rate[0] = 1;

    /*
     * Main control, navigation and servo routine
     */

    while(1) {
        /*
         * DATA Handling
         * Fetch current flight data
         */

        /* get position, attitude and rc inputs */
        // XXX add error checking
        orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos);
        orb_copy(ORB_ID(vehicle_global_position_setpoint), global_setpoint_sub, &global_setpoint);
        orb_copy(ORB_ID(vehicle_attitude), attitude_sub, &att);
        orb_copy(ORB_ID(rc_channels), rc_sub, &rc);

        /* scaling factors are defined by the data from the APM Planner
         * TODO: ifdef for other parameters (HIL/Real world switch)
         */

        /* position values*/
        plane_data.lat = global_pos.lat; /// 10000000.0;
        plane_data.lon = global_pos.lon; /// 10000000.0;
        plane_data.alt = global_pos.alt; /// 1000.0f;
        plane_data.vx = global_pos.vx / 100.0f;
        plane_data.vy = global_pos.vy / 100.0f;
        plane_data.vz = global_pos.vz / 100.0f;

        /* attitude values*/
        plane_data.roll = att.roll;
        plane_data.pitch = att.pitch;
        plane_data.yaw = att.yaw;
        plane_data.rollspeed = att.rollspeed;
        plane_data.pitchspeed = att.pitchspeed;
        plane_data.yawspeed = att.yawspeed;

        /* parameter values */
        get_parameters(&plane_data, &pid_s);

        /* Attitude control part */

        if (verbose && loopcounter % 20 == 0) {
            /******************************** DEBUG OUTPUT ************************************************************/

            printf("Parameter: %i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i \n", (int)pid_s.Kp_att, (int)pid_s.Ki_att,
                   (int)pid_s.Kd_att, (int)pid_s.intmax_att, (int)pid_s.Kp_pos, (int)pid_s.Ki_pos,
                   (int)pid_s.Kd_pos, (int)pid_s.intmax_pos, (int)plane_data.airspeed,
                   (int)plane_data.wp_x, (int)plane_data.wp_y, (int)plane_data.wp_z,
                   (int)global_data_parameter_storage->pm.param_values[PARAM_WPLON],
                   (int)global_data_parameter_storage->pm.param_values[PARAM_WPLAT],
                   (int)global_data_parameter_storage->pm.param_values[PARAM_WPALT],
                   global_setpoint.lat,
                   global_setpoint.lon,
                   (int)global_setpoint.altitude);

            printf("PITCH SETPOINT: %i\n", (int)(100.0f*plane_data.pitch_setpoint));
            printf("ROLL SETPOINT: %i\n", (int)(100.0f*plane_data.roll_setpoint));
            printf("THROTTLE SETPOINT: %i\n", (int)(100.0f*plane_data.throttle_setpoint));

            printf("\n\nVx: %i\t Vy: %i\t Current speed:%i\n\n", (int)plane_data.vx, (int)plane_data.vy, (int)(calc_gnd_speed(&plane_data)));

            printf("Current Position: \n %i \n %i \n %i \n", (int)plane_data.lat, (int)plane_data.lon, (int)plane_data.alt);

            printf("\nAttitude values: \n R:%i \n P: %i \n Y: %i \n\n RS: %i \n PS: %i \n YS: %i \n ",
                   (int)(180.0f * plane_data.roll/F_M_PI), (int)(180.0f * plane_data.pitch/F_M_PI), (int)(180.0f * plane_data.yaw/F_M_PI),
                   (int)(180.0f * plane_data.rollspeed/F_M_PI), (int)(180.0f * plane_data.pitchspeed/F_M_PI), (int)(180.0f * plane_data.yawspeed)/F_M_PI);

            printf("\nCalculated outputs: \n R: %i\n P: %i\n Y: %i\n T: %i \n",
                   (int)(10000.0f * control_outputs.roll_ailerons), (int)(10000.0f * control_outputs.pitch_elevator),
                   (int)(10000.0f * control_outputs.yaw_rudder), (int)(10000.0f * control_outputs.throttle));

            /************************************************************************************************************/
        }

        /*
         * Computation section
         *
         * The function calls to compute the required control values happen
         * in this section.
         */

        /* Set plane mode */
        set_plane_mode(&plane_data);

        /* Calculate the output values */
        control_outputs.roll_ailerons = calc_roll_ail(&plane_data, &pid_s);
        control_outputs.pitch_elevator = calc_pitch_elev(&plane_data, &pid_s);
        control_outputs.yaw_rudder = calc_yaw_rudder(&plane_data, &pid_s);
        control_outputs.throttle = calc_throttle(&plane_data, &pid_s);

        /*
         * Calculate rotation matrices
         */
        calc_rotation_matrix(&rmatrix_att, plane_data.roll, plane_data.pitch, plane_data.yaw);
        calc_rotation_matrix(&rmatrix_c, control_outputs.roll_ailerons, control_outputs.pitch_elevator, control_outputs.yaw_rudder);

        multiply_matrices(&rmatrix_att, &rmatrix_c, &rmatrix_b);

        calc_angles_from_rotation_matrix(&rmatrix_b, plane_data.rollb, plane_data.pitchb, plane_data.yawb);


        // TODO: fix RC input
        //if (rc.chan[rc.function[OVERRIDE]].scale < MANUAL) { // if we're flying in automated mode

        /*
         * TAKEOFF hack for HIL
         */
        if (plane_data.mode == TAKEOFF) {
            control.attitude_control_output[ROLL] = 0;
            control.attitude_control_output[PITCH] = 5000;
            control.attitude_control_output[THROTTLE] = 10000;
            //global_data_fixedwing_control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder);
        }

        if (plane_data.mode == CRUISE) {

            // TODO: substitute output with the body angles (rollb, pitchb)
            control.attitude_control_output[ROLL] = control_outputs.roll_ailerons;
            control.attitude_control_output[PITCH] = control_outputs.pitch_elevator;
            control.attitude_control_output[THROTTLE] = control_outputs.throttle;
            //control->attitude_control_output[YAW] = (int16_t)(control_outputs.yaw_rudder);
        }

        control.counter++;
        control.timestamp = hrt_absolute_time();
        //}

        /* Navigation part */

        /*
         * TODO: APM Planner Waypoint communication
         */
        // Get GPS Waypoint

        //	plane_data.wp_x = global_setpoint.lon;
        //	plane_data.wp_y = global_setpoint.lat;
        //	plane_data.wp_z = global_setpoint.altitude;

        /*
         * TODO: fix RC input
         */
        //if (rc.chan[rc.function[OVERRIDE]].scale < MANUAL) {	// AUTO mode
        // AUTO/HYBRID switch

        //if (rc.chan[rc.function[OVERRIDE]].scale < AUTO) {
        plane_data.roll_setpoint = calc_roll_setpoint(35.0f, &plane_data);
        plane_data.pitch_setpoint = calc_pitch_setpoint(35.0f, &plane_data);
        plane_data.throttle_setpoint = calc_throttle_setpoint(&plane_data);

//			} else {
//				plane_data.roll_setpoint = rc.chan[rc.function[ROLL]].scale / 200;
//				plane_data.pitch_setpoint = rc.chan[rc.function[PITCH]].scale / 200;
//				plane_data.throttle_setpoint = rc.chan[rc.function[THROTTLE]].scale / 200;
//			}

        //control_outputs.yaw_rudder = calc_yaw_rudder(plane_data.hdg);

//		} else {
//			control.attitude_control_output[ROLL] = rc.chan[rc.function[ROLL]].scale/10000;
//			control.attitude_control_output[PITCH] = rc.chan[rc.function[PITCH]].scale/10000;
//			control.attitude_control_output[THROTTLE] = rc.chan[rc.function[THROTTLE]].scale/10000;
        // since we don't have a yaw rudder
        //control.attitude_control_output[YAW] = rc.chan[rc.function[YAW]].scale/10000;

        control.counter++;
        control.timestamp = hrt_absolute_time();
        //}

        /* publish the control data */

        orb_publish(ORB_ID(fixedwing_control), fixedwing_control_pub, &control);

        /* Servo part */

        buffer_rc[ROLL] = (int16_t)(10000*control.attitude_control_output[ROLL]);
        buffer_rc[PITCH] = (int16_t)(10000*control.attitude_control_output[PITCH]);
        buffer_rc[THROTTLE] = (int16_t)(10000*control.attitude_control_output[THROTTLE]);

        //mix_and_link(mixers, 3, 2, &mixer_buffer);

        // Scaling and saturation of servo outputs happens here

        data[AIL_1] = buffer_servo[AIL_1] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE]
                      + global_data_parameter_storage->pm.param_values[PARAM_SERVO1_TRIM];

        if (data[AIL_1] > SERVO_MAX)
            data[AIL_1] = SERVO_MAX;

        if (data[AIL_1] < SERVO_MIN)
            data[AIL_1] = SERVO_MIN;

        data[AIL_2] = buffer_servo[AIL_2] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE]
                      + global_data_parameter_storage->pm.param_values[PARAM_SERVO2_TRIM];

        if (data[AIL_2] > SERVO_MAX)
            data[AIL_2] = SERVO_MAX;

        if (data[AIL_2] < SERVO_MIN)
            data[AIL_2] = SERVO_MIN;

        data[MOT] = buffer_servo[MOT] / global_data_parameter_storage->pm.param_values[PARAM_SERVO_SCALE]
                    + global_data_parameter_storage->pm.param_values[PARAM_SERVO3_TRIM];

        if (data[MOT] > SERVO_MAX)
            data[MOT] = SERVO_MAX;

        if (data[MOT] < SERVO_MIN)
            data[MOT] = SERVO_MIN;

        int result = write(fd, &data, sizeof(data));

        if (result != sizeof(data)) {
            if (failcounter < 10 || failcounter % 20 == 0) {
                printf("[fixedwing_control] failed writing servo outputs\n");
            }
            failcounter++;
        }

        loopcounter++;

        /* 20Hz loop*/
        usleep(50000);
    }

    return 0;
}
Example #26
0
void ModeGuided::update()
{
    switch (_guided_mode) {
        case Guided_WP:
        {
            if (!_reached_destination || rover.is_boat()) {
                // check if we've reached the destination
                _distance_to_destination = get_distance(rover.current_loc, _destination);
                if (!_reached_destination && (_distance_to_destination <= rover.g.waypoint_radius || location_passed_point(rover.current_loc, _origin, _destination))) {
                    _reached_destination = true;
                    rover.gcs().send_mission_item_reached_message(0);
                }
                // drive towards destination
                calc_steering_to_waypoint(_reached_destination ? rover.current_loc : _origin, _destination);
                calc_throttle(calc_reduced_speed_for_turn_or_distance(_desired_speed), true);
            } else {
                stop_vehicle();
            }
            break;
        }

        case Guided_HeadingAndSpeed:
        {
            // stop vehicle if target not updated within 3 seconds
            if (have_attitude_target && (millis() - _des_att_time_ms) > 3000) {
                gcs().send_text(MAV_SEVERITY_WARNING, "target not received last 3secs, stopping");
                have_attitude_target = false;
            }
            if (have_attitude_target) {
                // run steering and throttle controllers
                const float yaw_error = wrap_PI(radians((_desired_yaw_cd - ahrs.yaw_sensor) * 0.01f));
                const float steering_out = attitude_control.get_steering_out_angle_error(yaw_error, g2.motors.have_skid_steering(), g2.motors.limit.steer_left, g2.motors.limit.steer_right, _desired_speed < 0);
                g2.motors.set_steering(steering_out * 4500.0f);
                calc_throttle(_desired_speed, true);
            } else {
                stop_vehicle();
                g2.motors.set_steering(0.0f);
            }
            break;
        }

        case Guided_TurnRateAndSpeed:
        {
            // stop vehicle if target not updated within 3 seconds
            if (have_attitude_target && (millis() - _des_att_time_ms) > 3000) {
                gcs().send_text(MAV_SEVERITY_WARNING, "target not received last 3secs, stopping");
                have_attitude_target = false;
            }
            if (have_attitude_target) {
                // run steering and throttle controllers
                float steering_out = attitude_control.get_steering_out_rate(radians(_desired_yaw_rate_cds / 100.0f), g2.motors.have_skid_steering(), g2.motors.limit.steer_left, g2.motors.limit.steer_right, _desired_speed < 0);
                g2.motors.set_steering(steering_out * 4500.0f);
                calc_throttle(_desired_speed, true);
            } else {
                stop_vehicle();
                g2.motors.set_steering(0.0f);
            }
            break;
        }

        default:
            gcs().send_text(MAV_SEVERITY_WARNING, "Unknown GUIDED mode");
            break;
    }
}
Example #27
0
/*
  main flight mode dependent update code 
 */
void Plane::update_flight_mode(void)
{
    enum FlightMode effective_mode = control_mode;
    if (control_mode == AUTO && g.auto_fbw_steer == 42) {
        effective_mode = FLY_BY_WIRE_A;
    }

    if (effective_mode != AUTO) {
        // hold_course is only used in takeoff and landing
        steer_state.hold_course_cd = -1;
    }

    // ensure we are fly-forward
    if (quadplane.in_vtol_mode()) {
        ahrs.set_fly_forward(false);
    } else {
        ahrs.set_fly_forward(true);
    }

    switch (effective_mode) 
    {
    case AUTO:
        handle_auto_mode();
        break;

    case GUIDED:
        if (auto_state.vtol_loiter && quadplane.available()) {
            quadplane.guided_update();
            break;
        }
        // fall through

    case RTL:
    case LOITER:
        calc_nav_roll();
        calc_nav_pitch();
        calc_throttle();
        break;
        
    case TRAINING: {
        training_manual_roll = false;
        training_manual_pitch = false;
        update_load_factor();
        
        // if the roll is past the set roll limit, then
        // we set target roll to the limit
        if (ahrs.roll_sensor >= roll_limit_cd) {
            nav_roll_cd = roll_limit_cd;
        } else if (ahrs.roll_sensor <= -roll_limit_cd) {
            nav_roll_cd = -roll_limit_cd;                
        } else {
            training_manual_roll = true;
            nav_roll_cd = 0;
        }
        
        // if the pitch is past the set pitch limits, then
        // we set target pitch to the limit
        if (ahrs.pitch_sensor >= aparm.pitch_limit_max_cd) {
            nav_pitch_cd = aparm.pitch_limit_max_cd;
        } else if (ahrs.pitch_sensor <= pitch_limit_min_cd) {
            nav_pitch_cd = pitch_limit_min_cd;
        } else {
            training_manual_pitch = true;
            nav_pitch_cd = 0;
        }
        if (fly_inverted()) {
            nav_pitch_cd = -nav_pitch_cd;
        }
        break;
    }

    case ACRO: {
        // handle locked/unlocked control
        if (acro_state.locked_roll) {
            nav_roll_cd = acro_state.locked_roll_err;
        } else {
            nav_roll_cd = ahrs.roll_sensor;
        }
        if (acro_state.locked_pitch) {
            nav_pitch_cd = acro_state.locked_pitch_cd;
        } else {
            nav_pitch_cd = ahrs.pitch_sensor;
        }
        break;
    }

    case AUTOTUNE:
    case FLY_BY_WIRE_A: {
        // set nav_roll and nav_pitch using sticks
        nav_roll_cd  = channel_roll->norm_input() * roll_limit_cd;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
        update_load_factor();
        float pitch_input = channel_pitch->norm_input();
        if (pitch_input > 0) {
            nav_pitch_cd = pitch_input * aparm.pitch_limit_max_cd;
        } else {
            nav_pitch_cd = -(pitch_input * pitch_limit_min_cd);
        }
        adjust_nav_pitch_throttle();
        nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
        if (fly_inverted()) {
            nav_pitch_cd = -nav_pitch_cd;
        }
        if (failsafe.ch3_failsafe && g.short_fs_action == 2) {
            // FBWA failsafe glide
            nav_roll_cd = 0;
            nav_pitch_cd = 0;
            channel_throttle->set_servo_out(0);
        }
        if (g.fbwa_tdrag_chan > 0) {
            // check for the user enabling FBWA taildrag takeoff mode
            bool tdrag_mode = (hal.rcin->read(g.fbwa_tdrag_chan-1) > 1700);
            if (tdrag_mode && !auto_state.fbwa_tdrag_takeoff_mode) {
                if (auto_state.highest_airspeed < g.takeoff_tdrag_speed1) {
                    auto_state.fbwa_tdrag_takeoff_mode = true;
                    gcs_send_text(MAV_SEVERITY_WARNING, "FBWA tdrag mode");
                }
            }
        }
        break;
    }

    case FLY_BY_WIRE_B:
        // Thanks to Yury MonZon for the altitude limit code!
        nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
        update_load_factor();
        update_fbwb_speed_height();
        break;
        
    case CRUISE:
        /*
          in CRUISE mode we use the navigation code to control
          roll when heading is locked. Heading becomes unlocked on
          any aileron or rudder input
        */
        if ((channel_roll->get_control_in() != 0 ||
             rudder_input != 0)) {                
            cruise_state.locked_heading = false;
            cruise_state.lock_timer_ms = 0;
        }                 
        
        if (!cruise_state.locked_heading) {
            nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
            nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
            update_load_factor();
        } else {
            calc_nav_roll();
        }
        update_fbwb_speed_height();
        break;
        
    case STABILIZE:
        nav_roll_cd        = 0;
        nav_pitch_cd       = 0;
        // throttle is passthrough
        break;
        
    case CIRCLE:
        // we have no GPS installed and have lost radio contact
        // or we just want to fly around in a gentle circle w/o GPS,
        // holding altitude at the altitude we set when we
        // switched into the mode
        nav_roll_cd  = roll_limit_cd / 3;
        update_load_factor();
        calc_nav_pitch();
        calc_throttle();
        break;

    case MANUAL:
        // servo_out is for Sim control only
        // ---------------------------------
        channel_roll->set_servo_out(channel_roll->pwm_to_angle());
        channel_pitch->set_servo_out(channel_pitch->pwm_to_angle());
        steering_control.steering = steering_control.rudder = channel_rudder->pwm_to_angle();
        break;
        //roll: -13788.000,  pitch: -13698.000,   thr: 0.000, rud: -13742.000


    case QSTABILIZE:
    case QHOVER:
    case QLOITER:
    case QLAND:
    case QRTL: {
        // set nav_roll and nav_pitch using sticks
        int16_t roll_limit = MIN(roll_limit_cd, quadplane.aparm.angle_max);
        nav_roll_cd  = channel_roll->norm_input() * roll_limit;
        nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit, roll_limit);
        float pitch_input = channel_pitch->norm_input();
        if (pitch_input > 0) {
            nav_pitch_cd = pitch_input * MIN(aparm.pitch_limit_max_cd, quadplane.aparm.angle_max);
        } else {
            nav_pitch_cd = pitch_input * MIN(-pitch_limit_min_cd, quadplane.aparm.angle_max);
        }
        nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
        break;
    }
        
    case INITIALISING:
        // handled elsewhere
        break;
    }
}
Example #28
0
void ModeGuided::update()
{
    switch (_guided_mode) {
        case Guided_WP:
        {
            _distance_to_destination = get_distance(rover.current_loc, _destination);
            const bool near_wp = _distance_to_destination <= rover.g.waypoint_radius;
            // check if we've reached the destination
            if (!_reached_destination && (near_wp || location_passed_point(rover.current_loc, _origin, _destination))) {
                _reached_destination = true;
                rover.gcs().send_mission_item_reached_message(0);
            }
            // determine if we should keep navigating
            if (!_reached_destination || (rover.is_boat() && !near_wp)) {
                // drive towards destination
                calc_steering_to_waypoint(_reached_destination ? rover.current_loc : _origin, _destination, _reversed);
                calc_throttle(calc_reduced_speed_for_turn_or_distance(_reversed ? -_desired_speed : _desired_speed), true, true);
            } else {
                stop_vehicle();
            }
            break;
        }

        case Guided_HeadingAndSpeed:
        {
            // stop vehicle if target not updated within 3 seconds
            if (have_attitude_target && (millis() - _des_att_time_ms) > 3000) {
                gcs().send_text(MAV_SEVERITY_WARNING, "target not received last 3secs, stopping");
                have_attitude_target = false;
            }
            if (have_attitude_target) {
                // run steering and throttle controllers
                calc_steering_to_heading(_desired_yaw_cd, _desired_speed < 0);
                calc_throttle(calc_reduced_speed_for_turn_or_distance(_desired_speed), true, true);
            } else {
                stop_vehicle();
            }
            break;
        }

        case Guided_TurnRateAndSpeed:
        {
            // stop vehicle if target not updated within 3 seconds
            if (have_attitude_target && (millis() - _des_att_time_ms) > 3000) {
                gcs().send_text(MAV_SEVERITY_WARNING, "target not received last 3secs, stopping");
                have_attitude_target = false;
            }
            if (have_attitude_target) {
                // run steering and throttle controllers
                float steering_out = attitude_control.get_steering_out_rate(radians(_desired_yaw_rate_cds / 100.0f),
                                                                            g2.motors.limit.steer_left,
                                                                            g2.motors.limit.steer_right,
                                                                            rover.G_Dt);
                g2.motors.set_steering(steering_out * 4500.0f);
                calc_throttle(_desired_speed, true, true);
            } else {
                stop_vehicle();
            }
            break;
        }

        default:
            gcs().send_text(MAV_SEVERITY_WARNING, "Unknown GUIDED mode");
            break;
    }
}
Example #29
0
void Rover::update_current_mode(void)
{
    switch (control_mode){
    case AUTO:
    case RTL:
        set_reverse(false);
        calc_lateral_acceleration();
        calc_nav_steer();
        calc_throttle(g.speed_cruise);
        break;

    case GUIDED:
        set_reverse(false);
        if (rtl_complete || verify_RTL()) {
            // we have reached destination so stop where we are
            if (channel_throttle->servo_out != g.throttle_min.get()) {
                gcs_send_mission_item_reached_message(0);
            }
            channel_throttle->servo_out = g.throttle_min.get();
            channel_steer->servo_out = 0;
            lateral_acceleration = 0;
        } else {
            calc_lateral_acceleration();
            calc_nav_steer();
            calc_throttle(g.speed_cruise);
        }
        break;

    case STEERING: {
        /*
          in steering mode we control lateral acceleration
          directly. We first calculate the maximum lateral
          acceleration at full steering lock for this speed. That is
          V^2/R where R is the radius of turn. We get the radius of
          turn from half the STEER2SRV_P.
         */
        float max_g_force = ground_speed * ground_speed / steerController.get_turn_radius();

        // constrain to user set TURN_MAX_G
        max_g_force = constrain_float(max_g_force, 0.1f, g.turn_max_g * GRAVITY_MSS);

        lateral_acceleration = max_g_force * (channel_steer->pwm_to_angle()/4500.0f);
        calc_nav_steer();

        // and throttle gives speed in proportion to cruise speed, up
        // to 50% throttle, then uses nudging above that.
        float target_speed = channel_throttle->pwm_to_angle() * 0.01f * 2 * g.speed_cruise;
        set_reverse(target_speed < 0);
        if (in_reverse) {
            target_speed = constrain_float(target_speed, -g.speed_cruise, 0);
        } else {
            target_speed = constrain_float(target_speed, 0, g.speed_cruise);
        }
        calc_throttle(target_speed);
        break;
    }

    case LEARNING:
    case MANUAL:
        /*
          in both MANUAL and LEARNING we pass through the
          controls. Setting servo_out here actually doesn't matter, as
          we set the exact value in set_servos(), but it helps for
          logging
         */
        channel_throttle->servo_out = channel_throttle->control_in;
        channel_steer->servo_out = channel_steer->pwm_to_angle();

        // mark us as in_reverse when using a negative throttle to
        // stop AHRS getting off
        set_reverse(channel_throttle->servo_out < 0);
        break;

    case HOLD:
        // hold position - stop motors and center steering
        channel_throttle->servo_out = 0;
        channel_steer->servo_out = 0;
        set_reverse(false);
        break;

    case INITIALISING:
        break;
    }
}
Example #30
0
void Rover::update_current_mode(void)
{
    switch (control_mode) {
    case AUTO:
    case RTL:
        if (!in_auto_reverse) {
            set_reverse(false);
        }
        if (!do_auto_rotation) {
            calc_lateral_acceleration();
            calc_nav_steer();
            calc_throttle(g.speed_cruise);
        } else {
            do_yaw_rotation();
        }
        break;

    case GUIDED: {
        if (!in_auto_reverse) {
            set_reverse(false);
        }
        switch (guided_mode) {
        case Guided_Angle:
            nav_set_yaw_speed();
            break;

        case Guided_WP:
            if (rtl_complete || verify_RTL()) {
                // we have reached destination so stop where we are
                if (SRV_Channels::get_output_scaled(SRV_Channel::k_throttle) != g.throttle_min.get()) {
                    gcs_send_mission_item_reached_message(0);
                }
                SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, g.throttle_min.get());
                SRV_Channels::set_output_scaled(SRV_Channel::k_steering, 0);
                lateral_acceleration = 0;
            } else {
                calc_lateral_acceleration();
                calc_nav_steer();
                calc_throttle(g.speed_cruise);
                Log_Write_GuidedTarget(guided_mode, Vector3f(guided_WP.lat, guided_WP.lng, guided_WP.alt),
                                       Vector3f(g.speed_cruise, SRV_Channels::get_output_scaled(SRV_Channel::k_throttle), 0));
            }
            break;

        default:
            gcs_send_text(MAV_SEVERITY_WARNING, "Unknown GUIDED mode");
            break;
        }
        break;
    }

    case STEERING: {
        /*
          in steering mode we control lateral acceleration
          directly. We first calculate the maximum lateral
          acceleration at full steering lock for this speed. That is
          V^2/R where R is the radius of turn. We get the radius of
          turn from half the STEER2SRV_P.
         */
        float max_g_force = ground_speed * ground_speed / steerController.get_turn_radius();

        // constrain to user set TURN_MAX_G
        max_g_force = constrain_float(max_g_force, 0.1f, g.turn_max_g * GRAVITY_MSS);

        lateral_acceleration = max_g_force * (channel_steer->get_control_in()/4500.0f);
        calc_nav_steer();

        // and throttle gives speed in proportion to cruise speed, up
        // to 50% throttle, then uses nudging above that.
        float target_speed = channel_throttle->get_control_in() * 0.01f * 2 * g.speed_cruise;
        set_reverse(target_speed < 0);
        if (in_reverse) {
            target_speed = constrain_float(target_speed, -g.speed_cruise, 0);
        } else {
            target_speed = constrain_float(target_speed, 0, g.speed_cruise);
        }
        calc_throttle(target_speed);
        break;
    }

    case LEARNING:
    case MANUAL:
        /*
          in both MANUAL and LEARNING we pass through the
          controls. Setting servo_out here actually doesn't matter, as
          we set the exact value in set_servos(), but it helps for
          logging
         */
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, channel_throttle->get_control_in());
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, channel_steer->get_control_in());

        // mark us as in_reverse when using a negative throttle to
        // stop AHRS getting off
        set_reverse(SRV_Channels::get_output_scaled(SRV_Channel::k_throttle) < 0);
        break;

    case HOLD:
        // hold position - stop motors and center steering
        SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, 0);
        SRV_Channels::set_output_scaled(SRV_Channel::k_steering, 0);
        if (!in_auto_reverse) {
            set_reverse(false);
        }
        break;

    case INITIALISING:
        break;
    }
}