imusensor icon indicating copy to clipboard operation
imusensor copied to clipboard

caliberateAccelerometer() results in an error!

Open PatrickPB opened this issue 3 years ago • 4 comments

Whenever I activate calibrateAccelerometer() and after the 6 obligate positions, I get IndexError: list index out of range see below

".. Put the IMU in 6 position [-3.65328894 9.16576421 3.43421432] [9.416180537422752, -10.05599768734264] [8.000009931792171, 9.165764213321125] [-7.225422289768825] Traceback (most recent call last): File "kalman.py", line 29, in imu.caliberateAccelerometer() File "/home/pi/.local/lib/python3.7/site-packages/imusensor/MPU9250/MPU9250.py", line 307, in caliberateAccelerometer self.AccelBias[2] = -1*(zscale[0] + zscale[1])/(abs(zscale[0]) + abs(zscale[1])) IndexError: list index out of range " Can you help? I need calibration, the values are going too much up and down. Trying to use the 9250 for a 2 wheel balancing robot. Kp me informed

PatrickPB avatar Jul 07 '20 18:07 PatrickPB

Hi Patrick, In the above error, the last three lines showcase the mean acceleration across various axes -> [9.416180537422752, -10.05599768734264] -> +- x-axis [8.000009931792171, 9.165764213321125] -> +- y-axis [-7.225422289768825] -> +- z-axis Every time you put in a specific position, it calculates the mean acceleration value. However, if the mean value is below 7, it is not considered as the lowest g on earth does not go below 9, so I assumed 7 is a safe cutoff. If it is below 7, then I believe it has some other force acting on it while calibrating. I also see a lot of change in the values for mean values across the other axes. I would suggest the following steps -> The default imu.Accels and imu.AccelBias are [1,1,1] and [0,0,0] respectively. Use the below code to see how well they are working.

import os
import sys
import time
import smbus

from imusensor.MPU9250 import MPU9250

address = 0x68
bus = smbus.SMBus(1)
imu = MPU9250.MPU9250(bus, address)
imu.begin()
# imu.caliberateGyro()
# imu.caliberateAccelerometer()
# or load your own caliberation file
#imu.loadCalibDataFromFile("/home/pi/calib_real_bolder.json")

while True:
	imu.readSensor()
	imu.computeOrientation()

	print ("Accel x: {0} ; Accel y : {1} ; Accel z : {2}".format(imu.AccelVals[0], imu.AccelVals[1], imu.AccelVals[2]))
	time.sleep(0.1)

Use the above code to see the acceleration value in all directions. If you get roughly equal to 9.8 or close to it, that tells that the accelerometer has been properly calibrated at the factory itself, you might not need any change. However, in the case that you don't see proper values or values not so close to 9.8 or close to the gravity at your place Placing the sensor in 6 different positions can be a pain and doing this every time is not feasible. I would suggest you do this once properly and save the calibration values using the below code.

import smbus
import numpy as np
import sys
import os
import time

from imusensor.MPU9250 import MPU9250


address = 0x68
bus = smbus.SMBus(1)
imu = MPU9250.MPU9250(bus, address)
imu.begin()
print ("Gyro caliberation starting")
imu.caliberateGyro()
print ("Gyro caliberation finished")
print ("Accel caliberation starting")
imu.caliberateAccelerometer()
print ("Accel caliberation Finisehd")
print (imu.AccelBias)
print (imu.Accels)
imu.saveCalibDataToFile("/your_path/calib.json")

Make sure to give your path and also make sure it has .json at the end for the function imu.saveCalibDataToFile() Note: Make sure not to move the sensor when the gyro is being calibrated.

Once you have all the calibration saved, you can directly call the calibration file using imu.loadCalibDataFromFile and check the accelerometer values again.

import time
import smbus

from imusensor.MPU9250 import MPU9250

