00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <unistd.h> 00004 #include <sys/ioctl.h> 00005 #include <fcntl.h> 00006 #include <signal.h> 00007 00008 #include "cmtdef.h" 00009 #include "xsens_time.h" 00010 #include "xsens_list.h" 00011 #include "cmtscan.h" 00012 #include "cmt3.h" 00013 00014 #include "IMUDataServer.H" 00015 00016 #include "Component/ModelParam.H" 00017 #include "Component/ModelOptionDef.H" 00018 00019 #include <iostream> 00020 00021 #ifndef IMUDATASERVER_C 00022 #define IMUDATASERVER_C 00023 00024 using namespace xsens; 00025 00026 const ModelOptionCateg MOC_SeaBeeIIIIMUDataServer = { 00027 MOC_SORTPRI_3, "Options" }; 00028 00029 const ModelOptionDef OPT_EnableConfig = 00030 { MODOPT_ARG(int), "EnableConfig", &MOC_SeaBeeIIIIMUDataServer, OPTEXP_CORE, 00031 "Enable configuration of the IMU", 00032 "enable-config", '\0', "<float>", "0" }; 00033 00034 // ###################################################################### 00035 IMUDataServer::IMUDataServer(int id, OptionManager& mgr, 00036 const std::string& descrName, const std::string& tagName) : 00037 RobotBrainComponent(mgr, descrName, tagName), 00038 mEnableConfig(&OPT_EnableConfig, this, 0) 00039 //itsPort(new Serial(mgr)) 00040 { 00041 //itsPort->configure("/dev/ttyUSB2", 57600, "8N2", false, false, 1); 00042 //addSubComponent(itsPort); 00043 res = XRV_OK; 00044 inited = false; 00045 } 00046 00047 // ###################################################################### 00048 IMUDataServer::~IMUDataServer() 00049 { 00050 delete packet; 00051 //cmt3.closePort(); 00052 } 00053 00054 void IMUDataServer::stop2() 00055 { 00056 cout << "closing port: "; 00057 LFATAL("Testing to see if this fixes the port issues"); 00058 return; 00059 /*cmt3.closePort(); 00060 if(cmt3.isPortOpen()) 00061 { 00062 cout << "failed" << endl; 00063 } 00064 else 00065 { 00066 cout << "success" << endl; 00067 }*/ 00068 } 00069 00070 bool IMUDataServer::initMe() 00071 { 00072 unsigned long mtCount = doHardwareScan(cmt3, deviceIds); 00073 00074 if (mtCount == 0) 00075 { 00076 std::cout << "no MTs, quitting." << std::endl; 00077 cmt3.closePort(); 00078 inited = true; 00079 return false; 00080 } 00081 00082 if(mEnableConfig.getVal() == 1) 00083 { 00084 getUserInputs(mode, settings); 00085 } 00086 else 00087 { 00088 mode = CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT; 00089 settings = CMT_OUTPUTSETTINGS_ORIENTMODE_EULER; 00090 } 00091 00092 doMtSettings(cmt3, mode, settings, deviceIds); 00093 00094 // Initialize packet for data 00095 packet = new Packet((unsigned short) mtCount, cmt3.isXm()); 00096 msg = new RobotSimEvents::IMUDataServerMessage(); 00097 00098 inited = true; 00099 return true; 00100 } 00101 00102 // ###################################################################### 00103 void IMUDataServer::registerTopics() 00104 { 00105 registerPublisher("IMUDataServerMessageTopic"); 00106 //registerSubscription("IMUDataServerMessageTopic"); 00107 } 00108 00109 // ###################################################################### 00110 void IMUDataServer::evolve() 00111 { 00112 static int frames = 0; 00113 00114 if (!inited) 00115 { 00116 cout << "initing..." << endl; 00117 if(!initMe()) 00118 { 00119 LFATAL("No motion trackers found; can't continue"); 00120 //cout << "No motion trackers found; can't continue" << endl; 00121 return; 00122 } 00123 } 00124 00125 if (res != XRV_OK) 00126 { 00127 return; 00128 } 00129 00130 frames ++; 00131 00132 cmt3.waitForDataMessage(packet); 00133 00134 if(frames > 6) //drop frames 00135 { 00136 frames = 0; 00137 //LFATAL("Temporary call to quit"); 00138 } 00139 else 00140 { 00141 return; 00142 } 00143 00144 msg->angleMode = -1; 00145 00146 // Output Temperature 00147 if ((mode & CMT_OUTPUTMODE_TEMP) != 0) 00148 { 00149 tdata = packet->getTemp(0); 00150 00151 msg->temp = tdata; 00152 } 00153 00154 if ((mode & CMT_OUTPUTMODE_CALIB) != 0) 00155 { 00156 caldata = packet->getCalData(0); 00157 00158 msg->accel.x = caldata.m_acc.m_data[0]; 00159 msg->accel.y = caldata.m_acc.m_data[1]; 00160 msg->accel.z = caldata.m_acc.m_data[2]; 00161 00162 msg->gyro.x = caldata.m_gyr.m_data[0]; 00163 msg->gyro.y = caldata.m_gyr.m_data[1]; 00164 msg->gyro.z = caldata.m_gyr.m_data[2]; 00165 00166 msg->mag.x = caldata.m_mag.m_data[0]; 00167 msg->mag.y = caldata.m_mag.m_data[1]; 00168 msg->mag.z = caldata.m_mag.m_data[2]; 00169 00170 } 00171 00172 if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) 00173 { 00174 00175 switch (settings & CMT_OUTPUTSETTINGS_ORIENTMODE_MASK) 00176 { 00177 case CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION: 00178 // Output: quaternion 00179 msg->angleMode = Mode::quat; 00180 qat_data = packet->getOriQuat(0); 00181 00182 msg->orientation.resize(4); 00183 msg->orientation[0] = qat_data.m_data[0]; 00184 msg->orientation[1] = qat_data.m_data[1]; 00185 msg->orientation[2] = qat_data.m_data[2]; 00186 msg->orientation[3] = qat_data.m_data[3]; 00187 00188 break; 00189 00190 case CMT_OUTPUTSETTINGS_ORIENTMODE_EULER: 00191 // Output: Euler 00192 msg->angleMode = Mode::euler; 00193 euler_data = packet->getOriEuler(0); 00194 00195 msg->orientation.resize(3); 00196 msg->orientation[0] = euler_data.m_roll; 00197 msg->orientation[1] = euler_data.m_pitch; 00198 msg->orientation[2] = euler_data.m_yaw; 00199 00200 break; 00201 00202 case CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX: 00203 // Output: Cosine Matrix 00204 msg->angleMode = Mode::cos_mat; 00205 matrix_data = packet->getOriMatrix(0); 00206 00207 msg->orientation.resize(9); 00208 msg->orientation[0] = matrix_data.m_data[0][0]; 00209 msg->orientation[1] = matrix_data.m_data[0][1]; 00210 msg->orientation[2] = matrix_data.m_data[0][2]; 00211 msg->orientation[3] = matrix_data.m_data[1][0]; 00212 msg->orientation[4] = matrix_data.m_data[1][1]; 00213 msg->orientation[5] = matrix_data.m_data[1][2]; 00214 msg->orientation[6] = matrix_data.m_data[2][0]; 00215 msg->orientation[7] = matrix_data.m_data[2][1]; 00216 msg->orientation[8] = matrix_data.m_data[2][2]; 00217 00218 break; 00219 } 00220 00221 if ((mode & CMT_OUTPUTMODE_POSITION) != 0) 00222 { 00223 00224 if (packet->containsPositionLLA()) 00225 { 00226 /* output position */ 00227 /* CmtVector positionLLA = packet->getPositionLLA(); 00228 if (res != XRV_OK) 00229 { 00230 00231 } 00232 00233 for (int i = 0; i < 2; i++) 00234 { 00235 double deg = positionLLA.m_data[0]; 00236 double min = (deg - (int) deg) * 60; 00237 double sec = (min - (int) min) * 60; 00238 00239 }*/ 00240 00241 } 00242 else 00243 { 00244 00245 } 00246 } 00247 } 00248 00249 publish("IMUDataServerMessageTopic", msg); 00250 } 00251 00252 // ###################################################################### 00253 void IMUDataServer::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg, 00254 const Ice::Current&) 00255 { 00256 if (eMsg->ice_isA("::RobotSimEvents::IMUDataServerMessage") && false) 00257 { 00258 RobotSimEvents::IMUDataServerMessagePtr msg = RobotSimEvents::IMUDataServerMessagePtr::dynamicCast(eMsg); 00259 cout << "temperature" << endl; 00260 cout << msg->temp << endl; 00261 cout << "acceleration" << endl; 00262 cout << msg->accel.x << "," << msg->accel.y << "," << msg->accel.z << endl; 00263 cout << "gyroscope" << endl; 00264 cout << msg->gyro.x << "," << msg->gyro.y << "," << msg->gyro.z << endl; 00265 cout << "magnetometer" << endl; 00266 cout << msg->mag.x << "," << msg->mag.y << "," << msg->mag.z << endl; 00267 switch(msg->angleMode) 00268 { 00269 case 0: 00270 cout << "quaternian" << endl; 00271 cout << msg->orientation[0] << "," << msg->orientation[1] << "," << msg->orientation[2] << "," << msg->orientation[3] << endl; 00272 break; 00273 case 1: 00274 cout << "euler" << endl; 00275 cout << msg->orientation[0] << "," << msg->orientation[1] << "," << msg->orientation[2] << endl; 00276 break; 00277 case 2: 00278 cout << "cosine matrix" << endl; 00279 cout << msg->orientation[0] << "," << msg->orientation[1] << "," << msg->orientation[2] << endl; 00280 cout << msg->orientation[3] << "," << msg->orientation[4] << "," << msg->orientation[5] << endl; 00281 cout << msg->orientation[6] << "," << msg->orientation[7] << "," << msg->orientation[8] << endl; 00282 } 00283 } 00284 } 00285 00286 ////////////////////////////////////////////////////////////////////////// 00287 // doHardwareScan 00288 // 00289 // Checks available COM ports and scans for MotionTrackers 00290 int IMUDataServer::doHardwareScan(xsens::Cmt3 &cmt3, CmtDeviceId deviceIds[]) 00291 { 00292 XsensResultValue res; 00293 //List<CmtPortInfo> portInfo;// = {0,0,0,""}; 00294 CmtPortInfo port = {0,0,0,"/dev/ttyUSB0"}; 00295 00296 unsigned long portCount = 0; 00297 int mtCount; 00298 00299 std::cout << "Scanning for connected Xsens devices..." << std::endl; 00300 //xsens::cmtScanPorts(portInfo); 00301 //portCount = portInfo.length(); 00302 portCount = (xsens::cmtScanForIMU(port)); 00303 std::cout << "done" << std::endl; 00304 00305 if (portCount == 0) 00306 { 00307 std::cout << "No MotionTrackers found" << std::endl; 00308 return 0; 00309 } 00310 00311 for (int i = 0; i < (int) portCount; i++) 00312 { 00313 //std::cout << portInfo[i].m_baudrate << "|" << portInfo[i].m_deviceId << "|" << portInfo[i].m_portName << "|" << portInfo[i].m_portNr << std::endl; 00314 std::cout << "Using COM port at " << port.m_portName; 00315 00316 switch (port.m_baudrate) 00317 { 00318 case B9600: 00319 std::cout << "9k6"; 00320 break; 00321 case B19200: 00322 std::cout << "19k2"; 00323 break; 00324 case B38400: 00325 std::cout << "38k4"; 00326 break; 00327 case B57600: 00328 std::cout << "57k6"; 00329 break; 00330 case B115200: 00331 std::cout << "115k2"; 00332 break; 00333 case B230400: 00334 std::cout << "230k4"; 00335 break; 00336 case B460800: 00337 std::cout << "460k8"; 00338 break; 00339 case B921600: 00340 std::cout << "921k6"; 00341 break; 00342 default: 00343 std::cout << port.m_baudrate; 00344 } 00345 std::cout << "baud" << std::endl; 00346 } 00347 00348 std::cout << "Opening ports..."; 00349 //open the port which the device is connected to and connect at the device's baudrate. 00350 //for (int p = 0; p < (int) portCount; p++) 00351 //{ 00352 res = cmt3.openPort(port.m_portName, port.m_baudrate); 00353 // EXIT_ON_ERROR(res,"cmtOpenPort"); 00354 //} 00355 std::cout << "done" << std::endl; 00356 00357 //get the Mt sensor count. 00358 std::cout 00359 << "Retrieving MotionTracker count (excluding attached Xbus Master(s))" 00360 << std::endl; 00361 //mtCount = cmt3.getMtCount(); 00362 mtCount = portCount; 00363 std::cout << "MotionTracker count: " << mtCount << std::endl; 00364 00365 // retrieve the device IDs 00366 std::cout << "Retrieving MotionTrackers device ID(s)" << std::endl; 00367 /*for (int j = 0; j < mtCount; j++) 00368 { 00369 res = cmt3.getDeviceId((unsigned char) (j + 1), deviceIds[j]); 00370 // EXIT_ON_ERROR(res,"getDeviceId"); 00371 std::cout << "Device ID at busId " << j + 1 << "," 00372 << (long) deviceIds[j] << std::endl; 00373 }*/ 00374 00375 deviceIds[0] = port.m_deviceId; 00376 00377 return mtCount; 00378 //return 0; 00379 } 00380 00381 ////////////////////////////////////////////////////////////////////////// 00382 // getUserInputs 00383 // 00384 // Request user for output data 00385 void IMUDataServer::getUserInputs(CmtOutputMode &mode, 00386 CmtOutputSettings &settings) 00387 { 00388 mode = 0; 00389 00390 std::cout << "Select desired output:" << std::endl; 00391 std::cout << "1 - Calibrated data" << std::endl; 00392 std::cout << "2 - Orientation data and GPS Position (MTi-G only)" 00393 << std::endl; 00394 std::cout << "3 - Both Calibrated and Orientation data" << std::endl; 00395 std::cout << "4 - Temperature and Calibrated data" << std::endl; 00396 std::cout << "5 - Temperature and Orientation data" << std::endl; 00397 std::cout << "6 - Temperature, Calibrated and Orientation data" 00398 << std::endl; 00399 std::cout << "Enter your choice: "; 00400 00401 std::cin >> mode; 00402 00403 //nope 00404 /*if (mode < 1 || mode > 6) { 00405 std::cout << "\n\nPlease enter a valid output mode\n"); 00406 }*/ 00407 00408 switch (mode) 00409 { 00410 case 1: 00411 mode = CMT_OUTPUTMODE_CALIB; 00412 break; 00413 case 2: 00414 mode = CMT_OUTPUTMODE_ORIENT | CMT_OUTPUTMODE_POSITION; 00415 break; 00416 case 3: 00417 mode = CMT_OUTPUTMODE_CALIB | CMT_OUTPUTMODE_ORIENT; 00418 break; 00419 case 4: 00420 mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB; 00421 break; 00422 case 5: 00423 mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_ORIENT; 00424 break; 00425 case 6: 00426 mode = CMT_OUTPUTMODE_TEMP | CMT_OUTPUTMODE_CALIB 00427 | CMT_OUTPUTMODE_ORIENT; 00428 break; 00429 } 00430 00431 if ((mode & CMT_OUTPUTMODE_ORIENT) != 0) 00432 { 00433 settings = 0; 00434 00435 std::cout << std::endl; 00436 std::cout << "Select desired output format" << std::endl; 00437 std::cout << "1 - Quaternions" << std::endl; 00438 std::cout << "2 - Euler angles" << std::endl; 00439 std::cout << "3 - Matrix" << std::endl; 00440 std::cout << "Enter your choice: "; 00441 00442 std::cin >> settings; 00443 00444 //nope 00445 /*if (settings < 1 || settings > 3) { 00446 std::cout << "\n\nPlease enter a valid output format\n"); 00447 }*/ 00448 00449 // Update outputSettings to match data specs of SetOutputSettings 00450 switch (settings) 00451 { 00452 case 1: 00453 settings = CMT_OUTPUTSETTINGS_ORIENTMODE_QUATERNION; 00454 break; 00455 case 2: 00456 settings = CMT_OUTPUTSETTINGS_ORIENTMODE_EULER; 00457 break; 00458 case 3: 00459 settings = CMT_OUTPUTSETTINGS_ORIENTMODE_MATRIX; 00460 break; 00461 } 00462 } 00463 else 00464 { 00465 settings = 0; 00466 } 00467 settings |= CMT_OUTPUTSETTINGS_TIMESTAMP_SAMPLECNT; 00468 } 00469 00470 ////////////////////////////////////////////////////////////////////////// 00471 // doMTSettings 00472 // 00473 // Set user settings in MTi/MTx 00474 // Assumes initialized global MTComm class 00475 void IMUDataServer::doMtSettings(xsens::Cmt3 &cmt3, CmtOutputMode &mode, 00476 CmtOutputSettings &settings, CmtDeviceId deviceIds[]) 00477 { 00478 XsensResultValue res; 00479 unsigned long mtCount = cmt3.getMtCount(); 00480 00481 // set sensor to config sate 00482 res = cmt3.gotoConfig(); 00483 // EXIT_ON_ERROR(res,"gotoConfig"); 00484 00485 unsigned short sampleFreq; 00486 sampleFreq = cmt3.getSampleFrequency(); 00487 00488 // set the device output mode for the device(s) 00489 std::cout << "Configuring your mode selection" << std::endl; 00490 00491 for (unsigned int i = 0; i < mtCount; i++) 00492 { 00493 CmtDeviceMode deviceMode(mode, settings, sampleFreq); 00494 if ((deviceIds[i] & 0xFFF00000) != 0x00500000) 00495 { 00496 // not an MTi-G, remove all GPS related stuff 00497 deviceMode.m_outputMode &= 0xFF0F; 00498 } 00499 res = cmt3.setDeviceMode(deviceMode, true, deviceIds[i]); 00500 // EXIT_ON_ERROR(res,"setDeviceMode"); 00501 } 00502 00503 // start receiving data 00504 res = cmt3.gotoMeasurement(); 00505 // EXIT_ON_ERROR(res,"gotoMeasurement"); 00506 } 00507 #endif