Reputation: 1
I am trying to recompile an old Win32 software package in order to bring small modifications. The package is part of the MT SDK from Xsens and allows to get output from a inertial sensor (available here https://content.xsens.com/hubfs/Downloads/Software/mtsdk3.3_setup.zip). Example of a C++ routine using a DLL file responsible for the communication with hardware is located in Program Files\Xsens\MT SDK\Software Developpement\Examples\CMT Example Dll.
From directory I recompiled the source code, linking the DLL such as
i686-w64-mingw32-g++ -o test main.cpp -L. -lxsens_cmt
It requires changing a few scanf_s
calls to scanf
but compiled properly into test.exe.
However, when I try to run that executable in Windows I get the following error:
On the net I could find recommendation to compile with the following options but none could resolve my issue :
-static
-static-libstdc++
-static-libgcc
Examples folder of the MTSDK can be downloaded here if you don't want to install the software : https://gitlab.com/lenhofed/mtsdk_modifs.git
main.cpp
/* demo key, replace this key with your own */
#define KEY "b8r6RCoGjQJVsytwUMo8WCRiJiVCCdoL11cCj4HqnaKPHtTn"
#include <stdio.h> // Needed for printf etc
#include <objbase.h> // Needed for COM functionality
#include "xsens_cmt.h"
#include <conio.h> // included for _getch and _kbhit
#include "main.h"
// this macro tests for an error and exits the program with a message if there was one
#define EXIT_ON_ERROR(res,comment) if (res != XRV_OK) { printf("Error %d occurred in " comment ": %s\n",res,cmtGetResultText(res)); exit(1); }
long instance = -1;
// used to signal that the user initiated the exit, so we do not wait for an extra keypress-
int userQuit = 0;
CmtOutputMode mode;
CmtOutputSettings settings;
unsigned short mtCount = 0;
int screenSensorOffset = 0;
int temperatureOffset = 0;
CmtDeviceId deviceIds[256];
CmtVector positionLLA;
int main(void)
{
XsensResultValue res = XRV_OK;
short screenSkipFactor = 10;
short screenSkipFactorCnt = screenSkipFactor;
// Set exit function
atexit(exitFunc);
// lets create the Xsens CMT instance to handle the sensor(s)
printf("Creating an XsensCMT instance\n");
char serialNumber[] = KEY;
if (strcmp(serialNumber,"b8r6RCoGjQJVsytwUMo8WCRiJiVCCdoL11cCj4HqnaKPHtTn") == 0)
printf("Warning: Using the demo key as a serial code will limit CMT functionality to 1000 calls. Enter your own serial code for unlimited CMT functionality.\n");
instance = cmtCreateInstance(serialNumber);
if (instance != -1)
printf("CMT instance created\n\n");
else {
printf("Creation of CMT instance failed, probably because of an invalid serial number\n");
exit(1);
}
// Perform hardware scan
doHardwareScan();
// Give user a (short) chance to see hardware scan results
Sleep(2000);
//clear screen present & get the user output mode selection.
clrscr();
getUserInputs();
// Set device to user input settings
doMtSettings();
// Wait for first data item(s) to arrive. In production code, you would use a callback function instead (see cmtRegisterCallback function)
Sleep(20);
//get the placement offsets, clear the screen and write the fixed headers.
calcScreenOffset();
clrscr();
writeHeaders();
// vars for sample counter & temp.
unsigned short sdata;
double tdata;
//structs to hold data.
CmtCalData caldata;
CmtQuat qat_data;
CmtEuler euler_data;
CmtMatrix matrix_data;
while(!userQuit && res == XRV_OK)
{
//get the bundle of data
res = cmtGetNextDataBundle(instance);
Sleep(10);
//get sample count, goto position & display.
res = cmtDataGetSampleCounter(instance, &sdata, deviceIds[0] ,NULL);
gotoxy(0,0);
printf("Sample Counter %05hu\n", sdata);
if (screenSkipFactorCnt++ == screenSkipFactor) {
screenSkipFactorCnt = 0;
for (unsigned int i = 0; i < mtCount; i++) {
// Output Temperature
if ((mode & CMT_OUTPUTMODE_TEMP) != 0) {
gotoxy(0,4 + i * screenSensorOffset);
res = cmtDataGetTemp(instance, &tdata, deviceIds[i],NULL);
printf("%6.2f", tdata);
}
gotoxy(0,5 + temperatureOffset + i * screenSensorOffset); // Output Calibrated data
if ((mode & CMT_OUTPUTMODE_CALIB) != 0) {
res = cmtDataGetCalData(instance, &caldata, deviceIds[i]);
printf("%6.2f\t%6.2f\t%6.2f" , caldata.m_acc.m_data[0], caldata.m_acc.m_data[1], caldata.m_acc.m_data[2]);
gotoxy(0,7 + temperatureOffset + i * screenSensorOffset);
printf("%6.2f\t%6.2f\t%6.2f", caldata.m_gyr.m_data[0], caldata.m_gyr.m_data[1], caldata.m_gyr.m_data[2] );
gotoxy(0,9 + temperatureOffset + i * screenSensorOffset);
printf("%6.2f\t%6.2f\t%6.2f",caldata.m_mag.m_data[0], caldata.m_mag.m_data[1], caldata.m_mag.m_data[2]);
gotoxy(0,13 + temperatureOffset + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
// Output: quaternion
res = cmtDataGetOriQuat(instance, &qat_data, deviceIds[i]);
printf("%6.3f\t%6.3f\t%6.3f\t%6.3f\n", qat_data.m_data[0], qat_data.m_data[1],qat_data.m_data[2],qat_data.m_data[3]);
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
// Output: Euler
res = cmtDataGetOriEuler(instance, &euler_data, deviceIds[i]);
printf("%6.1f\t%6.1f\t%6.1f\n", euler_data.m_roll,euler_data.m_pitch, euler_data.m_yaw);
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
// Output: Cosine Matrix
res = cmtDataGetOriMatrix(instance, &matrix_data, deviceIds[i],NULL);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[0][0],matrix_data.m_data[0][1], matrix_data.m_data[0][2]);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[1][0],matrix_data.m_data[1][1], matrix_data.m_data[1][2]);
printf("%6.3f\t%6.3f\t%6.3f\n", matrix_data.m_data[2][0],matrix_data.m_data[2][1], matrix_data.m_data[2][2]);
break;
default:
;
}
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0) {
/* output position */
printf("\n\n");
if (cmtDataContainsPositionLLA(instance, deviceIds[i]) != 0) {
res = cmtDataGetPositionLLA(instance, &positionLLA, deviceIds[i]);
if (res != XRV_OK) {
printf("error %ud", res);
}
for (int i = 0; i < 2; i++) {
double deg = positionLLA.m_data[i];
double min = (deg - (int)deg)*60;
double sec = (min - (int)min)*60;
printf("%3d\xa7%2d\'%2.2lf\"\t", (int)deg, (int)min, sec);
}
printf(" %3.2lf\n", positionLLA.m_data[2]);
} else {
printf("No position data available\n");
}
}
}
}
if (_kbhit())
userQuit = 1;
}
clrscr();
cmtClose(instance);
return 0;
}
//////////////////////////////////////////////////////////////////////////
// doHardwareScan
//
// Checks available COM ports and scans for MotionTrackers
void doHardwareScan()
{
XsensResultValue res;
CmtPortInfo portInfo[256];
uint32_t portCount = 0;
printf("Scanning for connected Xsens devices...");
res = cmtScanPorts(portInfo, &portCount, 0);
EXIT_ON_ERROR(res,"cmtScanPorts");
printf("done\n");
if (portCount == 0) {
printf("No MotionTrackers found\n\n");
exit(0);
}
for(int i = 0; i < (int)portCount; i++) {
printf("Using COM port %d at %d baud\n\n",
(long) portInfo[i].m_portNr, portInfo[i].m_baudrate);
}
printf("Opening ports...");
//open the port which the device is connected to and connect at the device's baudrate.
for(int p = 0; p < (int)portCount; p++){
res = cmtOpenPort(instance, portInfo[p].m_portNr, portInfo[p].m_baudrate);
EXIT_ON_ERROR(res,"cmtOpenPort");
}
printf("done\n\n");
//get the Mt sensor count.
printf("Retrieving MotionTracker count (excluding attached Xbus Master(s))\n");
res = cmtGetMtCount(instance,&mtCount);
EXIT_ON_ERROR(res,"cmtGetMtCount");
printf("MotionTracker count: %i\n\n",mtCount);
// retrieve the device IDs
printf("Retrieving MotionTrackers device ID(s)\n");
for(unsigned int j = 0; j < mtCount; j++ ){
res = cmtGetMtDeviceId(instance, &deviceIds[j], j);
EXIT_ON_ERROR(res,"cmtGetDeviceId");
printf("Device ID at index %i: %08x\n",j,(long) deviceIds[j]);
}
// make sure that we get the freshest data
printf("\nSetting queue mode so that we always get the latest data\n\n");
res = cmtSetQueueMode(instance,CMT_QM_LAST);
EXIT_ON_ERROR(res,"cmtSetQueueMode");
}
//////////////////////////////////////////////////////////////////////////
// getUserInputs
//
// Request user for output data
void getUserInputs()
{
mode = 0;
while (mode < 1 || mode > 6) {
printf("Select desired output:\n");
printf("1 - Calibrated data\n");
printf("2 - Orientation data and GPS Position (MTi-G only)\n");
printf("3 - Both Calibrated and Orientation data\n");
printf("4 - Temperature and Calibrated data\n");
printf("5 - Temperature and Orientation data\n");
printf("6 - Temperature, Calibrated and Orientation data\n");
printf("Enter your choice: ");
scanf("%d", &mode);
// flush stdin
while (getchar() != '\n') continue;
if (mode < 1 || mode > 6) {
printf("\n\nPlease enter a valid output mode\n");
}
}
clrscr();
switch(mode)
{
case 1:
mode = CMT_OUTPUTMODE_CALIB;
break;
case 2:
mode = CMT_OUTPUTMODE_ORIENT | CMT_OUTPUTMODE_POSITION;
break;
case 3:
mode = CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT;
break;
case 4:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB;
break;
case 5:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_ORIENT;
break;
case 6:
mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT;
break;
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
do{
printf("Select desired output format\n");
printf("1 - Quaternions\n");
printf("2 - Euler angles\n");
printf("3 - Matrix\n");
printf("Enter your choice: ");
scanf("%d", &settings);
// flush stdin
while (getchar() != '\n') continue;
if (settings < 1 || settings > 3) {
printf("\n\nPlease enter a valid choice\n");
}
}while(settings < 1 || settings > 3);
// Update outputSettings to match data specs of SetOutputSettings
switch(settings) {
case 1:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION;
break;
case 2:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_EULER;
break;
case 3:
settings = CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX;
break;
}
}
else{
settings = 0;
}
settings |= CMT_OUTPUTSETTINGS_TIMESTAMP_SAMPLECNT;
}
//////////////////////////////////////////////////////////////////////////
// doMTSettings
//
// Set user settings in MTi/MTx
// Assumes initialized global MTComm class
void doMtSettings(void)
{
XsensResultValue res;
// set sensor to config sate
res = cmtGotoConfig(instance);
EXIT_ON_ERROR(res, "cmtGotoConfig");
unsigned short sampleFreq;
res = cmtGetSampleFrequency(instance, &sampleFreq, deviceIds[0]);
// set the device output mode for the device(s)
printf("Configuring your mode selection");
for (int i=0; i < mtCount; i++) {
if (cmtIdIsMtig(deviceIds[i])) {
res = cmtSetDeviceMode(instance, mode,settings, sampleFreq, deviceIds[i]);
} else {
res = cmtSetDeviceMode(instance, mode & 0xFF0F, settings, sampleFreq, deviceIds[i]);
}
EXIT_ON_ERROR(res, "setDeviceMode");
}
// start receiving data
res = cmtGotoMeasurement(instance);
EXIT_ON_ERROR(res, "cmtGotoMeasurement");
}
//////////////////////////////////////////////////////////////////////////
// writeHeaders
//
// Write appropriate headers to screen
void writeHeaders()
{
for (unsigned int i = 0; i < mtCount; i++) {
gotoxy(0, 2 + i * screenSensorOffset);
printf("MotionTracker %d\n", i + 1);
if ((mode & CMT_OUTPUTMODE_TEMP) != 0) {
temperatureOffset = 3;
gotoxy(0,3 + i * screenSensorOffset);
printf("Temperature");
gotoxy(7,4 + i * screenSensorOffset);
printf("degrees celcius");
gotoxy(0,6 + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_CALIB) != 0) {
gotoxy(0,3 + temperatureOffset + i * screenSensorOffset);
printf("Calibrated sensor data");
gotoxy(0,4 + temperatureOffset + i * screenSensorOffset);
printf(" Acc X\t Acc Y\t Acc Z");
gotoxy(23, 5 + temperatureOffset + i * screenSensorOffset);
printf("(m/s^2)");
gotoxy(0,6 + temperatureOffset + i * screenSensorOffset);
printf(" Gyr X\t Gyr Y\t Gyr Z");
gotoxy(23, 7 + temperatureOffset + i * screenSensorOffset);
printf("(rad/s)");
gotoxy(0,8 + temperatureOffset + i * screenSensorOffset);
printf(" Mag X\t Mag Y\t Mag Z");
gotoxy(23, 9 + temperatureOffset + i * screenSensorOffset);
printf("(a.u.)");
gotoxy(0,11 + temperatureOffset + i * screenSensorOffset);
}
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
printf("Orientation data\n");
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
printf(" q0\t q1\t q2\t q3\n");
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
printf(" Roll\t Pitch\t Yaw\n");
printf(" degrees\n");
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
printf(" Matrix\n");
break;
default:
;
}
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0) {
printf("\nLongitude\tLatitude\t Altitude\n");
}
}
}
//////////////////////////////////////////////////////////////////////////
// calcScreenOffset
//
// Calculates offset for screen data with multiple sensors.
void calcScreenOffset()
{
// 1 line for "Sensor ..."
screenSensorOffset += 1;
if ((mode & CMT_OUTPUTMODE_TEMP) != 0)
screenSensorOffset += 3;
if ((mode & CMT_OUTPUTMODE_CALIB) != 0)
screenSensorOffset += 8;
if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) {
switch(settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) {
case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION:
screenSensorOffset += 4;
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER:
screenSensorOffset += 4;
break;
case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX:
screenSensorOffset += 6;
break;
default:
;
}
if ((mode & CMT_OUTPUTMODE_POSITION) != 0)
screenSensorOffset += 4;
}
}
//////////////////////////////////////////////////////////////////////////
// clrscr
//
// Clear console screen
void clrscr()
{
#ifdef WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
DWORD count;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
SetConsoleCursorPosition(hStdOut, coord);
#else
int i;
for (i = 0; i < 100; i++)
// Insert new lines to create a blank screen
putchar('\n');
gotoxy(0,0);
#endif
}
//////////////////////////////////////////////////////////////////////////
// gotoxy
//
// Sets the cursor position at the specified console position
//
// Input
// x : New horizontal cursor position
// y : New vertical cursor position
void gotoxy(int x, int y)
{
#ifdef WIN32
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
#else
char essq[100]; // String variable to hold the escape sequence
char xstr[100]; // Strings to hold the x and y coordinates
char ystr[100]; // Escape sequences must be built with characters
/*
** Convert the screen coordinates to strings
*/
sprintf(xstr, "%d", x);
sprintf(ystr, "%d", y);
/*
** Build the escape sequence (vertical move)
*/
essq[0] = '\0';
strcat(essq, "\033[");
strcat(essq, ystr);
/*
** Described in man terminfo as vpa=\E[%p1%dd
** Vertical position absolute
*/
strcat(essq, "d");
/*
** Horizontal move
** Horizontal position absolute
*/
strcat(essq, "\033[");
strcat(essq, xstr);
// Described in man terminfo as hpa=\E[%p1%dG
strcat(essq, "G");
/*
** Execute the escape sequence
** This will move the cursor to x, y
*/
printf("%s", essq);
#endif
}
//////////////////////////////////////////////////////////////////////////
// exitFunc
//
// Closes cmt nicely
void exitFunc(void)
{
// if we have a valid instance, we should get rid of it at the end of the program
if (instance != -1) {
// Close any open COM ports
cmtClose(instance);
cmtDestroyInstance(instance);
}
// get rid of keystrokes before we post our message
while (_kbhit()) _getch();
// wait for a keypress
if (!userQuit)
{
//printf("Press a key to exit\n");
//_getch();
}
}
main.h
void doHardwareScan();
void doMtSettings(void);
void getUserInputs(void);
void clrscr(void);
void writeHeaders(void);
void gotoxy(int x, int y);
void calcScreenOffset(void);
void exitFunc(void);
Upvotes: 0
Views: 140