Skip to content

Instantly share code, notes, and snippets.

@okalachev
Created May 24, 2024 12:21
Show Gist options
  • Save okalachev/2259f3fdfd221749aa42e552dbe6922a to your computer and use it in GitHub Desktop.
Save okalachev/2259f3fdfd221749aa42e552dbe6922a to your computer and use it in GitHub Desktop.
Code for upside down flight for Flix quadcopter: https://github.com/okalachev/flix.
// Upside down flight control
#define DO_FLIP 0
void controlUpsideDown() {
float modeWas = controls[RC_CHANNEL_MODE];
controls[RC_CHANNEL_MODE] = 0; // base on STAB mode
interpretRC();
controls[RC_CHANNEL_MODE] = modeWas;
mode = USER; // restore mode
// increase thrust target as it's less effective upside down
thrustTarget += 0.5;
// turn thrust target upside down
thrustTarget = -thrustTarget;
// turn yaw rate target upside down
ratesTarget.z = -ratesTarget.z;
// turn attitude target upside down
attitudeTarget *= Quaternion::fromEulerZYX(Vector(PI, 0, 0));
controlAttitude();
controlRate();
if (!armed) {
memset(motors, 0, sizeof(motors));
return;
}
motors[MOTOR_FRONT_LEFT] = thrustTarget + torqueTarget.y + torqueTarget.x - torqueTarget.z;
motors[MOTOR_FRONT_RIGHT] = thrustTarget + torqueTarget.y - torqueTarget.x + torqueTarget.z;
motors[MOTOR_REAR_LEFT] = thrustTarget - torqueTarget.y + torqueTarget.x + torqueTarget.z;
motors[MOTOR_REAR_RIGHT] = thrustTarget - torqueTarget.y - torqueTarget.x - torqueTarget.z;
// allow negative thrust
motors[0] = constrain(motors[0], -1, 0);
motors[1] = constrain(motors[1], -1, 0);
motors[2] = constrain(motors[2], -1, 0);
motors[3] = constrain(motors[3], -1, 0);
}
void controlUser() {
if (!DO_FLIP) {
controlUpsideDown();
return;
}
static float start = 0;
static float stepT = 0;
if (start == 0 || t - stepT > 0.1) start = t;
stepT = t;
float elapsed = t - start;
const float BOUNCE_END = 0.5;
const float ACCELERATE_END = BOUNCE_END + 0.1 - 0.02; // 0.02 is the delay
const float BRAKE_END = ACCELERATE_END + 0.1;
const float REVERSE_PAUSE = 0.05;
if (elapsed < BOUNCE_END) {
thrustTarget = 0.8;
attitudeTarget = Quaternion::fromEulerZYX(Vector(0, 0, attitude.getYaw()));
yawMode = YAW;
controlAttitude();
controlRate();
controlTorque();
} else if (elapsed < ACCELERATE_END) {
thrustTarget = 0.1; // for log debug
motors[MOTOR_REAR_LEFT] = 1;
motors[MOTOR_REAR_RIGHT] = 0;
motors[MOTOR_FRONT_LEFT] = 1;
motors[MOTOR_FRONT_RIGHT] = 0;
} else if (elapsed < BRAKE_END) {
thrustTarget = 0.2; // for log debug
motors[MOTOR_REAR_LEFT] = 0;
motors[MOTOR_REAR_RIGHT] = 1;
motors[MOTOR_FRONT_LEFT] = 0;
motors[MOTOR_FRONT_RIGHT] = 1;
} else if (elapsed < BRAKE_END + REVERSE_PAUSE) {
thrustTarget = 0.3; // for log debug
motors[MOTOR_REAR_LEFT] = 0;
motors[MOTOR_REAR_RIGHT] = 0;
motors[MOTOR_FRONT_LEFT] = 0;
motors[MOTOR_FRONT_RIGHT] = 0;
rollRatePID.reset();
pitchRatePID.reset();
yawRatePID.reset();
} else {
controlUpsideDown();
}
}
diff --git a/flix/control.ino b/flix/control.ino
index ae60e4a..a432942 100644
--- a/flix/control.ino
+++ b/flix/control.ino
@@ -61,6 +61,8 @@ void control() {
controlTorque();
} else if (mode == MANUAL) {
controlTorque();
+ } else if (mode == USER) {
+ controlUser();
}
}
@@ -73,7 +75,7 @@ void interpretRC() {
} else if (controls[RC_CHANNEL_MODE] < 0.75) {
mode = STAB;
} else {
- mode = STAB;
+ mode = USER;
}
thrustTarget = controls[RC_CHANNEL_THROTTLE];
diff --git a/gazebo/simulator.cpp b/gazebo/simulator.cpp
index f7da906..e142946 100644
--- a/gazebo/simulator.cpp
+++ b/gazebo/simulator.cpp
@@ -26,6 +26,7 @@
#include "log.ino"
#include "cli.ino"
#include "mavlink.ino"
+#include "upside.ino"
#include "lpf.h"
using ignition::math::Vector3d;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment