2010-10-03 22:39:23 +02:00
|
|
|
/**
|
|
|
|
******************************************************************************
|
|
|
|
* @addtogroup OpenPilotModules OpenPilot Modules
|
|
|
|
* @{
|
|
|
|
* @addtogroup StabilizationModule Stabilization Module
|
|
|
|
* @brief Stabilization PID loops in an airframe type independent manner
|
|
|
|
* @note This object updates the @ref ActuatorDesired "Actuator Desired" based on the
|
2013-05-18 19:36:45 +02:00
|
|
|
* PID loops on the @ref AttitudeDesired "Attitude Desired" and @ref AttitudeState "Attitude State"
|
2010-10-03 22:39:23 +02:00
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file stabilization.c
|
|
|
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
|
|
|
* @brief Attitude stabilization module.
|
|
|
|
*
|
|
|
|
* @see The GNU Public License (GPL) Version 3
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2013-05-02 23:31:14 +02:00
|
|
|
#include <openpilot.h>
|
2013-09-01 12:10:55 +02:00
|
|
|
#include <pios_struct_helper.h>
|
2010-10-03 22:39:23 +02:00
|
|
|
#include "stabilization.h"
|
2010-10-08 17:38:23 +02:00
|
|
|
#include "stabilizationsettings.h"
|
2013-12-10 21:07:56 +01:00
|
|
|
#include "stabilizationbank.h"
|
2013-12-11 14:56:00 +01:00
|
|
|
#include "stabilizationsettingsbank1.h"
|
|
|
|
#include "stabilizationsettingsbank2.h"
|
|
|
|
#include "stabilizationsettingsbank3.h"
|
2010-10-03 22:39:23 +02:00
|
|
|
#include "actuatordesired.h"
|
2010-10-24 22:00:02 +02:00
|
|
|
#include "ratedesired.h"
|
2012-07-30 04:08:46 +02:00
|
|
|
#include "relaytuning.h"
|
2012-07-29 22:21:14 +02:00
|
|
|
#include "relaytuningsettings.h"
|
2011-03-02 02:25:27 +01:00
|
|
|
#include "stabilizationdesired.h"
|
2013-05-18 19:36:45 +02:00
|
|
|
#include "attitudestate.h"
|
2013-07-20 13:52:45 +02:00
|
|
|
#include "airspeedstate.h"
|
2013-05-18 19:36:45 +02:00
|
|
|
#include "gyrostate.h"
|
2011-05-03 18:04:44 +02:00
|
|
|
#include "flightstatus.h"
|
2014-01-15 19:53:14 +01:00
|
|
|
#include "manualcontrolsettings.h"
|
2014-03-02 14:45:17 +01:00
|
|
|
#include "manualcontrolcommand.h"
|
2014-02-09 19:33:29 +01:00
|
|
|
#include "flightmodesettings.h"
|
2013-05-02 23:31:14 +02:00
|
|
|
#include "taskinfo.h"
|
2012-08-02 11:12:12 +02:00
|
|
|
|
|
|
|
// Math libraries
|
2011-03-02 02:25:34 +01:00
|
|
|
#include "CoordinateConversions.h"
|
2012-08-02 11:12:12 +02:00
|
|
|
#include "pid.h"
|
2012-08-03 19:15:57 +02:00
|
|
|
#include "sin_lookup.h"
|
2010-10-03 22:39:23 +02:00
|
|
|
|
2012-08-02 00:52:53 +02:00
|
|
|
// Includes for various stabilization algorithms
|
|
|
|
#include "relay_tuning.h"
|
2012-08-02 10:24:18 +02:00
|
|
|
#include "virtualflybar.h"
|
2010-10-03 22:39:23 +02:00
|
|
|
|
2013-03-28 17:29:26 +01:00
|
|
|
// Includes for various stabilization algorithms
|
|
|
|
#include "relay_tuning.h"
|
|
|
|
|
2010-10-03 22:39:23 +02:00
|
|
|
// Private constants
|
2014-02-04 19:05:17 +01:00
|
|
|
#define UPDATE_EXPECTED (1.0f / 666.0f)
|
|
|
|
#define UPDATE_MIN 1.0e-6f
|
|
|
|
#define UPDATE_MAX 1.0f
|
2014-02-04 19:21:33 +01:00
|
|
|
#define UPDATE_ALPHA 1.0e-2f
|
2014-02-04 19:05:17 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
#define MAX_QUEUE_SIZE 1
|
2011-02-02 09:57:34 +01:00
|
|
|
|
|
|
|
#if defined(PIOS_STABILIZATION_STACK_SIZE)
|
2013-05-18 14:17:26 +02:00
|
|
|
#define STACK_SIZE_BYTES PIOS_STABILIZATION_STACK_SIZE
|
2011-02-02 09:57:34 +01:00
|
|
|
#else
|
2014-03-02 19:11:49 +01:00
|
|
|
#define STACK_SIZE_BYTES 860
|
2011-02-02 09:57:34 +01:00
|
|
|
#endif
|
|
|
|
|
2014-02-02 14:13:25 +01:00
|
|
|
#define TASK_PRIORITY (tskIDLE_PRIORITY + 3) // FLIGHT CONTROL priority
|
2010-10-24 22:00:05 +02:00
|
|
|
#define FAILSAFE_TIMEOUT_MS 30
|
2010-10-03 22:39:23 +02:00
|
|
|
|
2014-03-14 06:47:37 +01:00
|
|
|
// The PID_RATE_ROLL set is used by Rate mode and the rate portion of Attitude mode
|
|
|
|
// The PID_RATE set is used by the attitude portion of Attitude mode
|
|
|
|
enum { PID_RATE_ROLL, PID_RATE_PITCH, PID_RATE_YAW, PID_ROLL, PID_PITCH, PID_YAW, PID_MAX };
|
2014-01-14 20:03:42 +01:00
|
|
|
enum { RATE_P, RATE_I, RATE_D, RATE_LIMIT, RATE_OFFSET };
|
|
|
|
enum { ATT_P, ATT_I, ATT_LIMIT, ATT_OFFSET };
|
2010-10-03 22:39:23 +02:00
|
|
|
|
|
|
|
// Private variables
|
|
|
|
static xTaskHandle taskHandle;
|
2010-10-08 17:38:23 +02:00
|
|
|
static StabilizationSettingsData settings;
|
2010-10-03 22:39:23 +02:00
|
|
|
static xQueueHandle queue;
|
2011-06-22 02:49:20 +02:00
|
|
|
float gyro_alpha = 0;
|
2013-05-18 14:17:26 +02:00
|
|
|
float axis_lock_accum[3] = { 0, 0, 0 };
|
|
|
|
uint8_t max_axis_lock = 0;
|
2011-06-25 17:38:37 +02:00
|
|
|
uint8_t max_axislock_rate = 0;
|
2013-05-18 14:17:26 +02:00
|
|
|
float weak_leveling_kp = 0;
|
2011-07-03 17:45:01 +02:00
|
|
|
uint8_t weak_leveling_max = 0;
|
2011-08-10 10:51:46 +02:00
|
|
|
bool lowThrottleZeroIntegral;
|
2014-01-18 00:32:50 +01:00
|
|
|
float vbar_decay = 0.991f;
|
2012-08-02 11:12:12 +02:00
|
|
|
struct pid pids[PID_MAX];
|
2014-01-10 20:32:44 +01:00
|
|
|
|
2014-01-18 00:32:50 +01:00
|
|
|
int cur_flight_mode = -1;
|
2010-10-03 22:39:23 +02:00
|
|
|
|
2014-03-14 06:47:37 +01:00
|
|
|
static float rattitude_mode_transition_stick_position;
|
2014-02-09 19:33:29 +01:00
|
|
|
static float cruise_control_min_thrust;
|
|
|
|
static float cruise_control_max_thrust;
|
2014-01-11 22:22:20 +01:00
|
|
|
static uint8_t cruise_control_max_angle;
|
2014-01-18 00:32:50 +01:00
|
|
|
static float cruise_control_max_power_factor;
|
|
|
|
static float cruise_control_power_trim;
|
|
|
|
static int8_t cruise_control_inverted_power_switch;
|
2014-03-22 06:18:06 +01:00
|
|
|
static float cruise_control_max_power_factor_angle;
|
|
|
|
static float cruise_control_half_power_delay;
|
2014-03-26 18:48:24 +01:00
|
|
|
static float cruise_control_thrust_difference;
|
2014-03-22 03:34:03 +01:00
|
|
|
static uint8_t cruise_control_flight_mode_switch_pos_enable[FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_NUMELEM];
|
2010-10-03 22:39:23 +02:00
|
|
|
|
|
|
|
// Private functions
|
2013-05-18 14:17:26 +02:00
|
|
|
static void stabilizationTask(void *parameters);
|
2012-07-31 03:55:43 +02:00
|
|
|
static float bound(float val, float range);
|
2010-10-03 22:39:23 +02:00
|
|
|
static void ZeroPids(void);
|
2013-05-18 14:17:26 +02:00
|
|
|
static void SettingsUpdatedCb(UAVObjEvent *ev);
|
2013-12-10 21:07:56 +01:00
|
|
|
static void BankUpdatedCb(UAVObjEvent *ev);
|
2013-12-11 14:56:00 +01:00
|
|
|
static void SettingsBankUpdatedCb(UAVObjEvent *ev);
|
2014-03-26 18:48:24 +01:00
|
|
|
static float CruiseControlAngleToFactor(float angle);
|
|
|
|
static float CruiseControlFactorToThrust(float factor, float stick_thrust);
|
|
|
|
static float CruiseControlLimitThrust(float thrust);
|
2010-10-03 22:39:23 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Module initialization
|
|
|
|
*/
|
2011-06-20 07:35:40 +02:00
|
|
|
int32_t StabilizationStart()
|
2010-10-03 22:39:23 +02:00
|
|
|
{
|
2013-05-18 14:17:26 +02:00
|
|
|
// Initialize variables
|
|
|
|
// Create object queue
|
|
|
|
queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent));
|
|
|
|
|
|
|
|
// Listen for updates.
|
2013-05-18 19:36:45 +02:00
|
|
|
// AttitudeStateConnectQueue(queue);
|
|
|
|
GyroStateConnectQueue(queue);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
StabilizationSettingsConnectCallback(SettingsUpdatedCb);
|
|
|
|
SettingsUpdatedCb(StabilizationSettingsHandle());
|
|
|
|
|
2013-12-10 21:07:56 +01:00
|
|
|
StabilizationBankConnectCallback(BankUpdatedCb);
|
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
StabilizationSettingsBank1ConnectCallback(SettingsBankUpdatedCb);
|
|
|
|
StabilizationSettingsBank2ConnectCallback(SettingsBankUpdatedCb);
|
|
|
|
StabilizationSettingsBank3ConnectCallback(SettingsBankUpdatedCb);
|
|
|
|
|
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Start main task
|
|
|
|
xTaskCreate(stabilizationTask, (signed char *)"Stabilization", STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &taskHandle);
|
|
|
|
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_STABILIZATION, taskHandle);
|
2013-05-15 05:20:52 +02:00
|
|
|
#ifdef PIOS_INCLUDE_WDG
|
2013-05-18 14:17:26 +02:00
|
|
|
PIOS_WDG_RegisterFlag(PIOS_WDG_STABILIZATION);
|
2013-05-15 05:20:52 +02:00
|
|
|
#endif
|
2013-05-18 14:17:26 +02:00
|
|
|
return 0;
|
2011-06-20 07:35:40 +02:00
|
|
|
}
|
|
|
|
|
2010-10-03 22:39:23 +02:00
|
|
|
/**
|
|
|
|
* Module initialization
|
|
|
|
*/
|
|
|
|
int32_t StabilizationInitialize()
|
|
|
|
{
|
2013-05-18 14:17:26 +02:00
|
|
|
// Initialize variables
|
2014-03-02 18:59:36 +01:00
|
|
|
ManualControlCommandInitialize();
|
|
|
|
ManualControlSettingsInitialize();
|
|
|
|
FlightStatusInitialize();
|
|
|
|
StabilizationDesiredInitialize();
|
2013-05-18 14:17:26 +02:00
|
|
|
StabilizationSettingsInitialize();
|
2013-12-11 13:05:05 +01:00
|
|
|
StabilizationBankInitialize();
|
2013-12-11 14:56:00 +01:00
|
|
|
StabilizationSettingsBank1Initialize();
|
|
|
|
StabilizationSettingsBank2Initialize();
|
|
|
|
StabilizationSettingsBank3Initialize();
|
2013-05-18 14:17:26 +02:00
|
|
|
ActuatorDesiredInitialize();
|
Final step: lot of small fixes, last commit in this commit series
This is the first cleanup pass through makefiles and pios.
Probably it is difficult to track changes due to the nature of them.
I would recommend to look at resulting files and compiled code instead.
NOTE: original branch was rebased and lot of conflicts were fixed on
the way. So do not expect that every commit in this series will be
buildable (unlike original branch). Only final result was tested.
The main goal was to remove as much duplication of code (and copy/paste
errors) as possible, moving common parts out of Makefiles. It still is
not perfect, and mostly no code changes made - Makefiles and #ifdefs only.
But please while testing make sure that all code works as before, and no
modules/options are missed by accident.
Brief list of changes:
- Moved common parts of Makefiles into the set of *.mk files.
- Changed method of passing common vars from top Makefile to lower ones.
- Some pios cleanup, mostly #ifdefs, and all pios_config.h files.
- Many obsolete files removed (for instance, AHRS files, op_config.h).
- Many obsolete or unused macros removed or fixed/renamed (ALL_DIGNOSTICS).
- Unified pios_config.h template. Please don't remove lines for board
configs, only comment/uncomment them. Adding new PIOS options, please
propagate them to all board files keeping the same order.
- Some formatting, spacing, indentation (no line endings change yet).
- Some cosmetic fixes (no more C:\X\Y\filename.c printings on Windows).
- Added some library.mk files to move libs into AR achives later.
- EntireFlash target now uses cross-platform python script to generate bin
files. So it works on all supported platforms: Linux, OSX, Windows.
- Top level packaging is completely rewritten. Now it is a part of top
Makefile. As such, all dependencies are checked and accounted, no
more 'make -j' problems should occur.
- Default GCS_BUILD_CONF is release now, may be changed if necessary
using 'make GCS_BUILD_CONF=debug gcs'.
- GCS build paths are separated into debug and release, so no more obj
file clashes. Packaging system supports only release builds.
- New target is introduced: 'clean_package'. Now 'make package' does not
clean build directory. Use clean_package instead for distributable builds.
- Targets like 'all', 'opfw_resource', etc now will print extra contex
in parallel builds too.
- If any of 'package', 'clean_package', 'opfw_resource' targets are given
on command line, GCS build will depend on the resource, so all fw_*.opfw
targets will be built and embedded into GCS. By default GCS does not
depend on resource, and will be built w/o firmware (unless the resource
files already exist and the Qt resource file is generated).
- fw_simposix (ELF executable) is now packaged for linux. Run'n'play!
- Make help is refined and is now up to date.
Still broken:
- UnitTests, should be fixed
- SimPosix: buildable, but should be reworked.
Next planned passes to do:
- toolchain bootstrapping and packaging (including windows - WIP)
- CMSIS/StdPeriph lib cleanup
- more PIOS cleanup
- move libs into AR archives to save build time
- sim targets refactir and cleanup
- move android-related directories under <top>/android
- unit test targets fix
- source code line ending changes (there are many different, were not changed)
- coding style
Merging this, please use --no-ff git option to make it the real commit point
Conflicts:
A lot of... :-)
2013-03-24 12:02:08 +01:00
|
|
|
#ifdef DIAG_RATEDESIRED
|
2013-05-18 14:17:26 +02:00
|
|
|
RateDesiredInitialize();
|
2013-07-20 13:52:45 +02:00
|
|
|
#endif
|
|
|
|
#ifdef REVOLUTION
|
|
|
|
AirspeedStateInitialize();
|
2011-06-18 18:59:02 +02:00
|
|
|
#endif
|
2013-05-18 14:17:26 +02:00
|
|
|
// Code required for relay tuning
|
|
|
|
sin_lookup_initalize();
|
|
|
|
RelayTuningSettingsInitialize();
|
|
|
|
RelayTuningInitialize();
|
2012-08-03 19:15:57 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
return 0;
|
2010-10-03 22:39:23 +02:00
|
|
|
}
|
|
|
|
|
2013-06-04 05:37:40 +02:00
|
|
|
MODULE_INITCALL(StabilizationInitialize, StabilizationStart);
|
2011-06-20 07:35:40 +02:00
|
|
|
|
2010-10-03 22:39:23 +02:00
|
|
|
/**
|
|
|
|
* Module task
|
|
|
|
*/
|
2013-05-18 14:17:26 +02:00
|
|
|
static void stabilizationTask(__attribute__((unused)) void *parameters)
|
2010-10-03 22:39:23 +02:00
|
|
|
{
|
2013-05-18 14:17:26 +02:00
|
|
|
UAVObjEvent ev;
|
2014-02-04 19:05:17 +01:00
|
|
|
PiOSDeltatimeConfig timeval;
|
|
|
|
|
|
|
|
PIOS_DELTATIME_Init(&timeval, UPDATE_EXPECTED, UPDATE_MIN, UPDATE_MAX, UPDATE_ALPHA);
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
ActuatorDesiredData actuatorDesired;
|
|
|
|
StabilizationDesiredData stabDesired;
|
2014-02-09 19:33:29 +01:00
|
|
|
float throttleDesired;
|
2013-05-18 14:17:26 +02:00
|
|
|
RateDesiredData rateDesired;
|
2013-05-18 19:36:45 +02:00
|
|
|
AttitudeStateData attitudeState;
|
|
|
|
GyroStateData gyroStateData;
|
2013-05-18 14:17:26 +02:00
|
|
|
FlightStatusData flightStatus;
|
2013-12-10 21:07:56 +01:00
|
|
|
StabilizationBankData stabBank;
|
|
|
|
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-07-20 13:52:45 +02:00
|
|
|
#ifdef REVOLUTION
|
|
|
|
AirspeedStateData airspeedState;
|
|
|
|
#endif
|
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
SettingsUpdatedCb((UAVObjEvent *)NULL);
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Main task loop
|
|
|
|
ZeroPids();
|
|
|
|
while (1) {
|
|
|
|
float dT;
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
#ifdef PIOS_INCLUDE_WDG
|
|
|
|
PIOS_WDG_UpdateFlag(PIOS_WDG_STABILIZATION);
|
|
|
|
#endif
|
2011-07-03 17:45:01 +02:00
|
|
|
|
2013-12-19 09:21:30 +01:00
|
|
|
// Wait until the Gyro object is updated, if a timeout then go to failsafe
|
2013-05-18 14:17:26 +02:00
|
|
|
if (xQueueReceive(queue, &ev, FAILSAFE_TIMEOUT_MS / portTICK_RATE_MS) != pdTRUE) {
|
|
|
|
AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_WARNING);
|
|
|
|
continue;
|
|
|
|
}
|
2011-07-03 17:45:01 +02:00
|
|
|
|
2014-02-04 19:05:17 +01:00
|
|
|
dT = PIOS_DELTATIME_GetAverageSeconds(&timeval);
|
2013-05-18 14:17:26 +02:00
|
|
|
FlightStatusGet(&flightStatus);
|
|
|
|
StabilizationDesiredGet(&stabDesired);
|
2014-02-09 19:33:29 +01:00
|
|
|
ManualControlCommandThrottleGet(&throttleDesired);
|
2013-05-18 19:36:45 +02:00
|
|
|
AttitudeStateGet(&attitudeState);
|
|
|
|
GyroStateGet(&gyroStateData);
|
2013-12-10 21:07:56 +01:00
|
|
|
StabilizationBankGet(&stabBank);
|
2013-05-18 14:17:26 +02:00
|
|
|
#ifdef DIAG_RATEDESIRED
|
|
|
|
RateDesiredGet(&rateDesired);
|
|
|
|
#endif
|
2014-01-15 20:37:13 +01:00
|
|
|
uint8_t flight_mode_switch_position;
|
|
|
|
ManualControlCommandFlightModeSwitchPositionGet(&flight_mode_switch_position);
|
2013-12-10 21:10:01 +01:00
|
|
|
|
2014-01-15 20:37:13 +01:00
|
|
|
if (cur_flight_mode != flight_mode_switch_position) {
|
|
|
|
cur_flight_mode = flight_mode_switch_position;
|
2013-12-11 14:56:00 +01:00
|
|
|
SettingsBankUpdatedCb(NULL);
|
2013-12-10 21:10:01 +01:00
|
|
|
}
|
|
|
|
|
2013-07-20 13:52:45 +02:00
|
|
|
#ifdef REVOLUTION
|
|
|
|
float speedScaleFactor;
|
|
|
|
// Scale PID coefficients based on current airspeed estimation - needed for fixed wing planes
|
2013-07-20 14:52:22 +02:00
|
|
|
AirspeedStateGet(&airspeedState);
|
2013-07-20 16:59:00 +02:00
|
|
|
if (settings.ScaleToAirspeed < 0.1f || airspeedState.CalibratedAirspeed < 0.1f) {
|
2013-07-20 13:52:45 +02:00
|
|
|
// feature has been turned off
|
|
|
|
speedScaleFactor = 1.0f;
|
|
|
|
} else {
|
|
|
|
// scale the factor to be 1.0 at the specified airspeed (for example 10m/s) but scaled by 1/speed^2
|
|
|
|
speedScaleFactor = (settings.ScaleToAirspeed * settings.ScaleToAirspeed) / (airspeedState.CalibratedAirspeed * airspeedState.CalibratedAirspeed);
|
2013-09-01 12:10:55 +02:00
|
|
|
if (speedScaleFactor < settings.ScaleToAirspeedLimits.Min) {
|
|
|
|
speedScaleFactor = settings.ScaleToAirspeedLimits.Min;
|
2013-07-20 13:52:45 +02:00
|
|
|
}
|
2013-09-01 12:10:55 +02:00
|
|
|
if (speedScaleFactor > settings.ScaleToAirspeedLimits.Max) {
|
|
|
|
speedScaleFactor = settings.ScaleToAirspeedLimits.Max;
|
2013-07-20 13:52:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
const float speedScaleFactor = 1.0f;
|
|
|
|
#endif
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
#if defined(PIOS_QUATERNION_STABILIZATION)
|
|
|
|
// Quaternion calculation of error in each axis. Uses more memory.
|
|
|
|
float rpy_desired[3];
|
|
|
|
float q_desired[4];
|
|
|
|
float q_error[4];
|
|
|
|
float local_error[3];
|
|
|
|
|
|
|
|
// Essentially zero errors for anything in rate or none
|
2013-09-01 12:10:55 +02:00
|
|
|
if (stabDesired.StabilizationMode.Roll == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) {
|
2013-05-18 14:17:26 +02:00
|
|
|
rpy_desired[0] = stabDesired.Roll;
|
|
|
|
} else {
|
2013-05-18 19:36:45 +02:00
|
|
|
rpy_desired[0] = attitudeState.Roll;
|
2013-05-18 14:17:26 +02:00
|
|
|
}
|
|
|
|
|
2013-09-01 12:10:55 +02:00
|
|
|
if (stabDesired.StabilizationMode.Pitch == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) {
|
2013-05-18 14:17:26 +02:00
|
|
|
rpy_desired[1] = stabDesired.Pitch;
|
|
|
|
} else {
|
2013-05-18 19:36:45 +02:00
|
|
|
rpy_desired[1] = attitudeState.Pitch;
|
2013-05-18 14:17:26 +02:00
|
|
|
}
|
|
|
|
|
2013-09-01 12:10:55 +02:00
|
|
|
if (stabDesired.StabilizationMode.Yaw == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) {
|
2013-05-18 14:17:26 +02:00
|
|
|
rpy_desired[2] = stabDesired.Yaw;
|
|
|
|
} else {
|
2013-05-18 19:36:45 +02:00
|
|
|
rpy_desired[2] = attitudeState.Yaw;
|
2013-05-18 14:17:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RPY2Quaternion(rpy_desired, q_desired);
|
|
|
|
quat_inverse(q_desired);
|
2013-05-18 19:36:45 +02:00
|
|
|
quat_mult(q_desired, &attitudeState.q1, q_error);
|
2013-05-18 14:17:26 +02:00
|
|
|
quat_inverse(q_error);
|
|
|
|
Quaternion2RPY(q_error, local_error);
|
|
|
|
|
|
|
|
#else /* if defined(PIOS_QUATERNION_STABILIZATION) */
|
|
|
|
// Simpler algorithm for CC, less memory
|
2014-01-14 20:03:42 +01:00
|
|
|
float local_error[3] = { stabDesired.Roll - attitudeState.Roll,
|
2013-05-18 19:36:45 +02:00
|
|
|
stabDesired.Pitch - attitudeState.Pitch,
|
2014-01-14 20:03:42 +01:00
|
|
|
stabDesired.Yaw - attitudeState.Yaw };
|
2013-05-18 14:17:26 +02:00
|
|
|
// find shortest way
|
|
|
|
float modulo = fmodf(local_error[2] + 180.0f, 360.0f);
|
|
|
|
if (modulo < 0) {
|
|
|
|
local_error[2] = modulo + 180.0f;
|
|
|
|
} else {
|
|
|
|
local_error[2] = modulo - 180.0f;
|
|
|
|
}
|
|
|
|
#endif /* if defined(PIOS_QUATERNION_STABILIZATION) */
|
|
|
|
|
|
|
|
float gyro_filtered[3];
|
2013-05-18 19:36:45 +02:00
|
|
|
gyro_filtered[0] = gyro_filtered[0] * gyro_alpha + gyroStateData.x * (1 - gyro_alpha);
|
|
|
|
gyro_filtered[1] = gyro_filtered[1] * gyro_alpha + gyroStateData.y * (1 - gyro_alpha);
|
|
|
|
gyro_filtered[2] = gyro_filtered[2] * gyro_alpha + gyroStateData.z * (1 - gyro_alpha);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
2013-12-16 04:02:06 +01:00
|
|
|
float *stabDesiredAxis = &stabDesired.Roll;
|
2013-05-18 14:17:26 +02:00
|
|
|
float *actuatorDesiredAxis = &actuatorDesired.Roll;
|
|
|
|
float *rateDesiredAxis = &rateDesired.Roll;
|
|
|
|
|
|
|
|
ActuatorDesiredGet(&actuatorDesired);
|
|
|
|
|
|
|
|
// A flag to track which stabilization mode each axis is in
|
|
|
|
static uint8_t previous_mode[MAX_AXES] = { 255, 255, 255 };
|
|
|
|
bool error = false;
|
|
|
|
|
|
|
|
// Run the selected stabilization algorithm on each axis:
|
|
|
|
for (uint8_t i = 0; i < MAX_AXES; i++) {
|
|
|
|
// Check whether this axis mode needs to be reinitialized
|
2013-09-01 12:10:55 +02:00
|
|
|
bool reinit = (cast_struct_to_array(stabDesired.StabilizationMode, stabDesired.StabilizationMode.Roll)[i] != previous_mode[i]);
|
|
|
|
previous_mode[i] = cast_struct_to_array(stabDesired.StabilizationMode, stabDesired.StabilizationMode.Roll)[i];
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Apply the selected control law
|
2013-09-01 12:10:55 +02:00
|
|
|
switch (cast_struct_to_array(stabDesired.StabilizationMode, stabDesired.StabilizationMode.Roll)[i]) {
|
2013-05-18 14:17:26 +02:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATE:
|
|
|
|
if (reinit) {
|
|
|
|
pids[PID_RATE_ROLL + i].iAccumulator = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store to rate desired variable for storing to UAVO
|
2013-09-01 12:10:55 +02:00
|
|
|
rateDesiredAxis[i] =
|
2014-01-10 20:32:44 +01:00
|
|
|
bound(stabDesiredAxis[i], cast_struct_to_array(stabBank.ManualRate, stabBank.ManualRate.Roll)[i]);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Compute the inner loop
|
2013-08-11 15:12:17 +02:00
|
|
|
actuatorDesiredAxis[i] = pid_apply_setpoint(&pids[PID_RATE_ROLL + i], speedScaleFactor, rateDesiredAxis[i], gyro_filtered[i], dT);
|
2013-05-18 14:17:26 +02:00
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE:
|
|
|
|
if (reinit) {
|
|
|
|
pids[PID_ROLL + i].iAccumulator = 0;
|
|
|
|
pids[PID_RATE_ROLL + i].iAccumulator = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the outer loop
|
2013-09-01 12:10:55 +02:00
|
|
|
rateDesiredAxis[i] = pid_apply(&pids[PID_ROLL + i], local_error[i], dT);
|
|
|
|
rateDesiredAxis[i] = bound(rateDesiredAxis[i],
|
2013-12-10 21:07:56 +01:00
|
|
|
cast_struct_to_array(stabBank.MaximumRate, stabBank.MaximumRate.Roll)[i]);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Compute the inner loop
|
2013-08-11 15:12:17 +02:00
|
|
|
actuatorDesiredAxis[i] = pid_apply_setpoint(&pids[PID_RATE_ROLL + i], speedScaleFactor, rateDesiredAxis[i], gyro_filtered[i], dT);
|
2013-05-18 14:17:26 +02:00
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2013-12-18 11:01:16 +01:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE:
|
2014-01-14 20:03:42 +01:00
|
|
|
// A parameterization from Attitude mode at center stick
|
|
|
|
// - to Rate mode at full stick
|
|
|
|
// This is done by parameterizing to use the rotation rate that Attitude mode
|
|
|
|
// - would use at center stick to using the rotation rate that Rate mode
|
|
|
|
// - would use at full stick in a weighted average sort of way.
|
2013-12-16 04:02:06 +01:00
|
|
|
{
|
|
|
|
if (reinit) {
|
2014-01-14 20:03:42 +01:00
|
|
|
pids[PID_ROLL + i].iAccumulator = 0;
|
|
|
|
pids[PID_RATE_ROLL + i].iAccumulator = 0;
|
2013-12-16 04:02:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute what Rate mode would give for this stick angle's rate
|
2014-01-04 10:22:54 +01:00
|
|
|
// Save Rate's rate in a temp for later merging with Attitude's rate
|
2013-12-16 04:02:06 +01:00
|
|
|
float rateDesiredAxisRate;
|
|
|
|
rateDesiredAxisRate = bound(stabDesiredAxis[i], 1.0f)
|
2014-01-14 20:03:42 +01:00
|
|
|
* cast_struct_to_array(stabBank.ManualRate, stabBank.ManualRate.Roll)[i];
|
2013-12-16 04:02:06 +01:00
|
|
|
|
|
|
|
// Compute what Attitude mode would give for this stick angle's rate
|
|
|
|
|
|
|
|
// stabDesired for this mode is [-1.0f,+1.0f]
|
|
|
|
// - multiply by Attitude mode max angle to get desired angle
|
|
|
|
// - subtract off the actual angle to get the angle error
|
|
|
|
// This is what local_error[] holds for Attitude mode
|
|
|
|
float attitude_error = stabDesiredAxis[i]
|
2014-01-14 20:03:42 +01:00
|
|
|
* cast_struct_to_array(stabBank.RollMax, stabBank.RollMax)[i]
|
|
|
|
- cast_struct_to_array(attitudeState.Roll, attitudeState.Roll)[i];
|
2013-12-16 04:02:06 +01:00
|
|
|
|
|
|
|
// Compute the outer loop just like Attitude mode does
|
|
|
|
float rateDesiredAxisAttitude;
|
|
|
|
rateDesiredAxisAttitude = pid_apply(&pids[PID_ROLL + i], attitude_error, dT);
|
|
|
|
rateDesiredAxisAttitude = bound(rateDesiredAxisAttitude,
|
2014-03-14 06:47:37 +01:00
|
|
|
cast_struct_to_array(stabBank.ManualRate,
|
|
|
|
stabBank.ManualRate.Roll)[i]);
|
2013-12-16 04:02:06 +01:00
|
|
|
|
|
|
|
// Compute the weighted average rate desired
|
|
|
|
// Using max() rather than sqrt() for cpu speed;
|
|
|
|
// - this makes the stick region into a square;
|
|
|
|
// - this is a feature!
|
|
|
|
// - hold a roll angle and add just pitch without the stick sensitivity changing
|
|
|
|
// magnitude = sqrt(stabDesired.Roll*stabDesired.Roll + stabDesired.Pitch*stabDesired.Pitch);
|
|
|
|
float magnitude;
|
|
|
|
magnitude = fmaxf(fabsf(stabDesired.Roll), fabsf(stabDesired.Pitch));
|
2014-03-14 06:47:37 +01:00
|
|
|
|
|
|
|
// modify magnitude to move the Att to Rate transition to the place
|
|
|
|
// specified by the user
|
|
|
|
// we are looking for where the stick angle == transition angle
|
|
|
|
// and the Att rate equals the Rate rate
|
|
|
|
// that's where Rate x (1-StickAngle) [Attitude pulling down max X Ratt proportion]
|
|
|
|
// == Rate x StickAngle [Rate pulling up according to stick angle]
|
|
|
|
// * StickAngle [X Ratt proportion]
|
|
|
|
// so 1-x == x*x or x*x+x-1=0 where xE(0,1)
|
|
|
|
// (-1+-sqrt(1+4))/2 = (-1+sqrt(5))/2
|
|
|
|
// and quadratic formula says that is 0.618033989f
|
|
|
|
// I tested 14.01 and came up with .61 without even remembering this number
|
|
|
|
// I thought that moving the P,I, and maxangle terms around would change this value
|
|
|
|
// and that I would have to take these into account, but varying
|
|
|
|
// all P's and I's by factors of 1/2 to 2 didn't change it noticeably
|
|
|
|
// and varying maxangle from 4 to 120 didn't either.
|
|
|
|
// so for now I'm not taking these into account
|
|
|
|
// while working with this, it occurred to me that Attitude mode,
|
|
|
|
// set up with maxangle=190 would be similar to Ratt, and it is.
|
|
|
|
#define STICK_VALUE_AT_MODE_TRANSITION 0.618033989f
|
|
|
|
|
|
|
|
// the following assumes the transition would otherwise be at 0.618033989f
|
2014-03-26 18:48:24 +01:00
|
|
|
// and THAT assumes that Att ramps up to max roll rate
|
2014-03-14 06:47:37 +01:00
|
|
|
// when a small number of degrees off of where it should be
|
|
|
|
|
|
|
|
// if below the transition angle (still in attitude mode)
|
2014-03-20 17:41:48 +01:00
|
|
|
// '<=' instead of '<' keeps rattitude_mode_transition_stick_position==1.0 from causing DZ
|
2014-03-18 03:40:19 +01:00
|
|
|
if (magnitude <= rattitude_mode_transition_stick_position) {
|
2014-03-14 06:47:37 +01:00
|
|
|
magnitude *= STICK_VALUE_AT_MODE_TRANSITION / rattitude_mode_transition_stick_position;
|
|
|
|
} else {
|
2014-03-26 18:48:24 +01:00
|
|
|
magnitude = (magnitude - rattitude_mode_transition_stick_position)
|
|
|
|
* (1.0f-STICK_VALUE_AT_MODE_TRANSITION)
|
|
|
|
/ (1.0f - rattitude_mode_transition_stick_position)
|
|
|
|
+ STICK_VALUE_AT_MODE_TRANSITION;
|
2014-03-14 06:47:37 +01:00
|
|
|
}
|
2014-01-14 20:03:42 +01:00
|
|
|
rateDesiredAxis[i] = (1.0f - magnitude) * rateDesiredAxisAttitude
|
|
|
|
+ magnitude * rateDesiredAxisRate;
|
2013-12-16 04:02:06 +01:00
|
|
|
|
2014-03-14 06:47:37 +01:00
|
|
|
// Compute the inner loop for the averaged rate
|
|
|
|
// actuatorDesiredAxis[i] is the weighted average
|
2014-03-26 18:48:24 +01:00
|
|
|
actuatorDesiredAxis[i] = pid_apply_setpoint(&pids[PID_RATE_ROLL + i], speedScaleFactor,
|
|
|
|
rateDesiredAxis[i], gyro_filtered[i], dT);
|
2014-03-14 06:47:37 +01:00
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
2013-12-16 04:02:06 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR:
|
|
|
|
// Store for debugging output
|
2013-12-16 04:02:06 +01:00
|
|
|
rateDesiredAxis[i] = stabDesiredAxis[i];
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Run a virtual flybar stabilization algorithm on this axis
|
|
|
|
stabilization_virtual_flybar(gyro_filtered[i], rateDesiredAxis[i], &actuatorDesiredAxis[i], dT, reinit, i, &settings);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING:
|
2014-01-14 20:03:42 +01:00
|
|
|
// FIXME: local_error[] is rate - attitude for Weak Leveling
|
|
|
|
// The only ramifications are:
|
|
|
|
// Weak Leveling Kp is off by a factor of 3 to 12 and may need a different default in GCS
|
|
|
|
// Changing Rate mode max rate currently requires a change to Kp
|
|
|
|
// That would be changed to Attitude mode max angle affecting Kp
|
|
|
|
// Also does not take dT into account
|
2013-05-18 14:17:26 +02:00
|
|
|
{
|
|
|
|
if (reinit) {
|
|
|
|
pids[PID_RATE_ROLL + i].iAccumulator = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float weak_leveling = local_error[i] * weak_leveling_kp;
|
|
|
|
weak_leveling = bound(weak_leveling, weak_leveling_max);
|
|
|
|
|
|
|
|
// Compute desired rate as input biased towards leveling
|
2013-12-16 04:02:06 +01:00
|
|
|
rateDesiredAxis[i] = stabDesiredAxis[i] + weak_leveling;
|
2013-08-11 15:12:17 +02:00
|
|
|
actuatorDesiredAxis[i] = pid_apply_setpoint(&pids[PID_RATE_ROLL + i], speedScaleFactor, rateDesiredAxis[i], gyro_filtered[i], dT);
|
2013-05-18 14:17:26 +02:00
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK:
|
|
|
|
if (reinit) {
|
|
|
|
pids[PID_RATE_ROLL + i].iAccumulator = 0;
|
|
|
|
}
|
|
|
|
|
2013-12-16 04:02:06 +01:00
|
|
|
if (fabsf(stabDesiredAxis[i]) > max_axislock_rate) {
|
2013-05-18 14:17:26 +02:00
|
|
|
// While getting strong commands act like rate mode
|
2013-12-16 04:02:06 +01:00
|
|
|
rateDesiredAxis[i] = stabDesiredAxis[i];
|
2013-05-18 14:17:26 +02:00
|
|
|
axis_lock_accum[i] = 0;
|
|
|
|
} else {
|
|
|
|
// For weaker commands or no command simply attitude lock (almost) on no gyro change
|
2013-12-16 04:02:06 +01:00
|
|
|
axis_lock_accum[i] += (stabDesiredAxis[i] - gyro_filtered[i]) * dT;
|
2013-05-18 14:17:26 +02:00
|
|
|
axis_lock_accum[i] = bound(axis_lock_accum[i], max_axis_lock);
|
|
|
|
rateDesiredAxis[i] = pid_apply(&pids[PID_ROLL + i], axis_lock_accum[i], dT);
|
|
|
|
}
|
2011-09-11 19:27:17 +02:00
|
|
|
|
2013-09-01 12:10:55 +02:00
|
|
|
rateDesiredAxis[i] = bound(rateDesiredAxis[i],
|
2013-12-10 21:07:56 +01:00
|
|
|
cast_struct_to_array(stabBank.ManualRate, stabBank.ManualRate.Roll)[i]);
|
2011-06-23 01:51:25 +02:00
|
|
|
|
2013-08-11 15:12:17 +02:00
|
|
|
actuatorDesiredAxis[i] = pid_apply_setpoint(&pids[PID_RATE_ROLL + i], speedScaleFactor, rateDesiredAxis[i], gyro_filtered[i], dT);
|
2013-05-18 14:17:26 +02:00
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
2011-09-11 19:27:17 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
break;
|
2011-06-23 01:51:25 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE:
|
|
|
|
// Store to rate desired variable for storing to UAVO
|
2013-12-16 04:02:06 +01:00
|
|
|
rateDesiredAxis[i] = bound(stabDesiredAxis[i],
|
2013-12-10 21:07:56 +01:00
|
|
|
cast_struct_to_array(stabBank.ManualRate, stabBank.ManualRate.Roll)[i]);
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Run the relay controller which also estimates the oscillation parameters
|
|
|
|
stabilization_relay_rate(rateDesiredAxis[i] - gyro_filtered[i], &actuatorDesiredAxis[i], i, reinit);
|
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
2012-02-22 01:02:37 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
break;
|
2012-02-20 14:29:43 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE:
|
|
|
|
if (reinit) {
|
|
|
|
pids[PID_ROLL + i].iAccumulator = 0;
|
|
|
|
}
|
2012-02-20 14:29:43 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Compute the outer loop like attitude mode
|
|
|
|
rateDesiredAxis[i] = pid_apply(&pids[PID_ROLL + i], local_error[i], dT);
|
2013-09-01 12:10:55 +02:00
|
|
|
rateDesiredAxis[i] = bound(rateDesiredAxis[i],
|
2013-12-10 21:07:56 +01:00
|
|
|
cast_struct_to_array(stabBank.MaximumRate, stabBank.MaximumRate.Roll)[i]);
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Run the relay controller which also estimates the oscillation parameters
|
|
|
|
stabilization_relay_rate(rateDesiredAxis[i] - gyro_filtered[i], &actuatorDesiredAxis[i], i, reinit);
|
|
|
|
actuatorDesiredAxis[i] = bound(actuatorDesiredAxis[i], 1.0f);
|
2012-07-31 03:55:43 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
break;
|
2011-06-23 01:51:25 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
case STABILIZATIONDESIRED_STABILIZATIONMODE_NONE:
|
2013-12-16 04:02:06 +01:00
|
|
|
actuatorDesiredAxis[i] = bound(stabDesiredAxis[i], 1.0f);
|
2013-05-18 14:17:26 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-06-23 01:51:25 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
if (settings.VbarPiroComp == STABILIZATIONSETTINGS_VBARPIROCOMP_TRUE) {
|
|
|
|
stabilization_virtual_flybar_pirocomp(gyro_filtered[2], dT);
|
|
|
|
}
|
2012-07-31 03:55:43 +02:00
|
|
|
|
Final step: lot of small fixes, last commit in this commit series
This is the first cleanup pass through makefiles and pios.
Probably it is difficult to track changes due to the nature of them.
I would recommend to look at resulting files and compiled code instead.
NOTE: original branch was rebased and lot of conflicts were fixed on
the way. So do not expect that every commit in this series will be
buildable (unlike original branch). Only final result was tested.
The main goal was to remove as much duplication of code (and copy/paste
errors) as possible, moving common parts out of Makefiles. It still is
not perfect, and mostly no code changes made - Makefiles and #ifdefs only.
But please while testing make sure that all code works as before, and no
modules/options are missed by accident.
Brief list of changes:
- Moved common parts of Makefiles into the set of *.mk files.
- Changed method of passing common vars from top Makefile to lower ones.
- Some pios cleanup, mostly #ifdefs, and all pios_config.h files.
- Many obsolete files removed (for instance, AHRS files, op_config.h).
- Many obsolete or unused macros removed or fixed/renamed (ALL_DIGNOSTICS).
- Unified pios_config.h template. Please don't remove lines for board
configs, only comment/uncomment them. Adding new PIOS options, please
propagate them to all board files keeping the same order.
- Some formatting, spacing, indentation (no line endings change yet).
- Some cosmetic fixes (no more C:\X\Y\filename.c printings on Windows).
- Added some library.mk files to move libs into AR achives later.
- EntireFlash target now uses cross-platform python script to generate bin
files. So it works on all supported platforms: Linux, OSX, Windows.
- Top level packaging is completely rewritten. Now it is a part of top
Makefile. As such, all dependencies are checked and accounted, no
more 'make -j' problems should occur.
- Default GCS_BUILD_CONF is release now, may be changed if necessary
using 'make GCS_BUILD_CONF=debug gcs'.
- GCS build paths are separated into debug and release, so no more obj
file clashes. Packaging system supports only release builds.
- New target is introduced: 'clean_package'. Now 'make package' does not
clean build directory. Use clean_package instead for distributable builds.
- Targets like 'all', 'opfw_resource', etc now will print extra contex
in parallel builds too.
- If any of 'package', 'clean_package', 'opfw_resource' targets are given
on command line, GCS build will depend on the resource, so all fw_*.opfw
targets will be built and embedded into GCS. By default GCS does not
depend on resource, and will be built w/o firmware (unless the resource
files already exist and the Qt resource file is generated).
- fw_simposix (ELF executable) is now packaged for linux. Run'n'play!
- Make help is refined and is now up to date.
Still broken:
- UnitTests, should be fixed
- SimPosix: buildable, but should be reworked.
Next planned passes to do:
- toolchain bootstrapping and packaging (including windows - WIP)
- CMSIS/StdPeriph lib cleanup
- more PIOS cleanup
- move libs into AR archives to save build time
- sim targets refactir and cleanup
- move android-related directories under <top>/android
- unit test targets fix
- source code line ending changes (there are many different, were not changed)
- coding style
Merging this, please use --no-ff git option to make it the real commit point
Conflicts:
A lot of... :-)
2013-03-24 12:02:08 +01:00
|
|
|
#ifdef DIAG_RATEDESIRED
|
2013-05-18 14:17:26 +02:00
|
|
|
RateDesiredSet(&rateDesired);
|
2012-07-31 03:55:43 +02:00
|
|
|
#endif
|
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Save dT
|
|
|
|
actuatorDesired.UpdateTime = dT * 1000;
|
2014-02-09 19:33:29 +01:00
|
|
|
actuatorDesired.Thrust = stabDesired.Thrust;
|
2013-05-18 14:17:26 +02:00
|
|
|
|
2014-03-22 06:18:06 +01:00
|
|
|
// Cruise Control
|
2014-02-09 19:33:29 +01:00
|
|
|
// modify thrust according to 1/cos(bank angle)
|
2014-03-22 06:18:06 +01:00
|
|
|
// to maintain same altitude with changing bank angle
|
2014-02-09 19:33:29 +01:00
|
|
|
// but without manually adjusting thrust
|
2014-01-11 22:22:20 +01:00
|
|
|
// do it here and all the various flight modes (e.g. Altitude Hold) can use it
|
2014-03-22 03:34:03 +01:00
|
|
|
if (flight_mode_switch_position < FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_NUMELEM
|
2014-01-18 00:32:50 +01:00
|
|
|
&& cruise_control_flight_mode_switch_pos_enable[flight_mode_switch_position] != (uint8_t)0
|
2014-01-15 19:53:14 +01:00
|
|
|
&& cruise_control_max_power_factor > 0.0001f) {
|
2014-01-11 22:22:20 +01:00
|
|
|
static float factor;
|
2014-03-26 18:48:24 +01:00
|
|
|
static float previous_angle;
|
2014-03-22 06:18:06 +01:00
|
|
|
static uint32_t previous_time;
|
2014-03-26 18:48:24 +01:00
|
|
|
static bool previous_time_valid; // initially false
|
|
|
|
static bool inverted_flight_mode;
|
2014-03-22 06:18:06 +01:00
|
|
|
static uint8_t calc_count;
|
2014-03-26 18:48:24 +01:00
|
|
|
static uint8_t previous_flight_mode_switch_position;
|
2014-03-22 06:18:06 +01:00
|
|
|
uint32_t time;
|
|
|
|
|
2014-03-26 18:48:24 +01:00
|
|
|
// flight mode has changed. there could be a time gap. leave thrust alone.
|
|
|
|
// angle could be invalid because of the time spent with CC off
|
|
|
|
// if (cruise_control_flight_mode_switch_pos_enable[flight_mode_switch_position] != cruise_control_flight_mode_switch_pos_enable[previous_flight_mode_switch_position]) {
|
2014-03-22 06:18:06 +01:00
|
|
|
if (flight_mode_switch_position != previous_flight_mode_switch_position) {
|
2014-03-26 18:48:24 +01:00
|
|
|
previous_flight_mode_switch_position = flight_mode_switch_position;
|
|
|
|
// flag to skip delay comp calculations and just use thrust as it is
|
|
|
|
// because time diff may be invalid
|
|
|
|
previous_time_valid = false;
|
2014-03-22 06:18:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
time = PIOS_DELAY_GetuS(); // good for 72 minutes, then it wraps (handled OK)
|
2014-01-11 22:22:20 +01:00
|
|
|
// get attitude state and calculate angle
|
|
|
|
// do it every 8th iteration to save CPU
|
2014-03-26 18:48:24 +01:00
|
|
|
if ((time != previous_time && calc_count++ >= 8) || previous_time_valid == false) {
|
|
|
|
float angle;
|
2014-03-22 06:18:06 +01:00
|
|
|
|
|
|
|
calc_count = 0;
|
|
|
|
|
2014-01-11 22:22:20 +01:00
|
|
|
// spherical right triangle
|
2014-03-26 18:48:24 +01:00
|
|
|
// 0 <= acosf() <= Pi(180)
|
2014-01-11 22:22:20 +01:00
|
|
|
angle = RAD2DEG(acosf(cos_lookup_deg(attitudeState.Roll) * cos_lookup_deg(attitudeState.Pitch)));
|
2014-03-22 06:18:06 +01:00
|
|
|
|
|
|
|
// combined bank angle change rate in degrees per second
|
|
|
|
// rate is currently calculated over the most recent CALCCOUNT loops
|
2014-03-26 18:48:24 +01:00
|
|
|
// it may be that the angle doesn't change at all between two consecutive passes
|
|
|
|
// because the sensors aren't read that often
|
2014-03-22 06:18:06 +01:00
|
|
|
// keeping the sign for rate is important, it can be negative
|
2014-03-26 18:48:24 +01:00
|
|
|
if (previous_time_valid) {
|
|
|
|
float rate;
|
2014-03-22 06:18:06 +01:00
|
|
|
// handle wrap around
|
|
|
|
// the assumption here is that it's been less than 0x7fffffff since prev_time
|
|
|
|
// and thus likewise since time
|
|
|
|
// i.e. that casting prev_time to a signed type produces a negative
|
|
|
|
if (time >= previous_time) { // the usual case
|
|
|
|
rate = (angle - previous_angle) / ((float) (time - previous_time) / 1000000.0f);
|
|
|
|
} else { // the wrap around case
|
|
|
|
rate = (angle - previous_angle) / ((float) ((uint32_t) ((int32_t) time - (int32_t) previous_time)) / 1000000.0f);
|
|
|
|
}
|
|
|
|
|
2014-03-26 18:48:24 +01:00
|
|
|
// define "within range" to be those transitions that should be executing now
|
|
|
|
// - recall that each impulse transition is spread out over a range of time / angle
|
|
|
|
|
|
|
|
// there is only one transition and the high power level for it is either
|
|
|
|
// = full thrust
|
|
|
|
// = max power factor
|
|
|
|
// = 1/fabsf(cos(angle))
|
|
|
|
// OK, you could say there are two transitions in 360 degrees (90 and 270)
|
|
|
|
|
|
|
|
if (actuatorDesired.Thrust > 0.0f) {
|
|
|
|
float max_thrust;
|
|
|
|
// calculate the max positive thrust at the transition
|
|
|
|
// <5% t<5
|
|
|
|
// 5.01% 19.3
|
|
|
|
// 10% 38.6
|
|
|
|
// 50% max
|
|
|
|
// 100% max
|
|
|
|
thrust = CruiseControlFactorToThrust(CruiseControlAngleToFactor(cruise_control_max_angle), actuatorDesired.Thrust);
|
|
|
|
|
|
|
|
/*
|
|
|
|
revisit all the GCS settings
|
|
|
|
51 <= maxt <= 100
|
|
|
|
No (0 <= mint <= 49 plus -51 -> -100)
|
|
|
|
0 <= mint <= 49 or maybe -100 -> 49
|
|
|
|
1 <= mpf <= 50
|
|
|
|
50 <= trim <= 200
|
|
|
|
?? <= maxa <= 255?
|
|
|
|
0 <= pdc <= 2?
|
|
|
|
*/
|
|
|
|
|
|
|
|
// determine if we are in range of the transition
|
|
|
|
|
|
|
|
//CP helis go -max to +max and have min set to 0 and max to +1
|
|
|
|
|
|
|
|
//min_thrust is defined to be where the power goes when inverted
|
|
|
|
|
|
|
|
// calculate the actual proportion of change in thrust
|
|
|
|
switch (cruise_control_inverted_power_switch) {
|
|
|
|
case -3:
|
|
|
|
case -2:
|
|
|
|
// CP heli case, stroke is max to -max
|
|
|
|
thrust = (thrust + thrust) / cruise_control_thrust_difference;
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
// CP heli case, stroke is max to -stick
|
|
|
|
thrust = (thrust + CruiseControlLimitThrust(actuatorDesired.Thrust)) / cruise_control_thrust_difference;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
// normal multi-copter case, stroke is max to zero
|
|
|
|
// technically max to constant min_thrust
|
|
|
|
// can be used by CP
|
|
|
|
thrust = (thrust - cruise_control_min_thrust) / cruise_control_thrust_difference;
|
|
|
|
//shit, cruise_control_thrust_difference is a problem, maybe remove it
|
|
|
|
//thrust_difference is always max-min, and now for CP it needs to be max+max here
|
|
|
|
//maybe not a problem since we don't limit thrust on the negative side any more
|
|
|
|
//CP: max=1.0, min=-1.0 diff=2.0
|
|
|
|
//MR: max=0.9, min=0.1 diff=0.8
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// simply turn off boost, stroke is max to +stick
|
|
|
|
thrust = (thrust - CruiseControlLimitThrust(actuatorDesired.Thrust)) / cruise_control_thrust_difference;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// CP heli case, no transition, stroke is zero
|
|
|
|
thrust = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// multiply this proportion of max stroke, times the max stroke time, to get this stroke time
|
|
|
|
// we only want half of this time before the transition (and half after the transition)
|
|
|
|
thrust *= cruise_control_half_power_delay;
|
|
|
|
// times angular rate gives angle that this stroke will take to execute
|
|
|
|
thrust *= fabsf(rate);
|
|
|
|
// if the transition is within range we use it, else we just use the current calculated thrust
|
|
|
|
if (cruise_control_max_angle - thrust < angle
|
|
|
|
&& angle < cruise_control_max_angle + thrust) {
|
|
|
|
// default to a little above max angle
|
|
|
|
angle = cruise_control_max_angle + 0.01f;
|
|
|
|
// if roll direction is downward then thrust value is taken from below max angle
|
|
|
|
if (rate < 0.0f) {
|
|
|
|
angle -= 0.02f;
|
|
|
|
}
|
2014-01-11 22:22:20 +01:00
|
|
|
}
|
2014-03-22 06:18:06 +01:00
|
|
|
|
2014-03-26 18:48:24 +01:00
|
|
|
factor = CruiseControlAngleToFactor(angle);
|
|
|
|
} else { // if thrust > 0 set factor from angle; else
|
|
|
|
factor = 1.0f;
|
2014-03-22 06:18:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
convert these to enums? something like
|
|
|
|
upright power: zero, normal, boosted
|
|
|
|
inverted thrust direction: unchanged, reversed
|
|
|
|
inverted power: zero, normal, boosted
|
|
|
|
inverted yaw/pitch reverse: off, on
|
|
|
|
*/
|
2014-03-26 18:48:24 +01:00
|
|
|
inverted_flight_mode = false;
|
|
|
|
// if past max angle and so needing to go into an inverted mode
|
|
|
|
if (angle >= cruise_control_max_angle) {
|
|
|
|
// -3 inverted mode, -2 boosted reverse, -1 normal reverse, 0 zero power, 1 normal power, 2 boosted power
|
|
|
|
switch (cruise_control_inverted_power_switch) {
|
|
|
|
case -3: // reversed boosted thrust with pitch/yaw reverse
|
|
|
|
inverted_flight_mode = true;
|
|
|
|
factor = -factor;
|
|
|
|
break;
|
|
|
|
case -2: // reversed boosted thrust
|
|
|
|
factor = -factor;
|
|
|
|
break;
|
|
|
|
case -1: // reversed normal thrust
|
|
|
|
factor = -1.0f;
|
|
|
|
break;
|
|
|
|
case 0: // no thrust
|
|
|
|
factor = 0.0f;
|
|
|
|
break;
|
|
|
|
case 1: // normal thrust
|
|
|
|
factor = 1.0f;
|
|
|
|
break;
|
|
|
|
case 2: // normal boosted thrust
|
|
|
|
// no change to factor
|
|
|
|
break;
|
|
|
|
}
|
2014-01-11 22:22:20 +01:00
|
|
|
}
|
2014-03-26 18:48:24 +01:00
|
|
|
} // if previous_time_valid i.e. we've got a rate; else leave (angle and) factor alone
|
|
|
|
previous_time = time;
|
|
|
|
previous_time_valid = true;
|
|
|
|
previous_angle = angle;
|
|
|
|
} // every 8th time
|
|
|
|
|
|
|
|
// don't touch thrust if it's less than min_thrust
|
|
|
|
// without this test, props will spin up to min thrust even at zero throttle stick
|
|
|
|
actuatorDesired.Thrust = CruiseControlFactorToThrust(factor, actuatorDesired.Thrust);
|
|
|
|
if (inverted_flight_mode) {
|
|
|
|
actuatorDesired.Pitch = -actuatorDesired.Pitch;
|
|
|
|
actuatorDesired.Yaw = -actuatorDesired.Yaw;
|
2014-01-11 22:22:20 +01:00
|
|
|
}
|
2014-03-26 18:48:24 +01:00
|
|
|
} // if Cruise Control is enabled on this flight switch position
|
2014-03-22 06:18:06 +01:00
|
|
|
|
2014-02-16 19:07:31 +01:00
|
|
|
if (flightStatus.ControlChain.Stabilization == FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
|
2013-05-18 14:17:26 +02:00
|
|
|
ActuatorDesiredSet(&actuatorDesired);
|
|
|
|
} else {
|
|
|
|
// Force all axes to reinitialize when engaged
|
|
|
|
for (uint8_t i = 0; i < MAX_AXES; i++) {
|
|
|
|
previous_mode[i] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flightStatus.Armed != FLIGHTSTATUS_ARMED_ARMED ||
|
2014-02-09 19:33:29 +01:00
|
|
|
(lowThrottleZeroIntegral && throttleDesired < 0)) {
|
2013-05-18 14:17:26 +02:00
|
|
|
// Force all axes to reinitialize when engaged
|
|
|
|
for (uint8_t i = 0; i < MAX_AXES; i++) {
|
|
|
|
previous_mode[i] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear or set alarms. Done like this to prevent toggline each cycle
|
|
|
|
// and hammering system alarms
|
|
|
|
if (error) {
|
|
|
|
AlarmsSet(SYSTEMALARMS_ALARM_STABILIZATION, SYSTEMALARMS_ALARM_ERROR);
|
|
|
|
} else {
|
|
|
|
AlarmsClear(SYSTEMALARMS_ALARM_STABILIZATION);
|
|
|
|
}
|
|
|
|
}
|
2010-10-03 22:39:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-31 03:55:43 +02:00
|
|
|
/**
|
|
|
|
* Clear the accumulators and derivatives for all the axes
|
|
|
|
*/
|
2010-10-03 22:39:23 +02:00
|
|
|
static void ZeroPids(void)
|
|
|
|
{
|
2013-05-18 14:17:26 +02:00
|
|
|
for (uint32_t i = 0; i < PID_MAX; i++) {
|
|
|
|
pid_zero(&pids[i]);
|
|
|
|
}
|
2012-08-02 11:12:12 +02:00
|
|
|
|
2012-09-10 10:10:26 +02:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
for (uint8_t i = 0; i < 3; i++) {
|
|
|
|
axis_lock_accum[i] = 0.0f;
|
|
|
|
}
|
2010-10-03 22:39:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Bound input value between limits
|
|
|
|
*/
|
2012-07-31 03:55:43 +02:00
|
|
|
static float bound(float val, float range)
|
2010-10-03 22:39:23 +02:00
|
|
|
{
|
2013-05-18 14:17:26 +02:00
|
|
|
if (val < -range) {
|
2014-01-11 22:22:20 +01:00
|
|
|
return -range;
|
2013-05-18 14:17:26 +02:00
|
|
|
} else if (val > range) {
|
2014-01-11 22:22:20 +01:00
|
|
|
return range;
|
2013-05-18 14:17:26 +02:00
|
|
|
}
|
|
|
|
return val;
|
2010-10-03 22:39:23 +02:00
|
|
|
}
|
|
|
|
|
2014-01-04 10:22:54 +01:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
static void SettingsBankUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
|
2010-10-03 22:39:23 +02:00
|
|
|
{
|
2014-03-22 03:34:03 +01:00
|
|
|
if (cur_flight_mode < 0 || cur_flight_mode >= FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_NUMELEM) {
|
2014-01-14 20:03:42 +01:00
|
|
|
return;
|
|
|
|
}
|
2014-01-22 00:01:38 +01:00
|
|
|
if ((ev) && ((settings.FlightModeMap[cur_flight_mode] == 0 && ev->obj != StabilizationSettingsBank1Handle()) ||
|
|
|
|
(settings.FlightModeMap[cur_flight_mode] == 1 && ev->obj != StabilizationSettingsBank2Handle()) ||
|
|
|
|
(settings.FlightModeMap[cur_flight_mode] == 2 && ev->obj != StabilizationSettingsBank3Handle()) ||
|
|
|
|
settings.FlightModeMap[cur_flight_mode] > 2)) {
|
2014-01-21 22:43:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
StabilizationBankData bank;
|
2013-12-10 20:58:05 +01:00
|
|
|
|
2014-01-15 20:37:13 +01:00
|
|
|
switch (settings.FlightModeMap[cur_flight_mode]) {
|
2013-12-11 14:56:00 +01:00
|
|
|
case 0:
|
2014-01-14 20:03:42 +01:00
|
|
|
StabilizationSettingsBank1Get((StabilizationSettingsBank1Data *)&bank);
|
2013-12-11 14:56:00 +01:00
|
|
|
break;
|
2013-05-18 14:17:26 +02:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
case 1:
|
2014-01-14 20:03:42 +01:00
|
|
|
StabilizationSettingsBank2Get((StabilizationSettingsBank2Data *)&bank);
|
2013-12-11 14:56:00 +01:00
|
|
|
break;
|
2013-05-18 14:17:26 +02:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
case 2:
|
2014-01-14 20:03:42 +01:00
|
|
|
StabilizationSettingsBank3Get((StabilizationSettingsBank3Data *)&bank);
|
2013-12-11 14:56:00 +01:00
|
|
|
break;
|
2013-12-10 21:10:01 +01:00
|
|
|
}
|
2014-01-21 22:43:41 +01:00
|
|
|
StabilizationBankSet(&bank);
|
2013-12-10 21:07:56 +01:00
|
|
|
}
|
2013-05-18 14:17:26 +02:00
|
|
|
|
2013-12-10 21:07:56 +01:00
|
|
|
static void BankUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
|
|
|
|
{
|
2013-12-11 17:31:22 +01:00
|
|
|
StabilizationBankData bank;
|
2014-01-14 20:03:42 +01:00
|
|
|
|
2013-12-10 21:07:56 +01:00
|
|
|
StabilizationBankGet(&bank);
|
|
|
|
|
2014-01-14 20:03:42 +01:00
|
|
|
// this code will be needed if any other modules alter stabilizationbank
|
2013-12-11 17:31:22 +01:00
|
|
|
/*
|
|
|
|
StabilizationBankData curBank;
|
2013-12-11 14:56:00 +01:00
|
|
|
if(flight_mode < 0) return;
|
2013-12-10 21:07:56 +01:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
switch(cast_struct_to_array(settings.FlightModeMap, settings.FlightModeMap.Stabilized1)[flight_mode])
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
StabilizationSettingsBank1Get((StabilizationSettingsBank1Data *) &curBank);
|
|
|
|
if(memcmp(&curBank, &bank, sizeof(StabilizationBankDataPacked)) != 0)
|
|
|
|
{
|
|
|
|
StabilizationSettingsBank1Set((StabilizationSettingsBank1Data *) &bank);
|
|
|
|
}
|
|
|
|
break;
|
2013-12-10 21:07:56 +01:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
case 1:
|
|
|
|
StabilizationSettingsBank2Get((StabilizationSettingsBank2Data *) &curBank);
|
|
|
|
if(memcmp(&curBank, &bank, sizeof(StabilizationBankDataPacked)) != 0)
|
|
|
|
{
|
|
|
|
StabilizationSettingsBank2Set((StabilizationSettingsBank2Data *) &bank);
|
|
|
|
}
|
|
|
|
break;
|
2013-12-10 21:07:56 +01:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
case 2:
|
|
|
|
StabilizationSettingsBank3Get((StabilizationSettingsBank3Data *) &curBank);
|
|
|
|
if(memcmp(&curBank, &bank, sizeof(StabilizationBankDataPacked)) != 0)
|
|
|
|
{
|
|
|
|
StabilizationSettingsBank3Set((StabilizationSettingsBank3Data *) &bank);
|
|
|
|
}
|
|
|
|
break;
|
2013-12-10 21:07:56 +01:00
|
|
|
|
2013-12-11 14:56:00 +01:00
|
|
|
default:
|
|
|
|
return; //invalid bank number
|
2013-12-10 21:07:56 +01:00
|
|
|
}
|
2014-01-14 20:03:42 +01:00
|
|
|
*/
|
2013-12-11 17:31:22 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the roll rate PID constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_RATE_ROLL], bank.RollRatePID.Kp,
|
|
|
|
bank.RollRatePID.Ki,
|
|
|
|
bank.RollRatePID.Kd,
|
|
|
|
bank.RollRatePID.ILimit);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the pitch rate PID constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_RATE_PITCH], bank.PitchRatePID.Kp,
|
|
|
|
bank.PitchRatePID.Ki,
|
|
|
|
bank.PitchRatePID.Kd,
|
|
|
|
bank.PitchRatePID.ILimit);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the yaw rate PID constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_RATE_YAW], bank.YawRatePID.Kp,
|
|
|
|
bank.YawRatePID.Ki,
|
|
|
|
bank.YawRatePID.Kd,
|
|
|
|
bank.YawRatePID.ILimit);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the roll attitude PI constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_ROLL], bank.RollPI.Kp,
|
|
|
|
bank.RollPI.Ki,
|
2013-12-16 19:42:24 +01:00
|
|
|
0,
|
2013-12-10 21:07:56 +01:00
|
|
|
bank.RollPI.ILimit);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the pitch attitude PI constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_PITCH], bank.PitchPI.Kp,
|
|
|
|
bank.PitchPI.Ki,
|
2013-12-16 19:42:24 +01:00
|
|
|
0,
|
2013-12-10 21:07:56 +01:00
|
|
|
bank.PitchPI.ILimit);
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// Set the yaw attitude PI constants
|
2013-12-10 21:07:56 +01:00
|
|
|
pid_configure(&pids[PID_YAW], bank.YawPI.Kp,
|
|
|
|
bank.YawPI.Ki,
|
2013-12-16 19:42:24 +01:00
|
|
|
0,
|
2013-12-10 21:07:56 +01:00
|
|
|
bank.YawPI.ILimit);
|
2014-01-10 23:16:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-26 18:48:24 +01:00
|
|
|
static float CruiseControlAngleToFactor(float angle)
|
|
|
|
{
|
|
|
|
float factor;
|
|
|
|
// avoid singularity
|
|
|
|
if (angle > 89.999f && angle < 90.001f) {
|
|
|
|
factor = cruise_control_max_power_factor;
|
|
|
|
} else {
|
|
|
|
// the simple bank angle boost calculation that Cruise Control revolves around
|
|
|
|
factor = 1.0f / fabsf(cos_lookup_deg(angle));
|
|
|
|
// factor in the power trim, no effect at 1.0, linear effect increases with factor
|
|
|
|
factor = (factor - 1.0f) * cruise_control_power_trim + 1.0f;
|
|
|
|
// limit to user specified max power multiplier
|
|
|
|
if (factor > cruise_control_max_power_factor) {
|
|
|
|
factor = cruise_control_max_power_factor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (factor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// assumes 1.0 <= factor <= 100.0
|
|
|
|
// a factor of less than 1.0 could make it return a value less than cruise_control_min_thrust
|
|
|
|
static float CruiseControlFactorToThrust(float factor, float thrust)
|
|
|
|
{
|
|
|
|
// don't touch if below min_thrust or we never get to full down stick
|
|
|
|
// e.g. multicopter motors always spin
|
|
|
|
if (thrust > cruise_control_min_thrust) {
|
|
|
|
thrust = CruiseControlLimitThrust(thrust * factor);
|
|
|
|
}
|
|
|
|
return (thrust);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// we don't want to limit it to cruise_control_min_thrust on the low side
|
|
|
|
// because that is always close to zero, and CP helis need to run down to -1
|
|
|
|
// but CP needs to have min=-1
|
|
|
|
static float CruiseControlLimitThrust(float thrust)
|
|
|
|
{
|
|
|
|
// limit to user specified absolute max thrust
|
|
|
|
if (thrust > cruise_control_max_thrust) {
|
|
|
|
thrust = cruise_control_max_thrust;
|
|
|
|
// } else if (thrust < cruise_control_min_thrust) {
|
|
|
|
// thrust = cruise_control_min_thrust;
|
|
|
|
}
|
|
|
|
return (thrust);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-10 23:16:50 +01:00
|
|
|
static void SettingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
|
|
|
|
{
|
|
|
|
StabilizationSettingsGet(&settings);
|
2013-12-16 19:42:24 +01:00
|
|
|
|
2013-05-18 14:17:26 +02:00
|
|
|
// Set up the derivative term
|
|
|
|
pid_configure_derivative(settings.DerivativeCutoff, settings.DerivativeGamma);
|
|
|
|
|
|
|
|
// Maximum deviation to accumulate for axis lock
|
|
|
|
max_axis_lock = settings.MaxAxisLock;
|
|
|
|
max_axislock_rate = settings.MaxAxisLockRate;
|
|
|
|
|
|
|
|
// Settings for weak leveling
|
|
|
|
weak_leveling_kp = settings.WeakLevelingKp;
|
|
|
|
weak_leveling_max = settings.MaxWeakLevelingRate;
|
|
|
|
|
2014-02-09 19:33:29 +01:00
|
|
|
// Whether to zero the PID integrals while thrust is low
|
2014-03-02 15:25:49 +01:00
|
|
|
lowThrottleZeroIntegral = settings.LowThrottleZeroIntegral == STABILIZATIONSETTINGS_LOWTHROTTLEZEROINTEGRAL_TRUE;
|
2013-05-18 14:17:26 +02:00
|
|
|
|
|
|
|
// The dT has some jitter iteration to iteration that we don't want to
|
|
|
|
// make thie result unpredictable. Still, it's nicer to specify the constant
|
|
|
|
// based on a time (in ms) rather than a fixed multiplier. The error between
|
|
|
|
// update rates on OP (~300 Hz) and CC (~475 Hz) is negligible for this
|
|
|
|
// calculation
|
|
|
|
const float fakeDt = 0.0025f;
|
|
|
|
if (settings.GyroTau < 0.0001f) {
|
|
|
|
gyro_alpha = 0; // not trusting this to resolve to 0
|
|
|
|
} else {
|
|
|
|
gyro_alpha = expf(-fakeDt / settings.GyroTau);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute time constant for vbar decay term based on a tau
|
2014-01-18 00:32:50 +01:00
|
|
|
vbar_decay = expf(-fakeDt / settings.VbarTau);
|
2014-01-10 23:16:50 +01:00
|
|
|
|
2014-01-14 20:03:42 +01:00
|
|
|
// force flight mode update
|
2014-01-15 20:37:13 +01:00
|
|
|
cur_flight_mode = -1;
|
2013-12-18 11:01:16 +01:00
|
|
|
|
2014-03-18 03:40:19 +01:00
|
|
|
// Rattitude stick angle where the attitude to rate transition happens
|
2014-03-26 18:48:24 +01:00
|
|
|
if (settings.RattitudeModeTransition < (uint8_t) 10) {
|
2014-03-18 03:40:19 +01:00
|
|
|
rattitude_mode_transition_stick_position = 10.0f / 100.0f;
|
|
|
|
} else {
|
2014-03-26 18:48:24 +01:00
|
|
|
rattitude_mode_transition_stick_position = (float)settings.RattitudeModeTransition / 100.0f;
|
2014-03-18 03:40:19 +01:00
|
|
|
}
|
2014-01-11 22:22:20 +01:00
|
|
|
|
2014-03-22 06:18:06 +01:00
|
|
|
cruise_control_min_thrust = (float)settings.CruiseControlMinThrust / 100.0f;
|
|
|
|
cruise_control_max_thrust = (float)settings.CruiseControlMaxThrust / 100.0f;
|
|
|
|
cruise_control_max_angle = settings.CruiseControlMaxAngle;
|
|
|
|
cruise_control_max_power_factor = settings.CruiseControlMaxPowerFactor;
|
|
|
|
cruise_control_power_trim = settings.CruiseControlPowerTrim / 100.0f;
|
|
|
|
cruise_control_inverted_power_switch = settings.CruiseControlInvertedPowerSwitch;
|
|
|
|
cruise_control_half_power_delay = settings.CruiseControlPowerDelayComp / 2.0f;
|
|
|
|
cruise_control_max_power_factor_angle = RAD2DEG(acosf(1.0f / settings.CruiseControlMaxPowerFactor));
|
2014-03-26 18:48:24 +01:00
|
|
|
cruise_control_thrust_difference = cruise_control_max_thrust - cruise_control_min_thrust;
|
2014-01-15 19:53:14 +01:00
|
|
|
|
|
|
|
memcpy(
|
|
|
|
cruise_control_flight_mode_switch_pos_enable,
|
|
|
|
settings.CruiseControlFlightModeSwitchPosEnable,
|
|
|
|
sizeof(cruise_control_flight_mode_switch_pos_enable));
|
2010-10-03 22:39:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-03-02 02:25:30 +01:00
|
|
|
* @}
|
|
|
|
* @}
|
|
|
|
*/
|