@ -108,21 +108,6 @@ const AP_Param::GroupInfo AP_MotorsHeli_Single::var_info[] PROGMEM = {
@@ -108,21 +108,6 @@ const AP_Param::GroupInfo AP_MotorsHeli_Single::var_info[] PROGMEM = {
AP_GROUPEND
} ;
//
// public methods
//
// init
void AP_MotorsHeli_Single : : Init ( )
{
AP_MotorsHeli : : Init ( ) ;
// disable channels 7 and 8 from being used by RC_Channel_aux
RC_Channel_aux : : disable_aux_channel ( _motor_to_channel_map [ AP_MOTORS_HELI_SINGLE_AUX ] ) ;
RC_Channel_aux : : disable_aux_channel ( _motor_to_channel_map [ AP_MOTORS_HELI_SINGLE_RSC ] ) ;
}
// set update rate to motors - a value in hertz
void AP_MotorsHeli_Single : : set_update_rate ( uint16_t speed_hz )
{
@ -138,7 +123,7 @@ void AP_MotorsHeli_Single::set_update_rate( uint16_t speed_hz )
@@ -138,7 +123,7 @@ void AP_MotorsHeli_Single::set_update_rate( uint16_t speed_hz )
hal . rcout - > set_freq ( mask , _speed_hz ) ;
}
// enable - starts allowing signals to be sent to motors
// enable - starts allowing signals to be sent to motors and servos
void AP_MotorsHeli_Single : : enable ( )
{
// enable output channels
@ -146,8 +131,27 @@ void AP_MotorsHeli_Single::enable()
@@ -146,8 +131,27 @@ void AP_MotorsHeli_Single::enable()
hal . rcout - > enable_ch ( pgm_read_byte ( & _motor_to_channel_map [ AP_MOTORS_MOT_2 ] ) ) ; // swash servo 2
hal . rcout - > enable_ch ( pgm_read_byte ( & _motor_to_channel_map [ AP_MOTORS_MOT_3 ] ) ) ; // swash servo 3
hal . rcout - > enable_ch ( pgm_read_byte ( & _motor_to_channel_map [ AP_MOTORS_MOT_4 ] ) ) ; // yaw
hal . rcout - > enable_ch ( AP_MOTORS_HELI_SINGLE_AUX ) ; // output for gyro gain or direct drive variable pitch tail motor
hal . rcout - > enable_ch ( AP_MOTORS_HELI_SINGLE_RSC ) ; // output for main rotor esc
hal . rcout - > enable_ch ( AP_MOTORS_HELI_SINGLE_AUX ) ; // output for gyro gain or direct drive variable pitch tail motor
hal . rcout - > enable_ch ( AP_MOTORS_HELI_SINGLE_RSC ) ; // output for main rotor esc
// disable channels 7 and 8 from being used by RC_Channel_aux
RC_Channel_aux : : disable_aux_channel ( _motor_to_channel_map [ AP_MOTORS_HELI_SINGLE_AUX ] ) ;
RC_Channel_aux : : disable_aux_channel ( _motor_to_channel_map [ AP_MOTORS_HELI_SINGLE_RSC ] ) ;
}
// init_outputs - initialise Servo/PWM ranges and endpoints
void AP_MotorsHeli_Single : : init_outputs ( )
{
// reset swash servo range and endpoints
reset_swash_servo ( _swash_servo_1 ) ;
reset_swash_servo ( _swash_servo_2 ) ;
reset_swash_servo ( _swash_servo_3 ) ;
_yaw_servo . set_angle ( 4500 ) ;
// set main rotor servo range
// tail rotor servo use range as set in vehicle code for rc7
_main_rotor . init_servo ( ) ;
}
// output_test - spin a motor at the pwm value specified
@ -216,9 +220,31 @@ void AP_MotorsHeli_Single::set_desired_rotor_speed(int16_t desired_speed)
@@ -216,9 +220,31 @@ void AP_MotorsHeli_Single::set_desired_rotor_speed(int16_t desired_speed)
}
}
// recalc_scale rs - recalculates various scalers used.
void AP_MotorsHeli_Single : : recalc_scale rs( )
// calculate_scala rs - recalculates various scalers used.
void AP_MotorsHeli_Single : : calculate_scala rs( )
{
// range check collective min, max and mid
if ( _collective_min > = _collective_max ) {
_collective_min = AP_MOTORS_HELI_COLLECTIVE_MIN ;
_collective_max = AP_MOTORS_HELI_COLLECTIVE_MAX ;
}
_collective_mid = constrain_int16 ( _collective_mid , _collective_min , _collective_max ) ;
// calculate collective mid point as a number from 0 to 1000
_collective_mid_pwm = ( ( float ) ( _collective_mid - _collective_min ) ) / ( ( float ) ( _collective_max - _collective_min ) ) * 1000.0f ;
// calculate maximum collective pitch range from full positive pitch to zero pitch
_collective_range = 1000 - _collective_mid_pwm ;
// determine roll, pitch and collective input scaling
_roll_scaler = ( float ) _roll_max / 4500.0f ;
_pitch_scaler = ( float ) _pitch_max / 4500.0f ;
_collective_scalar = ( ( float ) ( _collective_max - _collective_min ) ) / 1000.0f ;
// calculate factors based on swash type and servo position
calculate_roll_pitch_collective_factors ( ) ;
// send setpoints to main rotor controller and trigger recalculation of scalars
_main_rotor . set_control_mode ( _rsc_mode ) ;
_main_rotor . set_ramp_time ( _rsc_ramp_time ) ;
_main_rotor . set_runup_time ( _rsc_runup_time ) ;
@ -227,6 +253,7 @@ void AP_MotorsHeli_Single::recalc_scalers()
@@ -227,6 +253,7 @@ void AP_MotorsHeli_Single::recalc_scalers()
_main_rotor . set_power_output_range ( _rsc_power_low , _rsc_power_high ) ;
_main_rotor . recalc_scalers ( ) ;
// send setpoints to tail rotor controller and trigger recalculation of scalars
if ( _rsc_mode = = AP_MOTORS_HELI_SINGLE_TAILTYPE_DIRECTDRIVE_VARPITCH ) {
_tail_rotor . set_control_mode ( AP_MOTORS_HELI_RSC_MODE_SETPOINT ) ;
_tail_rotor . set_ramp_time ( _rsc_ramp_time ) ;
@ -243,6 +270,45 @@ void AP_MotorsHeli_Single::recalc_scalers()
@@ -243,6 +270,45 @@ void AP_MotorsHeli_Single::recalc_scalers()
_tail_rotor . recalc_scalers ( ) ;
}
// calculate_roll_pitch_collective_factors - calculate factors based on swash type and servo position
void AP_MotorsHeli_Single : : calculate_roll_pitch_collective_factors ( )
{
if ( _swash_type = = AP_MOTORS_HELI_SINGLE_SWASH_CCPM ) { //CCPM Swashplate, perform control mixing
// roll factors
_rollFactor [ CH_1 ] = cosf ( radians ( _servo1_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
_rollFactor [ CH_2 ] = cosf ( radians ( _servo2_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
_rollFactor [ CH_3 ] = cosf ( radians ( _servo3_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
// pitch factors
_pitchFactor [ CH_1 ] = cosf ( radians ( _servo1_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
_pitchFactor [ CH_2 ] = cosf ( radians ( _servo2_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
_pitchFactor [ CH_3 ] = cosf ( radians ( _servo3_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
// collective factors
_collectiveFactor [ CH_1 ] = 1 ;
_collectiveFactor [ CH_2 ] = 1 ;
_collectiveFactor [ CH_3 ] = 1 ;
} else { //H1 Swashplate, keep servo outputs seperated
// roll factors
_rollFactor [ CH_1 ] = 1 ;
_rollFactor [ CH_2 ] = 0 ;
_rollFactor [ CH_3 ] = 0 ;
// pitch factors
_pitchFactor [ CH_1 ] = 0 ;
_pitchFactor [ CH_2 ] = 1 ;
_pitchFactor [ CH_3 ] = 0 ;
// collective factors
_collectiveFactor [ CH_1 ] = 0 ;
_collectiveFactor [ CH_2 ] = 0 ;
_collectiveFactor [ CH_3 ] = 1 ;
}
}
// get_motor_mask - returns a bitmask of which outputs are being used for motors or servos (1 means being used)
// this can be used to ensure other pwm outputs (i.e. for servos) do not conflict
uint16_t AP_MotorsHeli_Single : : get_motor_mask ( )
@ -255,7 +321,7 @@ uint16_t AP_MotorsHeli_Single::get_motor_mask()
@@ -255,7 +321,7 @@ uint16_t AP_MotorsHeli_Single::get_motor_mask()
void AP_MotorsHeli_Single : : output_min ( )
{
// move swash to mid
move_sw ash ( 0 , 0 , 500 , 0 ) ;
move_actuator s ( 0 , 0 , 500 , 0 ) ;
_main_rotor . output ( ROTOR_CONTROL_STOP ) ;
_tail_rotor . output ( ROTOR_CONTROL_STOP ) ;
@ -270,13 +336,15 @@ void AP_MotorsHeli_Single::output_min()
@@ -270,13 +336,15 @@ void AP_MotorsHeli_Single::output_min()
// sends commands to the motors
void AP_MotorsHeli_Single : : output_armed_stabilizing ( )
{
// if manual override active after arming, deactivate it.
// if manual override active after arming, deactivate it and reinitialize servos
if ( _servo_manual = = 1 ) {
reset_radio_passthrough ( ) ;
_servo_manual = 0 ;
init_outputs ( ) ;
calculate_scalars ( ) ;
}
move_sw ash ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
move_actuator s ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
if ( _tail_type = = AP_MOTORS_HELI_SINGLE_TAILTYPE_DIRECTDRIVE_VARPITCH ) {
_tail_rotor . output ( ROTOR_CONTROL_ACTIVE ) ;
@ -295,13 +363,15 @@ void AP_MotorsHeli_Single::output_armed_stabilizing()
@@ -295,13 +363,15 @@ void AP_MotorsHeli_Single::output_armed_stabilizing()
void AP_MotorsHeli_Single : : output_armed_not_stabilizing ( )
{
// if manual override active after arming, deactivate it.
// if manual override active after arming, deactivate it and reinitialize servos
if ( _servo_manual = = 1 ) {
reset_radio_passthrough ( ) ;
_servo_manual = 0 ;
init_outputs ( ) ;
calculate_scalars ( ) ;
}
move_sw ash ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
move_actuator s ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
if ( _tail_type = = AP_MOTORS_HELI_SINGLE_TAILTYPE_DIRECTDRIVE_VARPITCH ) {
_tail_rotor . output ( ROTOR_CONTROL_ACTIVE ) ;
@ -321,13 +391,15 @@ void AP_MotorsHeli_Single::output_armed_not_stabilizing()
@@ -321,13 +391,15 @@ void AP_MotorsHeli_Single::output_armed_not_stabilizing()
// output_armed_zero_throttle - sends commands to the motors
void AP_MotorsHeli_Single : : output_armed_zero_throttle ( )
{
// if manual override active after arming, deactivate it.
// if manual override active after arming, deactivate it and reinitialize servos
if ( _servo_manual = = 1 ) {
reset_radio_passthrough ( ) ;
_servo_manual = 0 ;
init_outputs ( ) ;
calculate_scalars ( ) ;
}
move_sw ash ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
move_actuator s ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
if ( _tail_type = = AP_MOTORS_HELI_SINGLE_TAILTYPE_DIRECTDRIVE_VARPITCH ) {
_tail_rotor . output ( ROTOR_CONTROL_IDLE ) ;
@ -344,7 +416,6 @@ void AP_MotorsHeli_Single::output_armed_zero_throttle()
@@ -344,7 +416,6 @@ void AP_MotorsHeli_Single::output_armed_zero_throttle()
_heliflags . rotor_runup_complete = _main_rotor . is_runup_complete ( ) ;
}
// output_disarmed - sends commands to the motors
void AP_MotorsHeli_Single : : output_disarmed ( )
{
@ -356,7 +427,13 @@ void AP_MotorsHeli_Single::output_disarmed()
@@ -356,7 +427,13 @@ void AP_MotorsHeli_Single::output_disarmed()
_yaw_control_input = _yaw_radio_passthrough ;
}
move_swash ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
// ensure swash servo endpoints haven't been moved
init_outputs ( ) ;
// continuously recalculate scalars to allow setup
calculate_scalars ( ) ;
move_actuators ( _roll_control_input , _pitch_control_input , _throttle_control_input , _yaw_control_input ) ;
if ( _tail_type = = AP_MOTORS_HELI_SINGLE_TAILTYPE_DIRECTDRIVE_VARPITCH ) {
_tail_rotor . output ( ROTOR_CONTROL_STOP ) ;
@ -367,66 +444,6 @@ void AP_MotorsHeli_Single::output_disarmed()
@@ -367,66 +444,6 @@ void AP_MotorsHeli_Single::output_disarmed()
_heliflags . rotor_runup_complete = false ;
}
// reset_servos
void AP_MotorsHeli_Single : : reset_servos ( )
{
reset_swash_servo ( _swash_servo_1 ) ;
reset_swash_servo ( _swash_servo_2 ) ;
reset_swash_servo ( _swash_servo_3 ) ;
}
// init_servos
void AP_MotorsHeli_Single : : init_servos ( )
{
// reset swash servo range and endpoints
reset_servos ( ) ;
_yaw_servo . set_angle ( 4500 ) ;
// set main rotor servo range
// tail rotor servo use range as set in vehicle code for rc7
_main_rotor . init_servo ( ) ;
}
// calculate_roll_pitch_collective_factors - calculate factors based on swash type and servo position
void AP_MotorsHeli_Single : : calculate_roll_pitch_collective_factors ( )
{
if ( _swash_type = = AP_MOTORS_HELI_SINGLE_SWASH_CCPM ) { //CCPM Swashplate, perform control mixing
// roll factors
_rollFactor [ CH_1 ] = cosf ( radians ( _servo1_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
_rollFactor [ CH_2 ] = cosf ( radians ( _servo2_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
_rollFactor [ CH_3 ] = cosf ( radians ( _servo3_pos + 90 - ( _phase_angle + _delta_phase_angle ) ) ) ;
// pitch factors
_pitchFactor [ CH_1 ] = cosf ( radians ( _servo1_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
_pitchFactor [ CH_2 ] = cosf ( radians ( _servo2_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
_pitchFactor [ CH_3 ] = cosf ( radians ( _servo3_pos - ( _phase_angle + _delta_phase_angle ) ) ) ;
// collective factors
_collectiveFactor [ CH_1 ] = 1 ;
_collectiveFactor [ CH_2 ] = 1 ;
_collectiveFactor [ CH_3 ] = 1 ;
} else { //H1 Swashplate, keep servo outputs seperated
// roll factors
_rollFactor [ CH_1 ] = 1 ;
_rollFactor [ CH_2 ] = 0 ;
_rollFactor [ CH_3 ] = 0 ;
// pitch factors
_pitchFactor [ CH_1 ] = 0 ;
_pitchFactor [ CH_2 ] = 1 ;
_pitchFactor [ CH_3 ] = 0 ;
// collective factors
_collectiveFactor [ CH_1 ] = 0 ;
_collectiveFactor [ CH_2 ] = 0 ;
_collectiveFactor [ CH_3 ] = 1 ;
}
}
// set_delta_phase_angle for setting variable phase angle compensation and force
// recalculation of collective factors
void AP_MotorsHeli_Single : : set_delta_phase_angle ( int16_t angle )
@ -437,14 +454,14 @@ void AP_MotorsHeli_Single::set_delta_phase_angle(int16_t angle)
@@ -437,14 +454,14 @@ void AP_MotorsHeli_Single::set_delta_phase_angle(int16_t angle)
}
//
// heli_move_swash - moves swash plate to attitude of parameters passed in
// move_actuators - moves swash plate and tail rotor
// - expected ranges:
// roll : -4500 ~ 4500
// pitch: -4500 ~ 4500
// collective: 0 ~ 1000
// yaw: -4500 ~ 4500
//
void AP_MotorsHeli_Single : : move_sw ash ( int16_t roll_out , int16_t pitch_out , int16_t coll_in , int16_t yaw_out )
void AP_MotorsHeli_Single : : move_actuator s ( int16_t roll_out , int16_t pitch_out , int16_t coll_in , int16_t yaw_out )
{
int16_t yaw_offset = 0 ;
int16_t coll_out_scaled ;
@ -455,67 +472,54 @@ void AP_MotorsHeli_Single::move_swash(int16_t roll_out, int16_t pitch_out, int16
@@ -455,67 +472,54 @@ void AP_MotorsHeli_Single::move_swash(int16_t roll_out, int16_t pitch_out, int16
limit . throttle_lower = false ;
limit . throttle_upper = false ;
if ( _servo_manual = = 1 ) { // are we in manual servo mode? (i.e. swash set-up mode)?
// check if we need to free up the swash
if ( _heliflags . swash_initialised ) {
reset_swash ( ) ;
}
// To-Do: This equation seems to be wrong. It probably restricts swash movement so that swash setup doesn't work right.
// _collective_scalar should probably not be used or set to 1?
coll_out_scaled = coll_in * _collective_scalar + _throttle_radio_min - 1000 ;
} else { // regular flight mode
// check if we need to reinitialise the swash
if ( ! _heliflags . swash_initialised ) {
init_swash ( ) ;
}
// rescale roll_out and pitch-out into the min and max ranges to provide linear motion
// across the input range instead of stopping when the input hits the constrain value
// these calculations are based on an assumption of the user specified roll_max and pitch_max
// coming into this equation at 4500 or less, and based on the original assumption of the
// total _servo_x.servo_out range being -4500 to 4500.
roll_out = roll_out * _roll_scaler ;
if ( roll_out < - _roll_max ) {
roll_out = - _roll_max ;
limit . roll_pitch = true ;
}
if ( roll_out > _roll_max ) {
roll_out = _roll_max ;
limit . roll_pitch = true ;
}
// rescale roll_out and pitch-out into the min and max ranges to provide linear motion
// across the input range instead of stopping when the input hits the constrain value
// these calculations are based on an assumption of the user specified roll_max and pitch_max
// coming into this equation at 4500 or less, and based on the original assumption of the
// total _servo_x.servo_out range being -4500 to 4500.
roll_out = roll_out * _roll_scaler ;
if ( roll_out < - _roll_max ) {
roll_out = - _roll_max ;
limit . roll_pitch = true ;
}
if ( roll_out > _roll_max ) {
roll_out = _roll_max ;
limit . roll_pitch = true ;
}
// scale pitch and update limits
pitch_out = pitch_out * _pitch_scaler ;
if ( pitch_out < - _pitch_max ) {
pitch_out = - _pitch_max ;
limit . roll_pitch = true ;
}
if ( pitch_out > _pitch_max ) {
pitch_out = _pitch_max ;
limit . roll_pitch = true ;
}
// scale pitch and update limits
pitch_out = pitch_out * _pitch_scaler ;
if ( pitch_out < - _pitch_max ) {
pitch_out = - _pitch_max ;
limit . roll_pitch = true ;
}
if ( pitch_out > _pitch_max ) {
pitch_out = _pitch_max ;
limit . roll_pitch = true ;
}
// constrain collective input
_collective_out = coll_in ;
if ( _collective_out < = 0 ) {
_collective_out = 0 ;
limit . throttle_lower = true ;
}
if ( _collective_out > = 1000 ) {
_collective_out = 1000 ;
limit . throttle_upper = true ;
}
// constrain collective input
_collective_out = coll_in ;
if ( _collective_out < = 0 ) {
_collective_out = 0 ;
limit . throttle_lower = true ;
}
if ( _collective_out > = 1000 ) {
_collective_out = 1000 ;
limit . throttle_upper = true ;
}
// ensure not below landed/landing collective
if ( _heliflags . landing_collective & & _collective_out < _land_collective_min ) {
_collective_out = _land_collective_min ;
limit . throttle_lower = true ;
}
// ensure not below landed/landing collective
if ( _heliflags . landing_collective & & _collective_out < _land_collective_min ) {
_collective_out = _land_collective_min ;
limit . throttle_lower = true ;
}
// scale collective pitch
coll_out_scaled = _collective_out * _collective_scalar + _collective_min - 1000 ;
// scale collective pitch
coll_out_scaled = _collective_out * _collective_scalar + _collective_min - 1000 ;
// if servo output not in manual mode, process pre-compensation factors
if ( _servo_manual = = 0 ) {
// rudder feed forward based on collective
// the feed-forward is not required when the motor is stopped or at idle, and thus not creating torque
// also not required if we are using external gyro
@ -524,6 +528,8 @@ void AP_MotorsHeli_Single::move_swash(int16_t roll_out, int16_t pitch_out, int16
@@ -524,6 +528,8 @@ void AP_MotorsHeli_Single::move_swash(int16_t roll_out, int16_t pitch_out, int16
_collective_yaw_effect = constrain_float ( _collective_yaw_effect , - AP_MOTORS_HELI_SINGLE_COLYAW_RANGE , AP_MOTORS_HELI_SINGLE_COLYAW_RANGE ) ;
yaw_offset = _collective_yaw_effect * abs ( _collective_out - _collective_mid_pwm ) ;
}
} else {
yaw_offset = 0 ;
}
// feed power estimate into main rotor controller