MTi.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2010, ISR University of Coimbra.
00006 *  Copyright (c) 2011-2012, INRIA, CNRS, all rights reserved
00007 *  All rights reserved.
00008 *
00009 *  Redistribution and use in source and binary forms, with or without
00010 *  modification, are permitted provided that the following conditions
00011 *  are met:
00012 *
00013 *   * Redistributions of source code must retain the above copyright
00014 *     notice, this list of conditions and the following disclaimer.
00015 *   * Redistributions in binary form must reproduce the above
00016 *     copyright notice, this list of conditions and the following
00017 *     disclaimer in the documentation and/or other materials provided
00018 *     with the distribution.
00019 *   * Neither the name of the ISR University of Coimbra nor the names of its
00020 *     contributors may be used to endorse or promote products derived
00021 *     from this software without specific prior written permission.
00022 *
00023 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034 *  POSSIBILITY OF SUCH DAMAGE.
00035 *
00036 * Author: Gonçalo Cabrita
00037 * Notes: Original code in Cocoa from 07/08/2009, went C++ on 10/11/2010
00038 *
00039 * Author: Nicolas Vignard on 2 MAY 2012
00040 * Notes: Add the ability to control the Mti-G
00041 *********************************************************************/
00042 #include "MTi.h"
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 
00046 #include <ros/ros.h>
00047 #include <netinet/in.h>
00048 
00049 // Small workaround for the hexa to float problem...
00050 float hexa2float(unsigned char * buffer)
00051 {
00052     union
00053     {
00054         float value;
00055         unsigned char buffer[4];
00056 
00057     }floatUnion;
00058 
00059     floatUnion.buffer[0] = buffer[3];
00060     floatUnion.buffer[1] = buffer[2];
00061     floatUnion.buffer[2] = buffer[1];
00062     floatUnion.buffer[3] = buffer[0];
00063 
00064     return floatUnion.value;
00065 }
00066 
00067 void float2hexa(float valuetoSwap, std::vector<unsigned char>& buffer )
00068 {
00069     union
00070     {
00071         float value;
00072         unsigned char buffer[4];
00073 
00074     }floatUnion;
00075     floatUnion.value = valuetoSwap;
00076 
00077     buffer.push_back(floatUnion.buffer[3]);
00078     buffer.push_back(floatUnion.buffer[2]);
00079     buffer.push_back(floatUnion.buffer[1]);
00080     buffer.push_back(floatUnion.buffer[0]);
00081 }
00082 
00083 int hexa2int(unsigned char * buffer)
00084 {
00085     union
00086     {
00087         unsigned int value;
00088         unsigned char buffer[4];
00089 
00090     }floatUnion;
00091 
00092     floatUnion.buffer[0] = buffer[3];
00093     floatUnion.buffer[1] = buffer[2];
00094     floatUnion.buffer[2] = buffer[1];
00095     floatUnion.buffer[3] = buffer[0];
00096 
00097     return floatUnion.value;
00098 }
00099 
00100 
00105 Xsens::MTi::MTi() : serial_port()
00106 {
00107     numOfBytes = 4;
00108 
00109     // Serial Port Settings
00110     this->resetPackage();
00111 
00112     // Queue Settings
00113     queueIsWaiting = false;
00114     queueIsRunning = false;
00115 
00116     accX = accY = accZ = 0.0;
00117     gyrX = gyrY = gyrZ = 0.0;
00118     magX = magY = magZ = 0.0;
00119     q0 = q1 = q2 = q3 = 0.0;
00120     eroll = epitch = eyaw = 0.0;
00121     mTemperature = 0.0;
00122     ts = 0;
00123 
00124 
00125     resetGPSValues();
00126     mVelocityX = mVelocityY = mVelocityZ = 0.0;
00127     mStatus = 0;
00128     mHorizontalAccuracy = mVerticalAccuracy = 0;
00129 
00130     mInitialPosition.x = 0.0;
00131     mInitialPosition.y = 0.0;
00132     mInitialPosition.z = 0.0;
00133 
00134 }
00135 
00140 Xsens::MTi::~MTi()
00141 {
00142     if(serial_port.portOpen()) this->closePort();
00143 }
00144 
00151 bool Xsens::MTi::isMtiG()
00152 {
00153     return (mDeviceID & 0xFFF00000) == 0x00500000;
00154 }
00155 
00161 bool Xsens::MTi::isSelfTestCompleted()
00162 {
00163     if(isMtiG())
00164     {
00165         return mStatus & SELF_TEST;
00166     }
00167     else
00168         return true;
00169 }
00170 
00186 bool Xsens::MTi::setSettings(outputMode mode, outputSettings settings, Scenario scenario, const std::string& rosNamespace, const std::string& frameID, const Position& GPSLeverArm, int timeout)
00187 {
00188     mRosNamespace =  rosNamespace.empty() == true ? "" : "/" + rosNamespace;
00189     mFrameID = mRosNamespace + frameID;
00190     this->outputModeData.clear();
00191     this->outputSettingsData.clear();
00192 
00193     unsigned char byte;
00194     unsigned short modeIn2Bytes = 0;
00195 
00196     // Go into config mode, set our preferences and go back to measuring
00197     addMessageToQueue(GoToConfig, NULL, GoToConfigAck);
00198     addMessageToQueue(ReqDID,NULL,DeviceID);
00199     waitForQueueToFinish(timeout);
00200 
00201 
00202     modeIn2Bytes =
00203             mode.temperatureData
00204             | mode.calibratedData<<1
00205                                    | mode.orientationData<<2
00206                                    |  mode.auxiliaryData<<3
00207                                    | mode.positionData<<4
00208                                    | mode.velocityData<<5
00209                                    | mode.statusData<<11
00210                                    | mode.rawGPSData<<12
00211                                    | mode.rawInertialData<<14;
00212 
00213     if (!isMtiG()) {
00214         // not an MTi-G, remove all GPS related stuff
00215         modeIn2Bytes &= 0x4007; //0x0FFF
00216         // CMT_OUTPUTMODE_POSITION = 0x001
00217         ROS_INFO("No GPS Position available : MTi only, %x", mDeviceID);
00218     }
00219     else
00220         ROS_INFO("MTi-G detected");
00221 
00222 
00223     byte = (modeIn2Bytes & 0xFF00) >> 8;
00224     outputModeData.push_back(byte);
00225     byte = (modeIn2Bytes & 0xFF);
00226     outputModeData.push_back(byte);
00227 
00228 
00229     unsigned int modeIn4Bytes = 0;
00230     modeIn4Bytes = settings.timeStamp
00231             | settings.orientationMode<<2
00232                                         | (!settings.enableAcceleration)<<4
00233                                         | (!settings.enableRateOfTurn)<<5
00234                                         | (!settings.enableMagnetometer)<<6
00235                                         | settings.velocityModeNED<<31;
00236 
00237     if (!isMtiG()) {
00238         // not an MTi-G, remove all GPS related stuff
00239         modeIn4Bytes &= 0x0000037F;
00240     }
00241 
00242 
00243     byte = (modeIn4Bytes & 0xFF000000) >> 24;
00244     outputSettingsData.push_back(byte);
00245     byte = (modeIn4Bytes & 0x00FF0000) >> 16;
00246     outputSettingsData.push_back(byte);
00247     byte = (modeIn4Bytes & 0x0000FF00) >> 8;
00248     outputSettingsData.push_back(byte);
00249     byte = (modeIn4Bytes & 0x000000FF);
00250     outputSettingsData.push_back(byte);
00251 
00252 
00253     this->addMessageToQueue(SetOutputMode, &outputModeData, SetOutputModeAck);
00254     this->addMessageToQueue(SetOutputSettings, &outputSettingsData, SetOutputSettingsAck);
00255 
00256     if(isMtiG())
00257     {
00258         modeIn2Bytes = scenario;
00259         byte = 0;
00260         byte = (modeIn2Bytes & 0xFF00) >> 8;
00261         mScenarioData.push_back(byte);
00262         byte = (modeIn2Bytes & 0x00FF);
00263         mScenarioData.push_back(byte);
00264 
00265         this->addMessageToQueue(SetCurrentScenario, &mScenarioData, SetCurrentScenarioAck);
00266         this->addMessageToQueue(ReqAvailableScenarios, NULL, AvailableScenarios);
00267         this->addMessageToQueue(ReqCurrentScenario, NULL, ReqCurrentScenarioAck);
00268 
00269         std::vector<unsigned char> GPSLeverArmVector;
00270 
00271         float2hexa(GPSLeverArm.x,GPSLeverArmVector);//X
00272         float2hexa(GPSLeverArm.y,GPSLeverArmVector);//Y
00273         float2hexa(GPSLeverArm.z,GPSLeverArmVector);//Z
00274         this->addMessageToQueue(SetLeverArmGps, &GPSLeverArmVector, SetLeverArmGpsAck);
00275         this->addMessageToQueue(ReqLeverArmGps, NULL, ReqLeverArmGpsAck);
00276         this->addMessageToQueue(ReqCurrentScenario, NULL, ReqCurrentScenarioAck);
00277     }
00278 
00279 
00280     this->addMessageToQueue(ReqOutputMode, NULL, ReqOutputModeAck);
00281     this->addMessageToQueue(ReqOutputSettings, NULL, ReqOutputSettingsAck);
00282 
00283     this->addMessageToQueue(GoToMeasurement, NULL, GoToMeasurementAck);
00284     bool result =  this->waitForQueueToFinish(timeout);
00285 
00286 
00287     /*  ROS_INFO("auxiliaryData: %d,calibratedData: %d,orientationData: %d,positionData: %d",output_mode.auxiliaryData,output_mode.calibratedData,output_mode.orientationData,output_mode.positionData);
00288     ROS_INFO("rawGPSData: %d,rawInertialData: %d,statusData: %d,temperatureData: %d,velocityData: %d",output_mode.rawGPSData,output_mode.rawInertialData,output_mode.statusData,output_mode.temperatureData,output_mode.velocityData);
00289     ROS_INFO("timeStamp: %d,orientationMode: %d",output_settings.timeStamp,output_settings.orientationMode);
00290     ROS_INFO("enableAcceleration: %d,enableMagnetometer: %d, enableRateOfTurn: %d",output_settings.enableAcceleration,output_settings.enableMagnetometer,output_settings.enableRateOfTurn);
00291     ROS_INFO("velocityModeNED: %d",output_settings.velocityModeNED);*/
00292     return result;
00293 }
00294 
00299 void Xsens::MTi::resetPackage()
00300 {
00301     packageInTransit = false;
00302     packageLength = 0;
00303     packageIndex = 0;
00304     package.clear();
00305 }
00306 
00314 void Xsens::MTi::addMessageToQueue(MTMessageIdentifier messageID, std::vector<unsigned char> * data, MTMessageIdentifier ack)
00315 {
00316     this->queue.push_back(MTMessage(messageID, data, ack));
00317     if(queueIsRunning == false) this->manageQueue();
00318 }
00319 
00324 void Xsens::MTi::manageQueue()
00325 {
00326     queueIsRunning = true;
00327     if(queueIsWaiting == true)
00328     {
00329         this->queue.erase(queue.begin());
00330         queueIsWaiting = false;
00331 
00332         if(this->queue.size() == 0) queueIsRunning = false;
00333     }
00334     if(queueIsWaiting == false && queueIsRunning == true)
00335     {
00336         MTMessage message2send = this->queue[0];
00337         std::vector<unsigned char> data2send;
00338         this->makeMessage(message2send.getMessageID(), message2send.getData(), &data2send);
00339         queueAck = message2send.getMessageAck();
00340         queueIsWaiting = true;
00341         this->serialPortSendData(&data2send);
00342     }
00343 }
00344 
00351 bool Xsens::MTi::waitForQueueToFinish(int timeout)
00352 {
00353     for(int i=0 ; i<timeout ; i++)
00354     {
00355         usleep(1000);   // sleep for 1ms
00356         if(queueIsRunning == false) return true;
00357     }
00358 
00359     queue.clear();
00360     queueIsWaiting = false;
00361     queueIsRunning = false;
00362 
00363     this->resetPackage();
00364 
00365     return false;
00366 }
00367 
00375 bool Xsens::MTi::openPort(char * name, int baudrate)
00376 {
00377     try{ serial_port.open(name, baudrate); }
00378     catch(cereal::Exception& e)
00379     {
00380         return false;
00381     }
00382     return serial_port.startReadStream(boost::bind(&Xsens::MTi::serialPortReadData, this, _1, _2));
00383 }
00384 
00390 bool Xsens::MTi::closePort()
00391 {
00392     try{ serial_port.close(); }
00393     catch(cereal::Exception& e)
00394     {
00395         return false;
00396     }
00397     return true;
00398 }
00399 
00404 void Xsens::MTi::getDeviceID()
00405 {
00406     this->addMessageToQueue(GoToConfig, NULL, GoToConfigAck);
00407     this->addMessageToQueue(ReqDID,NULL,DeviceID);
00408     this->addMessageToQueue(GoToMeasurement, NULL, GoToMeasurementAck);
00409     waitForQueueToFinish(1000);
00410 }
00411 
00418 bool Xsens::MTi::serialPortSendData(std::vector<unsigned char> * data)
00419 {
00420     /*printf("Sending data -");
00421     for(int i=0 ; i<data->size() ; i++) printf(" 0x%X", data->at(i));
00422     printf("\n");*/
00423 
00424     char buffer[data->size()];
00425 
00426     int i;
00427     std::vector<unsigned char>::iterator it;
00428     for(i=0, it=data->begin() ; it!=data->end() ; i++, it++) buffer[i] = (char)*it;
00429 
00430     try{ serial_port.write(buffer, data->size()); }
00431     catch(cereal::Exception& e)
00432     {
00433         return false;
00434     }
00435     return true;
00436 }
00437 
00444 void Xsens::MTi::serialPortReadData(char * data, int length)
00445 {       
00446     if(length > 0)
00447     {
00448         // Manage the received data...
00449         unsigned char buffer;
00450         for(int i=0 ; i<length ; i++)
00451         {
00452             buffer = (unsigned char)data[i];
00453 
00454             // PREAMBLE
00455             if(packageInTransit == false)
00456             {
00457                 if(buffer == PRE)
00458                 {
00459                     this->package.clear();
00460                     this->package.push_back(buffer);
00461                     packageInTransit = true;
00462                     packageIndex = 1;
00463                 }
00464 
00465             } else {
00466 
00467                 // CHECKSUM
00468                 if( (packageIsExtended == true && packageIndex == 6+packageLength) || (packageIsExtended == false && packageIndex == 4+packageLength) )
00469                 {
00470                     package.push_back(buffer);
00471 
00472                     unsigned char checksum = 0;
00473                     for(unsigned int i=1 ; i<this->package.size() ; i++)
00474                     {
00475                         buffer = this->package[i];
00476                         checksum += buffer;
00477                     }
00478                     // If message is ok manage it else reset the package
00479                     if(checksum == 0x00) this->manageIncomingData(&this->package, packageIsExtended);
00480                     else this->resetPackage();
00481                 }
00482                 // DATA
00483                 if((packageIndex >= 6 && packageIndex < 6+packageLength) || (packageIsExtended == false && packageIndex >= 4 && packageIndex < 4+packageLength) )
00484                 {
00485                     this->package.push_back(buffer);
00486                     packageIndex++;
00487                 }
00488                 // EXT_LEN
00489                 if(packageIsExtended == true && packageIndex == 4)
00490                 {
00491                     this->package.push_back(buffer);
00492                     packageIndex = 5;
00493                 }
00494                 if(packageIsExtended == true && packageIndex == 5)
00495                 {
00496                     this->package.push_back(buffer);
00497                     packageIndex = 6;
00498 
00499                     union
00500                     {
00501                         unsigned int value;
00502                         unsigned char buffer[2];
00503 
00504                     } intUnion;
00505                     intUnion.buffer[0] = this->package[4];
00506                     intUnion.buffer[1] = this->package[5];
00507                     packageLength = intUnion.value;
00508                 }
00509                 // LEN
00510                 if(packageIndex == 3)
00511                 {
00512                     this->package.push_back(buffer);
00513                     packageIndex = 4;
00514 
00515                     if(buffer == 0xFF) packageIsExtended = true;
00516                     else
00517                     {
00518                         packageIsExtended = false;
00519                         packageLength = (int)buffer;
00520                     }
00521                 }
00522                 // MID
00523                 if(packageIndex == 2)
00524                 {
00525                     this->package.push_back(buffer);
00526                     packageIndex = 3;
00527                 }
00528                 // BID
00529                 if(buffer == BID && packageIndex == 1)
00530                 {
00531                     this->package.push_back(buffer);
00532                     packageIndex = 2;
00533                 }
00534                 if(packageIndex == 1 && buffer != BID)
00535                 {
00536                     this->resetPackage();
00537                 }
00538             }
00539         }
00540     }
00541 }
00542 
00549 void Xsens::MTi::manageIncomingData(std::vector<unsigned char> * incomingData, bool dataIsExtended)
00550 {       
00551     /*printf("Getting data -");
00552     for(int i=0 ; i<incomingData->size() ; i++) printf(" 0x%X", incomingData->at(i));
00553     printf("\n");*/
00554 
00555     int dataIndex = 4;
00556     if(dataIsExtended) dataIndex = 6;
00557 
00558     // And now finnaly actualy manage the data
00559     std::vector<unsigned char> data;
00560 
00561     std::vector<unsigned char>::iterator it;
00562     for(it=incomingData->begin()+dataIndex ; it!=incomingData->end() ; it++)
00563     {
00564         data.push_back((unsigned char)*it);
00565     }
00566 
00567     unsigned char MID;
00568     MID = incomingData->at(2);
00569 
00570     this->resetPackage();
00571 
00572     if(queueIsWaiting == true && MID == queueAck) this->manageQueue();
00573 
00574     // Variables useful to manage the data
00575     unsigned char floatBuffer[numOfBytes];
00576     int index;
00577 
00578     // Switch case for managing the various MIDs that might arrive
00579     switch(MID)
00580     {
00581     case DeviceID:
00582         if(data.size()>0)
00583         {
00584             uint32_t* ID = (uint32_t*)data.data();
00585             mDeviceID = ntohl(ID[0]);
00586         }
00587         break;
00588     case GoToConfigAck:
00589         ConfigState = true;
00590         break;
00591 
00592     case GoToMeasurementAck:
00593         ConfigState = false;
00594         break;
00595 
00596     case ReqOutputModeAck:
00597         if(data.size()>0)
00598         {
00599             unsigned short mask;
00600             ushort* temp = (ushort*)data.data();
00601             unsigned short outputMode = ntohs(temp[0]);
00602             mask = 0x0001;
00603             output_mode.temperatureData = ((outputMode & mask) == mask);
00604             mask = mask << 1;
00605             output_mode.calibratedData = ((outputMode & mask) == mask);
00606             mask = mask << 1;
00607             output_mode.orientationData = ((outputMode & mask) == mask);
00608             mask = mask << 1;
00609             output_mode.auxiliaryData = ((outputMode & mask) == mask);
00610             mask = mask << 1;
00611             output_mode.positionData = ((outputMode & mask) == mask);
00612             mask = mask << 1;
00613             output_mode.velocityData = ((outputMode & mask) == mask);
00614             mask = 0x0800;
00615             output_mode.statusData = ((outputMode & mask) == mask);
00616             mask = mask << 1;
00617             output_mode.rawGPSData = ((outputMode & mask) == mask);
00618             mask = mask << 2;
00619             output_mode.rawInertialData = ((outputMode & mask) == mask);
00620         }
00621         break;
00622 
00623     case ReqOutputSettingsAck:
00624         if(data.size()>0)
00625         {
00626             unsigned int mask;
00627             uint32_t* temp = (uint32_t*)data.data();
00628             unsigned int outputSettings = ntohl(temp[0]);
00629             mask = 0x01;
00630             output_settings.timeStamp = ((outputSettings & mask) == mask);
00631             mask = 0x03;
00632             output_settings.orientationMode = (Xsens::MTOrientationMode)(outputSettings>>2 & mask);
00633             mask = 0x01;
00634             mask = mask << 4;
00635             output_settings.enableAcceleration = ((outputSettings & mask) == mask);
00636             mask = mask << 1;
00637             output_settings.enableRateOfTurn = ((outputSettings & mask) == mask);
00638             mask = mask << 1;
00639             output_settings.enableMagnetometer = ((outputSettings & mask) == mask);
00640             mask = 0x80000000;
00641             output_settings.velocityModeNED = ((outputSettings & mask) == mask);
00642         }
00643         break;
00644     case ReqCurrentScenarioAck:
00645         if(data.size()>1)
00646         {
00647             mScenario = (Scenario)(data.at(1));
00648         }
00649         break;
00650     case ReqLeverArmGpsAck:
00651         if(data.size()>0)
00652         {
00653             /*  uint32_t* lever_arm = (uint32_t*)data.data();
00654             int temp =  ntohl(lever_arm[0]);
00655             float x = *(float*)&temp;
00656             temp =  ntohl(lever_arm[1]);
00657             float y = *(float*)&temp;
00658             temp =  ntohl(lever_arm[2]);
00659             float z = *(float*)&temp;
00660             ROS_INFO("x: %f, y: %f, z: %f",x,y,z);*/
00661         }
00662         break;
00663     case AvailableScenarios:
00664         if(data.size()>0)
00665         { std::stringstream scenarios;
00666             int k = 0;
00667             for(int i = 0; i< 5; i++)
00668             {
00669                 scenarios << (int)data.at(k) <<" -> ";
00670                 for(int j=k+2;j<k+22;j++)
00671                     scenarios << data.at(j);
00672                 k +=22;
00673             }
00674             ROS_INFO("Available scenarios: %s",scenarios.str().c_str());
00675         }
00676         break;
00677         // Read incoming data according to mode and settings data
00678     case MTData:
00679         index = 0;
00680         if(output_mode.rawGPSData == true)
00681         {
00682             if(GPSFix())
00683             {
00684                 index = 7;
00685 
00686                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00687                 mLatitude = hexa2int(floatBuffer)*pow(10,-7);
00688                 index += numOfBytes;
00689                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00690                 mLongitude = hexa2int(floatBuffer)*pow(10,-7);
00691                 index += numOfBytes;
00692                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00693                 mAltitude = hexa2int(floatBuffer)/1000;
00694                 index += numOfBytes;
00695                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00696                 mVelocityNorth = hexa2int(floatBuffer);
00697                 index += numOfBytes;
00698                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00699                 mVelocityEast = hexa2int(floatBuffer);
00700                 index += numOfBytes;
00701                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00702                 mVelocityDown = hexa2int(floatBuffer);
00703                 index += numOfBytes;
00704                 unsigned char * buffer = (unsigned char * ) data.data();
00705                 unsigned int *temp = (unsigned int *)(&buffer[index]);
00706                 mHorizontalAccuracy = ntohl(*temp)/1000;
00707                 index += numOfBytes;
00708                 temp = (unsigned int *)(&buffer[index]);
00709                 mVerticalAccuracy = ntohl(*temp)/1000;
00710 
00711             }
00712             else
00713                 resetGPSValues();
00714 
00715             index = GPS_PVT_DATA_OFFSET;
00716         }
00717         if(output_mode.temperatureData == true)
00718         {
00719             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00720             mTemperature = hexa2float(floatBuffer);
00721             index += numOfBytes;
00722         }
00723         if(output_mode.calibratedData == true)
00724         {
00725             if(isSelfTestCompleted())
00726             {
00727                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00728                 accX = hexa2float(floatBuffer);
00729                 index += numOfBytes;
00730                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00731                 accY = hexa2float(floatBuffer);
00732                 index += numOfBytes;
00733                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00734                 accZ = hexa2float(floatBuffer);
00735                 index += numOfBytes;
00736                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00737                 gyrX = hexa2float(floatBuffer);
00738                 index += numOfBytes;
00739                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00740                 gyrY = hexa2float(floatBuffer);
00741                 index += numOfBytes;
00742                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00743                 gyrZ = hexa2float(floatBuffer);
00744                 index += numOfBytes;
00745                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00746                 magX = hexa2float(floatBuffer);
00747                 index += numOfBytes;
00748                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00749                 magY = hexa2float(floatBuffer);
00750                 index += numOfBytes;
00751                 for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00752                 magZ = hexa2float(floatBuffer);
00753                 index += numOfBytes;
00754             }
00755             else
00756                 index += 9*numOfBytes;
00757         }
00758         if(output_mode.orientationData == true)
00759         {
00760 
00761             if(output_settings.orientationMode == Quaternion)
00762             {
00763                 if(isSelfTestCompleted())
00764                 {
00765                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00766                     q0 = hexa2float(floatBuffer);
00767                     index += numOfBytes;
00768                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00769                     q1 = hexa2float(floatBuffer);
00770                     index += numOfBytes;
00771                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00772                     q2 = hexa2float(floatBuffer);
00773                     index += numOfBytes;
00774                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00775                     q3 = hexa2float(floatBuffer);
00776                     index += numOfBytes;
00777                 }
00778                 else
00779                     index += 4*numOfBytes;
00780             }
00781             if(output_settings.orientationMode == EulerAngles)
00782             {
00783                 if(isSelfTestCompleted())
00784                 {
00785                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00786                     eroll = hexa2float(floatBuffer);
00787                     index += numOfBytes;
00788                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00789                     epitch = hexa2float(floatBuffer);
00790                     index += numOfBytes;
00791                     for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00792                     eyaw = hexa2float(floatBuffer);
00793                     index += numOfBytes;
00794                 }
00795                 else
00796                     index += 3*numOfBytes;
00797             }
00798             if(output_settings.orientationMode == Matrix)
00799             {
00800                 index += 9*numOfBytes;
00801             }
00802 
00803         }
00804         if(output_mode.auxiliaryData == true)
00805         {
00806             index += numOfBytes;
00807         }
00808         if(output_mode.positionData == true)
00809         {
00810 
00811             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00812             mLatitude = hexa2float(floatBuffer);
00813             index += numOfBytes;
00814             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00815             mLongitude = hexa2float(floatBuffer);
00816             index += numOfBytes;
00817             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00818             mAltitude = hexa2float(floatBuffer);
00819             index += numOfBytes;
00820         }
00821         if(output_mode.velocityData == true)
00822         {
00823             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00824             mVelocityX = hexa2float(floatBuffer);
00825             index += numOfBytes;
00826             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00827             mVelocityY = hexa2float(floatBuffer);
00828             index += numOfBytes;
00829             for(int i=0 ; i<numOfBytes ; i++) floatBuffer[i] = data[index+i];
00830             mVelocityZ = hexa2float(floatBuffer);
00831             index += numOfBytes;
00832         }
00833         if(output_mode.statusData == true)
00834         {
00835             mStatus = data[index];
00836             index += ONE_BYTE;
00837         }
00838         if(output_settings.timeStamp == true)
00839         {
00840             index += 2*ONE_BYTE;
00841         }
00842         break;
00843 
00844     case ResetOrientationAck:
00845         // Reset ok.
00846         break;
00847     }
00848 }
00849 
00854 void Xsens::MTi::resetGPSValues()
00855 {
00856     mAltitude = mLongitude = mLatitude = 0.0;
00857     mVelocityNorth = mVelocityEast = mVelocityDown = 0.0;
00858 }
00859 
00867 void Xsens::MTi::makeMessage(MTMessageIdentifier mid, std::vector<unsigned char> * data, std::vector<unsigned char> * message)
00868 {
00869     int dataLength = 0;
00870     if(data!=NULL) dataLength = data->size();
00871     unsigned char byte;
00872 
00873     message->clear();
00874     // PREAMBLE
00875     message->push_back(PRE);
00876     // BID
00877     message->push_back(BID);
00878     // MID
00879     byte = (unsigned char)mid;
00880     message->push_back(byte);
00881     // LEN / EXT_LEN
00882     if(dataLength < 0xFF)
00883     {
00884         byte = (unsigned char)dataLength;
00885         message->push_back(byte);
00886 
00887     } else {
00888 
00889         byte = 0xFF;
00890         message->push_back(byte);
00891 
00892         union
00893         {
00894             int length;
00895             unsigned char buffer[2];
00896         }lengthUnion;
00897 
00898         lengthUnion.length = dataLength;
00899         message->push_back(lengthUnion.buffer[0]);
00900         message->push_back(lengthUnion.buffer[1]);
00901     }
00902     //  DATA
00903     if(data!=NULL)
00904     {
00905         if(data->size() > 0)
00906         {
00907             std::vector<unsigned char>::iterator it;
00908             for(it=data->begin() ; it!=data->end() ; it++) message->push_back(*it);
00909         }
00910     }
00911     // CHECKSUM
00912     unsigned char checksum = 0;
00913     // BID
00914     checksum += message->at(1);
00915     // MID
00916     checksum += message->at(2);
00917     // LEN
00918     if(dataLength < 0xFF)
00919     {
00920         checksum += message->at(3);
00921 
00922     } else {
00923 
00924         checksum += message->at(3);
00925         checksum += message->at(4);
00926         checksum += message->at(5);
00927     }
00928     // DATA
00929     for(int i=0 ; i<dataLength ; i++)
00930     {
00931         int dataIndex = 6;
00932         if(dataLength < 0xFF) dataIndex = 4;
00933         checksum += message->at(dataIndex+i);
00934     }
00935     int c = 0x100;
00936     byte = (unsigned char)(c-(int)checksum);
00937     message->push_back(byte);
00938 }
00939 
00948 nav_msgs::Odometry Xsens::MTi::fillOdometryMessage(const tf::TransformListener& listener, tf::TransformBroadcaster& odom_broadcaster, const ros::Time& now)
00949 {
00950     nav_msgs::Odometry odom_msg;
00951     double northing, easting;
00952     std::string zone;
00953     if(!GPSFix())
00954         return odom_msg;
00955 
00956 
00957 
00958     gps_common::LLtoUTM(latitude(), longitude(), northing, easting, zone);
00959 
00960     Position current_position;
00961     if(output_settings.velocityModeNED)
00962     {
00963         current_position.x = northing;
00964         current_position.y = easting;
00965         current_position.z = -altitude();
00966     }
00967     else
00968     {
00969         current_position.x = northing;
00970         current_position.y = -easting;
00971         current_position.z = altitude();
00972     }
00973 
00974     if(current_position.z < 1.0)//First value are not quite right
00975         return odom_msg;
00976 
00977     geometry_msgs::QuaternionStamped qt;
00978     double quaternionW, quaternionX, quaternionY, quaternionZ;
00979     fillQuaternionWithOutputSettings(quaternionX,quaternionY,quaternionZ,quaternionW);
00980 
00981     if( listener.frameExists(mRosNamespace + BASE_LINK_FRAME_ID) && listener.frameExists(mFrameID) && quaternionW != 0 && quaternionX != 0 && quaternionY != 0 && quaternionZ != 0)
00982     {
00983         qt.header.frame_id = mFrameID;
00984         qt.header.stamp = now;
00985 
00986         qt.quaternion.x = quaternionX;
00987         qt.quaternion.y = quaternionY;
00988         qt.quaternion.z = quaternionZ;
00989         qt.quaternion.w = quaternionW;
00990 
00991         if((mInitialPosition.x == 0.0) && (mInitialPosition.y == 0.0) && (mInitialPosition.z == 0.0)  )
00992         {
00993             mInitialPosition.x = current_position.x;
00994             mInitialPosition.y = current_position.y;
00995             mInitialPosition.z = current_position.z;
00996             ROS_INFO("INITIAL x: %f, y: %f, z: %f", current_position.x,current_position.y,current_position.z);
00997         }
00998 
00999         current_position.x = current_position.x - mInitialPosition.x;
01000         current_position.y = current_position.y - mInitialPosition.y;
01001         current_position.z = current_position.z - mInitialPosition.z;
01002 
01003         tf::StampedTransform T_base_imu;
01004         try{
01005             listener.lookupTransform(mRosNamespace + BASE_LINK_FRAME_ID, mFrameID,ros::Time(0), T_base_imu);
01006         }
01007         catch (tf::TransformException ex){
01008             ROS_ERROR("%s",ex.what());
01009             return odom_msg;
01010         }
01011 
01012         btTransform T_odom_imu(btQuaternion(quaternionX,quaternionY,quaternionZ,quaternionW),btVector3(current_position.x,current_position.y, current_position.z));
01013         tf::StampedTransform T_odom_base_st(T_odom_imu, now, mRosNamespace + ODOMETRY_FRAME_ID, mRosNamespace + BASE_LINK_FRAME_ID);
01014         T_odom_base_st *= T_base_imu.inverse();
01015         geometry_msgs::TransformStamped base_to_odom_msg;
01016         tf::transformStampedTFToMsg(T_odom_base_st, base_to_odom_msg);
01017         if(qt.quaternion.x != 0.0 && qt.quaternion.y != 0.0 && qt.quaternion.z != 0.0 && qt.quaternion.w != 0.0)
01018             odom_broadcaster.sendTransform(base_to_odom_msg);
01019 
01020         //next, we'll publish the odometry message over ROS
01021         odom_msg.header.stamp = now;
01022         odom_msg.header.frame_id = mRosNamespace + ODOMETRY_FRAME_ID;
01023         odom_msg.child_frame_id = mRosNamespace + BASE_LINK_FRAME_ID;
01024 
01025         //set the position
01026         odom_msg.pose.pose.position.x = base_to_odom_msg.transform.translation.x;
01027         odom_msg.pose.pose.position.y = base_to_odom_msg.transform.translation.y;
01028         odom_msg.pose.pose.position.z = base_to_odom_msg.transform.translation.z;
01029         odom_msg.pose.pose.orientation.w = base_to_odom_msg.transform.rotation.w;
01030         odom_msg.pose.pose.orientation.x = base_to_odom_msg.transform.rotation.x;
01031         odom_msg.pose.pose.orientation.y = base_to_odom_msg.transform.rotation.y;
01032         odom_msg.pose.pose.orientation.z = base_to_odom_msg.transform.rotation.z;
01033 
01034 
01035         //set the velocity
01036         tf::Transform orientation(tf::Quaternion(base_to_odom_msg.transform.rotation.x, base_to_odom_msg.transform.rotation.y, base_to_odom_msg.transform.rotation.z, base_to_odom_msg.transform.rotation.w));
01037         tf::Vector3 vel(velocity_x(), velocity_y(), velocity_z());
01038 
01039         vel = orientation.inverse() * vel;
01040         odom_msg.twist.twist.linear.x = vel.x();
01041         odom_msg.twist.twist.linear.y = vel.y();
01042         odom_msg.twist.twist.linear.z = vel.z();
01043 
01044         odom_msg.twist.twist.angular.x = gyroscope_x();
01045         odom_msg.twist.twist.angular.y = gyroscope_y();
01046         odom_msg.twist.twist.angular.z = gyroscope_z();
01047 
01048     }
01049 
01050     return odom_msg;
01051 }
01052 
01059 sensor_msgs::Imu Xsens::MTi::fillImuMessage(const ros::Time &now)
01060 {
01061     sensor_msgs::Imu imu_msg;
01062     imu_msg.header.stamp = now;
01063 
01064     imu_msg.header.frame_id = mFrameID.c_str();
01065 
01066     fillQuaternionWithOutputSettings(imu_msg.orientation.x,imu_msg.orientation.y,imu_msg.orientation.z,imu_msg.orientation.w);
01067 
01068 
01069     imu_msg.angular_velocity.x = gyroscope_x();
01070     imu_msg.angular_velocity.y = gyroscope_y();
01071     imu_msg.angular_velocity.z = gyroscope_z();
01072 
01073     imu_msg.linear_acceleration.x = accelerometer_x();
01074     imu_msg.linear_acceleration.y = accelerometer_y();
01075     imu_msg.linear_acceleration.z = accelerometer_z();
01076     return imu_msg;
01077 }
01078 
01087 void Xsens::MTi::fillQuaternionWithOutputSettings(double& x, double& y, double& z, double& w )
01088 {
01089     if(output_settings.orientationMode == EulerAngles)
01090     {
01091         tf::Quaternion quaternion = tf::createQuaternionFromRPY(roll(),pitch(),yaw());
01092 
01093         x = quaternion.x();
01094         y = quaternion.y();
01095         z = quaternion.z();
01096         w = quaternion.w();
01097 
01098     }
01099     else if(output_settings.orientationMode == Quaternion)
01100     {
01101         x = quaternion_x();
01102         y = quaternion_y();
01103         z = quaternion_z();
01104         w = quaternion_w();
01105     }
01106 }
01107 
01114 sensor_msgs::NavSatFix Xsens::MTi::fillNavFixMessage(const ros::Time& now)
01115 {
01116     sensor_msgs::NavSatFix nav_fix_msg;
01117     sensor_msgs::NavSatStatus nav_status_msg;
01118     nav_fix_msg.header.stamp = now;
01119     nav_fix_msg.header.frame_id = mFrameID.c_str();
01120 
01121     nav_fix_msg.altitude = altitude();
01122     nav_fix_msg.latitude = latitude();
01123     nav_fix_msg.longitude = longitude();
01124     nav_fix_msg.position_covariance_type = sensor_msgs::NavSatFix::COVARIANCE_TYPE_UNKNOWN;
01125 
01126     if(GPSFix())
01127         nav_status_msg.status = sensor_msgs::NavSatStatus::STATUS_FIX;
01128     else
01129         nav_status_msg.status = sensor_msgs::NavSatStatus::STATUS_NO_FIX;
01130 
01131     nav_fix_msg.status = nav_status_msg;
01132 
01133     return nav_fix_msg;
01134 }
01135 
01136 // EOF
01137 


lse_xsens_mti
Author(s): Gonçalo Cabrita, Nicolas Vignard
autogenerated on Mon Jan 6 2014 11:28:04