Obtaining raw data similar to a MEMS sensor #1084
Replies: 16 comments
-
For input to your IMU algorithm I'd suggest looking at using: jsbsim/src/models/FGPropagate.cpp Lines 833 to 835 in 56c6662 jsbsim/src/models/FGAccelerations.cpp Lines 356 to 358 in 56c6662 The units are pretty self explanatory given their encoding in the property name. |
Beta Was this translation helpful? Give feedback.
-
Thank you very much @seanmcleod . |
Beta Was this translation helpful? Give feedback.
-
Hmm, on second thoughts, what might actually be better input to an IMU algorithm that is trying to mimic the input from a real 3-axis gyro and 3-axis accelerometer is to make use of the gyro and accelerometer sensors in JSBSim. You can take a look at the equivalent .cpp files to see their implementation.
|
Beta Was this translation helpful? Give feedback.
-
In terms of frames of reference, you'll also see |
Beta Was this translation helpful? Give feedback.
-
This is valuable information collected in such a convenient form. You may know that you can somehow change the angle of roll and pitch on a non-moving aircraft. But in flight centrifugal forces act and everything works poorly. |
Beta Was this translation helpful? Give feedback.
-
So currently your implementation doesn't work well with actual accelerometers and gyros in a real aircraft, so the issue you're having isn't specific to JSBSim simulation. I'd suggest testing your implementation using some sample data from here and confirm that you can get your implementation to work with this data first. https://github.com/xioTechnologies/Fusion
https://github.com/xioTechnologies/Fusion/blob/main/Python/sensor_data.csv |
Beta Was this translation helpful? Give feedback.
-
You could always use something like this - https://www.adafruit.com/product/4754 that implements the IMU algorithm and simply spits out the calculated attitude. |
Beta Was this translation helpful? Give feedback.
-
This is a greatest #include <Fusion.h>
#include <stdbool.h>
#include <stdio.h>
// #define PRINTF
#define SAMPLE_PERIOD (0.01f) // replace this with actual sample period
#define SERIAL_BAUD 115200
FusionAhrs ahrs;
void setup() {
Serial.begin(SERIAL_BAUD);// PA9, PA10
FusionAhrsInitialise(&ahrs);
}
void loop() { // this loop should repeat each time new gyroscope data is available
const FusionVector gyroscope = {0.2f, 1.3f, 0.0f}; // replace this with actual gyroscope data in degrees/s
const FusionVector accelerometer = {0.0f, 0.0f, 1.0f}; // replace this with actual accelerometer data in g
FusionAhrsUpdateNoMagnetometer(&ahrs, gyroscope, accelerometer, SAMPLE_PERIOD);
const FusionEuler euler = FusionQuaternionToEuler(FusionAhrsGetQuaternion(&ahrs));
#ifdef PRINTF
printf("Roll %0.1f, Pitch %0.1f, Yaw %0.1f\n", euler.angle.roll, euler.angle.pitch, euler.angle.yaw);
#else
Serial.print(" \tEiler Roll: ");
Serial.print(euler.angle.roll);
Serial.print(" \tEiler Pitch: ");
Serial.print(euler.angle.pitch);
Serial.print(" \tEiler Yaw: ");
Serial.println(euler.angle.yaw);
#endif
} Their is a simple version that uses only a gyroscope and an accelerometer. |
Beta Was this translation helpful? Give feedback.
-
jsbsim/src/models/FGPropagate.cpp Lines 825 to 827 in 56c6662
When I looked into IMU algorithms many years ago briefly, I thought what they typically did, assuming only accelerometers and gyros was to reset the attitude periodically based only on the accelerometers when the total acceleration was close enough to 1g, which would get rid of drift in the attitude solution due to integrating noisy gyro data. But when the total acceleration was greater than 1g it would switch back to integrating the gyro rates. Possibly also making use of a Kalman filter, and then also in terms of more fusion making use of a magnetometer, GPS velocities, air data velocity etc. |
Beta Was this translation helpful? Give feedback.
-
Are these exactly the
|
Beta Was this translation helpful? Give feedback.
-
I succeeded to test a simple implementation of the At rolls of up to 10 degrees, the algorithm handles the evolutions quite well. |
Beta Was this translation helpful? Give feedback.
-
What JSBSim properties did you use/feed into the algorithm? Were they the outputs from the FGGyro and FGAccelerometer sensor models? In terms of https://github.com/xioTechnologies/Fusion/blob/main/README.md#algorithm-settings what settings values did you use, in particular for:
Given that you're getting perfect gyro data, unless you configured the FGGyro sensor with noise, bias, drift etc. then you could for example for the simulator case set gain very close to 0. What is also useful are the algorithm internal states and flags that let you know what the algorithm is doing for each sample. If you can't get this algorithm to work well enough for a flight application via the various settings then your other option is to look at say the algorithm used by something like ArduPilot. |
Beta Was this translation helpful? Give feedback.
-
I tried different parameters from, but did not notice any significant differences. void FusionAhrsInitialise(FusionAhrs *const ahrs) {
const FusionAhrsSettings settings = {
.convention = FusionConventionNwu,
// .convention = FusionConventionEnu,
// .convention = FusionConventionNed,
.gain = 0.5f,
// .gain = 0.01f,
.gyroscopeRange = 0.0f,
// .gyroscopeRange = 250.0f,
// .gyroscopeRange = 500.0f,
// .gyroscopeRange = 1000.0f,
// .gyroscopeRange = 2000.0f,
.accelerationRejection = 10.0f,
// .accelerationRejection = 0.0f,
// .magneticRejection = 90.0f,
.magneticRejection = 0.0f,
.recoveryTriggerPeriod = 10,
};
FusionAhrsSetSettings(ahrs, &settings);
FusionAhrsReset(ahrs);
} Probably, this is still a limitation of the algorithm’s capabilities based only on the |
Beta Was this translation helpful? Give feedback.
-
@brightproject you didn't answer my question about what JSBSim properties you were feeding into xioTechnologies algorithm. So I spent a little bit of time trying it out myself. First off, have you run their https://github.com/xioTechnologies/Fusion/blob/main/Python/advanced_example.py? It's very useful in terms of showing the state of the algorithm for each time step. So I added FGAccelerometers at the cg and also added FGGyros into the 737 aircraft in JSBSim. <system name="Sensors">
<channel name="accelerometers">
<accelerometer name="accelerometer_X">
<location unit="IN">
<x> 610.8 </x>
<y> 0 </y>
<z> -35.1 </z>
</location>
<axis> X </axis>
<output> fcs/accelerometer/X </output>
</accelerometer>
<accelerometer name="accelerometer_Y">
<location unit="IN">
<x> 610.8 </x>
<y> 0 </y>
<z> -35.1 </z>
</location>
<axis> Y </axis>
<output> fcs/accelerometer/Y </output>
</accelerometer>
<accelerometer name="accelerometer_Z">
<location unit="IN">
<x> 610.8 </x>
<y> 0 </y>
<z> -35.1 </z>
</location>
<axis> Z </axis>
<output> fcs/accelerometer/Z </output>
</accelerometer>
</channel>
<channel name="gyros">
<gyro name="fcs/gyro/X">
<axis> X </axis>
</gyro>
<gyro name="fcs/gyro/Y">
<axis> Y </axis>
</gyro>
<gyro name="fcs/gyro/Z">
<axis> Z </axis>
</gyro>
</channel>
</system> Then wrote some python code to trim the 737, let it fly for 30s and then add an elevator step input and then again at 60s add an additional elevator step input and let the aircraft fly for 180s. while fdm.get_sim_time() < 180:
fdm.run()
time_s.append(fdm.get_sim_time())
if fdm.get_sim_time() > 30:
fdm['fcs/elevator-cmd-norm'] = -0.1
if fdm.get_sim_time() > 60:
fdm['fcs/elevator-cmd-norm'] = -0.2
pitch_s.append(math.degrees(fdm['attitude/theta-rad']))
roll_s.append(math.degrees(fdm['attitude/phi-rad']))
ax = fdm['fcs/accelerometer/X']
ay = fdm['fcs/accelerometer/Y']
az = fdm['fcs/accelerometer/Z']
amag = math.sqrt(ax**2 + ay**2 + az**2)
ax_s.append(ax/g)
ay_s.append(ay/g)
az_s.append(az/g)
amag_s.append(amag/g)
gyrox = fdm['fcs/gyro/X']
gyroy = fdm['fcs/gyro/Y']
gyroz = fdm['fcs/gyro/Z']
gyrox_s.append(math.degrees(gyrox))
gyroy_s.append(math.degrees(gyroy))
gyroz_s.append(math.degrees(gyroz))
f.write(f'{fdm.get_sim_time()},{math.degrees(gyrox)},{math.degrees(gyroy)},{math.degrees(gyroz)},{-ax/g},{ay/g},{-az/g}')
f.write('\n') Note the sign changes for Then I plot JSBSim's results. Then I modified their Now in order to get such a close match I had to bump the gain way down to 0.01 from the default of 0.5. Here are some of the relevant snippets. Note the recovery trigger period is in terms of number of samples, not seconds. I noticed you had used a figure of 5 above, and I'm assuming you assumed that meant 5s. sample_rate = 120 # 120 Hz
timestamp = data[:, 0]
gyroscope = data[:, 1:4]
accelerometer = data[:, 4:7]
#magnetometer = data[:, 7:10]
# Instantiate algorithms
#offset = imufusion.Offset(sample_rate)
ahrs = imufusion.Ahrs()
ahrs.settings = imufusion.Settings(imufusion.CONVENTION_NWU, # convention
0.01, # gain
2000, # gyroscope range
10, # acceleration rejection
10, # magnetic rejection
5 * sample_rate) # recovery trigger period = 5 seconds
...
#ahrs.update(gyroscope[index], accelerometer[index], magnetometer[index], delta_time[index])
ahrs.update_no_magnetometer(gyroscope[index], accelerometer[index], delta_time[index]) So with a gain of 0.01 it means you're assuming your gyros are very good in terms of bias, drift, noise etc. which they are in my case, since I haven't configured bias, drift, noise etc. for the FGGyro it means they're perfect gyros outputting ground truth angular velocities. Just some very initial testing I've done this weekend. Will do some more to analyse their algorithm, generate more JSBSim test data etc. to use in the analysis etc. |
Beta Was this translation helpful? Give feedback.
-
And as a quick example to show how and when the accelerometer rejection and recovery etc. kicks in, I've changed the gain to 0.1 and the acceleration rejection to 2, with the following result. |
Beta Was this translation helpful? Give feedback.
-
I wanted to answer, but I forgot and answered with a different phrase, please forgive me and I get the following properties from the
and
Now I managed to collect some data received from my microcontroller: Left roll, descent, right roll, climb. Please note how the value of the roll angle or pitch angle calculated by the algorithm on my microcontroller differs from the output orientation angles of the simulator. First, the roll angle is calculated similarly to the obtained roll angle from the simulator. Either I messed up the signs of the original axes, or this is an incorrect setting of the algorithm... Raw data sampling from aviasim
Unfortunately, it’s still not easy for me to understand how the |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
To test the

