1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-02 10:24:11 +01:00

First attempt at ccpm mixing for single rotor helicopter.

This has throttle and pitch curves implemented and can be configured for many swashplate configurations.

This has flown a 450 clone (with training wheels) and the ccpm worked well.

Still need to neaten up some stuff and work out how to implement yaw stabilisation in manual mode.


git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1412 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
andrew 2010-08-26 06:00:57 +00:00 committed by andrew
parent d9a6ced655
commit 2361af19fb
3 changed files with 174 additions and 2 deletions

View File

@ -54,6 +54,8 @@ static void actuatorTask(void* parameters);
static int32_t mixerFixedWing(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd); static int32_t mixerFixedWing(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd);
static int32_t mixerFixedWingElevon(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd); static int32_t mixerFixedWingElevon(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd);
static int32_t mixerVTOL(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd); static int32_t mixerVTOL(const ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd);
static int32_t InterpolateCCPMCurve(float *Output, float input, const float *Curve);
static int32_t mixerCCPM( ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd);
static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral); static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral);
static void setFailsafe(); static void setFailsafe();
@ -150,6 +152,17 @@ static void actuatorTask(void* parameters)
AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR); AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR);
} }
} }
else if ( sysSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP )
{
if ( mixerCCPM(&settings, &desired, &cmd) == -1 )
{
AlarmsSet(SYSTEMALARMS_ALARM_ACTUATOR, SYSTEMALARMS_ALARM_CRITICAL);
}
else
{
AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR);
}
}
// Update output object // Update output object
ActuatorCommandSet(&cmd); ActuatorCommandSet(&cmd);
@ -260,6 +273,165 @@ static int32_t mixerVTOL(const ActuatorSettingsData* settings, const ActuatorDes
return -1; return -1;
} }
static int32_t InterpolateCCPMCurve(float *output, float input, const float *curve)
{
int8_t curvIndex;
float slope;
float offset;
float value;
//determine which section of the 5 point curve we are on
if (input <= .25)
{
curvIndex=0;
offset = 0;
}
else if (input <= .50)
{
curvIndex=1;
offset = 0.25;
}
else if (input <= .75)
{
curvIndex=2;
offset = 0.50;
}
else
{
curvIndex=3;
offset = 0.75;
}
//calculate the linear interpolation for the selected segment
slope = (curve[curvIndex+1]-curve[curvIndex])/0.25;
value=curve[curvIndex] + ((input-offset) * slope);
//bound the output to valid percentage values
if( value > 100.0 ) value = 100.0;
if( value < 0.0 ) value = 0.0;
*output=value;
return 0;
}
/**
* Mixer for CCPM (single rotor helicopters). Converts desired roll,pitch,yaw and throttle to servo outputs.
* @return -1 if error, 0 if success
*/
static int32_t mixerCCPM( ActuatorSettingsData* settings, const ActuatorDesiredData* desired, ActuatorCommandData* cmd)
{
#define degtorad 0.0174532925 //pi/180
// TODO: Implement CCPM mixers
int configOK;
float curveValue;
float throttle;
float bladePitch;
float CCPMCyclicConstant;
float servoW;
float servoX;
float servoY;
float servoZ;
configOK=0;
//calculate the throttle value based on the curve - scale to 0.0 -> +1.0
InterpolateCCPMCurve(&curveValue, desired->Throttle, settings->CCPMThrottleCurve);
throttle = curveValue/100.0;
//calculate the Blade Pitch value based on the curve - scale to -1.0 -> +1.0
InterpolateCCPMCurve(&curveValue, desired->Throttle, settings->CCPMPitchCurve);
bladePitch = (curveValue/50.0) -1.0;
//calculate how much Cyclic to apply to the mixing
CCPMCyclicConstant=1-settings->CCPMCollectiveConstant;
// Set ServoW servo command
if ( settings->CCPMServoW != ACTUATORSETTINGS_CCPMSERVOW_NONE )
{
servoW=(CCPMCyclicConstant * ((sin((settings->CCPMAngleW + settings->CCPMCorrectionAngle)*degtorad)*desired->Roll)
+(cos((settings->CCPMAngleW + settings->CCPMCorrectionAngle)*degtorad)*desired->Pitch)))
+ (settings->CCPMCollectiveConstant * bladePitch);
cmd->Channel[ settings->CCPMServoW ] = scaleChannel(servoW, settings->ChannelMax[ settings->CCPMServoW ],
settings->ChannelMin[ settings->CCPMServoW ],
settings->ChannelNeutral[ settings->CCPMServoW ]);
configOK++;
}
// Set ServoX servo command
if ( settings->CCPMServoX != ACTUATORSETTINGS_CCPMSERVOX_NONE )
{
servoX=(CCPMCyclicConstant * ((sin((settings->CCPMAngleX + settings->CCPMCorrectionAngle)*degtorad)*desired->Roll)
+(cos((settings->CCPMAngleX + settings->CCPMCorrectionAngle)*degtorad)*desired->Pitch)))
+ (settings->CCPMCollectiveConstant * bladePitch);
cmd->Channel[ settings->CCPMServoX ] = scaleChannel(servoX, settings->ChannelMax[ settings->CCPMServoX ],
settings->ChannelMin[ settings->CCPMServoX ],
settings->ChannelNeutral[ settings->CCPMServoX ]);
configOK++;
}
// Set ServoY servo command
if ( settings->CCPMServoY != ACTUATORSETTINGS_CCPMSERVOY_NONE )
{
servoY=(CCPMCyclicConstant * ((sin((settings->CCPMAngleY + settings->CCPMCorrectionAngle)*degtorad)*desired->Roll)
+(cos((settings->CCPMAngleY + settings->CCPMCorrectionAngle)*degtorad)*desired->Pitch)))
+ (settings->CCPMCollectiveConstant * bladePitch);
cmd->Channel[ settings->CCPMServoY ] = scaleChannel(servoY, settings->ChannelMax[ settings->CCPMServoY ],
settings->ChannelMin[ settings->CCPMServoY ],
settings->ChannelNeutral[ settings->CCPMServoY ]);
configOK++;
}
// Set ServoZ servo command
if ( settings->CCPMServoZ != ACTUATORSETTINGS_CCPMSERVOZ_NONE )
{
servoZ=(CCPMCyclicConstant * ((sin((settings->CCPMAngleZ + settings->CCPMCorrectionAngle)*degtorad)*desired->Roll)
+(cos((settings->CCPMAngleZ + settings->CCPMCorrectionAngle)*degtorad)*desired->Pitch)))
+ (settings->CCPMCollectiveConstant * bladePitch);
cmd->Channel[ settings->CCPMServoZ ] = scaleChannel(servoZ, settings->ChannelMax[ settings->CCPMServoZ ],
settings->ChannelMin[ settings->CCPMServoZ ],
settings->ChannelNeutral[ settings->CCPMServoZ ]);
configOK++;
}
// Set throttle servo command
if ( settings->CCPMThrottle != ACTUATORSETTINGS_CCPMTHROTTLE_NONE )
{
cmd->Channel[ settings->CCPMThrottle ] = scaleChannel(throttle, settings->ChannelMax[ settings->CCPMThrottle ],
settings->ChannelMin[ settings->CCPMThrottle ],
settings->ChannelNeutral[ settings->CCPMThrottle ]);
}
else
{
configOK=0;
}
// Set TailRotor servo command
if (settings->CCPMYawStabilizationInManualMode == ACTUATORSETTINGS_CCPMYAWSTABILIZATIONINMANUALMODE_FALSE)
{//update the servo as per the desired control mode (manual or stabalized)
if ( settings->CCPMTailRotor != ACTUATORSETTINGS_CCPMTAILROTOR_NONE )
{
cmd->Channel[ settings->CCPMTailRotor ] = scaleChannel(desired->Yaw, settings->ChannelMax[ settings->CCPMTailRotor ],
settings->ChannelMin[ settings->CCPMTailRotor ],
settings->ChannelNeutral[ settings->CCPMTailRotor ]);
}
else
{
configOK=0;
}
}
else
{//TODO need to implement the stabilization PID loop to provide heading hold gyro functionality in manual control mode
}
if (configOK<2)return -1;
return 0;
}
/** /**
* Convert channel from -1/+1 to servo pulse duration in microseconds * Convert channel from -1/+1 to servo pulse duration in microseconds
*/ */

View File

@ -188,7 +188,7 @@ static void stabilizationTask(void* parameters)
// local Yaw stabilization control loop (only enabled on VTOL airframes) // local Yaw stabilization control loop (only enabled on VTOL airframes)
if ( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_VTOL ) if (( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_VTOL )||( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP))
{ {
yawDerivative = yawError - yawErrorLast; yawDerivative = yawError - yawErrorLast;
yawIntegralLimit = YAW_INTEGRAL_LIMIT / stabSettings.YawKi; yawIntegralLimit = YAW_INTEGRAL_LIMIT / stabSettings.YawKi;

View File

@ -130,7 +130,7 @@ static void stabilizationTask(void* parameters)
rollErrorLast = rollError; rollErrorLast = rollError;
// Yaw stabilization control loop (only enabled on VTOL airframes) // Yaw stabilization control loop (only enabled on VTOL airframes)
if ( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_VTOL ) if (( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_VTOL )||( systemSettings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP))
{ {
yawError = attitudeDesired.Yaw - attitudeActual.Yaw; yawError = attitudeDesired.Yaw - attitudeActual.Yaw;
yawDerivative = yawError - yawErrorLast; yawDerivative = yawError - yawErrorLast;