Aircraft Parameter Identification and Performance

Any other Phidget projects you've done not related to the above subjects
DavidRusso
Phidgetsian
Posts: 6
Joined: Sat Apr 12, 2014 1:15 pm
Contact:

Aircraft Parameter Identification and Performance

Postby DavidRusso » Sun Apr 20, 2014 6:36 am

I am using a 1044 Spatial and 1040 GPS to record and identify aircraft performance parameters for my graduate thesis in aircraft performance. The boards are attached to a block of aluminum that is secured to the aircraft structure by any means possible. Maneuvers are flown that have been designed to characterize energy exchanges, while recording data to a laptop. Nearly all tests are less than sixty seconds long and usually about twenty seconds.

My discovery of these devices was serendipitous as I was wondering where I was going to get $3500 for an integrated commercial unit to do my thesis. These boards appear to meet the accuracy and environmental requirements for my tests. Well done Phidgets!

The software, written in ANSI C, records data to a *.csv file that is post processed using Matlab/Maple. All program features operate from a thumb drive to prevent aircraft accelerations from interfering with the hard drive. ANSI C was used in order to achieve WAAS precision from the 1040 GPS. The software allows specifying a filename, the sampling rate (8-1000 ms), and gives the option to zero the gyros. The *.c source code, from Visual Studio, is given below.


// statevector.c
// This work is based on the example at
// http://www.phidgets.com/docs/Simple_Spatial_Experiments
// It was commissioned by David Russo from Srdjan Raskovic via freelancer.com
// who upon receiving complete payment as agreed grants all the copyrights to
// David Russo, and declares him the sole owner of this source code, free
// to copy, modify and distribute it at his own discretion.
//
// by Srdjan Raskovic, Split, Croatia, April 2014.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "phidget21.h"

#define MAXCHAR 100

typedef enum {LOST, OBTAINED, BAD_GPS_DATA} STATUS;

typedef struct userdata {
FILE *filePtr;
int fixStatus;
CPhidgetGPSHandle gps;
NMEAData nmeaData;
int nmeaSet;
} USERDATA;

int getstring(char *str, int maxchar)
{
int ch, nch = 0;
--maxchar;

while((ch = getchar()) != EOF) {
if(ch == '\n')
break;
if(nch < maxchar)
str[nch++] = ch;
}
if(ch == EOF && nch == 0)
return EOF;
if(ch == '\n' && nch == 0)
str[nch++] = ch;
str[nch] = '\0';
return nch;
}

// This error handler can handle any CPhidget function that returns an int
int LocalErrorCatcher(int errorCode)
{
const char *errorDescription;

// If the error code is 0, everything is okay
if(errorCode != 0) {
// Otherwise, you can print specific messages or perform actions by error value.
switch (errorCode) {
default:
CPhidget_log(PHIDGET_LOG_ERROR, "STATEVECTOR",
"Error: An error occurred with code %d.", errorCode);
LocalErrorCatcher(
CPhidget_getErrorDescription(errorCode, &errorDescription));
CPhidget_log(PHIDGET_LOG_ERROR, "STATEVECTOR",
"The description for this error is: %s", errorDescription);
break;
}
}
return 0;
}

// clean-up to release resources
int close(CPhidgetGPSHandle gps, CPhidgetSpatialHandle spatial, FILE *file, USERDATA *dataPtr)
{
LocalErrorCatcher(CPhidget_close((CPhidgetHandle)spatial));
LocalErrorCatcher(CPhidget_close((CPhidgetHandle)gps));
LocalErrorCatcher(CPhidget_delete((CPhidgetHandle)spatial));
LocalErrorCatcher(CPhidget_delete((CPhidgetHandle)gps));
if(file != NULL)
fclose(file);
free(dataPtr);
CPhidget_disableLogging();
return 0;
}

// callback when the GPS fix status has changed
int CCONV fixChange(CPhidgetGPSHandle phid, void *userPtr, int status)
{
USERDATA *dataPtr = (USERDATA *) userPtr;
dataPtr->fixStatus = status;
return 0;
}

