Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mellinger: support to change gains in bindings #1180

Merged
merged 2 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 73 additions & 3 deletions src/modules/interface/controller_mellinger.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,82 @@
#define __CONTROLLER_MELLINGER_H__

#include "stabilizer_types.h"
#include "math3d.h"

void controllerMellingerInit(void);
bool controllerMellingerTest(void);
void controllerMellinger(control_t *control, const setpoint_t *setpoint,
typedef struct {
float mass;
float massThrust;

// XY Position PID
float kp_xy; // P
float kd_xy; // D
float ki_xy; // I
float i_range_xy;

// Z Position
float kp_z; // P
float kd_z; // D
float ki_z; // I
float i_range_z;

// Attitude
float kR_xy; // P
float kw_xy; // D
float ki_m_xy; // I
float i_range_m_xy;

// Yaw
float kR_z; // P
float kw_z; // D
float ki_m_z; // I
float i_range_m_z;

// roll and pitch angular velocity
float kd_omega_rp; // D

// Helper variables
float i_error_x;
float i_error_y;
float i_error_z;

float prev_omega_roll;
float prev_omega_pitch;
float prev_setpoint_omega_roll;
float prev_setpoint_omega_pitch;

float i_error_m_x;
float i_error_m_y;
float i_error_m_z;

// Logging variables
struct vec z_axis_desired;

float cmd_thrust;
float cmd_roll;
float cmd_pitch;
float cmd_yaw;
float r_roll;
float r_pitch;
float r_yaw;
float accelz;
} controllerMellinger_t;

void controllerMellingerInit(controllerMellinger_t* self);
bool controllerMellingerTest(controllerMellinger_t* self);
void controllerMellinger(controllerMellinger_t* self, control_t *control, const setpoint_t *setpoint,
const sensorData_t *sensors,
const state_t *state,
const uint32_t tick);

#ifdef CRAZYFLIE_FW
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually never noticed the CRAZYFLIE_FW define before. Is this to separate functionality for the python bindings build and the firmware build? Will there be an build error if you don't use it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this logic from collision_avoidance.c - might have been introduced there by @jpreiss. We want it here to avoid that these functions end up in the bindings, since they are "internal". A cleaner way could be to have separate files, but that makes code navigation more annoying.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered both choices. IIRC, I didn't have particularly strong motivation for choosing one file with #ifdef over two files. I probably just did it to reduce the number of files. I don't see any discussion in #567 either.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the option to use the UNIT_TEST_MODE define that is used in unit tests to show that some part of the code is added/removed to make the code testable. I just added it to the python tests in PR #1183 that I'm working on. Maybe it should be renamed though?

I prefer a solution where there are as few #ifs and buts as possible in the code, especially modifications related to test. I vote for separating the generic functionality and the global state into two files, even though it is a bit trickier to navigate.

As an extra input to this I also would like to add that we have (sort of) wanted to separate code that depends on FreeRTOS and the platform in src/modules, while generic code that could be used on other platforms goes into src/utils (I can see that this is not completely true at the moment...). I'm not sure it has been communicated outside the office but has been part of internal discussions. For the mellinger controller this would translate to maybe moving the generic file to utils while the file with the global state stays in modules. I think this is outside the scope of this PR but I just wanted to put it out there. To me this is related to cleaning up dependencies and make it easier to re-use/test code.


void controllerMellingerFirmwareInit(void);
bool controllerMellingerFirmwareTest(void);
void controllerMellingerFirmware(control_t *control, const setpoint_t *setpoint,
const sensorData_t *sensors,
const state_t *state,
const uint32_t tick);

#endif // CRAZYFLIE_FW

#endif //__CONTROLLER_MELLINGER_H__
2 changes: 1 addition & 1 deletion src/modules/src/controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ typedef struct {
static ControllerFcns controllerFunctions[] = {
{.init = 0, .test = 0, .update = 0, .name = "None"}, // Any
{.init = controllerPidInit, .test = controllerPidTest, .update = controllerPid, .name = "PID"},
{.init = controllerMellingerInit, .test = controllerMellingerTest, .update = controllerMellinger, .name = "Mellinger"},
{.init = controllerMellingerFirmwareInit, .test = controllerMellingerFirmwareTest, .update = controllerMellingerFirmware, .name = "Mellinger"},
knmcguire marked this conversation as resolved.
Show resolved Hide resolved
{.init = controllerINDIInit, .test = controllerINDITest, .update = controllerINDI, .name = "INDI"},
{.init = controllerBrescianiniInit, .test = controllerBrescianiniTest, .update = controllerBrescianini, .name = "Brescianini"},
};
Expand Down
Loading