Revision 177eb1b6
| b/common/IMU.cpp | ||
|---|---|---|
| 15 | 15 |
IMU::IMU(Hardware *hardware): |
| 16 | 16 |
QObject(), hardware(hardware), enabled(false), |
| 17 | 17 |
yaw(0), pitch(0), roll(0), |
| 18 |
q0(0), q1(0), q2(0), q3(0), |
|
| 18 |
q0(1), q1(0), q2(0), q3(0), |
|
| 19 | 19 |
exInt(0), eyInt(0), ezInt(0), |
| 20 | 20 |
lastUpdate(0), now(0), |
| 21 | 21 |
halfT(0) |
| ... | ... | |
| 29 | 29 |
gyroRaw8bit[0] = gyroRaw8bit[1] = gyroRaw8bit[2] = 0; |
| 30 | 30 |
magnRaw8bit[0] = magnRaw8bit[1] = magnRaw8bit[2] = 0; |
| 31 | 31 |
|
| 32 |
qDebug() << "In" << __FUNCTION__ << ", qX:" << q0 << q1 << q2 << q3; |
|
| 32 | 33 |
|
| 33 | 34 |
} |
| 34 | 35 |
|
| ... | ... | |
| 138 | 139 |
void IMU::pushSensorData(quint8 raw8bit[9], double data[9]) |
| 139 | 140 |
{
|
| 140 | 141 |
|
| 142 |
qDebug() << "In" << __FUNCTION__ << ", data: " << data[0] << data[1] << data[2] << data[3] << data[4] << data[5] << data[6] << data[7] << data[8]; |
|
| 143 |
|
|
| 141 | 144 |
// Accelerometer data |
| 142 | 145 |
accRaw[0] = data[0]; |
| 143 | 146 |
accRaw[1] = data[1]; |
| ... | ... | |
| 187 | 190 |
*/ |
| 188 | 191 |
void IMU::doIMUCalc() |
| 189 | 192 |
{
|
| 190 |
qDebug() << "In" << __FUNCTION__; |
|
| 193 |
//qDebug() << "In" << __FUNCTION__; |
|
| 191 | 194 |
|
| 192 | 195 |
// Update yaw/pitch/roll |
| 193 | 196 |
/* |
| ... | ... | |
| 196 | 199 |
double q[4]; // quaternion |
| 197 | 200 |
double gx, gy, gz; // estimated gravity direction |
| 198 | 201 |
getQ(q); |
| 199 |
|
|
| 202 |
|
|
| 203 |
//qDebug() << "In" << __FUNCTION__ << ", q: " << q[0] << q[1] << q[2] << q[3]; |
|
| 204 |
|
|
| 200 | 205 |
gx = 2 * (q[1]*q[3] - q[0]*q[2]); |
| 201 | 206 |
gy = 2 * (q[0]*q[1] + q[2]*q[3]); |
| 202 | 207 |
gz = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; |
| 203 |
|
|
| 208 |
|
|
| 209 |
//qDebug() << "In" << __FUNCTION__ << ", gravity: " << gx << gy << gz; |
|
| 210 |
|
|
| 204 | 211 |
yaw = atan2(2 * q[1] * q[2] - 2 * q[0] * q[3], 2 * q[0]*q[0] + 2 * q[1] * q[1] - 1) * 180/M_PI; |
| 212 |
if (isnan(yaw)) {
|
|
| 213 |
yaw = 0; |
|
| 214 |
} |
|
| 205 | 215 |
pitch = atan(gx / sqrt(gy*gy + gz*gz)) * 180/M_PI; |
| 216 |
if (isnan(pitch)) {
|
|
| 217 |
pitch = 0; |
|
| 218 |
} |
|
| 206 | 219 |
roll = atan(gy / sqrt(gx*gx + gz*gz)) * 180/M_PI; |
| 220 |
if (isnan(roll)) {
|
|
| 221 |
roll = 0; |
|
| 222 |
} |
|
| 207 | 223 |
|
| 208 | 224 |
qDebug() << "In" << __FUNCTION__ << ", yaw/pitch/roll:" << yaw << pitch << roll; |
| 209 | 225 |
} |
| ... | ... | |
| 240 | 256 |
double vx, vy, vz, wx, wy, wz; |
| 241 | 257 |
double ex, ey, ez; |
| 242 | 258 |
|
| 259 |
//qDebug() << "In" << __FUNCTION__ << ", data: " << gx << gy << gz << ax << ay << az << mx << my << mz; |
|
| 260 |
|
|
| 261 |
//qDebug() << "In" << __FUNCTION__ << ", qX:" << q0 << q1 << q2 << q3; |
|
| 262 |
|
|
| 243 | 263 |
// auxiliary variables to reduce number of repeated operations |
| 244 | 264 |
double q0q0 = q0*q0; |
| 245 | 265 |
double q0q1 = q0*q1; |
| ... | ... | |
| 252 | 272 |
double q2q3 = q2*q3; |
| 253 | 273 |
double q3q3 = q3*q3; |
| 254 | 274 |
|
| 275 |
//qDebug() << "In" << __FUNCTION__ << ", qXqY:" << q0q0 << q0q1 << q0q2 << q0q3 << q1q1 << q1q2 << q1q3 << q2q2 << q2q3 << q3q3; |
|
| 276 |
|
|
| 255 | 277 |
// normalise the measurements |
| 256 | 278 |
|
| 257 | 279 |
norm = sqrt(ax*ax + ay*ay + az*az); |
| 280 |
if (norm == 0) {
|
|
| 281 |
norm = 1; |
|
| 282 |
} |
|
| 258 | 283 |
ax = ax / norm; |
| 259 | 284 |
ay = ay / norm; |
| 260 | 285 |
az = az / norm; |
| 261 |
|
|
| 286 |
|
|
| 287 |
//qDebug() << "In" << __FUNCTION__ << ", acc:" << norm << ax << ay << az; |
|
| 288 |
|
|
| 262 | 289 |
// Get current time in milliseconds |
| 263 | 290 |
QTime time = QTime::currentTime(); |
| 264 | 291 |
now = time.hour() * 3600 * 1000 + time.minute() * 60 * 1000 + time.second() * 1000 + time.msec(); |
| 265 | 292 |
|
| 266 |
// Skip the first AHRS update as the halfT would be arbitrary |
|
| 293 |
// Estimate the lastUpdate if running this for the first time |
|
| 267 | 294 |
if (lastUpdate == 0) {
|
| 268 |
lastUpdate = now; |
|
| 269 |
return; |
|
| 295 |
lastUpdate = now - 10; |
|
| 270 | 296 |
} |
| 271 | 297 |
|
| 272 | 298 |
// If midnight just passed by, calculate the correct halfT |
| ... | ... | |
| 276 | 302 |
halfT = (now - lastUpdate) / 2000.0; |
| 277 | 303 |
} |
| 278 | 304 |
lastUpdate = now; |
| 279 |
|
|
| 305 |
|
|
| 306 |
//qDebug() << "In" << __FUNCTION__ << ", halfT:" << halfT; |
|
| 307 |
|
|
| 280 | 308 |
norm = sqrt(mx*mx + my*my + mz*mz); |
| 309 |
if (norm == 0) {
|
|
| 310 |
norm = 1; |
|
| 311 |
} |
|
| 281 | 312 |
mx = mx / norm; |
| 282 | 313 |
my = my / norm; |
| 283 | 314 |
mz = mz / norm; |
| 284 |
|
|
| 315 |
|
|
| 316 |
//qDebug() << "In" << __FUNCTION__ << ", magn:" << mx << my << mz; |
|
| 317 |
|
|
| 285 | 318 |
// compute reference direction of flux |
| 286 | 319 |
hx = 2*mx*(0.5 - q2q2 - q3q3) + 2*my*(q1q2 - q0q3) + 2*mz*(q1q3 + q0q2); |
| 287 | 320 |
hy = 2*mx*(q1q2 + q0q3) + 2*my*(0.5 - q1q1 - q3q3) + 2*mz*(q2q3 - q0q1); |
| 288 | 321 |
hz = 2*mx*(q1q3 - q0q2) + 2*my*(q2q3 + q0q1) + 2*mz*(0.5 - q1q1 - q2q2); |
| 289 | 322 |
bx = sqrt((hx*hx) + (hy*hy)); |
| 290 | 323 |
bz = hz; |
| 324 |
|
|
| 325 |
//qDebug() << "In" << __FUNCTION__ << ", direction of flux:" << hx << hy << hz; |
|
| 291 | 326 |
|
| 292 | 327 |
// estimated direction of gravity and flux (v and w) |
| 293 | 328 |
vx = 2*(q1q3 - q0q2); |
| ... | ... | |
| 297 | 332 |
wy = 2*bx*(q1q2 - q0q3) + 2*bz*(q0q1 + q2q3); |
| 298 | 333 |
wz = 2*bx*(q0q2 + q1q3) + 2*bz*(0.5 - q1q1 - q2q2); |
| 299 | 334 |
|
| 335 |
//qDebug() << "In" << __FUNCTION__ << ", direction of grav:" << vx << vy << vz; |
|
| 336 |
//qDebug() << "In" << __FUNCTION__ << ", direction of flux:" << wx << wy << wz; |
|
| 337 |
|
|
| 300 | 338 |
// error is sum of cross product between reference direction of fields and direction measured by sensors |
| 301 | 339 |
ex = (ay*vz - az*vy) + (my*wz - mz*wy); |
| 302 | 340 |
ey = (az*vx - ax*vz) + (mz*wx - mx*wz); |
| 303 | 341 |
ez = (ax*vy - ay*vx) + (mx*wy - my*wx); |
| 342 |
|
|
| 343 |
//qDebug() << "In" << __FUNCTION__ << ", sensor error:" << ex << ey << ez; |
|
| 304 | 344 |
|
| 305 | 345 |
// integral error scaled integral gain |
| 306 | 346 |
exInt = exInt + ex*Ki; |
| 307 | 347 |
eyInt = eyInt + ey*Ki; |
| 308 | 348 |
ezInt = ezInt + ez*Ki; |
| 309 | 349 |
|
| 350 |
//qDebug() << "In" << __FUNCTION__ << ", integral error:" << exInt << eyInt << ezInt; |
|
| 351 |
|
|
| 310 | 352 |
// adjusted gyroscope measurements |
| 311 | 353 |
gx = gx + Kp*ex + exInt; |
| 312 | 354 |
gy = gy + Kp*ey + eyInt; |
| 313 | 355 |
gz = gz + Kp*ez + ezInt; |
| 314 |
|
|
| 356 |
|
|
| 357 |
//qDebug() << "In" << __FUNCTION__ << ", gyro:" << gx << gy << gz; |
|
| 358 |
|
|
| 315 | 359 |
// integrate quaternion rate and normalise |
| 316 | 360 |
q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT; |
| 317 | 361 |
q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT; |
| 318 | 362 |
q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT; |
| 319 | 363 |
q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT; |
| 320 | 364 |
|
| 365 |
//qDebug() << "In" << __FUNCTION__ << ", qX1:" << q0 << q1 << q2 << q3; |
|
| 366 |
|
|
| 321 | 367 |
// normalise quaternion |
| 322 |
|
|
| 323 | 368 |
norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3); |
| 369 |
if (norm == 0) {
|
|
| 370 |
norm = 1; |
|
| 371 |
} |
|
| 324 | 372 |
q0 = q0 / norm; |
| 325 | 373 |
q1 = q1 / norm; |
| 326 | 374 |
q2 = q2 / norm; |
| 327 | 375 |
q3 = q3 / norm; |
| 328 |
|
|
| 376 |
|
|
| 377 |
//qDebug() << "In" << __FUNCTION__ << ", qX2:" << q0 << q1 << q2 << q3; |
|
| 329 | 378 |
} |
| 330 | 379 |
|
| 331 | 380 |
|
| ... | ... | |
| 336 | 385 |
void IMU::getQ(double * q) {
|
| 337 | 386 |
|
| 338 | 387 |
// gyro values are expressed in millidegrees/sec, the * M_PI/180 will convert it to radians/sec |
| 339 |
AHRSupdate((gyroRaw[3] / (double)1000) * M_PI/180, |
|
| 340 |
(gyroRaw[4] / (double)1000) * M_PI/180, |
|
| 341 |
(gyroRaw[5] / (double)1000) * M_PI/180, |
|
| 388 |
AHRSupdate((gyroRaw[0] / (double)1000) * M_PI/180, |
|
| 389 |
(gyroRaw[1] / (double)1000) * M_PI/180, |
|
| 390 |
(gyroRaw[2] / (double)1000) * M_PI/180, |
|
| 342 | 391 |
accRaw[0], accRaw[1], accRaw[2], |
| 343 |
magnRaw[6], magnRaw[7], magnRaw[8]); |
|
| 392 |
magnRaw[0], magnRaw[1], magnRaw[2]); |
|
| 344 | 393 |
q[0] = q0; |
| 345 | 394 |
q[1] = q1; |
| 346 | 395 |
q[2] = q2; |
Also available in: Unified diff