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

added most of the requirements needed for the structure of the QP in … #14

Open
wants to merge 38 commits into
base: col-trans
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
14d1d9b
added most of the requirements needed for the structure of the QP in …
Khaledwahba1994 Aug 30, 2022
74c7588
add osqp
whoenig Aug 30, 2022
ac521c5
small tweaks in the controller
Khaledwahba1994 Aug 31, 2022
be34342
Merge branch 'qp-lee-payload' of https://github.com/IMRCLab/crazyflie…
Khaledwahba1994 Aug 31, 2022
8d71690
added qp with printing lines to debug
Khaledwahba1994 Aug 31, 2022
7aeb71a
printing and debugging
Khaledwahba1994 Aug 31, 2022
4e1d9f4
add warm start for the qp and an integral controller for the payload …
Khaledwahba1994 Sep 1, 2022
c6e19dc
final changes for payload qp lee controller
Khaledwahba1994 Sep 26, 2022
cca94f5
added a proper example to change the constraints of the QP
Khaledwahba1994 Oct 18, 2022
630cfe9
one hyperplane geometric generation per uav for two uavs and updating…
Khaledwahba1994 Nov 17, 2022
7ee5819
fixes and typos
Khaledwahba1994 Nov 17, 2022
a594988
latest bugs and fixes
Khaledwahba1994 Nov 17, 2022
684792e
latest changes for qp for two uavs
Khaledwahba1994 Nov 22, 2022
d9af092
support for multiple QPs
whoenig Nov 30, 2022
1695a15
generalized neighbor state
whoenig Dec 1, 2022
965d8a0
working takeoffs
whoenig Dec 1, 2022
438a978
compute length dynamically
whoenig Dec 1, 2022
5977a6b
remove dead code
whoenig Dec 2, 2022
439f48c
better qp error checking
whoenig Dec 2, 2022
0647779
refactor qp into helper function
whoenig Dec 2, 2022
9e7a537
async QP (untested)
whoenig Dec 2, 2022
06c335c
receive -> peek bugfix
whoenig Dec 2, 2022
60aca21
downwash aware payload controller
Khaledwahba1994 Dec 2, 2022
4c41341
successful test flight
whoenig Dec 2, 2022
9474fc5
Merge branch 'qp-lee-payload' of github.com:IMRCLab/crazyflie-firmwar…
whoenig Dec 2, 2022
27bf117
condition for not to debug print if using the bindings
Khaledwahba1994 Dec 5, 2022
36fa0d5
add state_set_neighbor_position helper
whoenig Dec 5, 2022
acf8535
Merge branch 'qp-lee-payload' of https://github.com/IMRCLab/crazyflie…
Khaledwahba1994 Dec 5, 2022
144401a
extended the size of the contraint matrix from 25 to 27
Khaledwahba1994 Dec 5, 2022
11b0abf
3 uavs with 2 hyperplanes each
Khaledwahba1994 Dec 5, 2022
18b3e03
fix access to self in async qp
whoenig Dec 5, 2022
2460a02
comment printing lines
Khaledwahba1994 Dec 5, 2022
38db6fb
validating the workspace
Khaledwahba1994 Dec 8, 2022
9eb9900
fixing a computation for multiplying column by row vectors
Khaledwahba1994 Dec 8, 2022
77bed78
change the stack size and the priority of the QP task
Khaledwahba1994 Dec 8, 2022
f9e0ea2
Working 3 uavs test flight
Khaledwahba1994 Dec 8, 2022
b12465c
2uavs 1 hp each workspace set variables to static
Khaledwahba1994 Dec 12, 2022
2821d10
add new workspace for qp of rigid payload, 3 uavs, 2 hps each
Khaledwahba1994 Dec 12, 2022
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
6 changes: 5 additions & 1 deletion src/modules/interface/controller_lee_payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,22 @@ typedef struct controllerLeePayload_s {
struct vec u_i;
struct vec qidot_prev;
struct vec acc_prev;

// -----------------------FOR QP----------------------------//
// P_alloc matrix
struct mat36 P_alloc;
// Weight matrix of the QP
struct mat66 P;
// desired value from the QP
struct vec desVirtInp;
struct vec mu1;
struct vec mu2;
struct vec n1;
struct vec n2;
// inequality matrix A
struct mat26 A_in;
// value: 0,1: defines which part of the vector in desVirtInp goes to which UAV
float value;
float radius;
// angle limit for hyper plane
struct vec rpyPlane1;
float yawPlane1; // rpy and yaw for one plane of the first UAV
Expand Down
3 changes: 2 additions & 1 deletion src/modules/interface/stabilizer_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ typedef struct state_s {
point_t position; // m
velocity_t velocity; // m/s
acc_t acc; // Gs (but acc.z without considering gravity)

// position of the neighboring UAV
point_t position2;
// Measured state of the payload
point_t payload_pos; // m (world frame)
velocity_t payload_vel; // m/s (world frame)
Expand Down
99 changes: 76 additions & 23 deletions src/modules/src/controller_lee_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,37 @@ TODO
#include "math3d.h"
#include "controller_lee_payload.h"
#include "stdio.h"
// #include "debug.h"
#include "debug.h"
// QP
#include "workspace.h"
#include "osqp.h"

#define GRAVITY_MAGNITUDE (9.81f)


static inline struct vec computePlaneNormal(struct vec rpy, float yaw) {
// Compute the normal of a plane, given the extrinsic roll-pitch-yaw of the z-axis
// and the yaw representing the x-axis of the plan's frame
struct vec x = mkvec(cosf(yaw), sinf(yaw), 0);
struct quat q = rpy2quat(rpy);
struct mat33 Rq = quat2rotmat(q);
struct vec e3 = mkvec(0,0,1);
struct vec z = mvmul(Rq, e3);
struct vec xcrossz = vcross(x,z);
struct vec ni = vnormalize(xcrossz);
return ni;
// static inline struct vec computePlaneNormal(struct vec rpy, float yaw) {
// // Compute the normal of a plane, given the extrinsic roll-pitch-yaw of the z-axis
// // and the yaw representing the x-axis of the plan's frame
// struct vec x = mkvec(cosf(yaw), sinf(yaw), 0);
// struct quat q = rpy2quat(rpy);
// struct mat33 Rq = quat2rotmat(q);
// struct vec e3 = mkvec(0,0,1);
// struct vec z = mvmul(Rq, e3);
// struct vec xcrossz = vcross(x,z);
// struct vec ni = vnormalize(xcrossz);
// return ni;
// }
static inline struct vec computePlaneNormal(struct vec pos1, struct vec pos2, struct vec pload, float r) {
// Compute the normal of a plane, given the minimum desired distance r
struct vec mid = vscl(0.5, vsub(pos2, pos1));
struct vec rvec = vscl(r, vnormalize(vsub(pos1, pos2)));
struct vec pr = vadd(pos1, vadd(mid, rvec));

struct vec p0pr = vsub(pr, pload);
struct vec prp2 = vsub(pos2, pr);
struct vec ns = vcross(prp2, p0pr);
struct vec n_sol = vcross(p0pr, ns);
return n_sol;
}
static inline struct mat26 Ainequality(float angle_limit) {
struct vec q1_limit = mkvec(-radians(angle_limit), 0 , 0);
Expand Down Expand Up @@ -108,6 +120,9 @@ static controllerLeePayload_t g_self = {
// -----------------------FOR QP----------------------------//
// 0 for UAV 1 and, 1 for UAV 2
.value = 0.0,
.radius = 0.1,
// .mu1 = {0, 0, 0},
// .mu2 = {0, 0, 0},
// fixed angle hyperplane in degrees for each UAV
.rpyPlane1 = {0,0,0},
.yawPlane1 = 0,
Expand Down Expand Up @@ -190,6 +205,8 @@ void controllerLeePayload(controllerLeePayload_t* self, control_t *control, setp
struct vec plStPos = mkvec(state->payload_pos.x, state->payload_pos.y, state->payload_pos.z);
struct vec plStVel = mkvec(state->payload_vel.x, state->payload_vel.y, state->payload_vel.z);

struct vec statePos2 = mkvec(state->position2.x, state->position2.y, state->position2.z);

// errors
struct vec plpos_e = vclampscl(vsub(plPos_d, plStPos), -self->Kpos_P_limit, self->Kpos_P_limit);
struct vec plvel_e = vclampscl(vsub(plVel_d, plStVel), -self->Kpos_D_limit, self->Kpos_D_limit);
Expand All @@ -207,39 +224,59 @@ void controllerLeePayload(controllerLeePayload_t* self, control_t *control, setp
//------------------------------------------QP------------------------------//
// The QP will be added here for the desired virtual input (mu_des)
workspace.settings->warm_start = 0;
struct vec n1 = computePlaneNormal(self->rpyPlane1, self->yawPlane1);
struct vec n2 = computePlaneNormal(self->rpyPlane2, self->yawPlane2);
c_float Ax_new[12] = {1, n1.x, 1, n1.y, 1, n1.z, 1, n2.x, 1, n2.y, 1, n2.z, };
self->n1 = computePlaneNormal(statePos, statePos2, plStPos, self->radius);
self->n2 = computePlaneNormal(statePos2, statePos, plStPos, self->radius);
c_float Ax_new[12] = {1, self->n1.x, 1, self->n1.y, 1, self->n1.z, 1, self->n2.x, 1, self->n2.y, 1, self->n2.z};
c_float Px_new[6] = {1, 1, 100, 1, 1, 100};

c_int Ax_new_idx[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
c_int Px_new_idx[6] = {0, 1, 2, 3, 4, 5};
c_int Ax_new_n = 12;
c_int Px_new_n = 6;

c_float l_new[6] = {F_d.x, F_d.y, F_d.z, -INFINITY, -INFINITY,};
c_float u_new[6] = {F_d.x, F_d.y, F_d.z, 0, 0,};

osqp_update_A(&workspace, Ax_new, OSQP_NULL, Ax_new_n);
osqp_update_A(&workspace, Ax_new, Ax_new_idx, Ax_new_n);
osqp_update_P(&workspace, Px_new, Px_new_idx, Px_new_n);
osqp_update_lower_bound(&workspace, l_new);
osqp_update_upper_bound(&workspace, u_new);

osqp_solve(&workspace);

if (self->value == 0.0f) {
self->desVirtInp.x = (&workspace)->solution->x[0];
self->desVirtInp.y = (&workspace)->solution->x[1];
self->desVirtInp.z = (&workspace)->solution->x[2];
self->mu1.x = (&workspace)->solution->x[0];
self->mu1.y = (&workspace)->solution->x[1];
self->mu1.z = (&workspace)->solution->x[2];
self->mu2.x = (&workspace)->solution->x[3];
self->mu2.y = (&workspace)->solution->x[4];
self->mu2.z = (&workspace)->solution->x[5];
}
else if (self->value == 1.0f) {
self->desVirtInp.x = (&workspace)->solution->x[3];
self->desVirtInp.y = (&workspace)->solution->x[4];
self->desVirtInp.z = (&workspace)->solution->x[5];
self->desVirtInp.x = (&workspace)->solution->x[0];
self->desVirtInp.y = (&workspace)->solution->x[1];
self->desVirtInp.z = (&workspace)->solution->x[2];
Copy link

Choose a reason for hiding this comment

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

why did this change? shouldn't you use 3,4,5, like before?

self->mu1.x = (&workspace)->solution->x[3];
self->mu1.y = (&workspace)->solution->x[4];
self->mu1.z = (&workspace)->solution->x[5];
self->mu2.x = (&workspace)->solution->x[0];
self->mu2.y = (&workspace)->solution->x[1];
self->mu2.z = (&workspace)->solution->x[2];

}
// printf("workspace status: %s\n", (&workspace)->info->status);
// // printf("tick: %f \n uavID: %d solution: %f %f %f %f %f %f\n", tick, self->value, (&workspace)->solution->x[0], (&workspace)->solution->x[1], (&workspace)->solution->x[2], (&workspace)->solution->x[3], (&workspace)->solution->x[4], (&workspace)->solution->x[5]);
// DEBUG_PRINT("value: %f self->desVirtInp: %f %f %f\n", (double) self->value, (double)(self->desVirtInp.x),(double)(self->desVirtInp.y),(double)(self->desVirtInp.z));
// printf("tick: %f \n uavID: %d solution: %f %f %f %f %f %f\n", tick, self->value, (&workspace)->solution->x[0], (&workspace)->solution->x[1], (&workspace)->solution->x[2], (&workspace)->solution->x[3], (&workspace)->solution->x[4], (&workspace)->solution->x[5]);
// printf("tick: %d \n uavID: %f solution: %f %f %f %f %f %f\n", tick, self->value, self->mu1.x, self->mu1.y, self->mu1.z, self->mu2.x, self->mu2.y, self->mu2.z);
// printf("value: %f, desVirtInp: %f %f %f\n", (double) self->value, (double)(self->desVirtInp.x),(double)(self->desVirtInp.y),(double)(self->desVirtInp.z));

//------------------------------------------QP------------------------------//
// self->desVirtInp = F_d; // COMMENT THIS IF YOU ARE USING THE QP
//directional unit vector qi and angular velocity wi pointing from UAV to payload
struct vec qi = vnormalize(vsub(plStPos, statePos));

struct vec qidot = vdiv(vsub(plStVel, stateVel), vmag(vsub(plStPos, statePos)));
struct vec wi = vcross(qi, qidot);
struct mat33 qiqiT = vecmult(qi);
Expand Down Expand Up @@ -477,9 +514,25 @@ PARAM_ADD(PARAM_FLOAT, offsetx, &g_self.offset.x)
PARAM_ADD(PARAM_FLOAT, offsety, &g_self.offset.y)
PARAM_ADD(PARAM_FLOAT, offsetz, &g_self.offset.z)

PARAM_ADD(PARAM_FLOAT, n1, &g_self.n1.x)
PARAM_ADD(PARAM_FLOAT, n1, &g_self.n1.y)
PARAM_ADD(PARAM_FLOAT, n1, &g_self.n1.z)
PARAM_ADD(PARAM_FLOAT, n2, &g_self.n2.x)
PARAM_ADD(PARAM_FLOAT, n2, &g_self.n2.y)
PARAM_ADD(PARAM_FLOAT, n2, &g_self.n2.z)
Copy link

Choose a reason for hiding this comment

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

Remove. Also, they would need to have different names for this to work.



PARAM_ADD(PARAM_FLOAT, radius, &g_self.radius)


//For the QP
PARAM_ADD(PARAM_FLOAT, value, &g_self.value)
PARAM_ADD(PARAM_FLOAT, mu1x, &g_self.mu1.x)
PARAM_ADD(PARAM_FLOAT, mu1y, &g_self.mu1.y)
PARAM_ADD(PARAM_FLOAT, mu1z, &g_self.mu1.z)
PARAM_ADD(PARAM_FLOAT, mu2x, &g_self.mu2.x)
PARAM_ADD(PARAM_FLOAT, mu2y, &g_self.mu2.y)
PARAM_ADD(PARAM_FLOAT, mu2z, &g_self.mu2.z)
Copy link

Choose a reason for hiding this comment

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

Remove. If you want to be able to look at them, you would need to add them to logging, not to params


PARAM_GROUP_STOP(ctrlLeeP)

Expand Down
21 changes: 19 additions & 2 deletions src/modules/src/stabilizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static struct {
int16_t rateRoll;
int16_t ratePitch;
int16_t rateYaw;

// payload position - mm
int16_t px;
int16_t py;
Expand All @@ -110,6 +110,11 @@ static struct {
int16_t pvx;
int16_t pvy;
int16_t pvz;

// posiiton of neighboring UAV
int16_t p2x;
int16_t p2y;
int16_t p2z;
} stateCompressed;

static struct {
Expand All @@ -129,6 +134,7 @@ static struct {

// for payloads
static float payload_alpha = 0.9; // between 0...1; 1: no filter
static float otherID = 2.0;
Copy link

Choose a reason for hiding this comment

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

should be uint8_t

static point_t payload_pos_last; // m (world frame)
static velocity_t payload_vel_last; // m/s (world frame)

Expand Down Expand Up @@ -173,6 +179,10 @@ static void compressState()
stateCompressed.py = state.payload_pos.y * 1000.0f;
stateCompressed.pz = state.payload_pos.z * 1000.0f;

stateCompressed.p2x = state.position2.x * 1000.0f;
stateCompressed.p2y = state.position2.y * 1000.0f;
stateCompressed.p2z = state.position2.z * 1000.0f;

stateCompressed.pvx = state.payload_vel.x * 1000.0f;
stateCompressed.pvy = state.payload_vel.y * 1000.0f;
stateCompressed.pvz = state.payload_vel.z * 1000.0f;
Expand Down Expand Up @@ -292,8 +302,13 @@ static void stabilizerTask(void* param)

// add the payload state here
peerLocalizationOtherPosition_t* payloadPos = peerLocalizationGetPositionByID(255);
peerLocalizationOtherPosition_t* otherCF = peerLocalizationGetPositionByID(otherID);
if (otherCF != NULL) {
state.position2.x = otherCF->pos.x;
state.position2.x = otherCF->pos.y;
Copy link

Choose a reason for hiding this comment

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

state.position2.x -> state.position.y

state.position2.x = otherCF->pos.z;
Copy link

Choose a reason for hiding this comment

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

state.position2.x -> state.position.z

}
if (payloadPos != NULL) {

// if we got a new state
if (payload_pos_last.timestamp < payloadPos->pos.timestamp) {
struct vec vel_filtered = vzero();
Expand Down Expand Up @@ -431,6 +446,8 @@ PARAM_ADD_CORE(PARAM_UINT8, stop, &emergencyStop)

PARAM_ADD_CORE(PARAM_FLOAT, pAlpha, &payload_alpha)

PARAM_ADD_CORE(PARAM_FLOAT, otherID, &payload_alpha)
Copy link

Choose a reason for hiding this comment

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

  • PARAM_FLOAT -> PARAM_UINT8
  • &payload_alpha -> &otherID


PARAM_GROUP_STOP(stabilizer)


Expand Down