IMU
algorithm, I wanted to use theFlightGear
simulator.In a nutshell - I receive data in
ASCII
on the serial port from the simulator usingstm32f411
, parse the parcel and receive 14 variables with parameters:As far as I understand, the heart of the simulator is the flight data module
JSBSim
.Unfortunately, I am not very familiar with either
FlightGear
orJSBSim
.The problem was described in detail on the forum, please forgive me for creating a similar discussion in the
JSBSim
community, but these two projects are closely related and perhaps there will be a solution here.I'm mostly confused about the units the simulation gives when asking for the following parameters:
and
Video demonstrating the strange operation of
Mahony's
algorithm.I apologize for the quality of the video, sometimes part of the device disappears from view, this is due to filming (I hold the phone with one hand, the mouse with the other, to control the plane).
The video shows that if the movements of the control stick are small, for example towards or away from you, then the attitude indicator also repeats the movements.
If you rock the plane from side to side, just a little, the attitude indicator will display this.
If you fly with a bank of more than
30 degrees
, then the bank angle on the attitude indicator begins to jump, from -30 to +30 in roll.I hope for the help of the community, I myself cannot understand in what units the angular velocities are output by the simulator.
I was hoping to get gyroscope accelerations and angular velocities similar in parameters, like a mems sensor.
If I take data from a real mems sensor, then I get the raw data and multiply it by the
LSB
and axis sensitivity coefficient.Usually I get accelerations in
G
, and angular velocities of the gyroscope inDPS
- degrees per second.According to documentation and file and here also.
For
flightgear
- accelerations are inG's
, and gyro rates are inrads per second's
.But at least I can see
9.8 m/s^2
and understand that the units are1G
.Regarding the angular velocities of gyroscopes, I am at a loss and not sure what units of measurement they are.
In my code, I had to multiply the raw data by 2 in order for the attitude indicator to move at least somehow, and also add
minuses
in front of the axies, because the algorithmMahony
generally did not adequately determine orientation angles.The angular velocities are too low, in a real mems sensor, when rotating the sensor by hand, the speed is about
250
degrees per second or4.36
radians per second.But when I'm in flight on the simulator, I change the bank angle, the angular velocity barely reaches


1 radian per second
.Below is an example of the obtained values of angular velocities along the axes at the moment of performing the
half-barrel
turn.gyro_x: -0.903614 gyro_y: -0.090636 gyro_z: 0.271146
As far as I understand,
flightgear/jbsim
does not use theNED
reference system, which is used by algorithms for obtaining orientation angles based on mems sensors?or
Code for the parser and raw data processing using the
Mahony
algorithm(source):I would be grateful for help and tips on how to correctly scale the raw data of accelerations and angular velocities of the gyroscope from the simulator, as well as the directions of these axes.
Beta Was this translation helpful? Give feedback.
All reactions