// callback when the GPS position has changed
int CCONV posnChange(CPhidgetGPSHandle phid, void *userPtr, double latitude, double longitude, double altitude)
{
USERDATA *dataPtr = (USERDATA *) userPtr;
if(!CPhidgetGPS_getNMEAData(phid, &(dataPtr->nmeaData)))
dataPtr->nmeaSet = 1;
else
dataPtr->nmeaSet = 0;
return 0;
}

// Our function that gets called at the set data rate (default of 200 ms)
int CCONV SpatialDataHandler(CPhidgetSpatialHandle spatial, void *userPtr, CPhidgetSpatial_SpatialEventDataHandle *data, int count)
{
int i, j, toUnderscore = 0;
double latitude, longitude, altitude, heading, velocity;
char *GPSDataPtr = NULL;
USERDATA *dataPtr = (USERDATA *) userPtr;
STATUS fixStatus;
CPhidgetGPSHandle gps = dataPtr->gps;
GPSDate date;
GPSTime time;
NMEAData nmeaData;
if(dataPtr->fixStatus) {
if(!CPhidgetGPS_getLatitude(gps, &latitude) &&
!CPhidgetGPS_getLongitude(gps, &longitude) &&
!CPhidgetGPS_getAltitude(gps, &altitude) &&
!CPhidgetGPS_getDate(gps, &date) &&
!CPhidgetGPS_getTime(gps, &time) &&
!CPhidgetGPS_getHeading(gps, &heading) &&
!CPhidgetGPS_getVelocity(gps, &velocity)) {
fixStatus = OBTAINED;
if(dataPtr->nmeaSet)
nmeaData = dataPtr->nmeaData;
}
else
fixStatus = BAD_GPS_DATA;
}
else
fixStatus = LOST;

// Sometimes we get more than one packet per event, this counts through them
for(i = 0; i < count; i++) {
FILE *file = dataPtr->filePtr;
if(file != NULL) {
printf(".");
fflush(stdout);

fprintf(file, "%lf,", data[i]->timestamp.seconds +
(data[i]->timestamp.microseconds)/1000000.0);
fprintf(file, "%lf,%lf,%lf,", data[i]->acceleration[0],
data[i]->acceleration[1], data[i]->acceleration[2]);
fprintf(file, "%lf,%lf,%lf,", data[i]->angularRate[0],
data[i]->angularRate[1], data[i]->angularRate[2]);
// Due to time for internal calibration, the compass sometimes returns
// the large constant PUNK_DBL
if(data[i]->magneticField[0] == PUNK_DBL)
fprintf(file, "%6f,%6f,%6f,", 0.0, 0.0, 0.0);
else {
fprintf(file, "%lf,%lf,%lf,", data[i]->magneticField[0],
data[i]->magneticField[1], data[i]->magneticField[2]);
}
if(fixStatus == LOST)
fprintf(file, "LOST\n");
else if(fixStatus == OBTAINED) {
// GPS Day, Month, Year, Hours, Minutes, Seconds, Milliseconds
fprintf(file,"%02d,%02d,%02d,%02d,%02d,%02d,%03d,", date.tm_mday,
date.tm_mon, date.tm_year, time.tm_hour, time.tm_min,
time.tm_sec, time.tm_ms);
// GPS Lat, Long, Alt
fprintf(file,"%lf,%lf,%lf,", latitude, longitude, altitude);
// GPS Head, Velo
fprintf(file,"%lf,%lf,", heading, velocity);
if(dataPtr->nmeaSet) {
// RMC Status, SpeedKnt, Head
fprintf(file,"%c,%lf,%lf,", nmeaData.RMC.status,
nmeaData.RMC.speedKnots, nmeaData.RMC.heading);
// RMC MagVar, Mode
fprintf(file,"%lf,%c,", nmeaData.RMC.magneticVariation,
nmeaData.RMC.mode);
// GGA FixQty, NumSat, HeightOfGeoid
fprintf(file,"%i,%i,%lf,", nmeaData.GGA.fixQuality,
nmeaData.GGA.numSatellites, nmeaData.GGA.heightOfGeoid);
// VTG TrueHead, MagHead, SpeedKnt, Speed, Mode
fprintf(file,"%lf,%lf,%lf,%lf,%c,", nmeaData.VTG.trueHeading,
nmeaData.VTG.magneticHeading, nmeaData.VTG.speedKnots,
nmeaData.VTG.speed, nmeaData.VTG.mode);
// GSA Mode, FixType, SatUsed
fprintf(file,"%c,%i,", nmeaData.GSA.mode, nmeaData.GSA.fixType);
for(j = 0; j < 12; j++) {
int satUsed = nmeaData.GSA.satUsed[j];
if(j < 11 && satUsed) {
if(toUnderscore)
fprintf(file,"_");
fprintf(file,"%i", satUsed);
toUnderscore = 1;
}
else if(j == 11) {
if(satUsed) {
if(toUnderscore)
fprintf(file,"_");
fprintf(file,"%i", satUsed);
}
fprintf(file,",");
}
}
// GSA PDOP, HDOP, VDOP
fprintf(file,"%lf,%lf,%lf\n", nmeaData.GSA.posnDilution,
nmeaData.GSA.horizDilution, nmeaData.GSA.vertDilution);
}
else
fprintf(file,"NO_NMEA\n");
}
else
fprintf(file, "BAD_GPS_DATA\n");
fflush(file);
}
}
return 0;
}

