00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00110 this->resetPackage();
00111
00112
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
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
00215 modeIn2Bytes &= 0x4007;
00216
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
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);
00272 float2hexa(GPSLeverArm.y,GPSLeverArmVector);
00273 float2hexa(GPSLeverArm.z,GPSLeverArmVector);
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
00288
00289
00290
00291
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);
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
00421
00422
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
00449 unsigned char buffer;
00450 for(int i=0 ; i<length ; i++)
00451 {
00452 buffer = (unsigned char)data[i];
00453
00454
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
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
00479 if(checksum == 0x00) this->manageIncomingData(&this->package, packageIsExtended);
00480 else this->resetPackage();
00481 }
00482
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
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
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
00523 if(packageIndex == 2)
00524 {
00525 this->package.push_back(buffer);
00526 packageIndex = 3;
00527 }
00528
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
00552
00553
00554
00555 int dataIndex = 4;
00556 if(dataIsExtended) dataIndex = 6;
00557
00558
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
00575 unsigned char floatBuffer[numOfBytes];
00576 int index;
00577
00578
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
00654
00655
00656
00657
00658
00659
00660
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
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
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
00875 message->push_back(PRE);
00876
00877 message->push_back(BID);
00878
00879 byte = (unsigned char)mid;
00880 message->push_back(byte);
00881
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
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
00912 unsigned char checksum = 0;
00913
00914 checksum += message->at(1);
00915
00916 checksum += message->at(2);
00917
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
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)
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 tf::Transform T_odom_imu(tf::Quaternion(quaternionX,quaternionY,quaternionZ,quaternionW),tf::Vector3(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
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
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
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
01137