solaESKF_EIGEN

Dependencies:   mbed LPS25HB_I2C LSM9DS1 PIDcontroller LoopTicker GPSUBX_UART_Eigen SBUS_without_mainfile MedianFilter Eigen UsaPack solaESKF_Eigen Vector3 CalibrateMagneto FastPWM

Committer:
NaotoMorita
Date:
Wed Mar 03 03:34:11 2021 +0000
Revision:
36:e68ce293306e
Parent:
35:4535af88f7bf
Child:
37:dad55cf05e3d
quaternion attitude determination

Who changed what in which revision?

UserRevisionLine numberNew contents of line
NaotoMorita 0:6b18a09a6628 1 #include "mbed.h"
naker 20:2c3f113a8e8f 2 #include "PIDcontroller.h"
NaotoMorita 0:6b18a09a6628 3 #include "SBUS.hpp"
NaotoMorita 36:e68ce293306e 4 //#include <MadgwickAHRS.h>
cocorlow 6:2cba569272fe 5 #include "LoopTicker.hpp"
naker 15:6abaac6e5b03 6 #include "MPU6050.h"
NaotoMorita 17:6b7a363d06d2 7 #include <I2Cdev.h>
NaotoMorita 36:e68ce293306e 8 #include "FastPWM.h"
NaotoMorita 36:e68ce293306e 9 #include "Matrix.h"
NaotoMorita 36:e68ce293306e 10 #include "MatrixMath.h"
NaotoMorita 36:e68ce293306e 11 #include <math.h>
cocorlow 6:2cba569272fe 12
NaotoMorita 17:6b7a363d06d2 13 #define MPU6050_PWR_MGMT_1 0x6B
NaotoMorita 17:6b7a363d06d2 14 #define MPU_ADDRESS 0x68
NaotoMorita 17:6b7a363d06d2 15 #define pi 3.141562
NaotoMorita 17:6b7a363d06d2 16 #define ACCEL_FSR MPU6050_ACCEL_FS_8
NaotoMorita 17:6b7a363d06d2 17 #define ACCEL_SSF 36500.0
NaotoMorita 17:6b7a363d06d2 18 #define GYRO_FSR MPU6050_GYRO_FS_250
NaotoMorita 17:6b7a363d06d2 19 #define GYRO_SSF 131.0
NaotoMorita 17:6b7a363d06d2 20 #define MPU6050_LPF MPU6050_DLPF_BW_256
NaotoMorita 27:43bd0e444633 21
NaotoMorita 17:6b7a363d06d2 22 MPU6050 accelgyro;
NaotoMorita 36:e68ce293306e 23 //Madgwick MadgwickFilter;
NaotoMorita 0:6b18a09a6628 24 SBUS sbus(PD_5, PD_6);
NaotoMorita 0:6b18a09a6628 25 Serial pc(USBTX, USBRX);
naker 26:62d9857eaecc 26 Serial sd(PG_14,PG_9);
cocorlow 3:79e62f9b13c8 27 DigitalOut led1(LED1);
cocorlow 3:79e62f9b13c8 28 DigitalOut led3(LED3);
NaotoMorita 27:43bd0e444633 29
NaotoMorita 36:e68ce293306e 30 FastPWM servoRight(PE_9);
NaotoMorita 36:e68ce293306e 31 FastPWM servoLeft(PE_11);
NaotoMorita 36:e68ce293306e 32 FastPWM servoThrust(PA_0);
NaotoMorita 36:e68ce293306e 33 const double PID_dt = 0.015;
NaotoMorita 36:e68ce293306e 34 PID pitchPID(5.0, 0,0,PID_dt); //rad
NaotoMorita 31:8d02f3b9a067 35 PID pitchratePID(0.01, 0.0, 0.0, PID_dt);//rad/s
NaotoMorita 36:e68ce293306e 36 PID rollPID(5.0,0.0,0.0,PID_dt);
NaotoMorita 31:8d02f3b9a067 37 PID rollratePID(0.01, 0.0, 0.0, PID_dt);//rad/s
NaotoMorita 17:6b7a363d06d2 38 Timer t;
cocorlow 3:79e62f9b13c8 39
NaotoMorita 36:e68ce293306e 40 Matrix qhat(4,1);
NaotoMorita 36:e68ce293306e 41 Matrix Phat(4,4);
NaotoMorita 36:e68ce293306e 42 Matrix Racc(3,3);
NaotoMorita 36:e68ce293306e 43
NaotoMorita 36:e68ce293306e 44
NaotoMorita 36:e68ce293306e 45 int loop_count = 1;
NaotoMorita 36:e68ce293306e 46 float att_dt = 0.01;
naker 23:4a490fa8bf4a 47 float rc[16];
naker 25:5aca9b224226 48 float roll_ac;
naker 15:6abaac6e5b03 49 double pitch = 0.0;
naker 15:6abaac6e5b03 50 double roll = 0.0;
naker 15:6abaac6e5b03 51 double yaw = 0.0;
NaotoMorita 17:6b7a363d06d2 52 int16_t ax, ay, az;
NaotoMorita 17:6b7a363d06d2 53 int16_t gx, gy, gz;
NaotoMorita 17:6b7a363d06d2 54 double acc_x,acc_y,acc_z;
NaotoMorita 17:6b7a363d06d2 55 double gyro_x,gyro_y,gyro_z;
cocorlow 3:79e62f9b13c8 56 int out1, out2;
NaotoMorita 36:e68ce293306e 57 float scaledServoOut[3]= {0,0};
NaotoMorita 28:fc6c46c1db65 58 float scaledMotorOut[1]= {-1};
NaotoMorita 36:e68ce293306e 59 float servoOut[3] = {1500.0,1500.0};
NaotoMorita 36:e68ce293306e 60 float motorOut[1] = {1100.0};
NaotoMorita 36:e68ce293306e 61 float servoPwmMax = 1800.0;
NaotoMorita 36:e68ce293306e 62 float servoPwmMin = 1200.0;
NaotoMorita 36:e68ce293306e 63 float motorPwmMax = 2000.0;
NaotoMorita 36:e68ce293306e 64 float motorPwmMin = 1100.0;
NaotoMorita 36:e68ce293306e 65 int offsetVal[6] = {0,0,0,-600,570,265};
cocorlow 3:79e62f9b13c8 66
NaotoMorita 17:6b7a363d06d2 67 const double pitch_align = 0.0;
NaotoMorita 17:6b7a363d06d2 68 const double roll_align = -0.0;
NaotoMorita 27:43bd0e444633 69
NaotoMorita 27:43bd0e444633 70
NaotoMorita 35:4535af88f7bf 71 float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
cocorlow 7:70161eb0f854 72 {
cocorlow 7:70161eb0f854 73 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
cocorlow 7:70161eb0f854 74 }
NaotoMorita 27:43bd0e444633 75
NaotoMorita 30:214ddc613a35 76 void writeSdcard()
naker 20:2c3f113a8e8f 77 {
NaotoMorita 36:e68ce293306e 78 pc.printf("gx: %d, gy: %d, gz: %d roll: %f, pitch: %f \r\n",gx,gy,gz,roll* 57.29578f,pitch* 57.29578f);
naker 20:2c3f113a8e8f 79 }
NaotoMorita 27:43bd0e444633 80
naker 22:da9893b71f24 81 // 割り込まれた時点での出力(computeの結果)を返す関数
NaotoMorita 27:43bd0e444633 82 void calcServoOut(){
NaotoMorita 28:fc6c46c1db65 83 if(sbus.failSafe == false) {
NaotoMorita 28:fc6c46c1db65 84 // sbusデータの読み込み
NaotoMorita 28:fc6c46c1db65 85 for (int i =0 ; i < 16;i ++){
NaotoMorita 35:4535af88f7bf 86 rc[i] = 0.65f * mapfloat(float(sbus.getData(i)),368,1680,-1,1) + (1.0f - 0.65f) * rc[i]; // mapped input
NaotoMorita 27:43bd0e444633 87 }
NaotoMorita 28:fc6c46c1db65 88 }
NaotoMorita 28:fc6c46c1db65 89
NaotoMorita 36:e68ce293306e 90
NaotoMorita 36:e68ce293306e 91 //pitch = -MadgwickFilter.getPitchRadians()-pitch_align*pi/180;
NaotoMorita 36:e68ce293306e 92 //roll = -MadgwickFilter.getRollRadians()-roll_align*pi/180;
NaotoMorita 28:fc6c46c1db65 93 pitchPID.setProcessValue(pitch);
NaotoMorita 28:fc6c46c1db65 94 pitchratePID.setProcessValue(gyro_y);
NaotoMorita 28:fc6c46c1db65 95 rollPID.setProcessValue(roll);
NaotoMorita 28:fc6c46c1db65 96 rollratePID.setProcessValue(gyro_x);
NaotoMorita 36:e68ce293306e 97 float de = -pitchPID.compute()-pitchratePID.compute()-rc[1]+rc[0];
NaotoMorita 36:e68ce293306e 98 float da = rollPID.compute()+rollratePID.compute()+rc[0]+rc[1];
NaotoMorita 28:fc6c46c1db65 99 float dT = rc[2];
NaotoMorita 28:fc6c46c1db65 100
NaotoMorita 28:fc6c46c1db65 101 scaledServoOut[0]=de+da;
NaotoMorita 36:e68ce293306e 102 scaledServoOut[1]=-de+da;
NaotoMorita 28:fc6c46c1db65 103 scaledMotorOut[0]= dT;
NaotoMorita 31:8d02f3b9a067 104
NaotoMorita 36:e68ce293306e 105 double LP_servo = 0.2;
NaotoMorita 36:e68ce293306e 106 double LP_motor = 0.2;
NaotoMorita 36:e68ce293306e 107 for(int i = 0;i<sizeof(servoOut)/sizeof(servoOut[0]);i++){
NaotoMorita 36:e68ce293306e 108 servoOut[i] = LP_servo*(mapfloat(scaledServoOut[i],-1,1,servoPwmMin,servoPwmMax))+(1.0-LP_servo)*servoOut[i];
NaotoMorita 28:fc6c46c1db65 109 if(servoOut[i]<servoPwmMin) {
NaotoMorita 28:fc6c46c1db65 110 servoOut[i] = servoPwmMin;
NaotoMorita 28:fc6c46c1db65 111 };
NaotoMorita 28:fc6c46c1db65 112 if(servoOut[i]>servoPwmMax) {
NaotoMorita 28:fc6c46c1db65 113 servoOut[i] = servoPwmMax;
NaotoMorita 28:fc6c46c1db65 114 };
NaotoMorita 28:fc6c46c1db65 115 }
NaotoMorita 28:fc6c46c1db65 116
NaotoMorita 36:e68ce293306e 117 for(int i = 0;i<sizeof(motorOut)/sizeof(motorOut[0]) ;i++){
NaotoMorita 36:e68ce293306e 118 motorOut[i] = LP_motor*(mapfloat(scaledMotorOut[i],-1,1,motorPwmMin,motorPwmMax))+(1.0-LP_motor)*motorOut[i];
NaotoMorita 28:fc6c46c1db65 119 if(motorOut[i]<motorPwmMin) {
NaotoMorita 28:fc6c46c1db65 120 motorOut[i] = motorPwmMin;
NaotoMorita 28:fc6c46c1db65 121 };
NaotoMorita 28:fc6c46c1db65 122 if(motorOut[i]>motorPwmMax) {
NaotoMorita 28:fc6c46c1db65 123 motorOut[i] = motorPwmMax;
NaotoMorita 28:fc6c46c1db65 124 };
NaotoMorita 28:fc6c46c1db65 125 }
NaotoMorita 36:e68ce293306e 126 servoRight.pulsewidth_us(servoOut[0]);
NaotoMorita 36:e68ce293306e 127 servoLeft.pulsewidth_us(servoOut[1]);
NaotoMorita 36:e68ce293306e 128 servoThrust.pulsewidth_us(motorOut[0]);
NaotoMorita 32:c4f06cb0e1d6 129
NaotoMorita 36:e68ce293306e 130 if(loop_count > 10){
NaotoMorita 31:8d02f3b9a067 131 writeSdcard();
NaotoMorita 36:e68ce293306e 132 loop_count = 1;
NaotoMorita 27:43bd0e444633 133 }else{
NaotoMorita 27:43bd0e444633 134 loop_count +=1;
naker 26:62d9857eaecc 135 }
naker 22:da9893b71f24 136 }
cocorlow 7:70161eb0f854 137
NaotoMorita 27:43bd0e444633 138 void updateAttitude(){
NaotoMorita 17:6b7a363d06d2 139 // gx gy gz ax ay az
NaotoMorita 17:6b7a363d06d2 140 accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
NaotoMorita 17:6b7a363d06d2 141 // 加速度値を分解能で割って加速度(G)に変換する
NaotoMorita 17:6b7a363d06d2 142 acc_x = ax / ACCEL_SSF; //FS_SEL_0 16,384 LSB / g
NaotoMorita 17:6b7a363d06d2 143 acc_y = ay / ACCEL_SSF;
NaotoMorita 17:6b7a363d06d2 144 acc_z = az / ACCEL_SSF;
NaotoMorita 17:6b7a363d06d2 145 // 角速度値を分解能で割って角速度(deg per sec)に変換する
NaotoMorita 17:6b7a363d06d2 146 gyro_x = gx / GYRO_SSF; // (deg/s)
NaotoMorita 17:6b7a363d06d2 147 gyro_y = gy / GYRO_SSF;
NaotoMorita 17:6b7a363d06d2 148 gyro_z = gz / GYRO_SSF;
naker 20:2c3f113a8e8f 149 //Madgwickフィルターを用いて、PRY(pitch, roll, yaw)を計算
NaotoMorita 36:e68ce293306e 150 //MadgwickFilter.updateIMU(gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z);
NaotoMorita 27:43bd0e444633 151 }
NaotoMorita 27:43bd0e444633 152
NaotoMorita 33:e79457192a4b 153 void updateBetweenMeasures(){
NaotoMorita 36:e68ce293306e 154 // gx gy gz ax ay az
NaotoMorita 36:e68ce293306e 155 accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
NaotoMorita 36:e68ce293306e 156 ax = ax - offsetVal[0];
NaotoMorita 36:e68ce293306e 157 ay = ay - offsetVal[1];
NaotoMorita 36:e68ce293306e 158 az = az - offsetVal[2];
NaotoMorita 36:e68ce293306e 159 gx = gx - offsetVal[3];
NaotoMorita 36:e68ce293306e 160 gy = gy - offsetVal[4];
NaotoMorita 36:e68ce293306e 161 gz = gz - offsetVal[5];
NaotoMorita 36:e68ce293306e 162 // 加速度値を分解能で割って加速度(G)に変換する
NaotoMorita 36:e68ce293306e 163 acc_x = ax / ACCEL_SSF; //FS_SEL_0 16,384 LSB / g
NaotoMorita 36:e68ce293306e 164 acc_y = ay / ACCEL_SSF;
NaotoMorita 36:e68ce293306e 165 acc_z = az / ACCEL_SSF;
NaotoMorita 36:e68ce293306e 166 // 角速度値を分解能で割って角速度(rad per sec)に変換する
NaotoMorita 36:e68ce293306e 167 gyro_x = float(gx) / GYRO_SSF * 0.0174533f; // (rad/s)
NaotoMorita 36:e68ce293306e 168 gyro_y = float(gy) / GYRO_SSF * 0.0174533f;
NaotoMorita 36:e68ce293306e 169 gyro_z = float(gz) / GYRO_SSF * 0.0174533f;
NaotoMorita 36:e68ce293306e 170
NaotoMorita 36:e68ce293306e 171
NaotoMorita 36:e68ce293306e 172 Matrix phi(4,4);
NaotoMorita 36:e68ce293306e 173 phi << 1.0 << -gyro_x*0.5*att_dt <<-gyro_y*0.5*att_dt <<-gyro_z*0.5*att_dt
NaotoMorita 36:e68ce293306e 174 << gyro_x*0.5*att_dt << 1.0 << gyro_z*0.5*att_dt <<-gyro_y*0.5*att_dt
NaotoMorita 36:e68ce293306e 175 << gyro_y*0.5*att_dt << -gyro_z*0.5*att_dt << 1.0 << gyro_x*0.5*att_dt
NaotoMorita 36:e68ce293306e 176 << gyro_z*0.5*att_dt << gyro_y*0.5*att_dt <<-gyro_x*0.5*att_dt << 1.0;
NaotoMorita 36:e68ce293306e 177 qhat = phi*qhat;
NaotoMorita 36:e68ce293306e 178
NaotoMorita 36:e68ce293306e 179 float qnorm = sqrt(MatrixMath::dot(MatrixMath::Transpose(qhat),qhat));
NaotoMorita 36:e68ce293306e 180 qhat *= (1.0f/ qnorm);
NaotoMorita 36:e68ce293306e 181
NaotoMorita 36:e68ce293306e 182 }
NaotoMorita 36:e68ce293306e 183
NaotoMorita 36:e68ce293306e 184 void computeAngles()
NaotoMorita 36:e68ce293306e 185 {
NaotoMorita 36:e68ce293306e 186 float q0 = qhat.getNumber( 1, 1 );
NaotoMorita 36:e68ce293306e 187 float q1 = qhat.getNumber( 2, 1 );
NaotoMorita 36:e68ce293306e 188 float q2 = qhat.getNumber( 3, 1 );
NaotoMorita 36:e68ce293306e 189 float q3 = qhat.getNumber( 4, 1 );
NaotoMorita 36:e68ce293306e 190 roll = atan2f(q0*q1 + q2*q3, 0.5f - q1*q1 - q2*q2);
NaotoMorita 36:e68ce293306e 191 pitch = asinf(-2.0f * (q1*q3 - q0*q2));
NaotoMorita 36:e68ce293306e 192 yaw = atan2f(q1*q2 + q0*q3, 0.5f - q2*q2 - q3*q3);
NaotoMorita 33:e79457192a4b 193 }
NaotoMorita 33:e79457192a4b 194
NaotoMorita 27:43bd0e444633 195 int main()
NaotoMorita 36:e68ce293306e 196 {
NaotoMorita 28:fc6c46c1db65 197 pitchPID.setSetPoint(0.0);
NaotoMorita 28:fc6c46c1db65 198 pitchratePID.setSetPoint(0.0);
NaotoMorita 28:fc6c46c1db65 199 rollPID.setSetPoint(0.0);
NaotoMorita 28:fc6c46c1db65 200 rollratePID.setSetPoint(0.0);
NaotoMorita 28:fc6c46c1db65 201 pitchPID.setBias(0.0);
NaotoMorita 28:fc6c46c1db65 202 pitchratePID.setBias(0.0);
NaotoMorita 28:fc6c46c1db65 203 rollPID.setBias(0.0);
NaotoMorita 28:fc6c46c1db65 204 rollratePID.setBias(0.0);
NaotoMorita 28:fc6c46c1db65 205 pitchPID.setOutputLimits(-1.0,1.0);
NaotoMorita 28:fc6c46c1db65 206 pitchratePID.setOutputLimits(-1.0,1.0);
NaotoMorita 28:fc6c46c1db65 207 rollPID.setOutputLimits(-1.0,1.0);
NaotoMorita 29:34ee662f454e 208 rollratePID.setOutputLimits(-1.0,1.0);
NaotoMorita 28:fc6c46c1db65 209 pitchPID.setInputLimits(-pi,pi);
NaotoMorita 28:fc6c46c1db65 210 pitchratePID.setInputLimits(-pi,pi);
NaotoMorita 28:fc6c46c1db65 211 rollPID.setInputLimits(-pi,pi);
NaotoMorita 28:fc6c46c1db65 212 rollratePID.setInputLimits(-pi,pi);
NaotoMorita 29:34ee662f454e 213
NaotoMorita 36:e68ce293306e 214 servoRight.period_us(15000.0);
NaotoMorita 36:e68ce293306e 215 servoLeft.period_us(15000.0);
NaotoMorita 36:e68ce293306e 216 servoThrust.period_us(15000.0);
NaotoMorita 36:e68ce293306e 217 servoRight.pulsewidth_us(1500.0);
NaotoMorita 36:e68ce293306e 218 servoLeft.pulsewidth_us(1500.0);
NaotoMorita 36:e68ce293306e 219 servoThrust.pulsewidth_us(1100.0);
NaotoMorita 36:e68ce293306e 220
NaotoMorita 36:e68ce293306e 221 qhat << 1 << 0 << 0 << 0;
NaotoMorita 36:e68ce293306e 222
NaotoMorita 36:e68ce293306e 223 Phat << 0.0001 << 0 <<0 <<0
NaotoMorita 36:e68ce293306e 224 << 0 << 0.0001 <<0 <<0
NaotoMorita 36:e68ce293306e 225 << 0 << 0 <<0.0001 <<0
NaotoMorita 36:e68ce293306e 226 << 0 << 0 << 0 << 0.0001;
NaotoMorita 36:e68ce293306e 227
NaotoMorita 36:e68ce293306e 228 Racc << 0.0001 << 0 <<0
NaotoMorita 36:e68ce293306e 229 << 0 << 0.0001 <<0
NaotoMorita 36:e68ce293306e 230 << 0 << 0 <<0.0001;
NaotoMorita 36:e68ce293306e 231
NaotoMorita 36:e68ce293306e 232
NaotoMorita 36:e68ce293306e 233 LoopTicker PIDtick;
NaotoMorita 36:e68ce293306e 234 PIDtick.attach(calcServoOut,PID_dt);
NaotoMorita 36:e68ce293306e 235 //pc.baud(115200);
NaotoMorita 36:e68ce293306e 236 //sd.baud(115200);
NaotoMorita 36:e68ce293306e 237 accelgyro.initialize();
NaotoMorita 36:e68ce293306e 238 //加速度計のフルスケールレンジを設定
NaotoMorita 36:e68ce293306e 239 accelgyro.setFullScaleAccelRange(ACCEL_FSR);
NaotoMorita 36:e68ce293306e 240 //■角速度計のフルスケールレンジを設定
NaotoMorita 36:e68ce293306e 241 accelgyro.setFullScaleGyroRange(GYRO_FSR);
NaotoMorita 36:e68ce293306e 242 //MPU6050のLPFを設定
NaotoMorita 36:e68ce293306e 243 accelgyro.setDLPFMode(MPU6050_LPF);
NaotoMorita 36:e68ce293306e 244 //MadgwickFilter.begin(100); //サンプリング周波数Hza
NaotoMorita 27:43bd0e444633 245 t.start();
NaotoMorita 36:e68ce293306e 246 //servoRight.write(0.0f);
NaotoMorita 27:43bd0e444633 247 while(1) {
NaotoMorita 31:8d02f3b9a067 248 float tstart = t.read();
NaotoMorita 27:43bd0e444633 249 //姿勢角を更新
NaotoMorita 36:e68ce293306e 250 //updateAttitude();
NaotoMorita 36:e68ce293306e 251 updateBetweenMeasures();
NaotoMorita 36:e68ce293306e 252 computeAngles();
NaotoMorita 28:fc6c46c1db65 253 PIDtick.loop(); // scaled_servo に pidのcomputing結果を格納する
naker 22:da9893b71f24 254
NaotoMorita 17:6b7a363d06d2 255 float tend = t.read();
NaotoMorita 36:e68ce293306e 256 att_dt = (tend-tstart);
NaotoMorita 36:e68ce293306e 257 //MadgwickFilter.begin(1.0f/att_dt); //サンプリング周波数Hz
NaotoMorita 28:fc6c46c1db65 258
naker 20:2c3f113a8e8f 259 }
NaotoMorita 0:6b18a09a6628 260 }