C command 'volatile' & why my head hurts
5 posts
• Page 1 of 1
C command 'volatile' & why my head hurts
I can usually get a sense of what I need to do, but not with this issue..
Context: This is (hopefully) for gyro control. To cancel out noise & smooth the signal out low/high pass filters apparently can't do the job as well as a method called sensor fusion. (One of my high school classmates builds freaking missiles or something now, and he said so,, so that's good enough for me ).
ANYWAY it also has the benefit of stopping drift in the gyro or accelerometer in the DS4, and it seems to be what all the quadcopter drone guys and the robot building guys and some other guys who I forget now use.
Below is just a paste of (what I think is the C code). I'm thinking it may be a bit too much to expect my titan two to run it, but my plan is to cherry pick from it and jam it all together until it does something close to what I want.
Oh, and I was enthused to see it had PID loops in it as I'm familiar with them & it was what I thought I'd try to use when I first thought about trying gyro control.
So my method has been "Throw the code into Gtuner and see if it compiles, and comment out errors till it does, then go back and re-enable the problem lines one by one".
Firstly I commented out the #include ""MahonyAHRS.h" & the #include <math.h> lines, I've got the MahonyAHRS.h file and I'll paste it just below, but it's a separate file, and besides my 1st step is to comment all the error lines out until GtunerIV is happy & compiles it.
Next error is this 'volatile' command, and I googled it and when I read "The proper use of C's volatile keyword is poorly understood by many programmers." I got a bit scared because if actual programmers have problems with it, then I know I'm going to cause a small fire somehow minimum.. But I think it's worth trying, because while it seemed daunting to me, they also run this on arduino's and alot of small form factor things..
But first here is a video that shows what the results can be. Also this is LESS impressive than most of them, it's just the only one that's not an hour long with some guy at a whiteboard writing so much math out that he goes thru 2 or 3 dry-erase markers.
Also thanks for your time/input, now I'm going to have a beer and cry myself to sleep
Here's the paste of theMahonyAHRS.h file (which I'm guessing is a header file or similar)
(I also was going to use code tags or similar, but I didn't know if it would mess with the formatting. :unsure
Here's the paste of the MahonyAHRS.c file
Context: This is (hopefully) for gyro control. To cancel out noise & smooth the signal out low/high pass filters apparently can't do the job as well as a method called sensor fusion. (One of my high school classmates builds freaking missiles or something now, and he said so,, so that's good enough for me ).
ANYWAY it also has the benefit of stopping drift in the gyro or accelerometer in the DS4, and it seems to be what all the quadcopter drone guys and the robot building guys and some other guys who I forget now use.
Below is just a paste of (what I think is the C code). I'm thinking it may be a bit too much to expect my titan two to run it, but my plan is to cherry pick from it and jam it all together until it does something close to what I want.
Oh, and I was enthused to see it had PID loops in it as I'm familiar with them & it was what I thought I'd try to use when I first thought about trying gyro control.
So my method has been "Throw the code into Gtuner and see if it compiles, and comment out errors till it does, then go back and re-enable the problem lines one by one".
Firstly I commented out the #include ""MahonyAHRS.h" & the #include <math.h> lines, I've got the MahonyAHRS.h file and I'll paste it just below, but it's a separate file, and besides my 1st step is to comment all the error lines out until GtunerIV is happy & compiles it.
Next error is this 'volatile' command, and I googled it and when I read "The proper use of C's volatile keyword is poorly understood by many programmers." I got a bit scared because if actual programmers have problems with it, then I know I'm going to cause a small fire somehow minimum.. But I think it's worth trying, because while it seemed daunting to me, they also run this on arduino's and alot of small form factor things..
But first here is a video that shows what the results can be. Also this is LESS impressive than most of them, it's just the only one that's not an hour long with some guy at a whiteboard writing so much math out that he goes thru 2 or 3 dry-erase markers.
Also thanks for your time/input, now I'm going to have a beer and cry myself to sleep
Here's the paste of theMahonyAHRS.h file (which I'm guessing is a header file or similar)
(I also was going to use code tags or similar, but I didn't know if it would mess with the formatting. :unsure
- Code: Select all
//=====================================================================================================
// MahonyAHRS.h
//=====================================================================================================
//
// Madgwick's implementation of Mayhony's AHRS algorithm.
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
//
//=====================================================================================================
#ifndef MahonyAHRS_h
#define MahonyAHRS_h
//----------------------------------------------------------------------------------------------------
// Variable declaration
extern volatile float twoKp; // 2 * proportional gain (Kp)
extern volatile float twoKi; // 2 * integral gain (Ki)
extern volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
//---------------------------------------------------------------------------------------------------
// Function declarations
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az);
#endif
//=====================================================================================================
// End of file
//=====================================================================================================
Here's the paste of the MahonyAHRS.c file
- Code: Select all
//=====================================================================================================
// MahonyAHRS.c
//=====================================================================================================
//
// Madgwick's implementation of Mayhony's AHRS algorithm.
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
//
//=====================================================================================================
//---------------------------------------------------------------------------------------------------
// Header files
#include "MahonyAHRS.h"
#include <math.h>
//---------------------------------------------------------------------------------------------------
// Definitions
#define sampleFreq 512.0f // sample frequency in Hz
#define twoKpDef (2.0f * 0.5f) // 2 * proportional gain
#define twoKiDef (2.0f * 0.0f) // 2 * integral gain
//---------------------------------------------------------------------------------------------------
// Variable definitions
volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp)
volatile float twoKi = twoKiDef; // 2 * integral gain (Ki)
volatile float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame
volatile float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
//---------------------------------------------------------------------------------------------------
// Function declarations
float invSqrt(float x);
//====================================================================================================
// Functions
//---------------------------------------------------------------------------------------------------
// AHRS algorithm update
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
float recipNorm;
float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
float hx, hy, bx, bz;
float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
float halfex, halfey, halfez;
float qa, qb, qc;
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az);
return;
}
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
// Normalise accelerometer measurement
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Normalise magnetometer measurement
recipNorm = invSqrt(mx * mx + my * my + mz * mz);
mx *= recipNorm;
my *= recipNorm;
mz *= recipNorm;
// Auxiliary variables to avoid repeated arithmetic
q0q0 = q0 * q0;
q0q1 = q0 * q1;
q0q2 = q0 * q2;
q0q3 = q0 * q3;
q1q1 = q1 * q1;
q1q2 = q1 * q2;
q1q3 = q1 * q3;
q2q2 = q2 * q2;
q2q3 = q2 * q3;
q3q3 = q3 * q3;
// Reference direction of Earth's magnetic field
hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
bx = sqrt(hx * hx + hy * hy);
bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
// Estimated direction of gravity and magnetic field
halfvx = q1q3 - q0q2;
halfvy = q0q1 + q2q3;
halfvz = q0q0 - 0.5f + q3q3;
halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
// Error is sum of cross product between estimated direction and measured direction of field vectors
halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
// Compute and apply integral feedback if enabled
if(twoKi > 0.0f) {
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
gx += integralFBx; // apply integral feedback
gy += integralFBy;
gz += integralFBz;
}
else {
integralFBx = 0.0f; // prevent integral windup
integralFBy = 0.0f;
integralFBz = 0.0f;
}
// Apply proportional feedback
gx += twoKp * halfex;
gy += twoKp * halfey;
gz += twoKp * halfez;
}
// Integrate rate of change of quaternion
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
gy *= (0.5f * (1.0f / sampleFreq));
gz *= (0.5f * (1.0f / sampleFreq));
qa = q0;
qb = q1;
qc = q2;
q0 += (-qb * gx - qc * gy - q3 * gz);
q1 += (qa * gx + qc * gz - q3 * gy);
q2 += (qa * gy - qb * gz + q3 * gx);
q3 += (qa * gz + qb * gy - qc * gx);
// Normalise quaternion
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
}
//---------------------------------------------------------------------------------------------------
// IMU algorithm update
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az) {
float recipNorm;
float halfvx, halfvy, halfvz;
float halfex, halfey, halfez;
float qa, qb, qc;
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
// Normalise accelerometer measurement
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Estimated direction of gravity and vector perpendicular to magnetic flux
halfvx = q1 * q3 - q0 * q2;
halfvy = q0 * q1 + q2 * q3;
halfvz = q0 * q0 - 0.5f + q3 * q3;
// Error is sum of cross product between estimated and measured direction of gravity
halfex = (ay * halfvz - az * halfvy);
halfey = (az * halfvx - ax * halfvz);
halfez = (ax * halfvy - ay * halfvx);
// Compute and apply integral feedback if enabled
if(twoKi > 0.0f) {
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
gx += integralFBx; // apply integral feedback
gy += integralFBy;
gz += integralFBz;
}
else {
integralFBx = 0.0f; // prevent integral windup
integralFBy = 0.0f;
integralFBz = 0.0f;
}
// Apply proportional feedback
gx += twoKp * halfex;
gy += twoKp * halfey;
gz += twoKp * halfez;
}
// Integrate rate of change of quaternion
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
gy *= (0.5f * (1.0f / sampleFreq));
gz *= (0.5f * (1.0f / sampleFreq));
qa = q0;
qb = q1;
qc = q2;
q0 += (-qb * gx - qc * gy - q3 * gz);
q1 += (qa * gx + qc * gz - q3 * gy);
q2 += (qa * gy - qb * gz + q3 * gx);
q3 += (qa * gz + qb * gy - qc * gx);
// Normalise quaternion
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
}
//---------------------------------------------------------------------------------------------------
// Fast inverse square-root
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
float invSqrt(float x) {
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
return y;
}
//====================================================================================================
// END OF CODE
//====================================================================================================
-
Yearoh - Master Sergeant
- Posts: 38
- Joined: Fri Jul 10, 2020 9:32 am
Re: C command 'volatile' & why my head hurts
The T2 gpc2 language isn't 100% c compatible, it is gpc2 .. not C.
Not sure why you expect gtuner iv to compile it at all.
Not sure why you expect gtuner iv to compile it at all.
-
Scachi - Brigadier General
- Posts: 3044
- Joined: Wed May 11, 2016 6:25 am
- Location: Germany
Re: C command 'volatile' & why my head hurts
Yearoh wrote: I'm thinking it may be a bit too much to expect my titan two to run it, but my plan is to cherry pick from it and jam it all together until it does something close to what I want.
...
So my method has been "Throw the code into Gtuner and see if it compiles, and comment out errors till it does, then go back and re-enable the problem lines one by one".
-
Yearoh - Master Sergeant
- Posts: 38
- Joined: Fri Jul 10, 2020 9:32 am
Re: C command 'volatile' & why my head hurts
With C/C++ the volatile keyword is intended to prevent the compiler from applying optimizations on variables. The GPC2 compiler does not perform such optimizations, as such the volatile is not needed and can be removed from the code.
You can even use a null macro to automate this process:
You can even use a null macro to automate this process:
- Code: Select all
#define volatile
ConsoleTuner Support Team
-
J2Kbr - General of the Army
- Posts: 20323
- Joined: Tue Mar 18, 2014 1:39 pm
Re: C command 'volatile' & why my head hurts
J2Kbr wrote:With C/C++ the volatile keyword is intended to prevent the compiler from applying optimizations on variables. The GPC2 compiler does not perform such optimizations, as such the volatile is not needed and can be removed from the code.
You can even use a null macro to automate this process:
- Code: Select all
#define volatile
Great explanation, thanks!
Your definition on what it actually does in C/C++ is about a billion times clearer than anything else on the net as well
-
Yearoh - Master Sergeant
- Posts: 38
- Joined: Fri Jul 10, 2020 9:32 am
5 posts
• Page 1 of 1
Return to GPC2 Script Programming
Who is online
Users browsing this forum: No registered users and 118 guests