address = 0x68
bus = smbus.SMBus(1)
imu = MPU9250.MPU9250(bus, address)
imu.begin()
# imu.caliberateGyro()
# imu.caliberateAccelerometer()
# or load your own caliberation file
imu.loadCalibDataFromFile("/your_path/calib.json")

while True:
	imu.readSensor()
	imu.computeOrientation()

	print ("Accel x: {0} ; Accel y : {1} ; Accel z : {2}".format(imu.AccelVals[0], imu.AccelVals[1], imu.AccelVals[2]))
        print ("roll: {0} ; pitch : {1} ; yaw : {2}".format(imu.roll, imu.pitch, imu.yaw))
	time.sleep(0.1)

You can also have a look at the orientation computed as well. However, yaw might not be accurate until the magnetometer calibration is not done.

I have tested the above code once and I get the following axes values Put the IMU in 6 position [ 0.40221046 9.76319585 -0.40129463] [-9.5352143373769742, 9.8833130803387483] [-9.6117189636072311, 9.7631958489356823] [-10.336259255664912, 9.1167883231860838]

I felt most variations are around 8 to 11, but below 7, I felt it could be due to other external forces as well and hence put a check for it. I hope if the sensor properly placed should be able to calibrate. If you still face a problem or the above error, let me know.

I hope the above steps help. Mag calibration a different thing altogether and you can have a look at my example for that.

If your curious understand the calibration process for accelerometer, it is as follows -> Let's take one axis for example. The sensor comes with its own set of bias and scale internally which is normally set in the factory itself. raw_sensor_val = N(sensor_val*scale_factory + bias_factory) Here N is the sensitivity factor that maps volts to m/sec_square. It normally comes from the range we set to the accelerometer.

In ideal conditions, the raw_sensor_val should read +-g when its axis is parallel to Earth's g. This is isn't always the case and hence we get two more parameters scale and bias.

sensor_val = (scale)*raw_sensor_val + bias Using the above equation we get two equations when the sensor axis is aligned with Earth's g. g = (scale)*raw_sensor_val_1 + bias -g = (scale)*raw_sensor_val_2 + bias

From the above two equations we can find scale and bias scale = 2g/(raw_sensor_val_1 - raw_sensor_val_2) bias = -1(raw_sensor_val_1 + raw_sensor_val_2)/(raw_sensor_val_1 - raw_sensor_val_2)

In the code, I find raw_sensor_val_1 and raw_sensor_val_2 by averaging over 100 values in that respective position. Note: This method of calibration should be good for finding the orientation of the sensor as that would deal with ratios.

niru-5 avatar Jul 08 '20 07:07 niru-5

Hi,

I have updated the package with a small change in the calibration of accelerometer. You can get it by the following command pip install --upgrade imusensor or in your case pip3 install --upgrade imusensor

Note: In the above comment the equation for bias is as follows bias = -g*(raw_sensor_val_1 + raw_sensor_val_2)/(raw_sensor_val_1 - raw_sensor_val_2)

niru-5 avatar Jul 08 '20 10:07 niru-5

Thx, after updating ; error solved But looking into the accelero values, I will need good calibration - the values go up to 15,9 and -15,9 on one axe when the others are around 0 to 1; strange to have such deviation from 9.8 knowing its calibrated in prod; anyway i will dive into the details when more time avail and feed back. I have another question: Did you write code to get the dmp quaternion values directly? Did you make a comparison of performance of the internal dmp output with the Kalman output? Regards

PatrickPB avatar Jul 08 '20 19:07 PatrickPB

It is strange to see such drastic changes. Were the values any better after calibration?

About accessing DMP and a lot of its features, I will be working on it and update you when we release it. However, It could take a while, in the mean time, you can use the code of underlying commands like _write_register and _read_registers to your advantage. These functions are undocumented but you can get an idea when you see the code. They are present in imusensor/MPU9250/MPU9250.py

Thanks Niru

niru-5 avatar Jul 11 '20 04:07 niru-5