/** ****************************************************************************** * @addtogroup OpenPilotModules OpenPilot Modules * @{ * @addtogroup ManualControlModule Manual Control Module * @brief Provide manual control or allow it alter flight mode. * @{ * * Reads in the ManualControlCommand FlightMode setting from receiver then either * pass the settings straght to ActuatorDesired object (manual mode) or to * AttitudeDesired object (stabilized mode) * * @file manualcontrol.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014. * @brief ManualControl module. Handles safety R/C link and flight mode. * * @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 */ #include "inc/manualcontrol.h" #include #include #include #include #include #include #include #include // Private constants #if defined(PIOS_MANUAL_STACK_SIZE) #define STACK_SIZE_BYTES PIOS_MANUAL_STACK_SIZE #else #define STACK_SIZE_BYTES 1152 #endif #define CALLBACK_PRIORITY CALLBACK_PRIORITY_REGULAR #define CBTASK_PRIORITY CALLBACK_TASK_FLIGHTCONTROL // defined handlers static controlHandler handler_MANUAL = { .controlChain = { .Stabilization = false, .PathFollower = false, .PathPlanner = false, }, .handler = &manualHandler, }; static controlHandler handler_STABILIZED = { .controlChain = { .Stabilization = true, .PathFollower = false, .PathPlanner = false, }, .handler = &stabilizedHandler, }; // TODO: move the altitude handling into stabi static controlHandler handler_ALTITUDE = { .controlChain = { .Stabilization = true, .PathFollower = false, .PathPlanner = false, }, .handler = &altitudeHandler, }; static controlHandler handler_AUTOTUNE = { .controlChain = { .Stabilization = false, .PathFollower = false, .PathPlanner = false, }, .handler = NULL, }; static controlHandler handler_PATHFOLLOWER = { .controlChain = { .Stabilization = true, .PathFollower = true, .PathPlanner = false, }, .handler = &pathFollowerHandler, }; static controlHandler handler_PATHPLANNER = { .controlChain = { .Stabilization = true, .PathFollower = true, .PathPlanner = true, }, .handler = &pathPlannerHandler, }; // Private variables static DelayedCallbackInfo *callbackHandle; // Private functions static void configurationUpdatedCb(UAVObjEvent *ev); static void commandUpdatedCb(UAVObjEvent *ev); static void manualControlTask(void); #define assumptions (assumptions1 && assumptions3 && assumptions5 && assumptions_flightmode) /** * Module starting */ int32_t ManualControlStart() { // Run this initially to make sure the configuration is checked configuration_check(); // Whenever the configuration changes, make sure it is safe to fly SystemSettingsConnectCallback(configurationUpdatedCb); ManualControlSettingsConnectCallback(configurationUpdatedCb); ManualControlCommandConnectCallback(commandUpdatedCb); // clear alarms AlarmsClear(SYSTEMALARMS_ALARM_MANUALCONTROL); // Make sure unarmed on power up armHandler(true); // Start main task PIOS_CALLBACKSCHEDULER_Dispatch(callbackHandle); return 0; } /** * Module initialization */ int32_t ManualControlInitialize() { /* Check the assumptions about uavobject enum's are correct */ PIOS_STATIC_ASSERT(assumptions); ManualControlCommandInitialize(); FlightStatusInitialize(); ManualControlSettingsInitialize(); FlightModeSettingsInitialize(); SystemSettingsInitialize(); callbackHandle = PIOS_CALLBACKSCHEDULER_Create(&manualControlTask, CALLBACK_PRIORITY, CBTASK_PRIORITY, CALLBACKINFO_RUNNING_MANUALCONTROL, STACK_SIZE_BYTES); return 0; } MODULE_INITCALL(ManualControlInitialize, ManualControlStart); /** * Module task */ static void manualControlTask(void) { // Process Arming armHandler(false); // Process flight mode FlightStatusData flightStatus; FlightStatusGet(&flightStatus); ManualControlCommandData cmd; ManualControlCommandGet(&cmd); FlightModeSettingsData modeSettings; FlightModeSettingsGet(&modeSettings); uint8_t position = cmd.FlightModeSwitchPosition; uint8_t newMode = flightStatus.FlightMode; if (position < FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_NUMELEM) { newMode = modeSettings.FlightModePosition[position]; } // Depending on the mode update the Stabilization or Actuator objects controlHandler *handler = &handler_MANUAL; switch (newMode) { case FLIGHTSTATUS_FLIGHTMODE_MANUAL: handler = &handler_MANUAL; break; case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2: case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3: handler = &handler_STABILIZED; break; case FLIGHTSTATUS_FLIGHTMODE_VELOCITYCONTROL: case FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD: case FLIGHTSTATUS_FLIGHTMODE_RETURNTOBASE: case FLIGHTSTATUS_FLIGHTMODE_LAND: case FLIGHTSTATUS_FLIGHTMODE_POI: handler = &handler_PATHFOLLOWER; break; case FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER: handler = &handler_PATHPLANNER; break; case FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD: case FLIGHTSTATUS_FLIGHTMODE_ALTITUDEVARIO: handler = &handler_ALTITUDE; break; case FLIGHTSTATUS_FLIGHTMODE_AUTOTUNE: handler = &handler_AUTOTUNE; break; // There is no default, so if a flightmode is forgotten the compiler can throw a warning! } bool newinit = false; // FlightMode needs to be set correctly on first run (otherwise ControlChain is invalid) static bool firstRun = true; if (flightStatus.FlightMode != newMode || firstRun) { firstRun = false; flightStatus.ControlChain = handler->controlChain; flightStatus.FlightMode = newMode; FlightStatusSet(&flightStatus); newinit = true; } if (handler->handler) { handler->handler(newinit); } } /** * Called whenever a critical configuration component changes */ static void configurationUpdatedCb(__attribute__((unused)) UAVObjEvent *ev) { configuration_check(); } /** * Called whenever a critical configuration component changes */ static void commandUpdatedCb(__attribute__((unused)) UAVObjEvent *ev) { PIOS_CALLBACKSCHEDULER_Dispatch(callbackHandle); } /** * @} * @} */