int main(int argc, char* argv[]) {

/*### HERE CHANGE DIFFERENT CONFIGURATION VALUES ###*/

/*### GPS DEVICE SERIAL ###*/
int gpsSerial = 286453;

/*### SPATIAL DEVICE SERIAL ###*/
int spatialSerial = 302480;

/*### DEFAULT FILENAME ###*/
char filenameRoot[MAXCHAR] = "1.";

/*### WAITING FOR DEVICE ATTACHMENT IN ms ###*/
int waitAttachmentMillis = 1000;

/*### DEFAULT DATA RATE IN ms ###*/
int dataRateDefault = 200;

/*### LOG LEVEL, SOME POSSIBLE VALUES:
PHIDGET_LOG_INFO, PHIDGET_LOG_WARNING, PHIDGET_LOG_ERROR ###*/
CPhidgetLog_level logLevel = PHIDGET_LOG_INFO;

int result, dataRate, retCode = 0;
const int maxChar = MAXCHAR;
char filename[MAXCHAR], name[MAXCHAR], entered = '\0';
char *ext = NULL;
USERDATA *dataPtr = (USERDATA *) malloc(sizeof(USERDATA));
FILE *file = NULL;
CPhidgetGPSHandle gps = 0;
CPhidgetSpatialHandle spatial = 0;

CPhidget_enableLogging(logLevel, "statevector.log" );
LocalErrorCatcher(CPhidgetGPS_create(&gps));
LocalErrorCatcher(CPhidgetSpatial_create(&spatial));

dataPtr->filePtr = NULL;
dataPtr->fixStatus = 0;
dataPtr->gps = gps;
dataPtr->nmeaSet = 0;

LocalErrorCatcher(
CPhidgetGPS_set_OnPositionFixStatusChange_Handler(gps,
fixChange, (void *) dataPtr));
LocalErrorCatcher(
CPhidgetGPS_set_OnPositionChange_Handler(gps,
posnChange, (void *) dataPtr));
LocalErrorCatcher(
CPhidgetSpatial_set_OnSpatialData_Handler(spatial,
SpatialDataHandler, (void *) dataPtr));

LocalErrorCatcher(CPhidget_open((CPhidgetHandle)gps, gpsSerial));
LocalErrorCatcher(CPhidget_open((CPhidgetHandle)spatial, spatialSerial));

result = CPhidget_waitForAttachment((CPhidgetHandle)gps, waitAttachmentMillis);
if(result) {
printf("No GPS Device. Exiting.\n");
CPhidget_log(PHIDGET_LOG_ERROR, "STATEVECTOR","No GPS Device!");
close(gps, spatial, file, dataPtr);
return 0;
}
LocalErrorCatcher(
CPhidgetGPS_getPositionFixStatus(gps, &(dataPtr->fixStatus)));

result = CPhidget_waitForAttachment((CPhidgetHandle)spatial, waitAttachmentMillis);
if(result) {
printf("No Spatial Device. Exiting.\n");
CPhidget_log(PHIDGET_LOG_ERROR, "STATEVECTOR","No Spatial Device!");
close(gps, spatial, file, dataPtr);
return 0;
}
LocalErrorCatcher(CPhidgetSpatial_setDataRate(spatial, dataRateDefault));

printf("Enter file_name.txt (press Enter for %scsv): ", filenameRoot);
retCode = getstring(name, maxChar);
if(retCode == 1 && name[0] == '\n') {
strcpy(filename, filenameRoot);
strcat(filename, "csv");
}
else {
ext = strrchr(name, '.');
if(ext != NULL) {
size_t prefixSize = strlen(name) - strlen(ext);
char root[MAXCHAR];
strncpy(root, name, prefixSize);
if(prefixSize < MAXCHAR)
root[prefixSize] = '\0';
strcpy(filenameRoot, root);
strcpy(filename, filenameRoot);
strcat(filename, ext);
}
else {
ext = ".csv";
strcpy(filenameRoot, name);
strcpy(filename, filenameRoot);
strcat(filename, ext);
}
}
if((file = fopen(filename,"a")) == NULL) {
printf("Error while opening %s. Exiting.\n", filename);
return 0;
}

while(1) {
printf("\nRezero gyro Y or N: ");
while(!((retCode = getstring(name, maxChar)) == 1 &&
(name[0] == 'n' || name[0] == 'N' || name[0] == 'y' || name[0] == 'Y')))
;
entered = name[0];
if(entered == 'y' || entered == 'Y') {
printf("Please wait 1-2 seconds and don't move the spatial device.\n");
CPhidgetSpatial_zeroGyro(spatial);
printf("Redo rezero gyro Y or N: ");
while(!((retCode = getstring(name, maxChar)) == 1 &&
(name[0] == 'n' || name[0] == 'N' || name[0] == 'y' || name[0] == 'Y')))
;
entered = name[0];
if(entered == 'y' || entered == 'Y') {
printf("Please wait 1-2 seconds and don't move the spatial device.\n");
CPhidgetSpatial_zeroGyro(spatial);
}
else
break;
}
else
break;
}
printf("\nEnter sampling rate in 4 ms increments from 8 ms to 1000 ms: ");
retCode = getstring(name, maxChar);
if(retCode > 0 && retCode < 5) {
int rate = atoi(name);
if(rate == 0 || rate < 8 || rate > 1000 || rate%4 != 0)
dataRate = dataRateDefault;
else
dataRate = rate;
LocalErrorCatcher(CPhidgetSpatial_setDataRate(spatial, dataRate));
printf("%i ms sampling rate is set.\n", dataRate);
}
else {
dataRate = dataRateDefault;
LocalErrorCatcher(CPhidgetSpatial_setDataRate(spatial, dataRate));
printf("%i ms default sampling rate is set.\n", dataRate);
}
printf("\nPress Enter to Begin Recording to %s. ", filename);
while(!((retCode = getstring(name, maxChar)) == 1 && name[0] == '\n'))
;
// Print the header at the top of the file
fprintf(file,
"Time,Accel_X,Accel_Y,Accel_Z,Ang_X,Ang_Y,Ang_Z,Mag_X,Mag_Y,Mag_Z,\
Day,Mon,Year,Hour,Min,Sec,Milli,Lat,Long,Alt,Head,Velo,\
RMC_Status,RMC_SpeedKnt,RMC_Head,RMC_MagVar,RMC_Mode,\
GGA_FixQty,GGA_NumSat,GGA_HeightGeoid,\
VTG_TrueHead,VTG_MagHead,VTG_SpeedKnt,VTG_Speed,VTG_Mode,\
GSA_Mode,GSA_FixType,GSA_SatUsed,GSA_PDOP,GSA_HDOP,GSA_VDOP\n");
dataPtr->filePtr = file;
printf("Press Enter to Quit Recording\n");
fflush(stdout);
while(!((retCode = getstring(name, maxChar)) == 1 && name[0] == '\n'))
;

close(gps, spatial, file, dataPtr);
return 0;
}

Return to “Other”

Who is online

Users browsing this forum: No registered users and 1 guest