Skip to content

Commit

Permalink
[rotorcraft] add rpy/earth commands to quaternion transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
flixr committed Sep 11, 2013
1 parent 9c4b328 commit 0208011
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 141 deletions.
Expand Up @@ -3,6 +3,7 @@ STAB_ATT_CFLAGS += -DSTABILIZATION_ATTITUDE_TYPE_QUAT
STAB_ATT_CFLAGS += -DSTABILIZATION_ATTITUDE_TYPE_H=\"stabilization/stabilization_attitude_quat_float.h\"
STAB_ATT_SRCS = $(SRC_FIRMWARE)/stabilization/stabilization_attitude_ref_quat_float.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_quat_float.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_quat_transformations.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_rc_setpoint.c

ap.CFLAGS += $(STAB_ATT_CFLAGS)
Expand Down
Expand Up @@ -3,6 +3,7 @@ STAB_ATT_CFLAGS += -DSTABILIZATION_ATTITUDE_TYPE_QUAT
STAB_ATT_CFLAGS += -DSTABILIZATION_ATTITUDE_TYPE_H=\"stabilization/stabilization_attitude_quat_int.h\"
STAB_ATT_SRCS = $(SRC_FIRMWARE)/stabilization/stabilization_attitude_ref_quat_int.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_quat_int.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_quat_transformations.c
STAB_ATT_SRCS += $(SRC_FIRMWARE)/stabilization/stabilization_attitude_rc_setpoint.c

ap.CFLAGS += $(STAB_ATT_CFLAGS)
Expand Down
Expand Up @@ -25,6 +25,7 @@

#include "firmwares/rotorcraft/stabilization.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_rc_setpoint.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_quat_transformations.h"

