What's the best way to implement this?

Background: I have readings from a gyroscope (MPU6050) that tell me the angle (degrees) of each axis (x-roll, y-pitch, z-yaw), the yaw angle is irrelevant though. Each axis will experience a different amount of gravitational acceleration based on the angle that it's at. I need to be able to predict that acceleration on each axis so it can then be removed to get linear acceleration.

For example: when gyro_x = 45 and gyro_y = 30
then acceleration will be: acc_x = -0.54G, acc_y = 0.63G, acc_z = 0.58G

the gyroscope values will range from -90 to +90 and accelaration values from 0 (when axis is perpendicular to gravity) to 1 (when axis is parallel to gravity). So when sensor sits flat on the ground:
acc_x = 0G, acc_y = 0G, acc_z = 1G

I tried to find an equation that would let me calculate acceleration values based on rotation but had no luck. Then I considered using look-up-tables or if-else statements but that would take forever if I was to include each value.

Please let me know if there is a good way to implement this that won't slow down the code too much and doesn't involve recording readings at every angle combination and slapping down a 10,000 value-long LUT.

where did you get those numbers ?

the basic projection formulas would be

  double angleX = 45; // Test angle X = 45 degrees
  double angleY = 30; // Test angle Y = 30 degrees

  // Calculate gravitational acceleration components
  double angleXRad = angleX * M_PI / 180.0;
  double angleYRad = angleY * M_PI / 180.0;

  double accX = sin(angleYRad);
  double accY = -sin(angleXRad) * cos(angleYRad);
  double accZ = cos(angleXRad) * cos(angleYRad);

but that gives accX = 0.50G, accY = -0.61G, and accZ = 0.61G

1 Like

Welcome to the forum

Did you consider using an array with the angle being the index and the array holding the corresponding acceleration ?

Which Arduino board are you using ?

Given very accurate 3D orientation information, this is trivial. You simply subtract 1 g from the total acceleration vector. The orientation information is used to determine the direction of "Earth down" in the sensor frame of reference.

However, this is not possible with the MPU-6050 for two reasons: it has no mechanism to measure yaw, and the accel/gyro sensors too noisy and inaccurate. The latter is true of all consumer grade 9DOF IMU sensors as well.

For a complete explanation of the problem, see this article: Using Accelerometers to Estimate Position and Velocity | CH Robotics

2 Likes

The example values I used are from the sensor output. Seems to be quite close to your calculated ones considering that it might not be calibrated perfectly and it's hard to hold it still in that exact position.

I just implemented your code and it works exactly like I need it to. The acceleration values stay at 0 in all sensor positions (apart from the extremes like -90 and + 90 degrees where gimbal lock occurs), only exception is the acceleration-z drifting towards -0.1 with negative pitch (y-axis) angles but I bet that's fixable with some more calibration. Thanks for your help.

  float roll_rad = roll * M_PI / 180.0;
  float pitch_rad = pitch * M_PI / 180.0;

  float acc_offset_x = sin(pitch_rad);
  float acc_offset_y = -sin(roll_rad) * cos(pitch_rad);
  float acc_offset_z = cos(roll_rad) * cos(pitch_rad);

  //acc_cal_g => calibrated acceleration reading from sensor (acc_raw - error)
  acc_cal_g[0] = acc_cal_g[0] + acc_offset_x;
  acc_cal_g[1] = acc_cal_g[1] + acc_offset_y;
//adding '1G' that was removed during automatic system start calibration
  acc_cal_g[2] = acc_cal_g[2] - acc_offset_z + 1; 

That was my initial idea but if I wanted to achieve accuracy of +- 1 degree then I would need an array size of 90*90 which is 8100, unless I'm thinking about it wrong.
@J-M-L provided the solution I was looking for.

Take note of the remarks from @jremington, you won't get very precise data from the MPU-6050.

I know but this project is more of a proof of concept to show that you can control a 6-axis robotic arm with only an accelerometer and gyroscope and have it copy the hand movements of the operator. It doesn't need to work perfectly

Ok - you might need to add some sort of running average to smooth the variation (or filtering like take 90% of the previous calculations and 10% of the new one - you can vary the 90/10 ratio to add faster reaction time)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.