1 /* 2 $License: 3 Copyright 2011 InvenSense, Inc. 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 $ 17 */ 18 /****************************************************************************** 19 * 20 * $Id: mlarray.c 5085 2011-04-08 22:25:14Z phickey $ 21 * 22 *****************************************************************************/ 23 24 /** 25 * @defgroup ML 26 * @{ 27 * @file mlarray.c 28 * @brief APIs to read different data sets from FIFO. 29 */ 30 31 /* ------------------ */ 32 /* - Include Files. - */ 33 /* ------------------ */ 34 #include "ml.h" 35 #include "mltypes.h" 36 #include "mlinclude.h" 37 #include "mlMathFunc.h" 38 #include "mlmath.h" 39 #include "mlstates.h" 40 #include "mlFIFO.h" 41 #include "mlsupervisor.h" 42 #include "mldl.h" 43 #include "dmpKey.h" 44 #include "compass.h" 45 46 /** 47 * @brief inv_get_gyro is used to get the most recent gyroscope measurement. 48 * The argument array elements are ordered X,Y,Z. 49 * The values are scaled at 1 dps = 2^16 LSBs. 50 * 51 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 52 * must have been called. 53 * 54 * @param data 55 * A pointer to an array to be passed back to the user. 56 * <b>Must be 3 cells long </b>. 57 * 58 * @return Zero if the command is successful; an ML error code otherwise. 59 */ 60 61 /* inv_get_gyro implemented in mlFIFO.c */ 62 63 /** 64 * @brief inv_get_accel is used to get the most recent 65 * accelerometer measurement. 66 * The argument array elements are ordered X,Y,Z. 67 * The values are scaled in units of g (gravity), 68 * where 1 g = 2^16 LSBs. 69 * 70 * 71 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 72 * must have been called. 73 * 74 * @param data 75 * A pointer to an array to be passed back to the user. 76 * <b>Must be 3 cells long </b>. 77 * 78 * @return Zero if the command is successful; an ML error code otherwise. 79 */ 80 /* inv_get_accel implemented in mlFIFO.c */ 81 82 /** 83 * @brief inv_get_temperature is used to get the most recent 84 * temperature measurement. 85 * The argument array should only have one element. 86 * The value is in units of deg C (degrees Celsius), where 87 * 2^16 LSBs = 1 deg C. 88 * 89 * 90 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 91 * must have been called. 92 * 93 * @param data 94 * A pointer to the data to be passed back to the user. 95 * 96 * @return Zero if the command is successful; an ML error code otherwise. 97 */ 98 /* inv_get_temperature implemented in mlFIFO.c */ 99 100 /** 101 * @brief inv_get_rot_mat is used to get the rotation matrix 102 * representation of the current sensor fusion solution. 103 * The array format will be R11, R12, R13, R21, R22, R23, R31, R32, 104 * R33, representing the matrix: 105 * <center>R11 R12 R13</center> 106 * <center>R21 R22 R23</center> 107 * <center>R31 R32 R33</center> 108 * Values are scaled, where 1.0 = 2^30 LSBs. 109 * 110 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 111 * must have been called. 112 * 113 * @param data 114 * A pointer to an array to be passed back to the user. 115 * <b>Must be 9 cells long</b>. 116 * 117 * @return Zero if the command is successful; an ML error code otherwise. 118 */ 119 inv_error_t inv_get_rot_mat(long *data) 120 { 121 inv_error_t result = INV_SUCCESS; 122 long qdata[4]; 123 if (inv_get_state() < INV_STATE_DMP_OPENED) 124 return INV_ERROR_SM_IMPROPER_STATE; 125 126 if (NULL == data) { 127 return INV_ERROR_INVALID_PARAMETER; 128 } 129 130 inv_get_quaternion(qdata); 131 inv_quaternion_to_rotation(qdata, data); 132 133 return result; 134 } 135 136 /** 137 * @brief inv_get_quaternion is used to get the quaternion representation 138 * of the current sensor fusion solution. 139 * The values are scaled where 1.0 = 2^30 LSBs. 140 * 141 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 142 * must have been called. 143 * 144 * @param data 145 * A pointer to an array to be passed back to the user. 146 * <b>Must be 4 cells long </b>. 147 * 148 * @return INV_SUCCESS if the command is successful; an ML error code otherwise. 149 */ 150 /* inv_get_quaternion implemented in mlFIFO.c */ 151 152 /** 153 * @brief inv_get_linear_accel is used to get an estimate of linear 154 * acceleration, based on the most recent accelerometer measurement 155 * and sensor fusion solution. 156 * The values are scaled where 1 g (gravity) = 2^16 LSBs. 157 * 158 * 159 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 160 * must have been called. 161 * 162 * @param data 163 * A pointer to an array to be passed back to the user. 164 * <b>Must be 3 cells long </b>. 165 * 166 * @return Zero if the command is successful; an ML error code otherwise. 167 */ 168 /* inv_get_linear_accel implemented in mlFIFO.c */ 169 170 /** 171 * @brief inv_get_linear_accel_in_world is used to get an estimate of 172 * linear acceleration, in the world frame, based on the most 173 * recent accelerometer measurement and sensor fusion solution. 174 * The values are scaled where 1 g (gravity) = 2^16 LSBs. 175 * 176 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 177 * must have been called. 178 * 179 * @param data 180 * A pointer to an array to be passed back to the user. 181 * <b>Must be 3 cells long</b>. 182 * 183 * @return Zero if the command is successful; an ML error code otherwise. 184 */ 185 /* inv_get_linear_accel_in_world implemented in mlFIFO.c */ 186 187 /** 188 * @brief inv_get_gravity is used to get an estimate of the body frame 189 * gravity vector, based on the most recent sensor fusion solution. 190 * 191 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 192 * must have been called. 193 * 194 * @param data 195 * A pointer to an array to be passed back to the user. 196 * <b>Must be 3 cells long</b>. 197 * 198 * @return Zero if the command is successful; an ML error code otherwise. 199 */ 200 /* inv_get_gravity implemented in mlFIFO.c */ 201 202 /** 203 * @internal 204 * @brief inv_get_angular_velocity is used to get an estimate of the body 205 * frame angular velocity, which is computed from the current and 206 * previous sensor fusion solutions. 207 * 208 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 209 * must have been called. 210 * 211 * @param data 212 * A pointer to an array to be passed back to the user. 213 * <b>Must be 3 cells long </b>. 214 * 215 * @return Zero if the command is successful; an ML error code otherwise. 216 */ 217 inv_error_t inv_get_angular_velocity(long *data) 218 { 219 220 return INV_ERROR_FEATURE_NOT_IMPLEMENTED; 221 /* not implemented. old (invalid) implementation: 222 if ( inv_get_state() < INV_STATE_DMP_OPENED ) 223 return INV_ERROR_SM_IMPROPER_STATE; 224 225 if (NULL == data) { 226 return INV_ERROR_INVALID_PARAMETER; 227 } 228 data[0] = inv_obj.ang_v_body[0]; 229 data[1] = inv_obj.ang_v_body[1]; 230 data[2] = inv_obj.ang_v_body[2]; 231 232 return result; 233 */ 234 } 235 236 /** 237 * @brief inv_get_euler_angles is used to get the Euler angle representation 238 * of the current sensor fusion solution. 239 * Euler angles may follow various conventions. This function is equivelant 240 * to inv_get_euler_angles_x, refer to inv_get_euler_angles_x for more 241 * information. 242 * 243 * 244 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 245 * must have been called. 246 * 247 * @param data 248 * A pointer to an array to be passed back to the user. 249 * <b>Must be 3 cells long </b>. 250 * 251 * @return Zero if the command is successful; an ML error code otherwise. 252 */ 253 inv_error_t inv_get_euler_angles(long *data) 254 { 255 return inv_get_euler_angles_x(data); 256 } 257 258 /** 259 * @brief inv_get_euler_angles_x is used to get the Euler angle representation 260 * of the current sensor fusion solution. 261 * Euler angles are returned according to the X convention. 262 * This is typically the convention used for mobile devices where the X 263 * axis is the width of the screen, Y axis is the height, and Z the 264 * depth. In this case roll is defined as the rotation around the X 265 * axis of the device. 266 * <TABLE> 267 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 268 * <TR><TD> 0 </TD><TD>Roll </TD><TD>X axis </TD></TR> 269 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>Y axis </TD></TR> 270 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Z axis </TD></TR> 271 * </TABLE> 272 * 273 * Values are scaled where 1.0 = 2^16. 274 * 275 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 276 * must have been called. 277 * 278 * @param data 279 * A pointer to an array to be passed back to the user. 280 * <b>Must be 3 cells long </b>. 281 * 282 * @return Zero if the command is successful; an ML error code otherwise. 283 */ 284 inv_error_t inv_get_euler_angles_x(long *data) 285 { 286 inv_error_t result = INV_SUCCESS; 287 float rotMatrix[9]; 288 float tmp; 289 if (inv_get_state() < INV_STATE_DMP_OPENED) 290 return INV_ERROR_SM_IMPROPER_STATE; 291 292 if (NULL == data) { 293 return INV_ERROR_INVALID_PARAMETER; 294 } 295 296 result = inv_get_rot_mat_float(rotMatrix); 297 tmp = rotMatrix[6]; 298 if (tmp > 1.0f) { 299 tmp = 1.0f; 300 } 301 if (tmp < -1.0f) { 302 tmp = -1.0f; 303 } 304 data[0] = 305 (long)((float) 306 (atan2f(rotMatrix[7], rotMatrix[8]) * 57.29577951308) * 307 65536L); 308 data[1] = (long)((float)((double)asin(tmp) * 57.29577951308) * 65536L); 309 data[2] = 310 (long)((float) 311 (atan2f(rotMatrix[3], rotMatrix[0]) * 57.29577951308) * 312 65536L); 313 return result; 314 } 315 316 /** 317 * @brief inv_get_euler_angles_y is used to get the Euler angle representation 318 * of the current sensor fusion solution. 319 * Euler angles are returned according to the Y convention. 320 * This convention is typically used in augmented reality applications, 321 * where roll is defined as the rotation around the axis along the 322 * height of the screen of a mobile device, namely the Y axis. 323 * <TABLE> 324 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 325 * <TR><TD> 0 </TD><TD>Roll </TD><TD>Y axis </TD></TR> 326 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>X axis </TD></TR> 327 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Z axis </TD></TR> 328 * </TABLE> 329 * 330 * Values are scaled where 1.0 = 2^16. 331 * 332 * 333 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 334 * must have been called. 335 * 336 * @param data 337 * A pointer to an array to be passed back to the user. 338 * <b>Must be 3 cells long</b>. 339 * 340 * @return Zero if the command is successful; an ML error code otherwise. 341 */ 342 inv_error_t inv_get_euler_angles_y(long *data) 343 { 344 inv_error_t result = INV_SUCCESS; 345 float rotMatrix[9]; 346 float tmp; 347 if (inv_get_state() < INV_STATE_DMP_OPENED) 348 return INV_ERROR_SM_IMPROPER_STATE; 349 350 if (NULL == data) { 351 return INV_ERROR_INVALID_PARAMETER; 352 } 353 354 result = inv_get_rot_mat_float(rotMatrix); 355 tmp = rotMatrix[7]; 356 if (tmp > 1.0f) { 357 tmp = 1.0f; 358 } 359 if (tmp < -1.0f) { 360 tmp = -1.0f; 361 } 362 data[0] = 363 (long)((float) 364 (atan2f(rotMatrix[8], rotMatrix[6]) * 57.29577951308f) * 365 65536L); 366 data[1] = (long)((float)((double)asin(tmp) * 57.29577951308) * 65536L); 367 data[2] = 368 (long)((float) 369 (atan2f(rotMatrix[4], rotMatrix[1]) * 57.29577951308f) * 370 65536L); 371 return result; 372 } 373 374 /** @brief inv_get_euler_angles_z is used to get the Euler angle representation 375 * of the current sensor fusion solution. 376 * This convention is mostly used in application involving the use 377 * of a camera, typically placed on the back of a mobile device, that 378 * is along the Z axis. In this convention roll is defined as the 379 * rotation around the Z axis. 380 * Euler angles are returned according to the Y convention. 381 * <TABLE> 382 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 383 * <TR><TD> 0 </TD><TD>Roll </TD><TD>Z axis </TD></TR> 384 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>X axis </TD></TR> 385 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Y axis </TD></TR> 386 * </TABLE> 387 * 388 * Values are scaled where 1.0 = 2^16. 389 * 390 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 391 * must have been called. 392 * 393 * @param data 394 * A pointer to an array to be passed back to the user. 395 * <b>Must be 3 cells long</b>. 396 * 397 * @return INV_SUCCESS if the command is successful; an error code otherwise. 398 */ 399 400 inv_error_t inv_get_euler_angles_z(long *data) 401 { 402 inv_error_t result = INV_SUCCESS; 403 float rotMatrix[9]; 404 float tmp; 405 if (inv_get_state() < INV_STATE_DMP_OPENED) 406 return INV_ERROR_SM_IMPROPER_STATE; 407 408 if (NULL == data) { 409 return INV_ERROR_INVALID_PARAMETER; 410 } 411 412 result = inv_get_rot_mat_float(rotMatrix); 413 tmp = rotMatrix[8]; 414 if (tmp > 1.0f) { 415 tmp = 1.0f; 416 } 417 if (tmp < -1.0f) { 418 tmp = -1.0f; 419 } 420 data[0] = 421 (long)((float) 422 (atan2f(rotMatrix[6], rotMatrix[7]) * 57.29577951308) * 423 65536L); 424 data[1] = (long)((float)((double)asin(tmp) * 57.29577951308) * 65536L); 425 data[2] = 426 (long)((float) 427 (atan2f(rotMatrix[5], rotMatrix[2]) * 57.29577951308) * 428 65536L); 429 return result; 430 } 431 432 /** 433 * @brief inv_get_gyro_temp_slope is used to get is used to get the temperature 434 * compensation algorithm's estimate of the gyroscope bias temperature 435 * coefficient. 436 * The argument array elements are ordered X,Y,Z. 437 * Values are in units of dps per deg C (degrees per second per degree 438 * Celcius). Values are scaled so that 1 dps per deg C = 2^16 LSBs. 439 * Please refer to the provided "9-Axis Sensor Fusion 440 * Application Note" document. 441 * 442 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 443 * must have been called. 444 * 445 * @param data 446 * A pointer to an array to be passed back to the user. 447 * <b>Must be 3 cells long </b>. 448 * 449 * @return Zero if the command is successful; an ML error code otherwise. 450 */ 451 inv_error_t inv_get_gyro_temp_slope(long *data) 452 { 453 inv_error_t result = INV_SUCCESS; 454 if (inv_get_state() < INV_STATE_DMP_OPENED) 455 return INV_ERROR_SM_IMPROPER_STATE; 456 457 if (NULL == data) { 458 return INV_ERROR_INVALID_PARAMETER; 459 } 460 if (inv_params_obj.bias_mode & INV_LEARN_BIAS_FROM_TEMPERATURE) { 461 data[0] = (long)(inv_obj.x_gyro_coef[1] * 65536.0f); 462 data[1] = (long)(inv_obj.y_gyro_coef[1] * 65536.0f); 463 data[2] = (long)(inv_obj.z_gyro_coef[1] * 65536.0f); 464 } else { 465 data[0] = inv_obj.temp_slope[0]; 466 data[1] = inv_obj.temp_slope[1]; 467 data[2] = inv_obj.temp_slope[2]; 468 } 469 return result; 470 } 471 472 /** 473 * @brief inv_get_gyro_bias is used to get the gyroscope biases. 474 * The argument array elements are ordered X,Y,Z. 475 * The values are scaled such that 1 dps = 2^16 LSBs. 476 * 477 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 478 * must have been called. 479 * 480 * @param data 481 * A pointer to an array to be passed back to the user. 482 * <b>Must be 3 cells long</b>. 483 * 484 * @return Zero if the command is successful; an ML error code otherwise. 485 */ 486 inv_error_t inv_get_gyro_bias(long *data) 487 { 488 inv_error_t result = INV_SUCCESS; 489 if (inv_get_state() < INV_STATE_DMP_OPENED) 490 return INV_ERROR_SM_IMPROPER_STATE; 491 492 if (NULL == data) { 493 return INV_ERROR_INVALID_PARAMETER; 494 } 495 data[0] = inv_obj.gyro_bias[0]; 496 data[1] = inv_obj.gyro_bias[1]; 497 data[2] = inv_obj.gyro_bias[2]; 498 499 return result; 500 } 501 502 /** 503 * @brief inv_get_accel_bias is used to get the accelerometer baises. 504 * The argument array elements are ordered X,Y,Z. 505 * The values are scaled such that 1 g (gravity) = 2^16 LSBs. 506 * 507 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 508 * must have been called. 509 * 510 * @param data 511 * A pointer to an array to be passed back to the user. 512 * <b>Must be 3 cells long </b>. 513 * 514 * @return Zero if the command is successful; an ML error code otherwise. 515 */ 516 inv_error_t inv_get_accel_bias(long *data) 517 { 518 inv_error_t result = INV_SUCCESS; 519 if (inv_get_state() < INV_STATE_DMP_OPENED) 520 return INV_ERROR_SM_IMPROPER_STATE; 521 522 if (NULL == data) { 523 return INV_ERROR_INVALID_PARAMETER; 524 } 525 data[0] = inv_obj.accel_bias[0]; 526 data[1] = inv_obj.accel_bias[1]; 527 data[2] = inv_obj.accel_bias[2]; 528 529 return result; 530 } 531 532 /** 533 * @cond MPL 534 * @brief inv_get_mag_bias is used to get Magnetometer Bias 535 * 536 * 537 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 538 * must have been called. 539 * 540 * @param data 541 * A pointer to an array to be passed back to the user. 542 * <b>Must be 3 cells long </b>. 543 * 544 * @return Zero if the command is successful; an ML error code otherwise. 545 * @endcond 546 */ 547 inv_error_t inv_get_mag_bias(long *data) 548 { 549 inv_error_t result = INV_SUCCESS; 550 if (inv_get_state() < INV_STATE_DMP_OPENED) 551 return INV_ERROR_SM_IMPROPER_STATE; 552 553 if (NULL == data) { 554 return INV_ERROR_INVALID_PARAMETER; 555 } 556 data[0] = 557 inv_obj.compass_bias[0] + 558 (long)((long long)inv_obj.init_compass_bias[0] * inv_obj.compass_sens / 559 16384); 560 data[1] = 561 inv_obj.compass_bias[1] + 562 (long)((long long)inv_obj.init_compass_bias[1] * inv_obj.compass_sens / 563 16384); 564 data[2] = 565 inv_obj.compass_bias[2] + 566 (long)((long long)inv_obj.init_compass_bias[2] * inv_obj.compass_sens / 567 16384); 568 569 return result; 570 } 571 572 /** 573 * @brief inv_get_gyro_and_accel_sensor is used to get the most recent set of all sensor data. 574 * The argument array elements are ordered gyroscope X,Y, and Z, 575 * accelerometer X, Y, and Z, and magnetometer X,Y, and Z. 576 * \if UMPL The magnetometer elements are not populated in UMPL. \endif 577 * The gyroscope and accelerometer data is not scaled or offset, it is 578 * copied directly from the sensor registers. 579 * In the case of accelerometers with 8-bit output resolution, the data 580 * is scaled up to match the 2^14 = 1 g typical represntation of +/- 2 g 581 * full scale range 582 * 583 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 584 * must have been called. 585 * 586 * @param data 587 * A pointer to an array to be passed back to the user. 588 * <b>Must be 9 cells long</b>. 589 * 590 * @return Zero if the command is successful; an ML error code otherwise. 591 */ 592 /* inv_get_gyro_and_accel_sensor implemented in mlFIFO.c */ 593 594 /** 595 * @cond MPL 596 * @brief inv_get_mag_raw_data is used to get Raw magnetometer data. 597 * 598 * 599 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 600 * must have been called. 601 * 602 * @param data 603 * A pointer to an array to be passed back to the user. 604 * <b>Must be 3 cells long </b>. 605 * 606 * @return Zero if the command is successful; an ML error code otherwise. 607 * @endcond 608 */ 609 inv_error_t inv_get_mag_raw_data(long *data) 610 { 611 inv_error_t result = INV_SUCCESS; 612 if (inv_get_state() < INV_STATE_DMP_OPENED) 613 return INV_ERROR_SM_IMPROPER_STATE; 614 615 if (NULL == data) { 616 return INV_ERROR_INVALID_PARAMETER; 617 } 618 619 data[0] = inv_obj.compass_sensor_data[0]; 620 data[1] = inv_obj.compass_sensor_data[1]; 621 data[2] = inv_obj.compass_sensor_data[2]; 622 623 return result; 624 } 625 626 /** 627 * @cond MPL 628 * @brief inv_get_magnetometer is used to get magnetometer data. 629 * 630 * 631 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 632 * must have been called. 633 * 634 * @param data 635 * A pointer to an array to be passed back to the user. 636 * <b>Must be 3 cells long</b>. 637 * 638 * @return Zero if the command is successful; an ML error code otherwise. 639 * @endcond 640 */ 641 inv_error_t inv_get_magnetometer(long *data) 642 { 643 inv_error_t result = INV_SUCCESS; 644 if (inv_get_state() < INV_STATE_DMP_OPENED) 645 return INV_ERROR_SM_IMPROPER_STATE; 646 647 if (NULL == data) { 648 return INV_ERROR_INVALID_PARAMETER; 649 } 650 651 data[0] = inv_obj.compass_sensor_data[0] + inv_obj.init_compass_bias[0]; 652 data[1] = inv_obj.compass_sensor_data[1] + inv_obj.init_compass_bias[1]; 653 data[2] = inv_obj.compass_sensor_data[2] + inv_obj.init_compass_bias[2]; 654 655 return result; 656 } 657 658 /** 659 * @cond MPL 660 * @brief inv_get_pressure is used to get Pressure data. 661 * 662 * 663 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 664 * must have been called. 665 * 666 * @param data 667 * A pointer to data to be passed back to the user. 668 * 669 * @return Zero if the command is successful; an ML error code otherwise. 670 * @endcond 671 */ 672 inv_error_t inv_get_pressure(long *data) 673 { 674 inv_error_t result = INV_SUCCESS; 675 if (inv_get_state() < INV_STATE_DMP_OPENED) 676 return INV_ERROR_SM_IMPROPER_STATE; 677 678 if (NULL == data) { 679 return INV_ERROR_INVALID_PARAMETER; 680 } 681 682 data[0] = inv_obj.pressure; 683 684 return result; 685 } 686 687 /** 688 * @cond MPL 689 * @brief inv_get_heading is used to get heading from Rotation Matrix. 690 * 691 * 692 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 693 * must have been called. 694 * 695 * @param data 696 * A pointer to data to be passed back to the user. 697 * 698 * @return Zero if the command is successful; an ML error code otherwise. 699 * @endcond 700 */ 701 702 inv_error_t inv_get_heading(long *data) 703 { 704 inv_error_t result = INV_SUCCESS; 705 float rotMatrix[9]; 706 float tmp; 707 if (inv_get_state() < INV_STATE_DMP_OPENED) 708 return INV_ERROR_SM_IMPROPER_STATE; 709 710 if (NULL == data) { 711 return INV_ERROR_INVALID_PARAMETER; 712 } 713 result = inv_get_rot_mat_float(rotMatrix); 714 if ((rotMatrix[7] < 0.707) && (rotMatrix[7] > -0.707)) { 715 tmp = 716 (float)(atan2f(rotMatrix[4], rotMatrix[1]) * 57.29577951308 - 717 90.0f); 718 } else { 719 tmp = 720 (float)(atan2f(rotMatrix[5], rotMatrix[2]) * 57.29577951308 + 721 90.0f); 722 } 723 if (tmp < 0) { 724 tmp += 360.0f; 725 } 726 data[0] = (long)((360 - tmp) * 65536.0f); 727 728 return result; 729 } 730 731 /** 732 * @brief inv_get_gyro_cal_matrix is used to get the gyroscope 733 * calibration matrix. The gyroscope calibration matrix defines the relationship 734 * between the gyroscope sensor axes and the sensor fusion solution axes. 735 * Calibration matrix data members will have a value of 1, 0, or -1. 736 * The matrix has members 737 * <center>C11 C12 C13</center> 738 * <center>C21 C22 C23</center> 739 * <center>C31 C32 C33</center> 740 * The argument array elements are ordered C11, C12, C13, C21, C22, C23, C31, C32, C33. 741 * 742 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 743 * must have been called. 744 * 745 * @param data 746 * A pointer to an array to be passed back to the user. 747 * <b>Must be 9 cells long</b>. 748 * 749 * @return Zero if the command is successful; an ML error code otherwise. 750 */ 751 inv_error_t inv_get_gyro_cal_matrix(long *data) 752 { 753 inv_error_t result = INV_SUCCESS; 754 if (inv_get_state() < INV_STATE_DMP_OPENED) 755 return INV_ERROR_SM_IMPROPER_STATE; 756 757 if (NULL == data) { 758 return INV_ERROR_INVALID_PARAMETER; 759 } 760 761 data[0] = inv_obj.gyro_cal[0]; 762 data[1] = inv_obj.gyro_cal[1]; 763 data[2] = inv_obj.gyro_cal[2]; 764 data[3] = inv_obj.gyro_cal[3]; 765 data[4] = inv_obj.gyro_cal[4]; 766 data[5] = inv_obj.gyro_cal[5]; 767 data[6] = inv_obj.gyro_cal[6]; 768 data[7] = inv_obj.gyro_cal[7]; 769 data[8] = inv_obj.gyro_cal[8]; 770 771 return result; 772 } 773 774 /** 775 * @brief inv_get_accel_cal_matrix is used to get the accelerometer 776 * calibration matrix. 777 * Calibration matrix data members will have a value of 1, 0, or -1. 778 * The matrix has members 779 * <center>C11 C12 C13</center> 780 * <center>C21 C22 C23</center> 781 * <center>C31 C32 C33</center> 782 * The argument array elements are ordered C11, C12, C13, C21, C22, C23, C31, C32, C33. 783 * 784 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 785 * 786 * 787 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 788 * must have been called. 789 * 790 * @param data 791 * A pointer to an array to be passed back to the user. 792 * <b>Must be 9 cells long</b>. 793 * 794 * @return Zero if the command is successful; an ML error code otherwise. 795 */ 796 inv_error_t inv_get_accel_cal_matrix(long *data) 797 { 798 inv_error_t result = INV_SUCCESS; 799 if (inv_get_state() < INV_STATE_DMP_OPENED) 800 return INV_ERROR_SM_IMPROPER_STATE; 801 802 if (NULL == data) { 803 return INV_ERROR_INVALID_PARAMETER; 804 } 805 806 data[0] = inv_obj.accel_cal[0]; 807 data[1] = inv_obj.accel_cal[1]; 808 data[2] = inv_obj.accel_cal[2]; 809 data[3] = inv_obj.accel_cal[3]; 810 data[4] = inv_obj.accel_cal[4]; 811 data[5] = inv_obj.accel_cal[5]; 812 data[6] = inv_obj.accel_cal[6]; 813 data[7] = inv_obj.accel_cal[7]; 814 data[8] = inv_obj.accel_cal[8]; 815 816 return result; 817 } 818 819 /** 820 * @cond MPL 821 * @brief inv_get_mag_cal_matrix is used to get magnetometer calibration matrix. 822 * 823 * 824 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 825 * must have been called. 826 * 827 * @param data 828 * A pointer to an array to be passed back to the user. 829 * <b>Must be 9 cells long at least</b>. 830 * 831 * @return Zero if the command is successful; an ML error code otherwise. 832 * @endcond 833 */ 834 inv_error_t inv_get_mag_cal_matrix(long *data) 835 { 836 inv_error_t result = INV_SUCCESS; 837 if (inv_get_state() < INV_STATE_DMP_OPENED) 838 return INV_ERROR_SM_IMPROPER_STATE; 839 840 if (NULL == data) { 841 return INV_ERROR_INVALID_PARAMETER; 842 } 843 844 data[0] = inv_obj.compass_cal[0]; 845 data[1] = inv_obj.compass_cal[1]; 846 data[2] = inv_obj.compass_cal[2]; 847 data[3] = inv_obj.compass_cal[3]; 848 data[4] = inv_obj.compass_cal[4]; 849 data[5] = inv_obj.compass_cal[5]; 850 data[6] = inv_obj.compass_cal[6]; 851 data[7] = inv_obj.compass_cal[7]; 852 data[8] = inv_obj.compass_cal[8]; 853 854 return result; 855 } 856 857 /** 858 * @cond MPL 859 * @brief inv_get_mag_bias_error is used to get magnetometer Bias error. 860 * 861 * 862 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 863 * must have been called. 864 * 865 * @param data 866 * A pointer to an array to be passed back to the user. 867 * <b>Must be 3 cells long at least</b>. 868 * 869 * @return Zero if the command is successful; an ML error code otherwise. 870 * @endcond 871 */ 872 inv_error_t inv_get_mag_bias_error(long *data) 873 { 874 inv_error_t result = INV_SUCCESS; 875 if (inv_get_state() < INV_STATE_DMP_OPENED) 876 return INV_ERROR_SM_IMPROPER_STATE; 877 878 if (NULL == data) { 879 return INV_ERROR_INVALID_PARAMETER; 880 } 881 if (inv_obj.large_field == 0) { 882 data[0] = inv_obj.compass_bias_error[0]; 883 data[1] = inv_obj.compass_bias_error[1]; 884 data[2] = inv_obj.compass_bias_error[2]; 885 } else { 886 data[0] = P_INIT; 887 data[1] = P_INIT; 888 data[2] = P_INIT; 889 } 890 891 return result; 892 } 893 894 /** 895 * @cond MPL 896 * @brief inv_get_mag_scale is used to get magnetometer scale. 897 * 898 * 899 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 900 * must have been called. 901 * 902 * @param data 903 * A pointer to an array to be passed back to the user. 904 * <b>Must be 3 cells long at least</b>. 905 * 906 * @return Zero if the command is successful; an ML error code otherwise. 907 * @endcond 908 */ 909 inv_error_t inv_get_mag_scale(long *data) 910 { 911 inv_error_t result = INV_SUCCESS; 912 if (inv_get_state() < INV_STATE_DMP_OPENED) 913 return INV_ERROR_SM_IMPROPER_STATE; 914 915 if (NULL == data) { 916 return INV_ERROR_INVALID_PARAMETER; 917 } 918 919 data[0] = inv_obj.compass_scale[0]; 920 data[1] = inv_obj.compass_scale[1]; 921 data[2] = inv_obj.compass_scale[2]; 922 923 return result; 924 } 925 926 /** 927 * @cond MPL 928 * @brief inv_get_local_field is used to get local magnetic field data. 929 * 930 * 931 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 932 * must have been called. 933 * 934 * @param data 935 * A pointer to an array to be passed back to the user. 936 * <b>Must be 3 cells long at least</b>. 937 * 938 * @return Zero if the command is successful; an ML error code otherwise. 939 * @endcond 940 */ 941 inv_error_t inv_get_local_field(long *data) 942 { 943 inv_error_t result = INV_SUCCESS; 944 if (inv_get_state() < INV_STATE_DMP_OPENED) 945 return INV_ERROR_SM_IMPROPER_STATE; 946 947 if (NULL == data) { 948 return INV_ERROR_INVALID_PARAMETER; 949 } 950 951 data[0] = inv_obj.local_field[0]; 952 data[1] = inv_obj.local_field[1]; 953 data[2] = inv_obj.local_field[2]; 954 955 return result; 956 } 957 958 /** 959 * @cond MPL 960 * @brief inv_get_relative_quaternion is used to get relative quaternion. 961 * 962 * 963 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 964 * must have been called. 965 * 966 * @param data 967 * A pointer to an array to be passed back to the user. 968 * <b>Must be 4 cells long at least</b>. 969 * 970 * @return Zero if the command is successful; an ML error code otherwise. 971 * @endcond 972 */ 973 /* inv_get_relative_quaternion implemented in mlFIFO.c */ 974 975 /** 976 * @brief inv_get_gyro_float is used to get the most recent gyroscope measurement. 977 * The argument array elements are ordered X,Y,Z. 978 * The values are in units of dps (degrees per second). 979 * 980 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 981 * must have been called. 982 * 983 * @param data 984 * A pointer to an array to be passed back to the user. 985 * <b>Must be 3 cells long</b>. 986 * 987 * @return INV_SUCCESS if the command is successful; an error code otherwise. 988 */ 989 inv_error_t inv_get_gyro_float(float *data) 990 { 991 INVENSENSE_FUNC_START; 992 993 inv_error_t result = INV_SUCCESS; 994 long ldata[3]; 995 996 if (inv_get_state() < INV_STATE_DMP_OPENED) 997 return INV_ERROR_SM_IMPROPER_STATE; 998 999 if (NULL == data) { 1000 return INV_ERROR_INVALID_PARAMETER; 1001 } 1002 result = inv_get_gyro(ldata); 1003 data[0] = (float)ldata[0] / 65536.0f; 1004 data[1] = (float)ldata[1] / 65536.0f; 1005 data[2] = (float)ldata[2] / 65536.0f; 1006 1007 return result; 1008 } 1009 1010 /** 1011 * @internal 1012 * @brief inv_get_angular_velocity_float is used to get an array of three data points representing the angular 1013 * velocity as derived from <b>both</b> gyroscopes and accelerometers. 1014 * This requires that ML_SENSOR_FUSION be enabled, to fuse data from 1015 * the gyroscope and accelerometer device, appropriately scaled and 1016 * oriented according to the respective mounting matrices. 1017 * 1018 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1019 * must have been called. 1020 * @param data 1021 * A pointer to an array to be passed back to the user. 1022 * <b>Must be 3 cells long</b>. 1023 * 1024 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1025 */ 1026 inv_error_t inv_get_angular_velocity_float(float *data) 1027 { 1028 return INV_ERROR_FEATURE_NOT_IMPLEMENTED; 1029 /* not implemented. old (invalid) implementation: 1030 return inv_get_gyro_float(data); 1031 */ 1032 } 1033 1034 /** 1035 * @brief inv_get_accel_float is used to get the most recent accelerometer measurement. 1036 * The argument array elements are ordered X,Y,Z. 1037 * The values are in units of g (gravity). 1038 * 1039 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1040 * must have been called. 1041 * 1042 * @param data 1043 * A pointer to an array to be passed back to the user. 1044 * <b>Must be 3 cells long</b>. 1045 * 1046 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1047 */ 1048 /* inv_get_accel_float implemented in mlFIFO.c */ 1049 1050 /** 1051 * @brief inv_get_temperature_float is used to get the most recent 1052 * temperature measurement. 1053 * The argument array should only have one element. 1054 * The value is in units of deg C (degrees Celsius). 1055 * 1056 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1057 * must have been called. 1058 * 1059 * @param data 1060 * A pointer to data to be passed back to the user. 1061 * 1062 * @return Zero if the command is successful; an ML error code otherwise. 1063 */ 1064 inv_error_t inv_get_temperature_float(float *data) 1065 { 1066 INVENSENSE_FUNC_START; 1067 1068 inv_error_t result = INV_SUCCESS; 1069 long ldata[1]; 1070 1071 if (inv_get_state() < INV_STATE_DMP_OPENED) 1072 return INV_ERROR_SM_IMPROPER_STATE; 1073 1074 if (NULL == data) { 1075 return INV_ERROR_INVALID_PARAMETER; 1076 } 1077 1078 result = inv_get_temperature(ldata); 1079 data[0] = (float)ldata[0] / 65536.0f; 1080 1081 return result; 1082 } 1083 1084 /** 1085 * @brief inv_get_rot_mat_float is used to get an array of nine data points representing the rotation 1086 * matrix generated from all available sensors. 1087 * The array format will be R11, R12, R13, R21, R22, R23, R31, R32, 1088 * R33, representing the matrix: 1089 * <center>R11 R12 R13</center> 1090 * <center>R21 R22 R23</center> 1091 * <center>R31 R32 R33</center> 1092 * <b>Please refer to the "9-Axis Sensor Fusion Application Note" document, 1093 * section 7 "Sensor Fusion Output", for details regarding rotation 1094 * matrix output</b>. 1095 * 1096 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1097 * must have been called. 1098 * 1099 * @param data 1100 * A pointer to an array to be passed back to the user. 1101 * <b>Must be 9 cells long at least</b>. 1102 * 1103 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1104 */ 1105 inv_error_t inv_get_rot_mat_float(float *data) 1106 { 1107 INVENSENSE_FUNC_START; 1108 1109 inv_error_t result = INV_SUCCESS; 1110 1111 if (inv_get_state() < INV_STATE_DMP_OPENED) 1112 return INV_ERROR_SM_IMPROPER_STATE; 1113 1114 if (NULL == data) { 1115 return INV_ERROR_INVALID_PARAMETER; 1116 } 1117 { 1118 long qdata[4], rdata[9]; 1119 inv_get_quaternion(qdata); 1120 inv_quaternion_to_rotation(qdata, rdata); 1121 data[0] = (float)rdata[0] / 1073741824.0f; 1122 data[1] = (float)rdata[1] / 1073741824.0f; 1123 data[2] = (float)rdata[2] / 1073741824.0f; 1124 data[3] = (float)rdata[3] / 1073741824.0f; 1125 data[4] = (float)rdata[4] / 1073741824.0f; 1126 data[5] = (float)rdata[5] / 1073741824.0f; 1127 data[6] = (float)rdata[6] / 1073741824.0f; 1128 data[7] = (float)rdata[7] / 1073741824.0f; 1129 data[8] = (float)rdata[8] / 1073741824.0f; 1130 } 1131 1132 return result; 1133 } 1134 1135 /** 1136 * @brief inv_get_quaternion_float is used to get the quaternion representation 1137 * of the current sensor fusion solution. 1138 * 1139 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1140 * must have been called. 1141 * 1142 * @param data 1143 * A pointer to an array to be passed back to the user. 1144 * <b>Must be 4 cells long</b>. 1145 * 1146 * @return INV_SUCCESS if the command is successful; an ML error code otherwise. 1147 */ 1148 /* inv_get_quaternion_float implemented in mlFIFO.c */ 1149 1150 /** 1151 * @brief inv_get_linear_accel_float is used to get an estimate of linear 1152 * acceleration, based on the most recent accelerometer measurement 1153 * and sensor fusion solution. 1154 * The values are in units of g (gravity). 1155 * 1156 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1157 * must have been called. 1158 * 1159 * @param data 1160 * A pointer to an array to be passed back to the user. 1161 * <b>Must be 3 cells long</b>. 1162 * 1163 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1164 */ 1165 inv_error_t inv_get_linear_accel_float(float *data) 1166 { 1167 INVENSENSE_FUNC_START; 1168 1169 inv_error_t result = INV_SUCCESS; 1170 long ldata[3]; 1171 1172 if (inv_get_state() < INV_STATE_DMP_OPENED) 1173 return INV_ERROR_SM_IMPROPER_STATE; 1174 1175 if (NULL == data) { 1176 return INV_ERROR_INVALID_PARAMETER; 1177 } 1178 1179 result = inv_get_linear_accel(ldata); 1180 data[0] = (float)ldata[0] / 65536.0f; 1181 data[1] = (float)ldata[1] / 65536.0f; 1182 data[2] = (float)ldata[2] / 65536.0f; 1183 1184 return result; 1185 } 1186 1187 /** 1188 * @brief inv_get_linear_accel_in_world_float is used to get an estimate of 1189 * linear acceleration, in the world frame, based on the most 1190 * recent accelerometer measurement and sensor fusion solution. 1191 * The values are in units of g (gravity). 1192 * 1193 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1194 * must have been called. 1195 * 1196 * @param data 1197 * A pointer to an array to be passed back to the user. 1198 * <b>Must be 3 cells long</b>. 1199 * 1200 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1201 */ 1202 inv_error_t inv_get_linear_accel_in_world_float(float *data) 1203 { 1204 INVENSENSE_FUNC_START; 1205 1206 inv_error_t result = INV_SUCCESS; 1207 long ldata[3]; 1208 1209 if (inv_get_state() < INV_STATE_DMP_OPENED) 1210 return INV_ERROR_SM_IMPROPER_STATE; 1211 1212 if (NULL == data) { 1213 return INV_ERROR_INVALID_PARAMETER; 1214 } 1215 1216 result = inv_get_linear_accel_in_world(ldata); 1217 data[0] = (float)ldata[0] / 65536.0f; 1218 data[1] = (float)ldata[1] / 65536.0f; 1219 data[2] = (float)ldata[2] / 65536.0f; 1220 1221 return result; 1222 } 1223 1224 /** 1225 * @brief inv_get_gravity_float is used to get an estimate of the body frame 1226 * gravity vector, based on the most recent sensor fusion solution. 1227 * 1228 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1229 * must have been called. 1230 * 1231 * @param data 1232 * A pointer to an array to be passed back to the user. 1233 * <b>Must be 3 cells long at least</b>. 1234 * 1235 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1236 */ 1237 inv_error_t inv_get_gravity_float(float *data) 1238 { 1239 INVENSENSE_FUNC_START; 1240 1241 inv_error_t result = INV_SUCCESS; 1242 long ldata[3]; 1243 1244 if (inv_get_state() < INV_STATE_DMP_OPENED) 1245 return INV_ERROR_SM_IMPROPER_STATE; 1246 1247 if (NULL == data) { 1248 return INV_ERROR_INVALID_PARAMETER; 1249 } 1250 result = inv_get_gravity(ldata); 1251 data[0] = (float)ldata[0] / 65536.0f; 1252 data[1] = (float)ldata[1] / 65536.0f; 1253 data[2] = (float)ldata[2] / 65536.0f; 1254 1255 return result; 1256 } 1257 1258 /** 1259 * @brief inv_get_gyro_cal_matrix_float is used to get the gyroscope 1260 * calibration matrix. The gyroscope calibration matrix defines the relationship 1261 * between the gyroscope sensor axes and the sensor fusion solution axes. 1262 * Calibration matrix data members will have a value of 1.0, 0, or -1.0. 1263 * The matrix has members 1264 * <center>C11 C12 C13</center> 1265 * <center>C21 C22 C23</center> 1266 * <center>C31 C32 C33</center> 1267 * The argument array elements are ordered C11, C12, C13, C21, C22, C23, C31, C32, C33. 1268 * 1269 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1270 * must have been called. 1271 * 1272 * @param data 1273 * A pointer to an array to be passed back to the user. 1274 * <b>Must be 9 cells long</b>. 1275 * 1276 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1277 */ 1278 inv_error_t inv_get_gyro_cal_matrix_float(float *data) 1279 { 1280 INVENSENSE_FUNC_START; 1281 1282 inv_error_t result = INV_SUCCESS; 1283 1284 if (inv_get_state() < INV_STATE_DMP_OPENED) 1285 return INV_ERROR_SM_IMPROPER_STATE; 1286 1287 if (NULL == data) { 1288 return INV_ERROR_INVALID_PARAMETER; 1289 } 1290 1291 data[0] = (float)inv_obj.gyro_cal[0] / 1073741824.0f; 1292 data[1] = (float)inv_obj.gyro_cal[1] / 1073741824.0f; 1293 data[2] = (float)inv_obj.gyro_cal[2] / 1073741824.0f; 1294 data[3] = (float)inv_obj.gyro_cal[3] / 1073741824.0f; 1295 data[4] = (float)inv_obj.gyro_cal[4] / 1073741824.0f; 1296 data[5] = (float)inv_obj.gyro_cal[5] / 1073741824.0f; 1297 data[6] = (float)inv_obj.gyro_cal[6] / 1073741824.0f; 1298 data[7] = (float)inv_obj.gyro_cal[7] / 1073741824.0f; 1299 data[8] = (float)inv_obj.gyro_cal[8] / 1073741824.0f; 1300 1301 return result; 1302 } 1303 1304 /** 1305 * @brief inv_get_accel_cal_matrix_float is used to get the accelerometer 1306 * calibration matrix. 1307 * Calibration matrix data members will have a value of 1.0, 0, or -1.0. 1308 * The matrix has members 1309 * <center>C11 C12 C13</center> 1310 * <center>C21 C22 C23</center> 1311 * <center>C31 C32 C33</center> 1312 * The argument array elements are ordered C11, C12, C13, C21, C22, C23, C31, C32, C33. 1313 * 1314 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1315 * must have been called. 1316 * 1317 * @param data 1318 * A pointer to an array to be passed back to the user. 1319 * <b>Must be 9 cells long</b>. 1320 * 1321 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1322 */ 1323 1324 inv_error_t inv_get_accel_cal_matrix_float(float *data) 1325 { 1326 INVENSENSE_FUNC_START; 1327 1328 inv_error_t result = INV_SUCCESS; 1329 1330 if (inv_get_state() < INV_STATE_DMP_OPENED) 1331 return INV_ERROR_SM_IMPROPER_STATE; 1332 1333 if (NULL == data) { 1334 return INV_ERROR_INVALID_PARAMETER; 1335 } 1336 1337 data[0] = (float)inv_obj.accel_cal[0] / 1073741824.0f; 1338 data[1] = (float)inv_obj.accel_cal[1] / 1073741824.0f; 1339 data[2] = (float)inv_obj.accel_cal[2] / 1073741824.0f; 1340 data[3] = (float)inv_obj.accel_cal[3] / 1073741824.0f; 1341 data[4] = (float)inv_obj.accel_cal[4] / 1073741824.0f; 1342 data[5] = (float)inv_obj.accel_cal[5] / 1073741824.0f; 1343 data[6] = (float)inv_obj.accel_cal[6] / 1073741824.0f; 1344 data[7] = (float)inv_obj.accel_cal[7] / 1073741824.0f; 1345 data[8] = (float)inv_obj.accel_cal[8] / 1073741824.0f; 1346 1347 return result; 1348 } 1349 1350 /** 1351 * @cond MPL 1352 * @brief inv_get_mag_cal_matrix_float is used to get an array of nine data points 1353 * representing the calibration matrix for the compass: 1354 * <center>C11 C12 C13</center> 1355 * <center>C21 C22 C23</center> 1356 * <center>C31 C32 C33</center> 1357 * 1358 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1359 * must have been called. 1360 * 1361 * @param data 1362 * A pointer to an array to be passed back to the user. 1363 * <b>Must be 9 cells long at least</b>. 1364 * 1365 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1366 * @endcond 1367 */ 1368 inv_error_t inv_get_mag_cal_matrix_float(float *data) 1369 { 1370 INVENSENSE_FUNC_START; 1371 1372 inv_error_t result = INV_SUCCESS; 1373 1374 if (inv_get_state() < INV_STATE_DMP_OPENED) 1375 return INV_ERROR_SM_IMPROPER_STATE; 1376 1377 if (NULL == data) { 1378 return INV_ERROR_INVALID_PARAMETER; 1379 } 1380 1381 data[0] = (float)inv_obj.compass_cal[0] / 1073741824.0f; 1382 data[1] = (float)inv_obj.compass_cal[1] / 1073741824.0f; 1383 data[2] = (float)inv_obj.compass_cal[2] / 1073741824.0f; 1384 data[3] = (float)inv_obj.compass_cal[3] / 1073741824.0f; 1385 data[4] = (float)inv_obj.compass_cal[4] / 1073741824.0f; 1386 data[5] = (float)inv_obj.compass_cal[5] / 1073741824.0f; 1387 data[6] = (float)inv_obj.compass_cal[6] / 1073741824.0f; 1388 data[7] = (float)inv_obj.compass_cal[7] / 1073741824.0f; 1389 data[8] = (float)inv_obj.compass_cal[8] / 1073741824.0f; 1390 return result; 1391 } 1392 1393 /** 1394 * @brief inv_get_gyro_temp_slope_float is used to get the temperature 1395 * compensation algorithm's estimate of the gyroscope bias temperature 1396 * coefficient. 1397 * The argument array elements are ordered X,Y,Z. 1398 * Values are in units of dps per deg C (degrees per second per degree 1399 * Celcius) 1400 * Please refer to the provided "9-Axis Sensor Fusion 1401 * Application Note" document. 1402 * 1403 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1404 * must have been called. 1405 * 1406 * @param data 1407 * A pointer to an array to be passed back to the user. 1408 * <b>Must be 3 cells long </b>. 1409 * 1410 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1411 */ 1412 inv_error_t inv_get_gyro_temp_slope_float(float *data) 1413 { 1414 INVENSENSE_FUNC_START; 1415 1416 inv_error_t result = INV_SUCCESS; 1417 1418 if (inv_get_state() < INV_STATE_DMP_OPENED) 1419 return INV_ERROR_SM_IMPROPER_STATE; 1420 1421 if (NULL == data) { 1422 return INV_ERROR_INVALID_PARAMETER; 1423 } 1424 1425 if (inv_params_obj.bias_mode & INV_LEARN_BIAS_FROM_TEMPERATURE) { 1426 data[0] = inv_obj.x_gyro_coef[1]; 1427 data[1] = inv_obj.y_gyro_coef[1]; 1428 data[2] = inv_obj.z_gyro_coef[1]; 1429 } else { 1430 data[0] = (float)inv_obj.temp_slope[0] / 65536.0f; 1431 data[1] = (float)inv_obj.temp_slope[1] / 65536.0f; 1432 data[2] = (float)inv_obj.temp_slope[2] / 65536.0f; 1433 } 1434 1435 return result; 1436 } 1437 1438 /** 1439 * @brief inv_get_gyro_bias_float is used to get the gyroscope biases. 1440 * The argument array elements are ordered X,Y,Z. 1441 * The values are in units of dps (degrees per second). 1442 1443 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1444 * must have been called. 1445 * 1446 * @param data 1447 * A pointer to an array to be passed back to the user. 1448 * <b>Must be 3 cells long</b>. 1449 * 1450 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1451 */ 1452 inv_error_t inv_get_gyro_bias_float(float *data) 1453 { 1454 INVENSENSE_FUNC_START; 1455 1456 inv_error_t result = INV_SUCCESS; 1457 1458 if (inv_get_state() < INV_STATE_DMP_OPENED) 1459 return INV_ERROR_SM_IMPROPER_STATE; 1460 1461 if (NULL == data) { 1462 return INV_ERROR_INVALID_PARAMETER; 1463 } 1464 1465 data[0] = (float)inv_obj.gyro_bias[0] / 65536.0f; 1466 data[1] = (float)inv_obj.gyro_bias[1] / 65536.0f; 1467 data[2] = (float)inv_obj.gyro_bias[2] / 65536.0f; 1468 1469 return result; 1470 } 1471 1472 /** 1473 * @brief inv_get_accel_bias_float is used to get the accelerometer baises. 1474 * The argument array elements are ordered X,Y,Z. 1475 * The values are in units of g (gravity). 1476 * 1477 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1478 * must have been called. 1479 * 1480 * @param data 1481 * A pointer to an array to be passed back to the user. 1482 * <b>Must be 3 cells long</b>. 1483 * 1484 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1485 */ 1486 inv_error_t inv_get_accel_bias_float(float *data) 1487 { 1488 INVENSENSE_FUNC_START; 1489 1490 inv_error_t result = INV_SUCCESS; 1491 1492 if (inv_get_state() < INV_STATE_DMP_OPENED) 1493 return INV_ERROR_SM_IMPROPER_STATE; 1494 1495 if (NULL == data) { 1496 return INV_ERROR_INVALID_PARAMETER; 1497 } 1498 1499 data[0] = (float)inv_obj.accel_bias[0] / 65536.0f; 1500 data[1] = (float)inv_obj.accel_bias[1] / 65536.0f; 1501 data[2] = (float)inv_obj.accel_bias[2] / 65536.0f; 1502 1503 return result; 1504 } 1505 1506 /** 1507 * @cond MPL 1508 * @brief inv_get_mag_bias_float is used to get an array of three data points representing 1509 * the compass biases. 1510 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1511 * must have been called. 1512 * 1513 * @param data 1514 * A pointer to an array to be passed back to the user. 1515 * <b>Must be 3 cells long</b>. 1516 * 1517 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1518 * @endcond 1519 */ 1520 inv_error_t inv_get_mag_bias_float(float *data) 1521 { 1522 INVENSENSE_FUNC_START; 1523 1524 inv_error_t result = INV_SUCCESS; 1525 1526 if (inv_get_state() < INV_STATE_DMP_OPENED) 1527 return INV_ERROR_SM_IMPROPER_STATE; 1528 1529 if (NULL == data) { 1530 return INV_ERROR_INVALID_PARAMETER; 1531 } 1532 1533 data[0] = 1534 ((float) 1535 (inv_obj.compass_bias[0] + 1536 (long)((long long)inv_obj.init_compass_bias[0] * 1537 inv_obj.compass_sens / 16384))) / 65536.0f; 1538 data[1] = 1539 ((float) 1540 (inv_obj.compass_bias[1] + 1541 (long)((long long)inv_obj.init_compass_bias[1] * 1542 inv_obj.compass_sens / 16384))) / 65536.0f; 1543 data[2] = 1544 ((float) 1545 (inv_obj.compass_bias[2] + 1546 (long)((long long)inv_obj.init_compass_bias[2] * 1547 inv_obj.compass_sens / 16384))) / 65536.0f; 1548 1549 return result; 1550 } 1551 1552 /** 1553 * @brief inv_get_gyro_and_accel_sensor_float is used to get the most recent set of all sensor data. 1554 * The argument array elements are ordered gyroscope X,Y, and Z, 1555 * accelerometer X, Y, and Z, and magnetometer X,Y, and Z. 1556 * \if UMPL The magnetometer elements are not populated in UMPL. \endif 1557 * The gyroscope and accelerometer data is not scaled or offset, it is 1558 * copied directly from the sensor registers, and cast as a float. 1559 * In the case of accelerometers with 8-bit output resolution, the data 1560 * is scaled up to match the 2^14 = 1 g typical represntation of +/- 2 g 1561 * full scale range 1562 1563 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1564 * must have been called. 1565 * 1566 * @param data 1567 * A pointer to an array to be passed back to the user. 1568 * <b>Must be 9 cells long</b>. 1569 * 1570 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1571 */ 1572 inv_error_t inv_get_gyro_and_accel_sensor_float(float *data) 1573 { 1574 INVENSENSE_FUNC_START; 1575 1576 inv_error_t result = INV_SUCCESS; 1577 long ldata[6]; 1578 1579 if (inv_get_state() < INV_STATE_DMP_OPENED) 1580 return INV_ERROR_SM_IMPROPER_STATE; 1581 1582 if (NULL == data) { 1583 return INV_ERROR_INVALID_PARAMETER; 1584 } 1585 1586 result = inv_get_gyro_and_accel_sensor(ldata); 1587 data[0] = (float)ldata[0]; 1588 data[1] = (float)ldata[1]; 1589 data[2] = (float)ldata[2]; 1590 data[3] = (float)ldata[3]; 1591 data[4] = (float)ldata[4]; 1592 data[5] = (float)ldata[5]; 1593 data[6] = (float)inv_obj.compass_sensor_data[0]; 1594 data[7] = (float)inv_obj.compass_sensor_data[1]; 1595 data[8] = (float)inv_obj.compass_sensor_data[2]; 1596 1597 return result; 1598 } 1599 1600 /** 1601 * @brief inv_get_euler_angles_x is used to get the Euler angle representation 1602 * of the current sensor fusion solution. 1603 * Euler angles are returned according to the X convention. 1604 * This is typically the convention used for mobile devices where the X 1605 * axis is the width of the screen, Y axis is the height, and Z the 1606 * depth. In this case roll is defined as the rotation around the X 1607 * axis of the device. 1608 * <TABLE> 1609 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 1610 * <TR><TD> 0 </TD><TD>Roll </TD><TD>X axis </TD></TR> 1611 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>Y axis </TD></TR> 1612 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Z axis </TD></TR> 1613 * 1614 </TABLE> 1615 * 1616 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1617 * must have been called. 1618 * 1619 * @param data 1620 * A pointer to an array to be passed back to the user. 1621 * <b>Must be 3 cells long</b>. 1622 * 1623 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1624 */ 1625 inv_error_t inv_get_euler_angles_x_float(float *data) 1626 { 1627 INVENSENSE_FUNC_START; 1628 1629 inv_error_t result = INV_SUCCESS; 1630 float rotMatrix[9]; 1631 float tmp; 1632 1633 if (inv_get_state() < INV_STATE_DMP_OPENED) 1634 return INV_ERROR_SM_IMPROPER_STATE; 1635 1636 if (NULL == data) { 1637 return INV_ERROR_INVALID_PARAMETER; 1638 } 1639 1640 result = inv_get_rot_mat_float(rotMatrix); 1641 tmp = rotMatrix[6]; 1642 if (tmp > 1.0f) { 1643 tmp = 1.0f; 1644 } 1645 if (tmp < -1.0f) { 1646 tmp = -1.0f; 1647 } 1648 data[0] = 1649 (float)(atan2f(rotMatrix[7], 1650 rotMatrix[8]) * 57.29577951308); 1651 data[1] = (float)((double)asin(tmp) * 57.29577951308); 1652 data[2] = 1653 (float)(atan2f(rotMatrix[3], rotMatrix[0]) * 57.29577951308); 1654 1655 return result; 1656 } 1657 1658 /** 1659 * @brief inv_get_euler_angles_float is used to get an array of three data points three data points 1660 * representing roll, pitch, and yaw corresponding to the INV_EULER_ANGLES_X output and it is 1661 * therefore the default convention for Euler angles. 1662 * Please refer to the INV_EULER_ANGLES_X for a detailed description. 1663 * 1664 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1665 * must have been called. 1666 * 1667 * @param data 1668 * A pointer to an array to be passed back to the user. 1669 * <b>Must be 3 cells long</b>. 1670 * 1671 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1672 */ 1673 inv_error_t inv_get_euler_angles_float(float *data) 1674 { 1675 return inv_get_euler_angles_x_float(data); 1676 } 1677 1678 /** @brief inv_get_euler_angles_y_float is used to get the Euler angle representation 1679 * of the current sensor fusion solution. 1680 * Euler angles are returned according to the Y convention. 1681 * This convention is typically used in augmented reality applications, 1682 * where roll is defined as the rotation around the axis along the 1683 * height of the screen of a mobile device, namely the Y axis. 1684 * <TABLE> 1685 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 1686 * <TR><TD> 0 </TD><TD>Roll </TD><TD>Y axis </TD></TR> 1687 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>X axis </TD></TR> 1688 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Z axis </TD></TR> 1689 * </TABLE> 1690 * 1691 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1692 * must have been called. 1693 * 1694 * @param data 1695 * A pointer to an array to be passed back to the user. 1696 * <b>Must be 3 cells long</b>. 1697 * 1698 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1699 */ 1700 inv_error_t inv_get_euler_angles_y_float(float *data) 1701 { 1702 INVENSENSE_FUNC_START; 1703 1704 inv_error_t result = INV_SUCCESS; 1705 float rotMatrix[9]; 1706 float tmp; 1707 1708 if (inv_get_state() < INV_STATE_DMP_OPENED) 1709 return INV_ERROR_SM_IMPROPER_STATE; 1710 1711 if (NULL == data) { 1712 return INV_ERROR_INVALID_PARAMETER; 1713 } 1714 1715 result = inv_get_rot_mat_float(rotMatrix); 1716 tmp = rotMatrix[7]; 1717 if (tmp > 1.0f) { 1718 tmp = 1.0f; 1719 } 1720 if (tmp < -1.0f) { 1721 tmp = -1.0f; 1722 } 1723 data[0] = 1724 (float)(atan2f(rotMatrix[8], rotMatrix[6]) * 57.29577951308); 1725 data[1] = (float)((double)asin(tmp) * 57.29577951308); 1726 data[2] = 1727 (float)(atan2f(rotMatrix[4], rotMatrix[1]) * 57.29577951308); 1728 1729 return result; 1730 } 1731 1732 /** @brief inv_get_euler_angles_z_float is used to get the Euler angle representation 1733 * of the current sensor fusion solution. 1734 * This convention is mostly used in application involving the use 1735 * of a camera, typically placed on the back of a mobile device, that 1736 * is along the Z axis. In this convention roll is defined as the 1737 * rotation around the Z axis. 1738 * Euler angles are returned according to the Y convention. 1739 * <TABLE> 1740 * <TR><TD>Element </TD><TD><b>Euler angle</b></TD><TD><b>Rotation about </b></TD></TR> 1741 * <TR><TD> 0 </TD><TD>Roll </TD><TD>Z axis </TD></TR> 1742 * <TR><TD> 1 </TD><TD>Pitch </TD><TD>X axis </TD></TR> 1743 * <TR><TD> 2 </TD><TD>Yaw </TD><TD>Y axis </TD></TR> 1744 * </TABLE> 1745 * 1746 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1747 * must have been called. 1748 * 1749 * @param data 1750 * A pointer to an array to be passed back to the user. 1751 * <b>Must be 3 cells long</b>. 1752 * 1753 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1754 * must have been called. 1755 * 1756 * @param data 1757 * A pointer to an array to be passed back to the user. 1758 * <b>Must be 3 cells long</b>. 1759 * 1760 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1761 */ 1762 inv_error_t inv_get_euler_angles_z_float(float *data) 1763 { 1764 INVENSENSE_FUNC_START; 1765 1766 inv_error_t result = INV_SUCCESS; 1767 float rotMatrix[9]; 1768 float tmp; 1769 1770 if (inv_get_state() < INV_STATE_DMP_OPENED) 1771 return INV_ERROR_SM_IMPROPER_STATE; 1772 1773 if (NULL == data) { 1774 return INV_ERROR_INVALID_PARAMETER; 1775 } 1776 1777 result = inv_get_rot_mat_float(rotMatrix); 1778 tmp = rotMatrix[8]; 1779 if (tmp > 1.0f) { 1780 tmp = 1.0f; 1781 } 1782 if (tmp < -1.0f) { 1783 tmp = -1.0f; 1784 } 1785 data[0] = 1786 (float)(atan2f(rotMatrix[6], rotMatrix[7]) * 57.29577951308); 1787 data[1] = (float)((double)asin(tmp) * 57.29577951308); 1788 data[2] = 1789 (float)(atan2f(rotMatrix[5], rotMatrix[2]) * 57.29577951308); 1790 1791 return result; 1792 } 1793 1794 /** 1795 * @cond MPL 1796 * @brief inv_get_mag_raw_data_float is used to get Raw magnetometer data 1797 * 1798 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1799 * must have been called. 1800 * 1801 * @param data 1802 * A pointer to an array to be passed back to the user. 1803 * <b>Must be 3 cells long</b>. 1804 * 1805 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1806 * @endcond 1807 */ 1808 inv_error_t inv_get_mag_raw_data_float(float *data) 1809 { 1810 INVENSENSE_FUNC_START; 1811 1812 inv_error_t result = INV_SUCCESS; 1813 1814 if (inv_get_state() < INV_STATE_DMP_OPENED) 1815 return INV_ERROR_SM_IMPROPER_STATE; 1816 1817 if (NULL == data) { 1818 return INV_ERROR_INVALID_PARAMETER; 1819 } 1820 1821 data[0] = 1822 (float)(inv_obj.compass_sensor_data[0] + inv_obj.init_compass_bias[0]); 1823 data[1] = 1824 (float)(inv_obj.compass_sensor_data[1] + inv_obj.init_compass_bias[1]); 1825 data[2] = 1826 (float)(inv_obj.compass_sensor_data[2] + inv_obj.init_compass_bias[2]); 1827 1828 return result; 1829 } 1830 1831 /** 1832 * @cond MPL 1833 * @brief inv_get_magnetometer_float is used to get magnetometer data 1834 * 1835 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1836 * must have been called. 1837 * 1838 * @param data 1839 * A pointer to an array to be passed back to the user. 1840 * <b>Must be 3 cells long</b>. 1841 * 1842 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1843 * @endcond 1844 */ 1845 inv_error_t inv_get_magnetometer_float(float *data) 1846 { 1847 INVENSENSE_FUNC_START; 1848 1849 inv_error_t result = INV_SUCCESS; 1850 1851 if (inv_get_state() < INV_STATE_DMP_OPENED) 1852 return INV_ERROR_SM_IMPROPER_STATE; 1853 1854 if (NULL == data) { 1855 return INV_ERROR_INVALID_PARAMETER; 1856 } 1857 1858 data[0] = (float)inv_obj.compass_calibrated_data[0] / 65536.0f; 1859 data[1] = (float)inv_obj.compass_calibrated_data[1] / 65536.0f; 1860 data[2] = (float)inv_obj.compass_calibrated_data[2] / 65536.0f; 1861 1862 return result; 1863 } 1864 1865 /** 1866 * @cond MPL 1867 * @brief inv_get_pressure_float is used to get a single value representing the pressure in Pascal 1868 * 1869 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1870 * must have been called. 1871 * 1872 * @param data 1873 * A pointer to the data to be passed back to the user. 1874 * 1875 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1876 * @endcond 1877 */ 1878 inv_error_t inv_get_pressure_float(float *data) 1879 { 1880 INVENSENSE_FUNC_START; 1881 1882 inv_error_t result = INV_SUCCESS; 1883 1884 if (inv_get_state() < INV_STATE_DMP_OPENED) 1885 return INV_ERROR_SM_IMPROPER_STATE; 1886 1887 if (NULL == data) { 1888 return INV_ERROR_INVALID_PARAMETER; 1889 } 1890 1891 data[0] = (float)inv_obj.pressure; 1892 1893 return result; 1894 } 1895 1896 /** 1897 * @cond MPL 1898 * @brief inv_get_heading_float is used to get single number representing the heading of the device 1899 * relative to the Earth, in which 0 represents North, 90 degrees 1900 * represents East, and so on. 1901 * The heading is defined as the direction of the +Y axis if the Y 1902 * axis is horizontal, and otherwise the direction of the -Z axis. 1903 * 1904 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1905 * must have been called. 1906 * 1907 * @param data 1908 * A pointer to the data to be passed back to the user. 1909 * 1910 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1911 * @endcond 1912 */ 1913 inv_error_t inv_get_heading_float(float *data) 1914 { 1915 INVENSENSE_FUNC_START; 1916 1917 inv_error_t result = INV_SUCCESS; 1918 float rotMatrix[9]; 1919 float tmp; 1920 1921 if (inv_get_state() < INV_STATE_DMP_OPENED) 1922 return INV_ERROR_SM_IMPROPER_STATE; 1923 1924 if (NULL == data) { 1925 return INV_ERROR_INVALID_PARAMETER; 1926 } 1927 1928 inv_get_rot_mat_float(rotMatrix); 1929 if ((rotMatrix[7] < 0.707) && (rotMatrix[7] > -0.707)) { 1930 tmp = 1931 (float)(atan2f(rotMatrix[4], rotMatrix[1]) * 57.29577951308 - 1932 90.0f); 1933 } else { 1934 tmp = 1935 (float)(atan2f(rotMatrix[5], rotMatrix[2]) * 57.29577951308 + 1936 90.0f); 1937 } 1938 if (tmp < 0) { 1939 tmp += 360.0f; 1940 } 1941 data[0] = 360 - tmp; 1942 1943 return result; 1944 } 1945 1946 /** 1947 * @cond MPL 1948 * @brief inv_get_mag_bias_error_float is used to get an array of three numbers representing 1949 * the current estimated error in the compass biases. These numbers are unitless and serve 1950 * as rough estimates in which numbers less than 100 typically represent 1951 * reasonably well calibrated compass axes. 1952 * 1953 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1954 * must have been called. 1955 * 1956 * @param data 1957 * A pointer to an array to be passed back to the user. 1958 * <b>Must be 3 cells long</b>. 1959 * 1960 * @return INV_SUCCESS if the command is successful; an error code otherwise. 1961 * @endcond 1962 */ 1963 inv_error_t inv_get_mag_bias_error_float(float *data) 1964 { 1965 INVENSENSE_FUNC_START; 1966 1967 inv_error_t result = INV_SUCCESS; 1968 1969 if (inv_get_state() < INV_STATE_DMP_OPENED) 1970 return INV_ERROR_SM_IMPROPER_STATE; 1971 1972 if (NULL == data) { 1973 return INV_ERROR_INVALID_PARAMETER; 1974 } 1975 1976 if (inv_obj.large_field == 0) { 1977 data[0] = (float)inv_obj.compass_bias_error[0]; 1978 data[1] = (float)inv_obj.compass_bias_error[1]; 1979 data[2] = (float)inv_obj.compass_bias_error[2]; 1980 } else { 1981 data[0] = (float)P_INIT; 1982 data[1] = (float)P_INIT; 1983 data[2] = (float)P_INIT; 1984 } 1985 1986 return result; 1987 } 1988 1989 /** 1990 * @cond MPL 1991 * @brief inv_get_mag_scale_float is used to get magnetometer scale. 1992 * 1993 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 1994 * must have been called. 1995 * 1996 * @param data 1997 * A pointer to an array to be passed back to the user. 1998 * <b>Must be 3 cells long</b>. 1999 * 2000 * @return INV_SUCCESS if the command is successful; an error code otherwise. 2001 * @endcond 2002 */ 2003 inv_error_t inv_get_mag_scale_float(float *data) 2004 { 2005 INVENSENSE_FUNC_START; 2006 2007 inv_error_t result = INV_SUCCESS; 2008 2009 if (inv_get_state() < INV_STATE_DMP_OPENED) 2010 return INV_ERROR_SM_IMPROPER_STATE; 2011 2012 if (NULL == data) { 2013 return INV_ERROR_INVALID_PARAMETER; 2014 } 2015 2016 data[0] = (float)inv_obj.compass_scale[0] / 65536.0f; 2017 data[1] = (float)inv_obj.compass_scale[1] / 65536.0f; 2018 data[2] = (float)inv_obj.compass_scale[2] / 65536.0f; 2019 2020 return result; 2021 } 2022 2023 /** 2024 * @cond MPL 2025 * @brief inv_get_local_field_float is used to get local magnetic field data. 2026 * 2027 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 2028 * must have been called. 2029 * 2030 * @param data 2031 * A pointer to an array to be passed back to the user. 2032 * <b>Must be 3 cells long</b>. 2033 * 2034 * @return INV_SUCCESS if the command is successful; an error code otherwise. 2035 * @endcond 2036 */ 2037 inv_error_t inv_get_local_field_float(float *data) 2038 { 2039 INVENSENSE_FUNC_START; 2040 2041 inv_error_t result = INV_SUCCESS; 2042 2043 if (inv_get_state() < INV_STATE_DMP_OPENED) 2044 return INV_ERROR_SM_IMPROPER_STATE; 2045 2046 if (NULL == data) { 2047 return INV_ERROR_INVALID_PARAMETER; 2048 } 2049 2050 data[0] = (float)inv_obj.local_field[0] / 65536.0f; 2051 data[1] = (float)inv_obj.local_field[1] / 65536.0f; 2052 data[2] = (float)inv_obj.local_field[2] / 65536.0f; 2053 2054 return result; 2055 } 2056 2057 /** 2058 * @cond MPL 2059 * @brief inv_get_relative_quaternion_float is used to get relative quaternion data. 2060 * 2061 * @pre MLDmpOpen() \ifnot UMPL or MLDmpPedometerStandAloneOpen() \endif 2062 * must have been called. 2063 * 2064 * @param data 2065 * A pointer to an array to be passed back to the user. 2066 * <b>Must be 4 cells long at least</b>. 2067 * 2068 * @return INV_SUCCESS if the command is successful; an error code otherwise. 2069 * @endcond 2070 */ 2071 inv_error_t inv_get_relative_quaternion_float(float *data) 2072 { 2073 INVENSENSE_FUNC_START; 2074 2075 inv_error_t result = INV_SUCCESS; 2076 2077 if (inv_get_state() < INV_STATE_DMP_OPENED) 2078 return INV_ERROR_SM_IMPROPER_STATE; 2079 2080 if (NULL == data) { 2081 return INV_ERROR_INVALID_PARAMETER; 2082 } 2083 2084 data[0] = (float)inv_obj.relative_quat[0] / 1073741824.0f; 2085 data[1] = (float)inv_obj.relative_quat[1] / 1073741824.0f; 2086 data[2] = (float)inv_obj.relative_quat[2] / 1073741824.0f; 2087 data[3] = (float)inv_obj.relative_quat[3] / 1073741824.0f; 2088 2089 return result; 2090 } 2091 2092 /** 2093 * Returns the curren compass accuracy. 2094 * 2095 * - 0: Unknown: The accuracy is unreliable and compass data should not be used 2096 * - 1: Low: The compass accuracy is low. 2097 * - 2: Medium: The compass accuracy is medium. 2098 * - 3: High: The compas acurracy is high and can be trusted 2099 * 2100 * @param accuracy The accuracy level in the range 0-3 2101 * 2102 * @return ML_SUCCESS or non-zero error code 2103 */ 2104 inv_error_t inv_get_compass_accuracy(int *accuracy) 2105 { 2106 if (inv_get_state() != INV_STATE_DMP_STARTED) 2107 return INV_ERROR_SM_IMPROPER_STATE; 2108 2109 *accuracy = inv_obj.compass_accuracy; 2110 return INV_SUCCESS; 2111 } 2112 2113 /** 2114 * @brief inv_set_gyro_bias is used to set the gyroscope bias. 2115 * The argument array elements are ordered X,Y,Z. 2116 * The values are scaled at 1 dps = 2^16 LSBs. 2117 * 2118 * Please refer to the provided "9-Axis Sensor Fusion 2119 * Application Note" document provided. 2120 * 2121 * @pre MLDmpOpen() \ifnot UMPL or 2122 * MLDmpPedometerStandAloneOpen() \endif 2123 * 2124 * @param data A pointer to an array to be copied from the user. 2125 * 2126 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2127 */ 2128 inv_error_t inv_set_gyro_bias(long *data) 2129 { 2130 INVENSENSE_FUNC_START; 2131 inv_error_t result = INV_SUCCESS; 2132 long biasTmp; 2133 long sf = 0; 2134 short offset[GYRO_NUM_AXES]; 2135 int i; 2136 struct mldl_cfg *mldl_cfg = inv_get_dl_config(); 2137 2138 if (mldl_cfg->gyro_sens_trim != 0) { 2139 sf = 2000 * 131 / mldl_cfg->gyro_sens_trim; 2140 } else { 2141 sf = 2000; 2142 } 2143 for (i = 0; i < GYRO_NUM_AXES; i++) { 2144 inv_obj.gyro_bias[i] = data[i]; 2145 biasTmp = -inv_obj.gyro_bias[i] / sf; 2146 if (biasTmp < 0) 2147 biasTmp += 65536L; 2148 offset[i] = (short)biasTmp; 2149 } 2150 result = inv_set_offset(offset); 2151 if (result) { 2152 LOG_RESULT_LOCATION(result); 2153 return result; 2154 } 2155 2156 return INV_SUCCESS; 2157 } 2158 2159 /** 2160 * @brief inv_set_accel_bias is used to set the accelerometer bias. 2161 * The argument array elements are ordered X,Y,Z. 2162 * The values are scaled in units of g (gravity), 2163 * where 1 g = 2^16 LSBs. 2164 * 2165 * Please refer to the provided "9-Axis Sensor Fusion 2166 * Application Note" document provided. 2167 * 2168 * @pre MLDmpOpen() \ifnot UMPL or 2169 * MLDmpPedometerStandAloneOpen() \endif 2170 * 2171 * @param data A pointer to an array to be copied from the user. 2172 * 2173 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2174 */ 2175 inv_error_t inv_set_accel_bias(long *data) 2176 { 2177 INVENSENSE_FUNC_START; 2178 inv_error_t result = INV_SUCCESS; 2179 long biasTmp; 2180 int i, j; 2181 unsigned char regs[6]; 2182 struct mldl_cfg *mldl_cfg = inv_get_dl_config(); 2183 2184 for (i = 0; i < ACCEL_NUM_AXES; i++) { 2185 inv_obj.accel_bias[i] = data[i]; 2186 if (inv_obj.accel_sens != 0 && mldl_cfg && mldl_cfg->pdata) { 2187 long long tmp64; 2188 inv_obj.scaled_accel_bias[i] = 0; 2189 for (j = 0; j < ACCEL_NUM_AXES; j++) { 2190 inv_obj.scaled_accel_bias[i] += 2191 data[j] * 2192 (long)mldl_cfg->pdata->accel.orientation[i * 3 + j]; 2193 } 2194 tmp64 = (long long)inv_obj.scaled_accel_bias[i] << 13; 2195 biasTmp = (long)(tmp64 / inv_obj.accel_sens); 2196 } else { 2197 biasTmp = 0; 2198 } 2199 if (biasTmp < 0) 2200 biasTmp += 65536L; 2201 regs[2 * i + 0] = (unsigned char)(biasTmp / 256); 2202 regs[2 * i + 1] = (unsigned char)(biasTmp % 256); 2203 } 2204 result = inv_set_mpu_memory(KEY_D_1_8, 2, ®s[0]); 2205 if (result) { 2206 LOG_RESULT_LOCATION(result); 2207 return result; 2208 } 2209 result = inv_set_mpu_memory(KEY_D_1_10, 2, ®s[2]); 2210 if (result) { 2211 LOG_RESULT_LOCATION(result); 2212 return result; 2213 } 2214 result = inv_set_mpu_memory(KEY_D_1_2, 2, ®s[4]); 2215 if (result) { 2216 LOG_RESULT_LOCATION(result); 2217 return result; 2218 } 2219 2220 return INV_SUCCESS; 2221 } 2222 2223 /** 2224 * @cond MPL 2225 * @brief inv_set_mag_bias is used to set Compass Bias 2226 * 2227 * Please refer to the provided "9-Axis Sensor Fusion 2228 * Application Note" document provided. 2229 * 2230 * @pre MLDmpOpen() \ifnot UMPL or 2231 * MLDmpPedometerStandAloneOpen() \endif 2232 * @pre MLDmpStart() must <b>NOT</b> have been called. 2233 * 2234 * @param data A pointer to an array to be copied from the user. 2235 * 2236 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2237 * @endcond 2238 */ 2239 inv_error_t inv_set_mag_bias(long *data) 2240 { 2241 INVENSENSE_FUNC_START; 2242 inv_error_t result = INV_SUCCESS; 2243 2244 inv_set_compass_bias(data); 2245 inv_obj.init_compass_bias[0] = 0; 2246 inv_obj.init_compass_bias[1] = 0; 2247 inv_obj.init_compass_bias[2] = 0; 2248 inv_obj.got_compass_bias = 1; 2249 inv_obj.got_init_compass_bias = 1; 2250 inv_obj.compass_state = SF_STARTUP_SETTLE; 2251 2252 if (result) { 2253 LOG_RESULT_LOCATION(result); 2254 return result; 2255 } 2256 return INV_SUCCESS; 2257 } 2258 2259 /** 2260 * @brief inv_set_gyro_temp_slope is used to set the temperature 2261 * compensation algorithm's estimate of the gyroscope bias temperature 2262 * coefficient. 2263 * The argument array elements are ordered X,Y,Z. 2264 * Values are in units of dps per deg C (degrees per second per degree 2265 * Celcius), and scaled such that 1 dps per deg C = 2^16 LSBs. 2266 * Please refer to the provided "9-Axis Sensor Fusion 2267 * Application Note" document. 2268 * 2269 * @brief inv_set_gyro_temp_slope is used to set Gyro temperature slope 2270 * 2271 * 2272 * @pre MLDmpOpen() \ifnot UMPL or 2273 * MLDmpPedometerStandAloneOpen() \endif 2274 * 2275 * @param data A pointer to an array to be copied from the user. 2276 * 2277 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2278 */ 2279 inv_error_t inv_set_gyro_temp_slope(long *data) 2280 { 2281 INVENSENSE_FUNC_START; 2282 inv_error_t result = INV_SUCCESS; 2283 int i; 2284 long sf; 2285 unsigned char regs[3]; 2286 2287 inv_obj.factory_temp_comp = 1; 2288 inv_obj.temp_slope[0] = data[0]; 2289 inv_obj.temp_slope[1] = data[1]; 2290 inv_obj.temp_slope[2] = data[2]; 2291 for (i = 0; i < GYRO_NUM_AXES; i++) { 2292 sf = -inv_obj.temp_slope[i] / 1118; 2293 if (sf > 127) { 2294 sf -= 256; 2295 } 2296 regs[i] = (unsigned char)sf; 2297 } 2298 result = inv_set_offsetTC(regs); 2299 2300 if (result) { 2301 LOG_RESULT_LOCATION(result); 2302 return result; 2303 } 2304 return INV_SUCCESS; 2305 } 2306 2307 /** 2308 * @cond MPL 2309 * @brief inv_set_local_field is used to set local magnetic field 2310 * 2311 * Please refer to the provided "9-Axis Sensor Fusion 2312 * Application Note" document provided. 2313 * 2314 * @pre MLDmpOpen() \ifnot UMPL or 2315 * MLDmpPedometerStandAloneOpen() \endif 2316 * @pre MLDmpStart() must <b>NOT</b> have been called. 2317 * 2318 * @param data A pointer to an array to be copied from the user. 2319 * 2320 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2321 * @endcond 2322 */ 2323 inv_error_t inv_set_local_field(long *data) 2324 { 2325 INVENSENSE_FUNC_START; 2326 inv_error_t result = INV_SUCCESS; 2327 2328 inv_obj.local_field[0] = data[0]; 2329 inv_obj.local_field[1] = data[1]; 2330 inv_obj.local_field[2] = data[2]; 2331 inv_obj.new_local_field = 1; 2332 2333 if (result) { 2334 LOG_RESULT_LOCATION(result); 2335 return result; 2336 } 2337 return INV_SUCCESS; 2338 } 2339 2340 /** 2341 * @cond MPL 2342 * @brief inv_set_mag_scale is used to set magnetometer scale 2343 * 2344 * Please refer to the provided "9-Axis Sensor Fusion 2345 * Application Note" document provided. 2346 * 2347 * @pre MLDmpOpen() \ifnot UMPL or 2348 * MLDmpPedometerStandAloneOpen() \endif 2349 * @pre MLDmpStart() must <b>NOT</b> have been called. 2350 * 2351 * @param data A pointer to an array to be copied from the user. 2352 * 2353 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2354 * @endcond 2355 */ 2356 inv_error_t inv_set_mag_scale(long *data) 2357 { 2358 INVENSENSE_FUNC_START; 2359 inv_error_t result = INV_SUCCESS; 2360 2361 inv_obj.compass_scale[0] = data[0]; 2362 inv_obj.compass_scale[1] = data[1]; 2363 inv_obj.compass_scale[2] = data[2]; 2364 2365 if (result) { 2366 LOG_RESULT_LOCATION(result); 2367 return result; 2368 } 2369 return INV_SUCCESS; 2370 } 2371 2372 /** 2373 * @brief inv_set_gyro_temp_slope_float is used to get the temperature 2374 * compensation algorithm's estimate of the gyroscope bias temperature 2375 * coefficient. 2376 * The argument array elements are ordered X,Y,Z. 2377 * Values are in units of dps per deg C (degrees per second per degree 2378 * Celcius) 2379 2380 * Please refer to the provided "9-Axis Sensor Fusion 2381 * Application Note" document provided. 2382 * 2383 * @pre MLDmpOpen() \ifnot UMPL or 2384 * MLDmpPedometerStandAloneOpen() \endif 2385 * 2386 * @param data A pointer to an array to be copied from the user. 2387 * 2388 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2389 */ 2390 inv_error_t inv_set_gyro_temp_slope_float(float *data) 2391 { 2392 long arrayTmp[3]; 2393 arrayTmp[0] = (long)(data[0] * 65536.f); 2394 arrayTmp[1] = (long)(data[1] * 65536.f); 2395 arrayTmp[2] = (long)(data[2] * 65536.f); 2396 return inv_set_gyro_temp_slope(arrayTmp); 2397 } 2398 2399 /** 2400 * @brief inv_set_gyro_bias_float is used to set the gyroscope bias. 2401 * The argument array elements are ordered X,Y,Z. 2402 * The values are in units of dps (degrees per second). 2403 * 2404 * Please refer to the provided "9-Axis Sensor Fusion 2405 * Application Note" document provided. 2406 * 2407 * @pre MLDmpOpen() \ifnot UMPL or 2408 * MLDmpPedometerStandAloneOpen() \endif 2409 * @pre MLDmpStart() must <b>NOT</b> have been called. 2410 * 2411 * @param data A pointer to an array to be copied from the user. 2412 * 2413 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2414 */ 2415 inv_error_t inv_set_gyro_bias_float(float *data) 2416 { 2417 long arrayTmp[3]; 2418 arrayTmp[0] = (long)(data[0] * 65536.f); 2419 arrayTmp[1] = (long)(data[1] * 65536.f); 2420 arrayTmp[2] = (long)(data[2] * 65536.f); 2421 return inv_set_gyro_bias(arrayTmp); 2422 2423 } 2424 2425 /** 2426 * @brief inv_set_accel_bias_float is used to set the accelerometer bias. 2427 * The argument array elements are ordered X,Y,Z. 2428 * The values are in units of g (gravity). 2429 * 2430 * Please refer to the provided "9-Axis Sensor Fusion 2431 * Application Note" document provided. 2432 * 2433 * @pre MLDmpOpen() \ifnot UMPL or 2434 * MLDmpPedometerStandAloneOpen() \endif 2435 * @pre MLDmpStart() must <b>NOT</b> have been called. 2436 * 2437 * @param data A pointer to an array to be copied from the user. 2438 * 2439 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2440 */ 2441 inv_error_t inv_set_accel_bias_float(float *data) 2442 { 2443 long arrayTmp[3]; 2444 arrayTmp[0] = (long)(data[0] * 65536.f); 2445 arrayTmp[1] = (long)(data[1] * 65536.f); 2446 arrayTmp[2] = (long)(data[2] * 65536.f); 2447 return inv_set_accel_bias(arrayTmp); 2448 2449 } 2450 2451 /** 2452 * @cond MPL 2453 * @brief inv_set_mag_bias_float is used to set compass bias 2454 * 2455 * Please refer to the provided "9-Axis Sensor Fusion 2456 * Application Note" document provided. 2457 * 2458 * @pre MLDmpOpen()\ifnot UMPL or 2459 * MLDmpPedometerStandAloneOpen() \endif 2460 * @pre MLDmpStart() must <b>NOT</b> have been called. 2461 * 2462 * @param data A pointer to an array to be copied from the user. 2463 * 2464 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2465 * @endcond 2466 */ 2467 inv_error_t inv_set_mag_bias_float(float *data) 2468 { 2469 long arrayTmp[3]; 2470 arrayTmp[0] = (long)(data[0] * 65536.f); 2471 arrayTmp[1] = (long)(data[1] * 65536.f); 2472 arrayTmp[2] = (long)(data[2] * 65536.f); 2473 return inv_set_mag_bias(arrayTmp); 2474 } 2475 2476 /** 2477 * @cond MPL 2478 * @brief inv_set_local_field_float is used to set local magnetic field 2479 * 2480 * Please refer to the provided "9-Axis Sensor Fusion 2481 * Application Note" document provided. 2482 * 2483 * @pre MLDmpOpen() \ifnot UMPL or 2484 * MLDmpPedometerStandAloneOpen() \endif 2485 * @pre MLDmpStart() must <b>NOT</b> have been called. 2486 * 2487 * @param data A pointer to an array to be copied from the user. 2488 * 2489 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2490 * @endcond 2491 */ 2492 inv_error_t inv_set_local_field_float(float *data) 2493 { 2494 long arrayTmp[3]; 2495 arrayTmp[0] = (long)(data[0] * 65536.f); 2496 arrayTmp[1] = (long)(data[1] * 65536.f); 2497 arrayTmp[2] = (long)(data[2] * 65536.f); 2498 return inv_set_local_field(arrayTmp); 2499 } 2500 2501 /** 2502 * @cond MPL 2503 * @brief inv_set_mag_scale_float is used to set magnetometer scale 2504 * 2505 * Please refer to the provided "9-Axis Sensor Fusion 2506 * Application Note" document provided. 2507 * 2508 * @pre MLDmpOpen() \ifnot UMPL or 2509 * MLDmpPedometerStandAloneOpen() \endif 2510 * @pre MLDmpStart() must <b>NOT</b> have been called. 2511 * 2512 * @param data A pointer to an array to be copied from the user. 2513 * 2514 * @return INV_SUCCESS if successful; a non-zero error code otherwise. 2515 * @endcond 2516 */ 2517 inv_error_t inv_set_mag_scale_float(float *data) 2518 { 2519 long arrayTmp[3]; 2520 arrayTmp[0] = (long)(data[0] * 65536.f); 2521 arrayTmp[1] = (long)(data[1] * 65536.f); 2522 arrayTmp[2] = (long)(data[2] * 65536.f); 2523 return inv_set_mag_scale(arrayTmp); 2524 } 2525