#include <stdio.h>
#include "math/pprz_algebra_float.h"
Expand Down Expand Up @@ -145,72 +146,7 @@ void stabilization_attitude_set_failsafe_setpoint(void) {
void stabilization_attitude_set_cmd_i(struct Int32Eulers *sp_cmd) {
EULERS_FLOAT_OF_BFP(stab_att_sp_euler, *sp_cmd);

/* orientation vector describing simultaneous rotation of roll/pitch */
struct FloatVect3 ov;
ov.x = stab_att_sp_euler.phi;
ov.y = stab_att_sp_euler.theta;
ov.z = 0.0;
/* quaternion from that orientation vector */
struct FloatQuat q_rp;
FLOAT_QUAT_OF_ORIENTATION_VECT(q_rp, ov);

/// @todo optimize yaw angle calculation

/*
* Instead of using the psi setpoint angle to rotate around the body z-axis,
* calculate the real angle needed to align the projection of the body x-axis
* onto the horizontal plane with the psi setpoint.
*
* angle between two vectors a and b:
* angle = atan2(norm(cross(a,b)), dot(a,b)) * sign(dot(cross(a,b), n))
* where n is the thrust vector (i.e. both a and b lie in that plane)
*/
const struct FloatVect3 xaxis = {1.0, 0.0, 0.0};
const struct FloatVect3 zaxis = {0.0, 0.0, 1.0};
struct FloatVect3 a;
FLOAT_QUAT_VMULT(a, q_rp, xaxis);

// desired heading vect in earth x-y plane
struct FloatVect3 psi_vect;
psi_vect.x = cosf(stab_att_sp_euler.psi);
psi_vect.y = sinf(stab_att_sp_euler.psi);
psi_vect.z = 0.0;
// normal is the direction of the thrust vector
struct FloatVect3 normal;
FLOAT_QUAT_VMULT(normal, q_rp, zaxis);

// projection of desired heading onto body x-y plane
// b = v - dot(v,n)*n
float dot = FLOAT_VECT3_DOT_PRODUCT(psi_vect, normal);
struct FloatVect3 dotn;
FLOAT_VECT3_SMUL(dotn, normal, dot);

// b = v - dot(v,n)*n
struct FloatVect3 b;
FLOAT_VECT3_DIFF(b, psi_vect, dotn);
dot = FLOAT_VECT3_DOT_PRODUCT(a, b);
struct FloatVect3 cross;
VECT3_CROSS_PRODUCT(cross, a, b);
// norm of the cross product
float nc = FLOAT_VECT3_NORM(cross);
// angle = atan2(norm(cross(a,b)), dot(a,b))
float yaw2 = atan2(nc, dot) / 2.0;

// negative angle if needed
// sign(dot(cross(a,b), n)
float dot_cross_ab = FLOAT_VECT3_DOT_PRODUCT(cross, normal);
if (dot_cross_ab < 0) {
yaw2 = -yaw2;
}

/* quaternion with yaw command */
struct FloatQuat q_yaw;
QUAT_ASSIGN(q_yaw, cosf(yaw2), 0.0, 0.0, sinf(yaw2));

/* final setpoint: apply roll/pitch, then yaw around resulting body z-axis */
FLOAT_QUAT_COMP(stab_att_sp_quat, q_yaw, q_rp);
FLOAT_QUAT_NORMALIZE(stab_att_sp_quat);
FLOAT_QUAT_WRAP_SHORTEST(stab_att_sp_quat);
quat_from_rpy_cmd_f(&stab_att_sp_quat, &stab_att_sp_euler);
}

#ifndef GAIN_PRESCALER_FF
Expand Down
Expand Up @@ -25,6 +25,7 @@

#include "firmwares/rotorcraft/stabilization.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_rc_setpoint.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_quat_transformations.h"

#include <stdio.h>
#include "math/pprz_algebra_float.h"
Expand Down Expand Up @@ -96,81 +97,7 @@ void stabilization_attitude_set_cmd_i(struct Int32Eulers *sp_cmd) {
// copy euler setpoint for debugging
memcpy(&stab_att_sp_euler, sp_cmd, sizeof(struct Int32Eulers));

/// @todo calc sp_quat in fixed-point

/* orientation vector describing simultaneous rotation of roll/pitch */
struct FloatVect3 ov;
ov.x = ANGLE_FLOAT_OF_BFP(sp_cmd->phi);
ov.y = ANGLE_FLOAT_OF_BFP(sp_cmd->theta);
ov.z = 0.0;
/* quaternion from that orientation vector */
struct FloatQuat q_rp;
FLOAT_QUAT_OF_ORIENTATION_VECT(q_rp, ov);

const float psi_sp = ANGLE_FLOAT_OF_BFP(sp_cmd->psi);

/// @todo optimize yaw angle calculation

/*
* Instead of using the psi setpoint angle to rotate around the body z-axis,
* calculate the real angle needed to align the projection of the body x-axis
* onto the horizontal plane with the psi setpoint.
*
* angle between two vectors a and b:
* angle = atan2(norm(cross(a,b)), dot(a,b)) * sign(dot(cross(a,b), n))
* where n is the thrust vector (i.e. both a and b lie in that plane)
*/
const struct FloatVect3 xaxis = {1.0, 0.0, 0.0};
const struct FloatVect3 zaxis = {0.0, 0.0, 1.0};
struct FloatVect3 a;
FLOAT_QUAT_VMULT(a, q_rp, xaxis);

// desired heading vect in earth x-y plane
struct FloatVect3 psi_vect;
psi_vect.x = cosf(psi_sp);
psi_vect.y = sinf(psi_sp);
psi_vect.z = 0.0;
// normal is the direction of the thrust vector
struct FloatVect3 normal;
FLOAT_QUAT_VMULT(normal, q_rp, zaxis);

// projection of desired heading onto body x-y plane
// b = v - dot(v,n)*n
float dot = FLOAT_VECT3_DOT_PRODUCT(psi_vect, normal);
struct FloatVect3 dotn;
FLOAT_VECT3_SMUL(dotn, normal, dot);

// b = v - dot(v,n)*n
struct FloatVect3 b;
FLOAT_VECT3_DIFF(b, psi_vect, dotn);

dot = FLOAT_VECT3_DOT_PRODUCT(a, b);
struct FloatVect3 cross;
VECT3_CROSS_PRODUCT(cross, a, b);
// norm of the cross product
float nc = FLOAT_VECT3_NORM(cross);
// angle = atan2(norm(cross(a,b)), dot(a,b))
float yaw2 = atan2(nc, dot) / 2.0;

// negative angle if needed
// sign(dot(cross(a,b), n)
float dot_cross_ab = FLOAT_VECT3_DOT_PRODUCT(cross, normal);
if (dot_cross_ab < 0) {
yaw2 = -yaw2;
}

/* quaternion with yaw command */
struct FloatQuat q_yaw;
QUAT_ASSIGN(q_yaw, cosf(yaw2), 0.0, 0.0, sinf(yaw2));

/* final setpoint: apply roll/pitch, then yaw around resulting body z-axis */
struct FloatQuat q_sp;
FLOAT_QUAT_COMP(q_sp, q_yaw, q_rp);
FLOAT_QUAT_NORMALIZE(q_sp);
FLOAT_QUAT_WRAP_SHORTEST(q_sp);

/* convert to fixed point */
QUAT_BFP_OF_REAL(stab_att_sp_quat, q_sp);
quat_from_rpy_cmd_i(&stab_att_sp_quat, &stab_att_sp_euler);
}

#define OFFSET_AND_ROUND(_a, _b) (((_a)+(1<<((_b)-1)))>>(_b))
Expand Down
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2013 Felix Ruess <felix.ruess@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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 2, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

/** @file stabilization_attitude_quat_transformations.c
* Quaternion transformation functions.
*/

#include "stabilization_attitude_quat_transformations.h"

void quat_from_rpy_cmd_i(struct Int32Quat *quat, struct Int32Eulers *rpy) {
struct FloatEulers rpy_f;
EULERS_FLOAT_OF_BFP(rpy_f, *rpy);
struct FloatQuat quat_f;
quat_from_rpy_cmd_f(&quat_f, &rpy_f);
QUAT_BFP_OF_REAL(*quat, quat_f);
}

void quat_from_rpy_cmd_f(struct FloatQuat *quat, struct FloatEulers *rpy) {
// only a plug for now... doesn't apply roll/pitch wrt. current yaw angle

/* orientation vector describing simultaneous rotation of roll/pitch/yaw */
const struct FloatVect3 ov = {rpy->phi, rpy->theta, rpy->psi};
/* quaternion from that orientation vector */
FLOAT_QUAT_OF_ORIENTATION_VECT(*quat, ov);

}

void quat_from_earth_cmd_i(struct Int32Quat *quat, struct Int32Vect2 *cmd, int32_t heading) {
// use float conversion for now...
struct FloatVect2 cmd_f;
cmd_f.x = ANGLE_FLOAT_OF_BFP(cmd->x);
cmd_f.y = ANGLE_FLOAT_OF_BFP(cmd->y);
float heading_f = ANGLE_FLOAT_OF_BFP(heading);

struct FloatQuat quat_f;
quat_from_earth_cmd_f(&quat_f, &cmd_f, heading_f);

// convert back to fixed point
QUAT_BFP_OF_REAL(*quat, quat_f);
}

void quat_from_earth_cmd_f(struct FloatQuat *quat, struct FloatVect2 *cmd, float heading) {

/* orientation vector describing simultaneous rotation of roll/pitch */
const struct FloatVect3 ov = {cmd->x, cmd->y, 0.0};
/* quaternion from that orientation vector */
struct FloatQuat q_rp;
FLOAT_QUAT_OF_ORIENTATION_VECT(q_rp, ov);

/* as rotation matrix */
struct FloatRMat R_rp;
FLOAT_RMAT_OF_QUAT(R_rp, q_rp);
/* body x-axis (before heading command) is first column */
struct FloatVect3 b_x;
VECT3_ASSIGN(b_x, R_rp.m[0], R_rp.m[3], R_rp.m[6]);
/* body z-axis (thrust vect) is last column */
struct FloatVect3 thrust_vect;
VECT3_ASSIGN(thrust_vect, R_rp.m[2], R_rp.m[5], R_rp.m[8]);

/// @todo optimize yaw angle calculation

/*
* Instead of using the psi setpoint angle to rotate around the body z-axis,
* calculate the real angle needed to align the projection of the body x-axis
* onto the horizontal plane with the psi setpoint.
*
* angle between two vectors a and b:
* angle = atan2(norm(cross(a,b)), dot(a,b)) * sign(dot(cross(a,b), n))
* where the normal n is the thrust vector (i.e. both a and b lie in that plane)
*/

// desired heading vect in earth x-y plane
const struct FloatVect3 psi_vect = {cosf(heading), sinf(heading), 0.0};

/* projection of desired heading onto body x-y plane
* b = v - dot(v,n)*n
*/
float dot = FLOAT_VECT3_DOT_PRODUCT(psi_vect, thrust_vect);
struct FloatVect3 dotn;
FLOAT_VECT3_SMUL(dotn, thrust_vect, dot);

// b = v - dot(v,n)*n
struct FloatVect3 b;
FLOAT_VECT3_DIFF(b, psi_vect, dotn);
dot = FLOAT_VECT3_DOT_PRODUCT(b_x, b);
struct FloatVect3 cross;
VECT3_CROSS_PRODUCT(cross, b_x, b);
// norm of the cross product
float nc = FLOAT_VECT3_NORM(cross);
// angle = atan2(norm(cross(a,b)), dot(a,b))
float yaw2 = atan2(nc, dot) / 2.0;

// negative angle if needed
// sign(dot(cross(a,b), n)
float dot_cross_ab = FLOAT_VECT3_DOT_PRODUCT(cross, thrust_vect);
if (dot_cross_ab < 0) {
yaw2 = -yaw2;
}

/* quaternion with yaw command */
struct FloatQuat q_yaw;
QUAT_ASSIGN(q_yaw, cosf(yaw2), 0.0, 0.0, sinf(yaw2));

/* final setpoint: apply roll/pitch, then yaw around resulting body z-axis */
FLOAT_QUAT_COMP(*quat, q_rp, q_yaw);
FLOAT_QUAT_NORMALIZE(*quat);
FLOAT_QUAT_WRAP_SHORTEST(*quat);

}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2013 Felix Ruess <felix.ruess@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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 2, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

/** @file stabilization_attitude_quat_transformations.h
* Quaternion transformation functions.
*/

#ifndef STABILIZATION_ATTITUDE_QUAT_TRANSFORMATIONS_H
#define STABILIZATION_ATTITUDE_QUAT_TRANSFORMATIONS_H

#include "math/pprz_algebra_float.h"
#include "math/pprz_algebra_int.h"

extern void quat_from_rpy_cmd_i(struct Int32Quat *quat, struct Int32Eulers *rpy);
extern void quat_from_rpy_cmd_f(struct FloatQuat *quat, struct FloatEulers *rpy);

extern void quat_from_earth_cmd_i(struct Int32Quat *quat, struct Int32Vect2 *cmd, int32_t heading);
extern void quat_from_earth_cmd_f(struct FloatQuat *quat, struct FloatVect2 *cmd, float heading);

#endif

0 comments on commit 0208011

Please sign in to comment.