diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f76fd514f1a4ebe76a353db1600d50c1c4f301a2..69c932ef1650dddf0eaebb9bb128b6ee73e3fc23 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ # driver source files -SET(sources asterx1_gps.cpp) +SET(sources asterx1_gps.cpp stream_gps.cpp) # application header files -SET(headers asterx1_gps.h) +SET(headers asterx1_gps.h stream_gps.h) # locate the the necessary dependencies FIND_PACKAGE(iriutils) diff --git a/src/asterx1_gps.cpp b/src/asterx1_gps.cpp index 7533be0d94b28c7accb095655d4d240a7040fb94..5d437070e1aabee3256a5009feae09f563f7f270 100644 --- a/src/asterx1_gps.cpp +++ b/src/asterx1_gps.cpp @@ -1,849 +1,1107 @@ #include "asterx1_gps.h" - -CasteRx1::CasteRx1(const string & hwPortName, const int acqRate) +#include "gps_types.h" +#include "ctime.h" + +/* Look up table for fast computation of the CCITT 16-bit CRC. */ +static const unsigned short CRC_16CCIT_LookUp[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +CasteRx1::CasteRx1(const std::string &name,const std::string &hwPortName) { - status = 0; - config.portName = hwPortName; - config.acqPeriod = acqPeriodValues[acqRate]; + this->serialPort=NULL; + this->serial_device=hwPortName; + this->gps_running=false; + /* initialize events */ + this->event_server=CEventServer::instance(); + this->finish_thread_event_id=name+"_finish_thread_event"; + this->event_server->create_event(this->finish_thread_event_id); + this->new_reply_event_id=name+"_new_reply_event"; + this->event_server->create_event(this->new_reply_event_id); + this->new_meas_block_event_id=name+"_new_meas_block"; + this->event_server->create_event(this->new_meas_block_event_id); + this->new_gps_nav_block_event_id=name+"_new_gps_nav_block"; + this->event_server->create_event(this->new_gps_nav_block_event_id); + this->new_gps_alm_block_event_id=name+"_new_gps_alm_block"; + this->event_server->create_event(this->new_gps_alm_block_event_id); + this->new_gps_ion_block_event_id=name+"_new_gps_ion_block"; + this->event_server->create_event(this->new_gps_ion_block_event_id); + this->new_gps_utc_block_event_id=name+"_new_gps_utc_block"; + this->event_server->create_event(this->new_gps_utc_block_event_id); + this->new_pvt_block_event_id=name+"_new_pvt_block"; + this->event_server->create_event(this->new_pvt_block_event_id); + /* initialize threads */ + this->thread_server=CThreadServer::instance(); + this->gps_process_data_thread_id=name+"_gps_process_data_thread"; + this->thread_server->create_thread(this->gps_process_data_thread_id); + this->thread_server->attach_thread(this->gps_process_data_thread_id,this->gps_process_data_thread,this); } CasteRx1::~CasteRx1() { - blockList.clear(); - if( (status & ACQUISITION_RUNNING) ) stopAcquisition(); - if( (status & DEVICE_OPEN) ) closeDevice(); - delete serialPort; - cout << "CasteRx1::~CasteRx1(). End of CasteRx1 destructor" << endl; //bye bye message -} - -int CasteRx1::openDevice() -{ - TRS232_config serialConfig; - int retValue = BASIC_SUCCESS; - - try{ - serialPort = new CRS232(config.portName); //creates a new object to manage serial connection - }catch(CException &e) - { - cout << e.what() << endl; - cout << "CasteRx1::openDevice(). ERROR. Allocation error when creating new object CRS232" << endl; - retValue = PORT_OPEN_ERROR; - } - - if ( retValue == BASIC_SUCCESS ) //if successfully created , we can open it - { - try{ - serialPort->open( (void*)&config.portName ); - }catch(CCommException &e) - { - cout << e.what() << endl; - cout << "CasteRx1::openDevice(). ERROR. Fail to open serial port" << endl; - retValue = PORT_OPEN_ERROR; - } - } - - if ( retValue == BASIC_SUCCESS ) //if open is successful, we can configure - { - serialConfig.baud = ASTERX_BAUDRATE; - serialConfig.num_bits = 8; - serialConfig.parity = none; - serialConfig.stop_bits = 1; - try{ - serialPort->config( &serialConfig ); - }catch(CCommException &e) - { - cout << e.what() << endl; - cout << "CasteRx1::openDevice(). ERROR. Fail to configure serial port" << endl; - retValue = PORT_CONFIG_ERROR; - } - } - - if (retValue == BASIC_SUCCESS) - { - status |= DEVICE_OPEN; - cout << "CasteRx1::openDevice(). SUCCESS. Serial port " << config.portName << " opened successfully." << endl; - - } - - return retValue; -} - -int CasteRx1::closeDevice() -{ - int retValue = BASIC_SUCCESS; - - if ( (status & DEVICE_OPEN) ) - { - try{ - serialPort->close(); - //status &= ~DEVICE_OPEN; - }catch(CException &e)// catch(CCommException &e) - { - cout << e.what() << endl; - cout << "CasteRx1::openDevice(). ERROR. Fail to close serial port " << config.portName << endl; - retValue = PORT_CLOSE_ERROR; - //status |= DEVICE_OPEN; //close() has failed , so it is still opened - } - } - if ( retValue == BASIC_SUCCESS ) //if close() is successful, we delete the object - { - status &= ~DEVICE_OPEN; - cout << "CasteRx1::closeDevice(). SUCCESS. Serial port " << config.portName << " closed successfully." << endl; - } - - return retValue; -} - -int CasteRx1::startAcquisition() -{ - int retValue=0; - sbfBlockManager *blockMng; - string cmnd; - - //enables commands at USB1 device input - retValue += sendCommand("setDataInOut,USB1,CMD,none\n"); - - //stops data transmission if it was running - retValue += sendCommand("setSBFOutput,all,USB1,none\n"); - - //enables septentrio binary format (SBF) as output at USB1 - retValue += sendCommand("setDataInOut,USB1,CMD,+SBF\n"); - - //GPS signal processing options for urban mobile robots - retValue += sendCommand("setMultipathMitigation,on\n");//enables processing for multipath removing (pag.26) - retValue += sendCommand("setReceiverDynamics,Moderate\n");//Mobile robots moves at moderate speeds - retValue += sendCommand("setPVTMode,Rover,StandAlone\n");//rover mode and enables standalone - - //data configuration. Add blocks of interest to "group 1" - retValue += sendCommand("setSBFGroups,Group1,PVTCartesian\n"); - blockMng = new sbfBlockManager; blockMng->blockId = PVTCartesian_ID; blockMng->received = false; - blockList.push_back(*blockMng); - - retValue += sendCommand("setSBFGroups,Group1,+PosCovCartesian\n"); - blockMng = new sbfBlockManager; blockMng->blockId = PosCovCartesian_ID; blockMng->received = false; - blockList.push_back(*blockMng); - - retValue += sendCommand("setSBFGroups,Group1,+DOP\n"); - blockMng = new sbfBlockManager; blockMng->blockId = DOP_ID; blockMng->received = false; - blockList.push_back(*blockMng); - - retValue += sendCommand("setSBFGroups,Group1,+PVTGeodetic\n"); - blockMng = new sbfBlockManager; blockMng->blockId = PVTGeodetic_ID; blockMng->received = false; - blockList.push_back(*blockMng); - - //requests "Group1" data to be output to USB1 at specified rate - cmnd = "setSBFOutput,Stream1,USB1,Group1,"; - cmnd.append(config.acqPeriod); - cmnd.append("\n"); - retValue += sendCommand(cmnd); - - if ( retValue == BASIC_SUCCESS*11 ) //success on all commands - { - status |= ACQUISITION_RUNNING; - retValue = BASIC_SUCCESS; - cout << "CasteRx1::startAcquisition(). SUCCESS on device configuration. The device is now transmitting data ..." << endl; - } - else //otherwise - { - status &= ~ACQUISITION_RUNNING; - retValue = ASTERX1_CONFIG_ERROR; - cout << "CasteRx1::startAcquisition(). ERROR on device configuration for data transmission" << endl; - } - - return retValue; -} - -int CasteRx1::stopAcquisition() -{ - int retValue=0; - - if( (status & ACQUISITION_RUNNING) ) - { - blockList.clear(); - - retValue += sendCommand("setSBFOutput,Stream1,USB1,none\n");//stops data transmission from device - retValue += sendCommand("setDataInOut,USB1,CMD,none\n");//enables commands as input at USB1 - if ( retValue == BASIC_SUCCESS*2 ) - { - status &= ~ACQUISITION_RUNNING; - retValue = BASIC_SUCCESS; - cout << "CasteRx1::stopAcquisition(). SUCCESS on stopping the device data transmission." << endl; - } - else - { - retValue = ASTERX1_STOPPINTG_ERROR; - cout << "CasteRx1::stopAcquisition(). ERROR on stopping the device data transmission." << endl; - } - } - else - { - cout << "CasteRx1::stopAcquisition(). Nothing to do, the acquisition was already stopped." << endl; - retValue = BASIC_SUCCESS; - } - - return retValue; -} - -int CasteRx1::readDataFromDevice() -{ - int retValue; - unsigned char buffer[MAX_BLOCK_SIZE]; - unsigned short int crcValue, crcComputed; //crc value from device and crc computed - unsigned short int blockId; //data block id from receiver - unsigned short int blockLength; //size of the SBF block in bytes - timeval tmStmp; - list<sbfBlockManager>::iterator iiBlock; - bool allReceived = false; - - //reset received field of block managers - for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++){ iiBlock->received = false; } - - //acquisition up to all requested blocks are received - while (!allReceived) - { - //Sets Time Stamp (this is the system time stamp, not the GPS time!) - gettimeofday(&tmStmp, NULL); - timeStamp = (double)(tmStmp.tv_sec + tmStmp.tv_usec/1e6); - - retValue = synchronizeHeader((const unsigned char *)"$@", DATA_TIMEOUT); - if ( retValue != BASIC_SUCCESS ) //if !BASIC_SUCCESS, status will be either COMMTIMEOUT or SERIALCOMMERROR - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR. when synchronizing with header. Expected header = $@" << endl; - return ACQUISITION_ERROR; - } - - //starts reading header - retValue = 0; - retValue += readNbytes(&buffer[0],2,DATA_TIMEOUT);//reads transmitted crc value - crcValue = getUI2(&buffer[0]); //decodes crc value - retValue += readNbytes(&buffer[0],2,DATA_TIMEOUT);//reads block id field - blockId = (buffer[0] & 0xff)|((buffer[1] & 0x1f)<<8);//decodes blockId (uses only the 13 LS bits) - retValue += readNbytes(&buffer[2],2,DATA_TIMEOUT);//reads block length - blockLength = getUI2(&buffer[2]);//decodes block length (in bytes) - - //check for some errors - if ( retValue != 3*BASIC_SUCCESS ) - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR. Error reading block header." << endl; - return ACQUISITION_ERROR; - } - if ( (blockLength%4!=0) || (blockLength < MIN_BLOCK_SIZE) || (blockLength > MAX_BLOCK_SIZE) ) - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR. SBF block Length not correct: " << blockLength << " bytes" << endl; - return ACQUISITION_ERROR; - } - - //cout << "readDataFromDevice(): "<< __LINE__ << "; blockLength = " << blockLength << endl; - - //reads the rest of the block and loads it to the buffer - retValue = readNbytes(&buffer[4],(blockLength-8),DATA_TIMEOUT); - if ( retValue != BASIC_SUCCESS ) - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR. Error reading block data." << endl; - return ACQUISITION_ERROR; - } - - //Computes & checks CRC - crcComputed = CRC_compute16CCITT(buffer, blockLength-4); - //cout << "Expected value: " << crcValue << "; Computed value: " << crcComputed << endl; - if ( crcComputed != crcValue ) - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR. CRC error. Expected value: " << crcValue << "; Computed value: " << crcComputed << endl; - return ACQUISITION_ERROR; - } - - //decodes SBF block - switch(blockId) - { - case PVTCartesian_ID: - retValue = decodePVTCartesian(&buffer[4]); - markBlockAsReceived(PVTCartesian_ID); - break; - - case PVTGeodetic_ID: - retValue = decodePVTGeodetic(&buffer[4]); - markBlockAsReceived(PVTGeodetic_ID); - break; - - case PosCovCartesian_ID: - retValue = decodePosCovCartesian(&buffer[4]); - markBlockAsReceived(PosCovCartesian_ID); - break; - - case DOP_ID: - retValue = decodeDOP(&buffer[4]); - markBlockAsReceived(DOP_ID); - break; - - default: - cout << "CasteRx1::readDataFromDevice(). ERROR. Unknown SBF blockId: " << blockId << endl; - retValue = ACQUISITION_ERROR; - break; - } - - //check resulting status of the decoding function - if ( retValue != BASIC_SUCCESS ) - { - status &= ~DATA_BLOCK_OK; - cout << "CasteRx1::readDataFromDevice(). ERROR on decoding SBF block. BlockId = " << blockId << ". Status = " << status << endl; - return ACQUISITION_ERROR; - } - else//sets status and checks recursively if all blocks have been received - { - status |= DATA_BLOCK_OK; - allReceived = true; - for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++){ allReceived = iiBlock->received & allReceived; } - } - } - - //check gps availability - if ( pvtError == 0 ) - { - status |= GPS_AVAILABLE; - fromWgsToMap(); //conversion to map coordinates - computeTMenu(); //compute rotation matrix form WGS to local tangential ENU frame - computeENUcovs(); //compute covariances from WGS to local tangential ENU frame - } - else - { - status &= ~GPS_AVAILABLE; - } - - return BASIC_SUCCESS; -} - -void CasteRx1::printData(ostream & ost) -{ - streamsize nn; - - ost << status << " "; - nn=ost.precision(12); ost << timeStamp << " "; ost.precision(nn); - ost << wnc << " " << tow << " " << numSatellites << " " << PDOP << " "; - nn=ost.precision(12); ost << lat << " " << lon << " " << alt << " "; ost.precision(nn); - ost << xWgs << " " << yWgs << " " << zWgs << " "; - ost << xMap << " " << yMap << " " << zMap << " "; - ost << vxWgs << " " << vyWgs << " " << vzWgs << " "; - ost << vxMap << " " << vyMap << " " << vzMap << " "; - ost << cxxWgs << " " << cyyWgs << " " << czzWgs << " " << cxyWgs << " "; - ost << cxxMap << " " << cyyMap << " " << czzMap << " " << cxyMap << " "; - ost << endl; -} - -void CasteRx1::setMapOrigin(double mapLat0, double mapLon0, double mapAlt0, double mapAlpha0) -{ - lat0 = mapLat0*M_PI/180.0; - lon0 = mapLon0*M_PI/180.0; - alt0 = mapAlt0; - alpha0 = mapAlpha0*M_PI/180.0; - - computeTM(); -} - -void CasteRx1::setPortName(string pName) -{ - if( (status & DEVICE_OPEN) ) //if device is open, port name can't be changed - { - cout << "CasteRx1::setPortName(): WARNING! Serial port resource can't be changed when port is open. Keeping old settings: " << config.portName << endl; - } - else - { - config.portName = pName; - cout << "CasteRx1::setPortName(): Serial port name setting has changed. New serial port is " << config.portName << endl; - } -} - -void CasteRx1::setAcquisitionRate(int rateIndex) -{ - if (status & ACQUISITION_RUNNING) - { - cout << "CasteRx1::setAcquisitionRate(): WARNING! Rate can't be changed when acquisition is running. Keeping old settings: " << config.acqPeriod << endl; - } - else - { - if ( ( rateIndex<ONCHANGE )|| ( rateIndex>SEC10 ) ) - { - cout << "CasteRx1::setAcquisitionRate(): WARNING! Invalid rate index. Keeping old settings: " << config.acqPeriod << endl; - } - else - { - config.acqPeriod = acqPeriodValues[rateIndex]; - cout << "CasteRx1::setAcquisitionRate(): Acquisition rate has changed. New rate is " << config.acqPeriod << endl; - } - } -} - -void CasteRx1::printTM() -{ - streamsize nn; - - cout << endl << "MAP ORIGIN (GEODETIC) ----------------------------------" << endl; - nn=cout.precision(15); - cout << "lat0 = " << lat0 << endl << "lon0 = " << lon0 << endl << "alt0 = " << alt0 << endl << "alpha0 = " << alpha0 << endl; - cout.precision(nn); - - cout << endl << "MATRIX TRANSFORM FROM ECEF to MAP-----------------------" << endl; - cout << TM[0][0] << '\t' << TM[0][1] << '\t' << TM[0][2] << '\t' << TM[0][3] << endl - << TM[1][0] << '\t' << TM[1][1] << '\t' << TM[1][2] << '\t' << TM[1][3] << endl - << TM[2][0] << '\t' << TM[2][1] << '\t' << TM[2][2] << '\t' << TM[2][3] << endl - << TM[3][0] << '\t' << '\t' << TM[3][1] << '\t' << '\t' << TM[3][2] << '\t' << '\t' << TM[3][3] << endl; - cout << "--------------------------------------------------------" << endl << endl; -} - -unsigned int CasteRx1::getStatus(){ return status; } -double CasteRx1::getTimeStamp(){ return timeStamp; } -unsigned short int CasteRx1::getWnc(){ return wnc; } -unsigned int CasteRx1::getTow(){ return tow; } -unsigned int CasteRx1::getNumSatellites(){ return numSatellites; } -float CasteRx1::getPDOP(){ return PDOP; } -float CasteRx1::getTDOP(){ return TDOP; } -float CasteRx1::getHDOP(){ return HDOP; } -float CasteRx1::getVDOP(){ return VDOP; } -float CasteRx1::getUndulation(){ return undulation; } -unsigned short int CasteRx1::getPVTerror(){ return pvtError;} - -double CasteRx1::getLat(bool units) -{ - if ( units == inRADS ) return lat; - else return lat*180.0/M_PI; -} - -double CasteRx1::getLon(bool units) -{ - if ( units == inRADS ) return lon; - else return lon*180.0/M_PI; -} - -double CasteRx1::getAlt(){ return alt; } -double CasteRx1::getXWgs(){ return xWgs; } -double CasteRx1::getYWgs(){ return yWgs; } -double CasteRx1::getZWgs(){ return zWgs; } -double CasteRx1::getXMap(){ return xMap; } -double CasteRx1::getYMap(){ return yMap; } -double CasteRx1::getZMap(){ return zMap; } -double CasteRx1::getVxWgs(){ return vxWgs; } -double CasteRx1::getVyWgs(){ return vyWgs; } -double CasteRx1::getVzWgs(){ return vzWgs; } -double CasteRx1::getVxMap(){ return vxMap; } -double CasteRx1::getVyMap(){ return vyMap; } -double CasteRx1::getVzMap(){ return vzMap; } -double CasteRx1::getCxxWgs(){ return cxxWgs; } -double CasteRx1::getCyyWgs(){ return cyyWgs; } -double CasteRx1::getCzzWgs(){ return czzWgs; } -double CasteRx1::getCxyWgs(){ return cxyWgs; } -double CasteRx1::getCxxMap(){ return cxxMap; } -double CasteRx1::getCyyMap(){ return cyyMap; } -double CasteRx1::getCzzMap(){ return czzMap; } -double CasteRx1::getCxyMap(){ return cxyMap; } -double CasteRx1::getCxxEnu(){ return cxxEnu; } -double CasteRx1::getCyyEnu(){ return cyyEnu; } -double CasteRx1::getCzzEnu(){ return czzEnu; } -double CasteRx1::getCxyEnu(){ return cxyEnu; } -double CasteRx1::getCxzEnu(){ return cxzEnu; } -double CasteRx1::getCyzEnu(){ return cyzEnu; } + // stop data acquiaition + this->stopAcquisition(); + // close the gps module + this->closeDevice(); + // delete threads and events + this->thread_server->detach_thread(gps_process_data_thread_id); + this->thread_server->delete_thread(gps_process_data_thread_id); + this->gps_process_data_thread_id=""; + this->event_server->delete_event(this->finish_thread_event_id); + this->finish_thread_event_id=""; + this->event_server->delete_event(this->new_reply_event_id); + this->new_reply_event_id=""; + this->event_server->delete_event(this->new_meas_block_event_id); + this->new_meas_block_event_id=""; + this->event_server->delete_event(this->new_gps_nav_block_event_id); + this->new_gps_nav_block_event_id=""; + this->event_server->delete_event(this->new_gps_alm_block_event_id); + this->new_gps_alm_block_event_id=""; + this->event_server->delete_event(this->new_gps_ion_block_event_id); + this->new_gps_ion_block_event_id=""; + this->event_server->delete_event(this->new_gps_utc_block_event_id); + this->new_gps_utc_block_event_id=""; + this->event_server->delete_event(this->new_pvt_block_event_id); + this->new_pvt_block_event_id=""; + if(this->serialPort!=NULL) + { + delete this->serialPort; + this->serialPort=NULL; + } +} + +void CasteRx1::openDevice() +{ + TRS232_config serialConfig; + + try + { + this->serialPort = new CRS232(this->serial_device); //creates a new object to manage serial connection + this->serialPort->open((void*)&this->serial_device); + serialConfig.baud = 115200; + serialConfig.num_bits = 8; + serialConfig.parity = none; + serialConfig.stop_bits = 1; + this->serialPort->config(&serialConfig); + // start the GPS processing data thread + this->thread_server->start_thread(this->gps_process_data_thread_id); + // configure the data streams + this->configureStreams(); + }catch(CCommException &e){ + if(this->serialPort!=NULL) + { + delete this->serialPort; + this->serialPort=NULL; + } + } +} + +void CasteRx1::closeDevice() +{ + // stop the internal acquisition thread if necessary + this->stopAcquisition(); + // close the serial port + if(this->thread_server->get_thread_state(this->gps_process_data_thread_id)==active) + { + this->event_server->set_event(this->finish_thread_event_id); + this->thread_server->end_thread(this->gps_process_data_thread_id); + } + if(this->serialPort!=NULL) + this->serialPort->close(); +} + +void CasteRx1::startAcquisition() +{ + if(this->thread_server->get_thread_state(this->gps_process_data_thread_id)==active) + { + if(!this->gps_running) + { + this->sendCommand("setSBFOutput,Stream1,USB1,Group1,onChange\n"); + this->sendCommand("setSBFOutput,Stream2,USB1,Group2,onChange\n"); + this->sendCommand("setSBFOutput,Stream3,USB1,Group3,onChange\n"); + this->sendCommand("setSBFOutput,Stream4,USB1,Group4,onChange\n"); + this->gps_running=true; + } + } +} + +void CasteRx1::stopAcquisition() +{ + if(this->gps_running) + { + this->sendCommand("setSBFOutput,Stream1,USB1,none\n"); + this->sendCommand("setSBFOutput,Stream2,USB1,none\n"); + this->sendCommand("setSBFOutput,Stream3,USB1,none\n"); + this->sendCommand("setSBFOutput,Stream4,USB1,none\n"); + this->gps_running=false; + } +} + +std::string CasteRx1::get_new_meas_data_event_id(void) +{ + return this->new_meas_block_event_id; +} + +void CasteRx1::get_meas_data(TMeasEpoch &meas_epoch, TMeasExtra &meas_extra) +{ + this->meas_access.enter(); + meas_epoch=this->current_meas_epoch; + meas_extra=this->current_meas_extra; + if(this->event_server->event_is_set(this->new_meas_block_event_id)) + this->event_server->reset_event(this->new_meas_block_event_id); + this->meas_access.exit(); +} + +std::string CasteRx1::get_new_gps_nav_data_event_id(void) +{ + return this->new_gps_nav_block_event_id; +} + +void CasteRx1::get_gps_nav_data(TGPSNav &gps_nav) +{ + this->nav_access.enter(); + gps_nav=this->current_gps_nav; + if(this->event_server->event_is_set(this->new_gps_nav_block_event_id)) + this->event_server->reset_event(this->new_gps_nav_block_event_id); + this->nav_access.exit(); +} + +std::string CasteRx1::get_new_gps_alm_data_event_id(void) +{ + return this->new_gps_alm_block_event_id; +} + +void CasteRx1::get_gps_alm_data(TGPSAlm &gps_alm) +{ + this->nav_access.enter(); + gps_alm=this->current_gps_alm; + if(this->event_server->event_is_set(this->new_gps_alm_block_event_id)) + this->event_server->reset_event(this->new_gps_alm_block_event_id); + this->nav_access.exit(); +} + +std::string CasteRx1::get_new_gps_ion_data_event_id(void) +{ + return this->new_gps_ion_block_event_id; +} + +void CasteRx1::get_gps_ion_data(TGPSIon &gps_ion) +{ + this->nav_access.enter(); + gps_ion=this->current_gps_ion; + if(this->event_server->event_is_set(this->new_gps_ion_block_event_id)) + this->event_server->reset_event(this->new_gps_ion_block_event_id); + this->nav_access.exit(); +} + +std::string CasteRx1::get_new_gps_utc_data_event_id(void) +{ + return this->new_gps_utc_block_event_id; +} + +void CasteRx1::get_gps_utc_data(TGPSUtc &gps_utc) +{ + this->nav_access.enter(); + gps_utc=this->current_gps_utc; + if(this->event_server->event_is_set(this->new_gps_utc_block_event_id)) + this->event_server->reset_event(this->new_gps_utc_block_event_id); + this->nav_access.exit(); +} + +std::string CasteRx1::get_new_pvt_data_event_id(void) +{ + return this->new_pvt_block_event_id; +} +void CasteRx1::get_pvt_data(TPVTCartesian &pvt_cart,TPVTGeodetic &pvt_geo) +{ + this->pvt_access.enter(); + pvt_cart=this->current_pvt_cartesian; + pvt_geo=this->current_pvt_geodetic; + if(this->event_server->event_is_set(this->new_pvt_block_event_id)) + this->event_server->reset_event(this->new_pvt_block_event_id); + this->pvt_access.exit(); +} + +void CasteRx1::get_pvt_cov_data(TPVTCov &pvt_pos_cov_cart,TPVTCov &pvt_pos_cov_geo,TPVTCov &pvt_vel_cov_cart,TPVTCov &pvt_vel_cov_geo) +{ + this->pvt_access.enter(); + pvt_pos_cov_cart=this->current_pvt_pos_cov_cartesian; + pvt_pos_cov_geo=this->current_pvt_pos_cov_geodetic; + pvt_vel_cov_cart=this->current_pvt_vel_cov_cartesian; + pvt_vel_cov_geo=this->current_pvt_vel_cov_geodetic; + if(this->event_server->event_is_set(this->new_pvt_block_event_id)) + this->event_server->reset_event(this->new_pvt_block_event_id); + this->pvt_access.exit(); +} + +void CasteRx1::get_pvt_dop_data(TPVTDOP &pvt_dop) +{ + this->pvt_access.enter(); + pvt_dop=this->current_pvt_dop; + if(this->event_server->event_is_set(this->new_pvt_block_event_id)) + this->event_server->reset_event(this->new_pvt_block_event_id); + this->pvt_access.exit(); +} /******************************* PROTECTED MEMBERS ************************************************/ -int CasteRx1::readNbytes(unsigned char *buffer, unsigned int nn, unsigned int msecTimeOut) -{ - CEventServer *eventServer=CEventServer::instance(); - string rxEvent; - list<string> eventList; - unsigned int bytesRead = 0; - unsigned int queueSize = 0; - unsigned int desiredBytes = 0; - int retValue = BASIC_SUCCESS; - - //sets the event list with the reception event from serialPort object - rxEvent = serialPort->get_rx_event_id(); - eventList.push_back(rxEvent); - - //first check if some byte is already in the queue - queueSize = serialPort->get_num_data(); - if ( queueSize > 0) - { - desiredBytes = min( queueSize , (nn-bytesRead) ); - bytesRead += serialPort->read((unsigned char *)(buffer+bytesRead),desiredBytes); - } - - //starts the waiting loop if not all bytes are already read - while ( (bytesRead<nn) && (retValue == BASIC_SUCCESS) ) - { - try{ - eventServer->wait_all(eventList, msecTimeOut);//waits for reception event - }catch(CEventServerException &e) - { - cout << e.what() << ". Line: " << __LINE__ << endl; - retValue = PORT_READ_TIMEOUT; - } - if (retValue == BASIC_SUCCESS) - { - queueSize = serialPort->get_num_data(); - desiredBytes = min( queueSize , (nn-bytesRead) ); - bytesRead += serialPort->read((unsigned char *)(buffer+bytesRead),desiredBytes); - } - } - - return retValue; -} - -int CasteRx1::synchronizeHeader(const unsigned char *mark, int msecTimeOut, unsigned int markSize) -{ - unsigned char cc; - string readMark, targetMark; - int retValue = BASIC_SUCCESS; - unsigned int ii=0; - - //sets targetMark - targetMark.append((const char*)mark,markSize); - - //reads mark from comm device - for (ii=0; ii<markSize; ii++) - { - retValue = readNbytes(&cc,1,msecTimeOut); - readMark.push_back((char)cc); - } - - //continue reading while mark is not reached or while timeout - while ( (readMark.compare(targetMark) != 0) && (retValue == BASIC_SUCCESS) ) - { - for (ii=1; ii<markSize; ii++) readMark.at(ii-1) = readMark.at(ii); //left displacement of all bytes - retValue = readNbytes(&cc,1,msecTimeOut); //gets a new byte - readMark.at(markSize-1) = (char)cc; //replace the last byte by the new one - //cout << endl << "readMark: " << readMark << endl << "targetMark: " << targetMark << endl; - } - - return retValue; -} - -int CasteRx1::sendCommand(const string & cmnd) -{ - int retValue; - unsigned char replyBuffer[200]; - string receivedReply, expectedReply; - - //relax if we concatenate commands. (200 ms were suggested by Septentrio support team in a personal communication). 50ms tested and it seems it is not enough!!! - usleep(100000); - - //sends the command string - serialPort->write((unsigned char*)cmnd.c_str(),cmnd.size()); - - //synchronize with the reply header - retValue = synchronizeHeader((const unsigned char *)"$R",500); - - //cout << "CasteRx1. Line: " << __LINE__ << ". Reply Sync achieved" << endl; - if ( retValue != BASIC_SUCCESS ) - { - cout << "CasteRx1::sendCommand(). ERROR. Synchronization with repky header $R not achieved after timeout" << endl; - return retValue; //it will be either COMMTIMEOUT or SERIALCOMMERROR - } - - //reads response up to receive expected length bytes (2 + cmnd.size()). Expected response : "$R: <cmnd>", but $R has been already read - retValue = readNbytes(&replyBuffer[0],cmnd.size()+2,500); - if ( retValue != BASIC_SUCCESS ) - { - cout << "CasteRx1::sendCommand(). ERROR. Expected reply string not received after timeout" << endl; - return retValue; //it will be either COMMTIMEOUT or SERIALCOMMERROR - } - - //check response - if ( replyBuffer[0] == '?' ) - { - cout << "CasteRx1::sendCommand(). ERROR. Unknown command: " << cmnd << endl; - return ASTERX1_INVALID_COMMAND; - } - receivedReply.append((const char*)replyBuffer,cmnd.size()+2); - receivedReply.append("\n"); - expectedReply = ": "; - expectedReply.append(cmnd); - expectedReply.append("\n"); - if ( receivedReply.compare(0, cmnd.size()+1, expectedReply, 0, cmnd.size()+1) == 0) //expected = received - { - //cout << "CasteRx1::sendCommand(). Command Successful: " << cmnd << endl; - return BASIC_SUCCESS; - } - else //otherwise - { - cout << "CasteRx1::sendCommand(). Error. " << endl; - cout << " Sent command: " << cmnd << endl; - cout << " Device Reply: " << receivedReply << endl; - cout << " Expected Reply: " << expectedReply << endl; - return ASTERX1_CONFIG_ERROR; - } -} - -unsigned short int CasteRx1::getUI1(unsigned char *buf) -{ - //return ( (buf[0] & 0xff) | (0x0 << 8) ); - return (buf[0] & 0x00ff); -} - -unsigned short int CasteRx1::getUI2(unsigned char *buf) -{ - return ( (buf[0] & 0xff) | ((buf[1]&0xff)<<8) ); -} - -unsigned int CasteRx1::getUI4(unsigned char *buf) -{ - return ( (buf[0]&0xff) | ((buf[1]&0xff)<<8) | ((buf[2]&0xff)<<16) | ((buf[3]&0xff)<<24) ); -} - -float CasteRx1::getFloat(unsigned char *buf) -{ - unsigned int uintL; - uniFloat uniF; - - uintL=(buf[0]&0xff)|((buf[1]&0xff)<<8)|((buf[2]&0xff)<<16)|((buf[3]&0xff)<<24); - uniF.i = uintL; - - return uniF.flt; -} - -double CasteRx1::getDouble(unsigned char *buf) -{ - unsigned int uintL; - unsigned long long int uintH; - uniDouble uniD; - - uintL=(buf[0]&0xff)|((buf[1]&0xff)<<8)|((buf[2]&0xff)<<16)|((buf[3]&0xff)<<24); - uintH=(buf[4]&0xff)|((buf[5]&0xff)<<8)|((buf[6]&0xff)<<16)|((buf[7]&0xff)<<24); - //uniD.i = uintL|((uintH&0xffff)<<32); - uniD.i = uintL|uintH<<32; - - return uniD.dbl; -} - -int CasteRx1::decodePVTCartesian(unsigned char *sbfMsg) -{ - unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...) - - tow = getUI4(&sbfMsg[0]); - wnc = getUI2(&sbfMsg[4]); - mode = getUI1(&sbfMsg[6]); - pvtError = getUI1(&sbfMsg[7]); - if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error) - { - //cout << "CasteRx1::decodePVTCartesian(): PVT_ERROR: " << pvtError << endl; - } - else - { - xWgs = getDouble(&sbfMsg[8]); - yWgs = getDouble(&sbfMsg[16]); - zWgs = getDouble(&sbfMsg[24]); - undulation = (double) getFloat(&sbfMsg[32]); - vxWgs = (double) getFloat(&sbfMsg[36]); - vyWgs = (double) getFloat(&sbfMsg[40]); - vzWgs = (double) getFloat(&sbfMsg[44]); - numSatellites = getUI1(&sbfMsg[66]); - } - - //cout << "CasteRx1::decodePVTCartesian()" << endl; - return BASIC_SUCCESS; -} - -int CasteRx1::decodePVTGeodetic(unsigned char *sbfMsg) -{ - unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...) - - tow = getUI4(&sbfMsg[0]); - wnc = getUI2(&sbfMsg[4]); - mode = getUI1(&sbfMsg[6]); - pvtError = getUI1(&sbfMsg[7]); - if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error) - { - //cout << "CasteRx1::decodePVTGeodetic(): PVT_ERROR: " << pvtError << endl; - } - else - { - lat = getDouble(&sbfMsg[8]); - lon = getDouble(&sbfMsg[16]); - alt = getDouble(&sbfMsg[24]); - } - - //cout << "CasteRx1::decodePVTGeodetic()" << endl; - return BASIC_SUCCESS; -} - -int CasteRx1::decodePosCovCartesian(unsigned char *sbfMsg) -{ - unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...) - - tow = getUI4(&sbfMsg[0]); - wnc = getUI2(&sbfMsg[4]); - mode = getUI1(&sbfMsg[6]); - pvtError = getUI1(&sbfMsg[7]); - if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error) - { - //cout << "CasteRx1::decodePosCovCartesian(): PVT_ERROR: " << pvtError << endl; - } - else - { - cxxWgs = (double) getFloat(&sbfMsg[8]); - cyyWgs = (double) getFloat(&sbfMsg[12]); - czzWgs = (double) getFloat(&sbfMsg[16]); - cxyWgs = (double) getFloat(&sbfMsg[24]); - cxzWgs = (double) getFloat(&sbfMsg[28]); - cyzWgs = (double) getFloat(&sbfMsg[36]); - } - - //cout << "CasteRx1::decodePosCovCartesian()" << endl; - return BASIC_SUCCESS; -} - -int CasteRx1::decodeDOP(unsigned char *sbfMsg) -{ - unsigned char nrsv;//total number of satellites for DOP computation - - tow = getUI4(&sbfMsg[0]); - wnc = getUI2(&sbfMsg[4]); - nrsv = getUI1(&sbfMsg[6]); - - PDOP = (double)getUI2(&sbfMsg[8])/100.0; - TDOP = (double)getUI2(&sbfMsg[10])/100.0; - HDOP = (double)getUI2(&sbfMsg[12])/100.0; - VDOP = (double)getUI2(&sbfMsg[14])/100.0; - - //cout << "CasteRx1::decodeDOP()" << endl; - return BASIC_SUCCESS; -} - -//unsigned short CasteRx1::CRC_compute16CCITT(const void *buf, size_t buf_length) -unsigned short CasteRx1::CRC_compute16CCITT(unsigned char *buf, unsigned short int nBytes) -{ - unsigned int ii; - unsigned short crc = 0; - //const unsigned char *buf8 = buf; /* Convert the type to access by byte. */ - - /* see for example the BINEX web site */ - for (ii=0; ii<nBytes; ii++) { - crc = (crc << 8) ^ CRC_16CCIT_LookUp[ (crc >> 8) ^ buf[ii] ]; +void *CasteRx1::gps_process_data_thread(void *params) +{ + unsigned int event_id,num,i,length=0; + CasteRx1 *gps=(CasteRx1 *)params; + static gps_state_t state=header1; + std::list<std::string> events; + unsigned char *data,*sbf_data; + std::string reply; + bool end=false; + + events.push_back(gps->finish_thread_event_id); + events.push_back(gps->serialPort->get_rx_event_id()); + while(!end) + { + event_id=gps->event_server->wait_first(events); + if(event_id==0)// finish the thread + end=true; + else if(event_id==1)// new data available + { + num=gps->serialPort->get_num_data(); + if(data!=NULL) + delete[] data; + data=new unsigned char[num]; + gps->serialPort->read(data,num); + for(i=0;i<num;i++) + { + switch(state) + { + case header1: if(data[i]=='$') + state=header2; + else + state=header1; + break; + case header2: if(data[i]=='R')// answer to a command + state=get_cmd_reply; + else if(data[i]=='@')// gps data + { + state=get_block_header; + length=2; + gps->current_header.sync[0]='$'; + gps->current_header.sync[1]='@'; + } + break; + case get_cmd_reply: if(data[i]=='\r') + { + // signal that an answer is available + gps->reply_queue.push(reply); + if(!gps->event_server->event_is_set(gps->new_reply_event_id)) + gps->event_server->set_event(gps->new_reply_event_id); + reply=""; + state=header1; + } + else// add the data to the answer string + { + reply.push_back(data[i]); + state=get_cmd_reply; + } + break; + case get_block_header: ((unsigned char *)&gps->current_header)[length]=data[i]; + length++; + if(length==sizeof(TGPSBlockHeader)) + { + if((gps->current_header.length%4)!=0)// length must be a multiple of 4 + state=header1; + else + { + if(sbf_data!=NULL) + delete sbf_data; + sbf_data=new unsigned char[gps->current_header.length]; + state=get_sbf_data; + } + } + break; + case get_sbf_data: sbf_data[length-sizeof(TGPSBlockHeader)]=data[i]; + length++; + if(length==gps->current_header.length) + { + /* compute CRC and check it */ + if(gps->compute_crc(sbf_data,length-8)==gps->current_header.crc)// invalid Block CRC + gps->process_block(sbf_data,length-8); + else + std::cout << "CRC error" << std::endl; + delete[] sbf_data; + sbf_data=0; + state=header1; + } + break; + } + } + delete[] data; + data=NULL; + } + } + pthread_exit(NULL); +} + +void CasteRx1::process_block(unsigned char *data,unsigned short int length) +{ + switch(this->current_header.id.id) + { + case PVTCartesian_ID: //std::cout << "PVTCartesian_ID" << std::endl; + this->process_pvt_cartesian(data,length); + break; + case PVTGeodetic_ID: //std::cout << "PVTGeodetic_ID" << std::endl; + this->process_pvt_geodetic(data,length); + break; + case PosCovCartesian_ID: //std::cout << "PosCovCartesian_ID" << std::endl; + this->process_pos_cov_cartesian(data,length); + break; + case PosCovGeodetic_ID: //std::cout << "PosCovGeodetic_ID" << std::endl; + this->process_pos_cov_geodetic(data,length); + break; + case VelCovCartesian_ID: //std::cout << "VelCovCartesian_ID" << std::endl; + this->process_vel_cov_cartesian(data,length); + break; + case VelCovGeodetic_ID: //std::cout << "VelCovGeodetic_ID" << std::endl; + this->process_vel_cov_geodetic(data,length); + break; + case DOP_ID: //std::cout << "DOP_ID" << std::endl; + this->process_dop(data,length); + break; + case EndOfPVT_ID: //std::cout << "EndofPVT_ID" << std::endl; + this->process_end_of_pvt(data,length); + break; + case MeasEpoch_ID: //std::cout << "MeasEpoch_ID" << std::endl; + this->process_meas_epoch(data,length); + break; + case MeasExtra_ID: //std::cout << "MeasExtra_ID" << std::endl; + this->process_meas_extra(data,length); + break; + case EndOfMeas_ID: //std::cout << "EndofMeas_ID" << std::endl; + this->process_end_of_meas(data,length); + break; + case GPSNav_ID: //std::cout << "GPSNav_ID" << std::endl; + this->process_gps_nav(data,length); + break; + case GPSAlm_ID: //std::cout << "GPSAlm_ID" << std::endl; + this->process_gps_alm(data,length); + break; + case GPSIon_ID: //std::cout << "GPSIon_ID" << std::endl; + this->process_gps_ion(data,length); + break; + case GPSUtc_ID: //std::cout << "GPSUtc_ID" << std::endl; + this->process_gps_utc(data,length); + break; + case ReceiverStatus_ID: //std::cout << "ReceiverStatus_ID" << std::endl; + this->process_receiver_status(data,length); + break; + case ChannelStatus_ID: //std::cout << "ChannelStatus_ID" << std::endl; + this->process_channel_status(data,length); + break; + case SatVisibility_ID: //std::cout << "SatVisibility_ID" << std::endl; + this->process_sat_visibility(data,length); + break; + default: std::cout << "Unknown block ID: " << this->current_header.id.id << std::endl; + break; + } +} + +void CasteRx1::process_channel_status(unsigned char *data,unsigned short int length) +{ + TGPSChannelStatus gps_channel_status; + TGPSChannelSatInfo gps_sat_info; + TGPSChannelStateInfo gps_state_info; + unsigned short int index=0,i,j; + TChannelStatus channel_status; + TChannelSatInfo sat_info; + TChannelStateInfo state_info; + + memcpy((unsigned char *)&gps_channel_status,data,sizeof(TGPSChannelStatus)); + index+=sizeof(TGPSChannelStatus); + channel_status.gps_timestamp.wnc=gps_channel_status.timestamp.wnc; + channel_status.gps_timestamp.tow=gps_channel_status.timestamp.tow; + channel_status.local_timestamp=this->local_time.getTimeInSeconds(); + channel_status.info.clear(); + for(i=0;i<gps_channel_status.num_ch;i++) + { + memcpy((unsigned char *)&gps_sat_info,&data[index],sizeof(TGPSChannelSatInfo)); + index+=gps_channel_status.length_ch_sat_info; + sat_info.sat_id=gps_sat_info.sat_id; + sat_info.azimuth=gps_sat_info.azimuth_rise_set.azimuth; + sat_info.rise_set=(rise_set_t)gps_sat_info.azimuth_rise_set.rise_set; + sat_info.health=(health_t)gps_sat_info.health; + sat_info.elevation=gps_sat_info.elevation; + sat_info.state.clear(); + for(j=0;j<gps_sat_info.num_state_info;j++) + { + memcpy((unsigned char *)&gps_state_info,&data[index],sizeof(TGPSChannelStateInfo)); + index+=gps_channel_status.length_ch_state_info; + state_info.antenna_id=(antenna_t)gps_state_info.antenna; + state_info.track_status=(track_status_t)gps_state_info.tracking_status; + state_info.pvt_status=(pvt_status_t)gps_state_info.pvt_status; + sat_info.state.push_back(state_info); + } + } +} + +void CasteRx1::process_receiver_status(unsigned char *data,unsigned short int length) +{ + TGPSReceiverStatus gps_receiver_status; + unsigned short int index=0,i; + TGPSAGCData gps_agc_data; + TAGCData agc_data; + + memcpy((unsigned char *)&gps_receiver_status,data,sizeof(TGPSReceiverStatus)); + index+=sizeof(TGPSReceiverStatus); + this->receiver_status.gps_timestamp.wnc=gps_receiver_status.timestamp.wnc; + this->receiver_status.gps_timestamp.tow=gps_receiver_status.timestamp.tow; + this->receiver_status.local_timestamp=this->local_time.getTimeInSeconds(); + this->receiver_status.cpu_load=gps_receiver_status.cpu_load; + this->receiver_status.up_time=gps_receiver_status.up_time; + // state flags + this->receiver_status.state=*((int*)&gps_receiver_status.rx_state); + this->receiver_status.error=*((int*)&gps_receiver_status.rx_error); + this->receiver_status.agc.clear(); + for(i=0;i<gps_receiver_status.num_agc_states;i++) + { + memcpy((unsigned char *)&gps_agc_data,&data[index],sizeof(TGPSAGCData)); + index+=gps_receiver_status.length_agc_states; + agc_data.frontend_id=(frontend_t)gps_agc_data.frontend_id.code; + agc_data.antenna_id=(antenna_t)gps_agc_data.frontend_id.antenna_id; + agc_data.gain=gps_agc_data.gain; + agc_data.sample_var=gps_agc_data.sample_var; + agc_data.blanking_stat=gps_agc_data.blanking_stat; + this->receiver_status.agc.push_back(agc_data); + } +} + +void CasteRx1::process_sat_visibility(unsigned char *data,unsigned short int length) +{ + TGPSSatVisibility gps_sat_visibility; + unsigned short int index=0,i; + TGPSSatInfo gps_sat_info; + TSatInfo sat_info; + + memcpy((unsigned char *)&gps_sat_visibility,data,sizeof(TGPSSatVisibility)); + index+=sizeof(TGPSSatVisibility); + for(i=0;i<gps_sat_visibility.num_sat;i++) + { + memcpy((unsigned char *)&gps_sat_info,&data[index],sizeof(TGPSSatInfo)); + index+=gps_sat_visibility.length_sat; + sat_info.gps_timestamp.wnc=gps_sat_visibility.timestamp.wnc; + sat_info.gps_timestamp.tow=gps_sat_visibility.timestamp.tow; + sat_info.local_timestamp=this->local_time.getTimeInSeconds(); + sat_info.sat_id=gps_sat_info.sat_id; + sat_info.azimuth=gps_sat_info.azimuth*0.01; + sat_info.elevation=gps_sat_info.elevation*0.01; + sat_info.rise_set=(rise_set_t)gps_sat_info.rise_set; + sat_info.sat_info=(sat_info_t)gps_sat_info.sat_info; + } +} + +void CasteRx1::process_gps_nav(unsigned char *data,unsigned short int length) +{ + TGPSGPSNav gps_gps_nav; + + this->nav_access.enter(); + memcpy((unsigned char *)&gps_gps_nav,data,sizeof(TGPSGPSNav)); + this->current_gps_nav.gps_timestamp.wnc=gps_gps_nav.timestamp.wnc; + this->current_gps_nav.gps_timestamp.tow=gps_gps_nav.timestamp.tow; + this->current_gps_nav.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_gps_nav.sat_id=gps_gps_nav.prn; + this->current_gps_nav.wn=gps_gps_nav.wn; + this->current_gps_nav.ca_or_pon_l2=gps_gps_nav.ca_or_pon_l2; + this->current_gps_nav.ura=gps_gps_nav.ura; + this->current_gps_nav.health=gps_gps_nav.health; + this->current_gps_nav.l2_data_flag=gps_gps_nav.l2_data_flag; + this->current_gps_nav.iodc=gps_gps_nav.iodc; + this->current_gps_nav.iode2=gps_gps_nav.iode2; + this->current_gps_nav.iode3=gps_gps_nav.iode3; + this->current_gps_nav.fit_int_flag=gps_gps_nav.fit_int_flag; + this->current_gps_nav.t_gd=gps_gps_nav.t_gd; + this->current_gps_nav.t_oc=gps_gps_nav.t_oc; + this->current_gps_nav.a_f2=gps_gps_nav.a_f2; + this->current_gps_nav.a_f1=gps_gps_nav.a_f1; + this->current_gps_nav.a_f0=gps_gps_nav.a_f0; + this->current_gps_nav.c_rs=gps_gps_nav.c_rs; + this->current_gps_nav.delta_n=gps_gps_nav.delta_n; + this->current_gps_nav.m_0=gps_gps_nav.m_0; + this->current_gps_nav.c_uc=gps_gps_nav.c_uc; + this->current_gps_nav.e=gps_gps_nav.e; + this->current_gps_nav.c_us=gps_gps_nav.c_us; + this->current_gps_nav.sqrt_a=gps_gps_nav.sqrt_a; + this->current_gps_nav.t_oe=gps_gps_nav.t_oe; + this->current_gps_nav.c_ic=gps_gps_nav.c_ic; + this->current_gps_nav.omega_0=gps_gps_nav.omega_0; + this->current_gps_nav.c_is=gps_gps_nav.c_is; + this->current_gps_nav.i_0=gps_gps_nav.i_0; + this->current_gps_nav.c_rc=gps_gps_nav.c_rc; + this->current_gps_nav.omega=gps_gps_nav.omega; + this->current_gps_nav.omega_dot=gps_gps_nav.omega_dot; + this->current_gps_nav.i_dot=gps_gps_nav.i_dot; + this->current_gps_nav.wnt_oc=gps_gps_nav.wnt_oc; + this->current_gps_nav.wnt_oe=gps_gps_nav.wnt_oe; + if(!this->event_server->event_is_set(this->new_gps_nav_block_event_id)) + this->event_server->set_event(new_gps_nav_block_event_id); + this->nav_access.exit(); +} + +void CasteRx1::process_gps_alm(unsigned char *data,unsigned short int length) +{ + TGPSGPSAlm gps_gps_alm; + + this->nav_access.enter(); + memcpy((unsigned char *)&gps_gps_alm,data,sizeof(TGPSGPSAlm)); + this->current_gps_alm.gps_timestamp.wnc=gps_gps_alm.timestamp.wnc; + this->current_gps_alm.gps_timestamp.tow=gps_gps_alm.timestamp.tow; + this->current_gps_alm.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_gps_alm.sat_id=gps_gps_alm.prn; + this->current_gps_alm.e=gps_gps_alm.e; + this->current_gps_alm.t_oa=gps_gps_alm.t_oa; + this->current_gps_alm.delta_i=gps_gps_alm.delta_i; + this->current_gps_alm.omega_dot=gps_gps_alm.omega_dot; + this->current_gps_alm.sqrt_a=gps_gps_alm.sqrt_a; + this->current_gps_alm.omega_0=gps_gps_alm.omega_0; + this->current_gps_alm.omega=gps_gps_alm.omega; + this->current_gps_alm.m_0=gps_gps_alm.m_0; + this->current_gps_alm.a_f1=gps_gps_alm.a_f1; + this->current_gps_alm.a_f0=gps_gps_alm.a_f0; + this->current_gps_alm.wn_a=gps_gps_alm.wn_a; + this->current_gps_alm.as_config=gps_gps_alm.as_config; + this->current_gps_alm.health8=gps_gps_alm.health8; + this->current_gps_alm.health6=gps_gps_alm.health6; + if(!this->event_server->event_is_set(this->new_gps_alm_block_event_id)) + this->event_server->set_event(new_gps_alm_block_event_id); + this->nav_access.exit(); +} + +void CasteRx1::process_gps_ion(unsigned char *data,unsigned short int length) +{ + TGPSGPSIon gps_gps_ion; + + this->nav_access.enter(); + memcpy((unsigned char *)&gps_gps_ion,data,sizeof(TGPSGPSIon)); + this->current_gps_ion.gps_timestamp.wnc=gps_gps_ion.timestamp.wnc; + this->current_gps_ion.gps_timestamp.tow=gps_gps_ion.timestamp.tow; + this->current_gps_ion.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_gps_ion.sat_id=gps_gps_ion.prn; + this->current_gps_ion.alpha_0=gps_gps_ion.alpha_0; + this->current_gps_ion.alpha_1=gps_gps_ion.alpha_1; + this->current_gps_ion.alpha_2=gps_gps_ion.alpha_2; + this->current_gps_ion.alpha_3=gps_gps_ion.alpha_3; + this->current_gps_ion.beta_0=gps_gps_ion.beta_0; + this->current_gps_ion.beta_1=gps_gps_ion.beta_1; + this->current_gps_ion.beta_2=gps_gps_ion.beta_2; + this->current_gps_ion.beta_3=gps_gps_ion.beta_3; + if(!this->event_server->event_is_set(this->new_gps_ion_block_event_id)) + this->event_server->set_event(new_gps_ion_block_event_id); + this->nav_access.exit(); +} + +void CasteRx1::process_gps_utc(unsigned char *data,unsigned short int length) +{ + TGPSGPSUtc gps_gps_utc; + + this->nav_access.enter(); + memcpy((unsigned char *)&gps_gps_utc,data,sizeof(TGPSGPSUtc)); + this->current_gps_utc.gps_timestamp.wnc=gps_gps_utc.timestamp.wnc; + this->current_gps_utc.gps_timestamp.tow=gps_gps_utc.timestamp.tow; + this->current_gps_utc.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_gps_utc.sat_id=gps_gps_utc.prn; + this->current_gps_utc.a_1=gps_gps_utc.a_1; + this->current_gps_utc.a_0=gps_gps_utc.a_0; + this->current_gps_utc.t_ot=gps_gps_utc.t_ot; + this->current_gps_utc.wn_t=gps_gps_utc.wn_t; + this->current_gps_utc.del_t_ls=gps_gps_utc.del_t_ls; + this->current_gps_utc.wn_lsf=gps_gps_utc.wn_lsf; + this->current_gps_utc.dn=gps_gps_utc.dn; + this->current_gps_utc.del_t_lsf=gps_gps_utc.del_t_lsf; + if(!this->event_server->event_is_set(this->new_gps_utc_block_event_id)) + this->event_server->set_event(new_gps_utc_block_event_id); + this->nav_access.exit(); +} + +void CasteRx1::process_meas_epoch(unsigned char *data,unsigned short int length) +{ + TGPSMeasEpoch gps_meas_epoch; + TGPSMeasBlockType1 gps_meas_epoch_type1; + TGPSMeasBlockType2 gps_meas_epoch_type2; + unsigned short int index=0,i,j; + TMeasEpochType1 meas_epoch_type1; + TMeasEpochType2 meas_epoch_type2; + + this->meas_access.enter(); + memcpy((unsigned char *)&gps_meas_epoch,data,sizeof(TGPSMeasEpoch)); + index+=sizeof(TGPSMeasEpoch); + this->current_meas_epoch.gps_timestamp.wnc=gps_meas_epoch.timestamp.wnc; + this->current_meas_epoch.gps_timestamp.tow=gps_meas_epoch.timestamp.tow; + this->current_meas_epoch.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_meas_epoch.flags=gps_meas_epoch.common_flags; + this->current_meas_epoch.type1_data.clear(); + for(i=0;i<gps_meas_epoch.num_type1;i++) + { + memcpy((unsigned char *)&gps_meas_epoch_type1,&data[index],sizeof(TGPSMeasBlockType1)); + index+=gps_meas_epoch.length_type1; + meas_epoch_type1.rx_channel=gps_meas_epoch_type1.rx_channel; + meas_epoch_type1.signal_type=(signal_t)gps_meas_epoch_type1.type.master_signal_type; + meas_epoch_type1.antenna_id=(antenna_t)gps_meas_epoch_type1.type.antenna_id; + meas_epoch_type1.sat_id=gps_meas_epoch_type1.svid; + if(gps_meas_epoch_type1.code.msb==0 && gps_meas_epoch_type1.code.lsb==0)// the pseudo range is not valid + meas_epoch_type1.pseudo_range=0.0; + else + meas_epoch_type1.pseudo_range=((double)gps_meas_epoch_type1.code.msb)*4294967.296+((double)gps_meas_epoch_type1.code.lsb)/1000.0; + meas_epoch_type1.doppler=gps_meas_epoch_type1.doppler*0.0001; + if(gps_meas_epoch_type1.carrier.msb==-128 && gps_meas_epoch_type1.carrier.lsb==0)// the carrier phase is not valid + meas_epoch_type1.carrier_phase=0.0; + else + meas_epoch_type1.carrier_phase=((double)gps_meas_epoch_type1.carrier.msb)*65.536+((double)gps_meas_epoch_type1.carrier.lsb)/1000.0; + meas_epoch_type1.cn0=((double)gps_meas_epoch_type1.cn0)*0.25; + if(meas_epoch_type1.signal_type==GPS_L1_PY || meas_epoch_type1.signal_type==GPS_L2_PY) + meas_epoch_type1.cn0+=10; + meas_epoch_type1.lock_time=gps_meas_epoch_type1.lock_time; + if(gps_meas_epoch_type1.info.smoothed==1) + meas_epoch_type1.pseudorange_smoothed=true; + else + meas_epoch_type1.pseudorange_smoothed=false; + if(gps_meas_epoch_type1.info.smoothing_int_reached==1) + meas_epoch_type1.smoothing_int_reached=true; + else + meas_epoch_type1.smoothing_int_reached=false; + if(gps_meas_epoch_type1.info.phase_ambiguity==1) + meas_epoch_type1.half_cycle_ambiguity=true; + else + meas_epoch_type1.half_cycle_ambiguity=false; + meas_epoch_type1.type2_data.clear(); + for(j=0;j<gps_meas_epoch_type1.num_type2;j++) + { + memcpy((unsigned char *)&gps_meas_epoch_type2,&data[index],sizeof(TGPSMeasBlockType2)); + index+=gps_meas_epoch.length_type2; + meas_epoch_type2.signal_type=(signal_t)gps_meas_epoch_type2.type.master_signal_type; + meas_epoch_type2.antenna_id=(antenna_t)gps_meas_epoch_type2.type.antenna_id; + meas_epoch_type2.lock_time=gps_meas_epoch_type2.lock_time; + meas_epoch_type2.cn0=((double)gps_meas_epoch_type2.cn0)*0.25; + if(meas_epoch_type2.signal_type==GPS_L1_PY || meas_epoch_type2.signal_type==GPS_L2_PY) + meas_epoch_type2.cn0+=10; + if(gps_meas_epoch_type2.offsets_msb.code_offset_msb==-4 && gps_meas_epoch_type2.code_offset_lsb==0)// the pseudo range is not valid + meas_epoch_type2.pseudo_range=0.0; + else + meas_epoch_type2.pseudo_range=((double)gps_meas_epoch_type2.offsets_msb.code_offset_msb)*65.536+((double)gps_meas_epoch_type2.code_offset_lsb)/1000.0; + if(gps_meas_epoch_type2.offsets_msb.doppler_offset_msb==-128 && gps_meas_epoch_type2.doppler_offset_lsb==0)// the doppler is not valid + meas_epoch_type2.doppler=0.0; + else + meas_epoch_type2.doppler=((double)gps_meas_epoch_type2.offsets_msb.doppler_offset_msb)*6.5536+((double)gps_meas_epoch_type2.doppler_offset_lsb)/10000.0; + if(gps_meas_epoch_type2.carrier_msb==-16 && gps_meas_epoch_type2.carrier_lsb==0)// the carrier phase is not valid + meas_epoch_type2.carrier_phase=0.0; + else + meas_epoch_type2.carrier_phase=((double)gps_meas_epoch_type2.carrier_msb)*65.536+((double)gps_meas_epoch_type2.carrier_lsb)/1000.0; + if(gps_meas_epoch_type2.info.smoothed==1) + meas_epoch_type2.pseudorange_smoothed=true; + else + meas_epoch_type2.pseudorange_smoothed=false; + if(gps_meas_epoch_type2.info.smoothing_int_reached==1) + meas_epoch_type2.smoothing_int_reached=true; + else + meas_epoch_type2.smoothing_int_reached=false; + if(gps_meas_epoch_type2.info.phase_ambiguity==1) + meas_epoch_type2.half_cycle_ambiguity=true; + else + meas_epoch_type2.half_cycle_ambiguity=false; + meas_epoch_type1.type2_data.push_back(meas_epoch_type2); + } + this->current_meas_epoch.type1_data.push_back(meas_epoch_type1); } + this->meas_access.exit(); +} + +void CasteRx1::process_meas_extra(unsigned char *data,unsigned short int length) +{ + TGPSMeasExtra gps_meas_extra; + TGPSMeasExtraBlock gps_meas_extra_block; + unsigned short int index=0,i; + TMeasExtraBlock meas_extra_block; + + this->meas_access.enter(); + memcpy((unsigned char *)&gps_meas_extra,data,sizeof(TGPSMeasExtra)); + index+=sizeof(TGPSMeasExtra); + this->current_meas_extra.gps_timestamp.wnc=gps_meas_extra.timestamp.wnc; + this->current_meas_extra.gps_timestamp.tow=gps_meas_extra.timestamp.tow; + this->current_meas_extra.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_meas_extra.doppler_var_factor=gps_meas_extra.doppler_var_factor; + this->current_meas_extra.blocks.clear(); + for(i=0;i<gps_meas_extra.num_blocks;i++) + { + memcpy((unsigned char *)&gps_meas_extra_block,&data[index],sizeof(TGPSMeasExtraBlock)); + index+=gps_meas_extra.length_blocks; + meas_extra_block.rx_channel=gps_meas_extra_block.rx_channel; + meas_extra_block.signal_type=(signal_t)gps_meas_extra_block.type.master_signal_type; + meas_extra_block.antenna_id=(antenna_t)gps_meas_extra_block.type.antenna_id; + meas_extra_block.mp_correction=((double)gps_meas_extra_block.mp_correction)/1000.0; + meas_extra_block.smoothing_correction=((double)gps_meas_extra_block.smoothing_correction)/1000.0; + meas_extra_block.code_var=((double)gps_meas_extra_block.code_var)/10000.0; + meas_extra_block.carrier_var=gps_meas_extra_block.carrier_var; + meas_extra_block.lock_time=gps_meas_extra_block.lock_time; + meas_extra_block.cum_lost_cont=gps_meas_extra_block.cum_lost_cont; + this->current_meas_extra.blocks.push_back(meas_extra_block); + } + this->meas_access.exit(); +} + +void CasteRx1::process_end_of_meas(unsigned char *data,unsigned short int length) +{ + TGPSEndOfMeas gps_end_of_meas; + + memcpy((unsigned char *)&gps_end_of_meas,data,sizeof(TGPSEndOfMeas)); + if(!this->event_server->event_is_set(this->new_meas_block_event_id)) + this->event_server->set_event(new_meas_block_event_id); +} + +void CasteRx1::process_pvt_cartesian(unsigned char *data,unsigned short int length) +{ + TGPSPVTCartesian gps_pvt_cartesian; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_cartesian,data,sizeof(TGPSPVTCartesian)); + this->current_pvt_cartesian.gps_timestamp.wnc=gps_pvt_cartesian.timestamp.wnc; + this->current_pvt_cartesian.gps_timestamp.tow=gps_pvt_cartesian.timestamp.tow; + this->current_pvt_cartesian.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_cartesian.mode=(pvt_mode_t)gps_pvt_cartesian.mode.mode; + this->current_pvt_cartesian.solution=(solution_t)gps_pvt_cartesian.mode.solution_type; + this->current_pvt_cartesian.error=gps_pvt_cartesian.error; + this->current_pvt_cartesian.x=gps_pvt_cartesian.x; + this->current_pvt_cartesian.y=gps_pvt_cartesian.y; + this->current_pvt_cartesian.z=gps_pvt_cartesian.z; + this->current_pvt_cartesian.undulation=gps_pvt_cartesian.undulation; + this->current_pvt_cartesian.vx=gps_pvt_cartesian.vx; + this->current_pvt_cartesian.vy=gps_pvt_cartesian.vy; + this->current_pvt_cartesian.vz=gps_pvt_cartesian.vz; + this->current_pvt_cartesian.cog=gps_pvt_cartesian.cog; + this->current_pvt_cartesian.rx_clk_bias=gps_pvt_cartesian.rx_clk_bias; + this->current_pvt_cartesian.rx_clk_drift=gps_pvt_cartesian.rx_clk_drift; + this->current_pvt_cartesian.time_system=(sys_time_t)gps_pvt_cartesian.time_system; + this->current_pvt_cartesian.datum=(datum_t)gps_pvt_cartesian.datum; + this->current_pvt_cartesian.num_sat=gps_pvt_cartesian.num_sat; + this->current_pvt_cartesian.wa_corr_info=gps_pvt_cartesian.wa_corr_info; + if(gps_pvt_cartesian.corr_info.orbit_clock_corr==1) + this->current_pvt_cartesian.orbit_sat_clock_corr=true; + else + this->current_pvt_cartesian.orbit_sat_clock_corr=false; + if(gps_pvt_cartesian.corr_info.range_corr==1) + this->current_pvt_cartesian.range_corr_info=true; + else + this->current_pvt_cartesian.range_corr_info=false; + if(gps_pvt_cartesian.corr_info.ion_info==1) + this->current_pvt_cartesian.ion_info=true; + else + this->current_pvt_cartesian.ion_info=false; + if(gps_pvt_cartesian.corr_info.orbit_acc_info==1) + this->current_pvt_cartesian.orbit_accuracy_info=true; + else + this->current_pvt_cartesian.orbit_accuracy_info=false; + if(gps_pvt_cartesian.corr_info.do229_mode==1) + this->current_pvt_cartesian.DO299_used=true; + else + this->current_pvt_cartesian.DO299_used=false; + this->current_pvt_cartesian.reference_id=gps_pvt_cartesian.reference_id; + this->current_pvt_cartesian.mean_corr_age=gps_pvt_cartesian.mean_corr_age; + this->current_pvt_cartesian.signal_info=gps_pvt_cartesian.signal_info; + if(gps_pvt_cartesian.alert_flag.int_mon==1) + this->current_pvt_cartesian.integrity_mon=true; + else + this->current_pvt_cartesian.integrity_mon=false; + if(gps_pvt_cartesian.alert_flag.int_failed_raim==1) + this->current_pvt_cartesian.integrity_failed_RAIM=true; + else + this->current_pvt_cartesian.integrity_failed_RAIM=false; + if(gps_pvt_cartesian.alert_flag.int_failed_hpca==1) + this->current_pvt_cartesian.integrity_failed_HPCA=true; + else + this->current_pvt_cartesian.integrity_failed_HPCA=false; + this->pvt_access.exit(); +} + +void CasteRx1::process_pvt_geodetic(unsigned char *data,unsigned short int length) +{ + TGPSPVTGeodetic gps_pvt_geodetic; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_geodetic,data,sizeof(TGPSPVTGeodetic)); + this->current_pvt_geodetic.gps_timestamp.wnc=gps_pvt_geodetic.timestamp.wnc; + this->current_pvt_geodetic.gps_timestamp.tow=gps_pvt_geodetic.timestamp.tow; + this->current_pvt_geodetic.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_geodetic.mode=(pvt_mode_t)gps_pvt_geodetic.mode.mode; + this->current_pvt_geodetic.solution=(solution_t)gps_pvt_geodetic.mode.solution_type; + this->current_pvt_geodetic.error=gps_pvt_geodetic.error; + this->current_pvt_geodetic.latitude=gps_pvt_geodetic.latitude; + this->current_pvt_geodetic.longitude=gps_pvt_geodetic.longitude; + this->current_pvt_geodetic.h=gps_pvt_geodetic.h; + this->current_pvt_geodetic.undulation=gps_pvt_geodetic.undulation; + this->current_pvt_geodetic.vn=gps_pvt_geodetic.vn; + this->current_pvt_geodetic.ve=gps_pvt_geodetic.ve; + this->current_pvt_geodetic.vu=gps_pvt_geodetic.vu; + this->current_pvt_geodetic.cog=gps_pvt_geodetic.cog; + this->current_pvt_geodetic.rx_clk_bias=gps_pvt_geodetic.rx_clk_bias; + this->current_pvt_geodetic.rx_clk_drift=gps_pvt_geodetic.rx_clk_drift; + this->current_pvt_geodetic.time_system=(sys_time_t)gps_pvt_geodetic.time_system; + this->current_pvt_geodetic.datum=(datum_t)gps_pvt_geodetic.datum; + this->current_pvt_geodetic.num_sat=gps_pvt_geodetic.num_sat; + this->current_pvt_geodetic.wa_corr_info=gps_pvt_geodetic.wa_corr_info; + if(gps_pvt_geodetic.corr_info.orbit_clock_corr==1) + this->current_pvt_geodetic.orbit_sat_clock_corr=true; + else + this->current_pvt_geodetic.orbit_sat_clock_corr=false; + if(gps_pvt_geodetic.corr_info.range_corr==1) + this->current_pvt_geodetic.range_corr_info=true; + else + this->current_pvt_geodetic.range_corr_info=false; + if(gps_pvt_geodetic.corr_info.ion_info==1) + this->current_pvt_geodetic.ion_info=true; + else + this->current_pvt_geodetic.ion_info=false; + if(gps_pvt_geodetic.corr_info.orbit_acc_info==1) + this->current_pvt_geodetic.orbit_accuracy_info=true; + else + this->current_pvt_geodetic.orbit_accuracy_info=false; + if(gps_pvt_geodetic.corr_info.do229_mode==1) + this->current_pvt_geodetic.DO299_used=true; + else + this->current_pvt_geodetic.DO299_used=false; + this->current_pvt_geodetic.reference_id=gps_pvt_geodetic.reference_id; + this->current_pvt_geodetic.mean_corr_age=gps_pvt_geodetic.mean_corr_age; + this->current_pvt_geodetic.signal_info=gps_pvt_geodetic.signal_info; + if(gps_pvt_geodetic.alert_flag.int_mon==1) + this->current_pvt_geodetic.integrity_mon=true; + else + this->current_pvt_geodetic.integrity_mon=false; + if(gps_pvt_geodetic.alert_flag.int_failed_raim==1) + this->current_pvt_geodetic.integrity_failed_RAIM=true; + else + this->current_pvt_geodetic.integrity_failed_RAIM=false; + if(gps_pvt_geodetic.alert_flag.int_failed_hpca==1) + this->current_pvt_geodetic.integrity_failed_HPCA=true; + else + this->current_pvt_geodetic.integrity_failed_HPCA=false; + this->pvt_access.exit(); +} + +void CasteRx1::process_pos_cov_cartesian(unsigned char *data,unsigned short int length) +{ + TGPSPVTCov gps_pvt_pos_cov_cartesian; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_pos_cov_cartesian,data,sizeof(TGPSPVTCov)); + this->current_pvt_pos_cov_cartesian.gps_timestamp.wnc=gps_pvt_pos_cov_cartesian.timestamp.wnc; + this->current_pvt_pos_cov_cartesian.gps_timestamp.tow=gps_pvt_pos_cov_cartesian.timestamp.tow; + this->current_pvt_pos_cov_cartesian.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_pos_cov_cartesian.mode=(pvt_mode_t)gps_pvt_pos_cov_cartesian.mode.mode; + this->current_pvt_pos_cov_cartesian.solution=(solution_t)gps_pvt_pos_cov_cartesian.mode.solution_type; + this->current_pvt_pos_cov_cartesian.error=gps_pvt_pos_cov_cartesian.error; + this->current_pvt_pos_cov_cartesian.cov_00=gps_pvt_pos_cov_cartesian.cov_00; + this->current_pvt_pos_cov_cartesian.cov_11=gps_pvt_pos_cov_cartesian.cov_11; + this->current_pvt_pos_cov_cartesian.cov_22=gps_pvt_pos_cov_cartesian.cov_22; + this->current_pvt_pos_cov_cartesian.cov_33=gps_pvt_pos_cov_cartesian.cov_33; + this->current_pvt_pos_cov_cartesian.cov_01=gps_pvt_pos_cov_cartesian.cov_01; + this->current_pvt_pos_cov_cartesian.cov_02=gps_pvt_pos_cov_cartesian.cov_02; + this->current_pvt_pos_cov_cartesian.cov_03=gps_pvt_pos_cov_cartesian.cov_03; + this->current_pvt_pos_cov_cartesian.cov_12=gps_pvt_pos_cov_cartesian.cov_12; + this->current_pvt_pos_cov_cartesian.cov_13=gps_pvt_pos_cov_cartesian.cov_13; + this->current_pvt_pos_cov_cartesian.cov_23=gps_pvt_pos_cov_cartesian.cov_23; + this->pvt_access.exit(); +} + +void CasteRx1::process_pos_cov_geodetic(unsigned char *data,unsigned short int length) +{ + TGPSPVTCov gps_pvt_pos_cov_geodetic; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_pos_cov_geodetic,data,sizeof(TGPSPVTCov)); + this->current_pvt_pos_cov_geodetic.gps_timestamp.wnc=gps_pvt_pos_cov_geodetic.timestamp.wnc; + this->current_pvt_pos_cov_geodetic.gps_timestamp.tow=gps_pvt_pos_cov_geodetic.timestamp.tow; + this->current_pvt_pos_cov_geodetic.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_pos_cov_geodetic.mode=(pvt_mode_t)gps_pvt_pos_cov_geodetic.mode.mode; + this->current_pvt_pos_cov_geodetic.solution=(solution_t)gps_pvt_pos_cov_geodetic.mode.solution_type; + this->current_pvt_pos_cov_geodetic.error=gps_pvt_pos_cov_geodetic.error; + this->current_pvt_pos_cov_geodetic.cov_00=gps_pvt_pos_cov_geodetic.cov_00; + this->current_pvt_pos_cov_geodetic.cov_11=gps_pvt_pos_cov_geodetic.cov_11; + this->current_pvt_pos_cov_geodetic.cov_22=gps_pvt_pos_cov_geodetic.cov_22; + this->current_pvt_pos_cov_geodetic.cov_33=gps_pvt_pos_cov_geodetic.cov_33; + this->current_pvt_pos_cov_geodetic.cov_01=gps_pvt_pos_cov_geodetic.cov_01; + this->current_pvt_pos_cov_geodetic.cov_02=gps_pvt_pos_cov_geodetic.cov_02; + this->current_pvt_pos_cov_geodetic.cov_03=gps_pvt_pos_cov_geodetic.cov_03; + this->current_pvt_pos_cov_geodetic.cov_12=gps_pvt_pos_cov_geodetic.cov_12; + this->current_pvt_pos_cov_geodetic.cov_13=gps_pvt_pos_cov_geodetic.cov_13; + this->current_pvt_pos_cov_geodetic.cov_23=gps_pvt_pos_cov_geodetic.cov_23; + this->pvt_access.exit(); +} + +void CasteRx1::process_vel_cov_cartesian(unsigned char *data,unsigned short int length) +{ + TGPSPVTCov gps_pvt_vel_cov_cartesian; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_vel_cov_cartesian,data,sizeof(TGPSPVTCov)); + this->current_pvt_vel_cov_cartesian.gps_timestamp.wnc=gps_pvt_vel_cov_cartesian.timestamp.wnc; + this->current_pvt_vel_cov_cartesian.gps_timestamp.tow=gps_pvt_vel_cov_cartesian.timestamp.tow; + this->current_pvt_vel_cov_cartesian.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_vel_cov_cartesian.mode=(pvt_mode_t)gps_pvt_vel_cov_cartesian.mode.mode; + this->current_pvt_vel_cov_cartesian.solution=(solution_t)gps_pvt_vel_cov_cartesian.mode.solution_type; + this->current_pvt_vel_cov_cartesian.error=gps_pvt_vel_cov_cartesian.error; + this->current_pvt_vel_cov_cartesian.cov_00=gps_pvt_vel_cov_cartesian.cov_00; + this->current_pvt_vel_cov_cartesian.cov_11=gps_pvt_vel_cov_cartesian.cov_11; + this->current_pvt_vel_cov_cartesian.cov_22=gps_pvt_vel_cov_cartesian.cov_22; + this->current_pvt_vel_cov_cartesian.cov_33=gps_pvt_vel_cov_cartesian.cov_33; + this->current_pvt_vel_cov_cartesian.cov_01=gps_pvt_vel_cov_cartesian.cov_01; + this->current_pvt_vel_cov_cartesian.cov_02=gps_pvt_vel_cov_cartesian.cov_02; + this->current_pvt_vel_cov_cartesian.cov_03=gps_pvt_vel_cov_cartesian.cov_03; + this->current_pvt_vel_cov_cartesian.cov_12=gps_pvt_vel_cov_cartesian.cov_12; + this->current_pvt_vel_cov_cartesian.cov_13=gps_pvt_vel_cov_cartesian.cov_13; + this->current_pvt_vel_cov_cartesian.cov_23=gps_pvt_vel_cov_cartesian.cov_23; + this->pvt_access.exit(); +} + +void CasteRx1::process_vel_cov_geodetic(unsigned char *data,unsigned short int length) +{ + TGPSPVTCov gps_pvt_vel_cov_geodetic; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_vel_cov_geodetic,data,sizeof(TGPSPVTCov)); + this->current_pvt_vel_cov_geodetic.gps_timestamp.wnc=gps_pvt_vel_cov_geodetic.timestamp.wnc; + this->current_pvt_vel_cov_geodetic.gps_timestamp.tow=gps_pvt_vel_cov_geodetic.timestamp.tow; + this->current_pvt_vel_cov_geodetic.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_vel_cov_geodetic.mode=(pvt_mode_t)gps_pvt_vel_cov_geodetic.mode.mode; + this->current_pvt_vel_cov_geodetic.solution=(solution_t)gps_pvt_vel_cov_geodetic.mode.solution_type; + this->current_pvt_vel_cov_geodetic.error=gps_pvt_vel_cov_geodetic.error; + this->current_pvt_vel_cov_geodetic.cov_00=gps_pvt_vel_cov_geodetic.cov_00; + this->current_pvt_vel_cov_geodetic.cov_11=gps_pvt_vel_cov_geodetic.cov_11; + this->current_pvt_vel_cov_geodetic.cov_22=gps_pvt_vel_cov_geodetic.cov_22; + this->current_pvt_vel_cov_geodetic.cov_33=gps_pvt_vel_cov_geodetic.cov_33; + this->current_pvt_vel_cov_geodetic.cov_01=gps_pvt_vel_cov_geodetic.cov_01; + this->current_pvt_vel_cov_geodetic.cov_02=gps_pvt_vel_cov_geodetic.cov_02; + this->current_pvt_vel_cov_geodetic.cov_03=gps_pvt_vel_cov_geodetic.cov_03; + this->current_pvt_vel_cov_geodetic.cov_12=gps_pvt_vel_cov_geodetic.cov_12; + this->current_pvt_vel_cov_geodetic.cov_13=gps_pvt_vel_cov_geodetic.cov_13; + this->current_pvt_vel_cov_geodetic.cov_23=gps_pvt_vel_cov_geodetic.cov_23; + this->pvt_access.exit(); +} + +void CasteRx1::process_dop(unsigned char *data,unsigned short int length) +{ + TGPSPVTDOP gps_pvt_dop; + + this->pvt_access.enter(); + memcpy((unsigned char *)&gps_pvt_dop,data,sizeof(TGPSPVTDOP)); + this->current_pvt_dop.gps_timestamp.wnc=gps_pvt_dop.timestamp.wnc; + this->current_pvt_dop.gps_timestamp.tow=gps_pvt_dop.timestamp.tow; + this->current_pvt_dop.local_timestamp=this->local_time.getTimeInSeconds(); + this->current_pvt_dop.num_sat=gps_pvt_dop.num_sat; + this->current_pvt_dop.p_dop=gps_pvt_dop.p_dop; + this->current_pvt_dop.t_dop=gps_pvt_dop.t_dop; + this->current_pvt_dop.t_dop=gps_pvt_dop.h_dop; + this->current_pvt_dop.v_dop=gps_pvt_dop.v_dop; + this->current_pvt_dop.hpl=gps_pvt_dop.hpl; + this->current_pvt_dop.vpl=gps_pvt_dop.vpl; + this->pvt_access.exit(); +} + +void CasteRx1::process_end_of_pvt(unsigned char *data,unsigned short int length) +{ + TGPSEndOfPVT gps_end_of_pvt; + + memcpy((unsigned char *)&gps_end_of_pvt,data,sizeof(TGPSEndOfMeas)); + if(!this->event_server->event_is_set(this->new_pvt_block_event_id)) + this->event_server->set_event(new_pvt_block_event_id); +} + +unsigned short int CasteRx1::compute_crc(unsigned char *data,unsigned short int length) +{ + unsigned short int crc=0; + unsigned int i=0; + + // compute the crc from part of the header + for(i=0;i<4;i++) + crc=(crc<<8)^CRC_16CCIT_LookUp[(crc>>8)^((unsigned char *)&this->current_header)[i+4]]; + // compute the crc from the data + for(i=0;i<length;i++) + crc=(crc<<8)^CRC_16CCIT_LookUp[(crc>>8)^data[i]]; return crc; } -void CasteRx1::computeTM() -{ - double kk; //constant - double xx0,yy0,zz0; //wgs-ecef coordinates of the origin - double auxTM[4][4]; - - //sets the rotation part of TM, from ECEF to ENU coordinates - auxTM[0][0] = -sin(lon0); - auxTM[0][1] = cos(lon0); - auxTM[0][2] = 0.0; - auxTM[1][0] = -sin(lat0)*cos(lon0); - auxTM[1][1] = -sin(lat0)*sin(lon0); - auxTM[1][2] = cos(lat0); - auxTM[2][0] = cos(lat0)*cos(lon0); - auxTM[2][1] = cos(lat0)*sin(lon0); - auxTM[2][2] = sin(lat0); - - //computes final alignement of x with respect to the campus baseline as a rotation of alpha0 on z axis - //Ra=[cos(alpha0) sin(alpha0) 0; - // -sin(alpha0) cos(alpha0) 0; - // 0 0 1]; - TM[0][0]=cos(alpha0)*auxTM[0][0] + sin(alpha0)*auxTM[1][0]; - TM[0][1]=cos(alpha0)*auxTM[0][1] + sin(alpha0)*auxTM[1][1]; - TM[0][2]=cos(alpha0)*auxTM[0][2] + sin(alpha0)*auxTM[1][2]; - TM[1][0]=-sin(alpha0)*auxTM[0][0] + cos(alpha0)*auxTM[1][0]; - TM[1][1]=-sin(alpha0)*auxTM[0][1] + cos(alpha0)*auxTM[1][1]; - TM[1][2]=-sin(alpha0)*auxTM[0][2] + cos(alpha0)*auxTM[1][2]; - TM[2][0]=auxTM[2][0]; - TM[2][1]=auxTM[2][1]; - TM[2][2]=auxTM[2][2]; - - //computes the translation part - kk = EARTH_RADIUS/sqrt(1-(pow(EARTH_EXCENTRICITY*sin(lat0),2.0))); - xx0 = (kk + alt0) * cos(lat0) * cos(lon0); - yy0 = (kk + alt0) * cos(lat0) * sin(lon0); - zz0 = ((1-EARTH_EXCENTRICITY*EARTH_EXCENTRICITY)* kk + alt0) * sin(lat0); - TM[0][3] = - ( TM[0][0]*xx0 + TM[0][1]*yy0 + TM[0][2]*zz0 ); - TM[1][3] = - ( TM[1][0]*xx0 + TM[1][1]*yy0 + TM[1][2]*zz0 ); - TM[2][3] = - ( TM[2][0]*xx0 + TM[2][1]*yy0 + TM[2][2]*zz0 ); - TM[3][0] = 0.0; - TM[3][1] = 0.0; - TM[3][2] = 0.0; - TM[3][3] = 1.0; -} - -void CasteRx1::computeTMenu() -{ - //uses current position to compute ENU rotation - TMenu[0][0] = -sin(lon); - TMenu[0][1] = cos(lon); - TMenu[0][2] = 0.0; - TMenu[1][0] = -sin(lat)*cos(lon); - TMenu[1][1] = -sin(lat)*sin(lon); - TMenu[1][2] = cos(lat); - TMenu[2][0] = cos(lat)*cos(lon); - TMenu[2][1] = cos(lat)*sin(lon); - TMenu[2][2] = sin(lat); -} - -void CasteRx1::fromWgsToMap() -{ - double auxM[3][3]; - int ii; - - //compute map coords - xMap=TM[0][0]*xWgs+TM[0][1]*yWgs+TM[0][2]*zWgs+TM[0][3]; - yMap=TM[1][0]*xWgs+TM[1][1]*yWgs+TM[1][2]*zWgs+TM[1][3]; - zMap=TM[2][0]*xWgs+TM[2][1]*yWgs+TM[2][2]*zWgs+TM[2][3]; - - //compute velocities - vxMap=TM[0][0]*vxWgs+TM[0][1]*vyWgs+TM[0][2]*vzWgs; - vyMap=TM[1][0]*vxWgs+TM[1][1]*vyWgs+TM[1][2]*vzWgs; - vzMap=TM[2][0]*vxWgs+TM[2][1]*vyWgs+TM[2][2]*vzWgs; - - //compute covariance matrix - //firts step: auxM=TM*covEcef - for(ii=0;ii<3;ii++) - { - auxM[ii][0]=TM[ii][0]*cxxWgs+TM[ii][1]*cxyWgs+TM[ii][2]*cxzWgs; - auxM[ii][1]=TM[ii][0]*cxyWgs+TM[ii][1]*cyyWgs+TM[ii][2]*cyzWgs; - auxM[ii][2]=TM[ii][0]*cxzWgs+TM[ii][1]*cyzWgs+TM[ii][2]*czzWgs; - } - //second step: covMap = auxM*TM^T - cxxMap=auxM[0][0]*TM[0][0]+auxM[0][1]*TM[0][1]+auxM[0][2]*TM[0][2]; - cyyMap=auxM[1][0]*TM[1][0]+auxM[1][1]*TM[1][1]+auxM[1][2]*TM[1][2]; - czzMap=auxM[2][0]*TM[2][0]+auxM[2][1]*TM[2][1]+auxM[2][2]*TM[2][2]; - cxyMap=auxM[0][0]*TM[1][0]+auxM[0][1]*TM[1][1]+auxM[0][2]*TM[1][2]; -} - -void CasteRx1::computeENUcovs() -{ - double auxM[3][3]; - int ii; - - //compute covariance matrix - //firts step: auxM=TMenu*covEcef - for(ii=0;ii<3;ii++) - { - auxM[ii][0]=TMenu[ii][0]*cxxWgs+TMenu[ii][1]*cxyWgs+TMenu[ii][2]*cxzWgs; - auxM[ii][1]=TMenu[ii][0]*cxyWgs+TMenu[ii][1]*cyyWgs+TMenu[ii][2]*cyzWgs; - auxM[ii][2]=TMenu[ii][0]*cxzWgs+TMenu[ii][1]*cyzWgs+TMenu[ii][2]*czzWgs; - } - //second step: covMap = auxM*TMenu^T - cxxEnu=auxM[0][0]*TMenu[0][0]+auxM[0][1]*TMenu[0][1]+auxM[0][2]*TMenu[0][2]; - cyyEnu=auxM[1][0]*TMenu[1][0]+auxM[1][1]*TMenu[1][1]+auxM[1][2]*TMenu[1][2]; - czzEnu=auxM[2][0]*TMenu[2][0]+auxM[2][1]*TMenu[2][1]+auxM[2][2]*TMenu[2][2]; - cxyEnu=auxM[0][0]*TMenu[1][0]+auxM[0][1]*TMenu[1][1]+auxM[0][2]*TMenu[1][2]; - cxzEnu=auxM[0][0]*TMenu[2][0]+auxM[0][1]*TMenu[2][1]+auxM[0][2]*TMenu[2][2]; - cyzEnu=auxM[1][0]*TMenu[2][0]+auxM[1][1]*TMenu[2][1]+auxM[1][2]*TMenu[2][2]; -} - -void CasteRx1::markBlockAsReceived(unsigned short int id) -{ - list<sbfBlockManager>::iterator iiBlock; - - for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++) - { - if ( iiBlock->blockId == id ) iiBlock->received = true; - } +void CasteRx1::sendCommand(const std::string &cmd) +{ + std::list<std::string> events; + std::string reply; + + //relax if we concatenate commands. (200 ms were suggested by Septentrio support team in a personal communication). 50ms tested and it seems it is not enough!!! + usleep(100000); + + events.push_back(this->new_reply_event_id); + try{ + this->serialPort->write((unsigned char *)cmd.c_str(),cmd.size()); + this->event_server->wait_all(events,500); + // compare the answer with the command + reply=this->reply_queue.front();// get the reply + this->reply_queue.pop();// remove it from the queue + if(reply.find("Invalid command!")!=std::string::npos) + { + /* handle invalid command */ + std::cout << "Invalid Command" << std::endl; + } + else if(reply.find(cmd.c_str(),0,cmd.size()-1)==std::string::npos) + { + /* handle unexpected answer */ + std::cout << "Unexpected answer" << std::endl; + } + else + std::cout << "Command ok" << std::endl; + }catch(CEventTimeoutException &e){ + // no answer in the allowed time + std::cout << e.what() << std::endl; + } +} + +void CasteRx1::configureStreams(void) +{ + // stop any incomming data + this->sendCommand("setSBFOutput,all,USB1,none\n"); + //enables septentrio binary format (SBF) as output at USB1 + this->sendCommand("setDataInOut,USB1,CMD,SBF\n"); + // create group 1 blocks (PVTCartesian,PosCovCartesian,DOP,PVTGeodetic) + this->sendCommand("setSBFGroups,Group1,PVTCartesian+PosCovCartesian+VelCovCartesian+DOP+PVTGeodetic+PosCovGeodetic+VelCovGeodetic+EndOfPVT\n"); + // create group 2 blocks (GPSNav,GPSAlm,GPSIon,GPSUtc) + this->sendCommand("setSBFGroups,Group2,GPSNav+GPSAlm+GPSIon+GPSUtc\n"); + // create group 3 blocks (MeasEpoch,MeasExtra,EndOfMeas) + this->sendCommand("setSBFGroups,Group3,MeasEpoch+MeasExtra+EndOfMeas\n"); + // create group 4 blocks (ChannelStatus,ReceiverStatus,SatVisivility) + this->sendCommand("setSBFGroups,Group4,ChannelStatus+ReceiverStatus+SatVisibility\n"); } + diff --git a/src/asterx1_gps.h b/src/asterx1_gps.h index bfd759b39fb6ef63b239859a17f9973a1622be17..0dde8715073093870e827abb0380ebfd8317359e 100644 --- a/src/asterx1_gps.h +++ b/src/asterx1_gps.h @@ -1,75 +1,24 @@ - #ifndef asterx1_gps_h #define asterx1_gps_h //include #include <iostream> #include <list> +#include <vector> +#include <queue> #include <math.h> +#include <time.h> +#include <sys/time.h> +#include <stdint.h> #include "rs232.h" #include "eventserver.h" +#include "threadserver.h" #include "commexceptions.h" #include "eventexceptions.h" -#include <time.h> -#include <sys/time.h> - -using namespace std; +#include "gps_types.h" +#include "ctime.h" -/* Look up table for fast computation of the CCITT 16-bit CRC. */ -static const unsigned short CRC_16CCIT_LookUp[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -union uniFloat { - float flt; - unsigned int i; -}; - -union uniDouble { - double dbl; - unsigned long long int i; -}; - -struct sbfBlockManager { - unsigned short int blockId; - bool received; -}; - -struct asterx1DeviceConfig { - string portName; //serial port system name - string acqPeriod; //string indicating acquisition period. Takes one of the values of the vector "acqPeriodValues" -}; +typedef enum {header1,header2,get_cmd_reply,get_block_header,get_sbf_data} gps_state_t; //physical constants const double EARTH_RADIUS = 6378137.0; @@ -79,45 +28,28 @@ const double EARTH_EXCENTRICITY = 0.0818191908426220; const unsigned short int PVTCartesian_ID = 4006; const unsigned short int PVTGeodetic_ID = 4007; const unsigned short int PosCovCartesian_ID = 5905; +const unsigned short int PosCovGeodetic_ID = 5906; +const unsigned short int VelCovCartesian_ID = 5907; +const unsigned short int VelCovGeodetic_ID = 5908; const unsigned short int DOP_ID = 4001; +const unsigned short int EndOfPVT_ID = 5921; +const unsigned short int MeasEpoch_ID = 4027; +const unsigned short int MeasExtra_ID = 4000; +const unsigned short int EndOfMeas_ID = 5922; +const unsigned short int GPSNav_ID = 5891; +const unsigned short int GPSAlm_ID = 5892; +const unsigned short int GPSIon_ID = 5893; +const unsigned short int GPSUtc_ID = 5894; +const unsigned short int ReceiverStatus_ID = 4014; +const unsigned short int ChannelStatus_ID = 4013; +const unsigned short int SatVisibility_ID = 4012; //acquisition constants -const unsigned int ASTERX_BAUDRATE = 115200; const int DATA_TIMEOUT = 11000; //msec const int CONFIG_TIMEOUT = 500; //msec -const string acqPeriodValues[] = {"onChange","msec20","msec50","msec100","msec200","msec500","sec1","sec2","sec5","sec10"}; -enum acqPeriodValuesIndex {ONCHANGE = 0, MSEC20, MSEC50, MSEC100, MSEC200, MSEC500, SEC1, SEC2, SEC5, SEC10}; //data sizes const unsigned int BLOCK_HEADER_SIZE = 8; -const unsigned int MIN_BLOCK_SIZE = BLOCK_HEADER_SIZE +1; -const unsigned int MAX_BLOCK_SIZE = 200; - -/** - Member functions that returns an integer associated to success or not, should return one of these values -*/ -const int BASIC_SUCCESS = 1; -const int PORT_OPEN_ERROR = -1; -const int PORT_CLOSE_ERROR = -2; -const int PORT_CONFIG_ERROR = -3; -const int ASTERX1_CONFIG_ERROR = -4; -const int ASTERX1_INVALID_COMMAND = -5; -const int ASTERX1_STOPPINTG_ERROR = -6; -const int PORT_READ_TIMEOUT = -7; -const int ACQUISITION_ERROR = -8; - -/** - Status of a class object is a bitwise OR of different values. The given bit is set when positive cases, and reset if negative significance. -*/ -const unsigned int DEVICE_OPEN = 0x1; -const unsigned int ACQUISITION_RUNNING = 0x2; -const unsigned int DATA_BLOCK_OK = 0x4; -const unsigned int GPS_AVAILABLE = 0x8; -const unsigned int ALL_OK = DEVICE_OPEN | ACQUISITION_RUNNING | DATA_BLOCK_OK | GPS_AVAILABLE; - -//unit identifiers -const bool inRADS = 0; -const bool inDEGREES = 1; /** CasteRx1 implements continuous data acquisition from the asteRx1 GPS receiver. @@ -125,286 +57,279 @@ const bool inDEGREES = 1; Detailed documentation about SBF data transfer protocol can be found in the device manual. PLEASE NOTE: This driver only implements a part of the AsteRx1 device functionalities (the most useful part for mobile robot navigation). PLEASE NOTE: For extended functionalities , please refer to the manual. - Programmer: Andreu Corominas Murtra, acorominas@iri.upc.edu - Device website: www.septentrio.com -*/ +Programmer: Andreu Corominas Murtra, acorominas@iri.upc.edu +Device website: www.septentrio.com + */ class CasteRx1 { - public: - /** \brief Default constructor - * - * Constructor. Requires port file name and, optionally, acquisition rate. - * - */ - CasteRx1(const string & hwPortName = "/dev/ttyACM0", const int acqRate = MSEC500); - - /** \brief Destructor - * - * Destructor: Stops acquisition in case it was running and closes serial Port in case it was opened. - * - */ - virtual ~CasteRx1(); - - /** \brief Open and configure serial device. - * - * Open and configure serial device to 8N1 Byte transmission. - * Launches a thread for serial in/out comms - * Return values are: - * BASIC_SUCCESS - * PORT_OPEN_ERROR if thread can't be created or port can't be opened - * PORT_CONFIG_ERROR if port can't be configured - */ - int openDevice(); - - /** \brief Closes serial comm - * - * Closes serial comm's , stops comm thread and deletes comm object. - * If success , resets status bit DEVICE_OPEN. - * Return values are: - * BASIC_SUCCESS - * PORT_CLOSE_ERROR - */ - int closeDevice(); - - /** \brief Starts basic data acquisition - * - * Configures the device to perform some signal processing basics for mobile robotics. - * Starts a mode of operation of continuos data flow from the device at a rate of 2Hz. - * Return values are: - * BASIC_SUCCESS - * ASTERX1_CONFIG_ERROR - */ - int startAcquisition(); - - /** \brief Stops acquisition - * - * Stops continuous acquisition mode - * Return values are: - * BASIC_SUCCESS when device stop is ok - * ASTERX1_STOPPINTG_ERROR otherwise. - */ - int stopAcquisition(); - - /** \brief Decodes the device SBF stream - * - * Reads current data produced by the device. Ends when all data blocks requested have been received. - * Sets status and all data fields. - * Return values are: - * BASIC_SUCCESS if all blocks are successfully decodes. - * ACQUISITION_ERROR otherwise. - * - * After calling this function, call getStatus() to check for gps availability. - */ - int readDataFromDevice(); - - /** - Prints all current data in a single row of the given ostream (cout or file) - */ - void printData(ostream & ost); - - /** - Sets map origin and computes transformation matrix. - Angles in degrees and altitude in meters. - A call to this function is mandatory if local coordinate related position is required. - */ - void setMapOrigin(double mapLat0, double mapLon0, double mapAlt0, double mapAlpha0); - - /** - Sets serial port name - */ - void setPortName(string pName); - - /** - Sets acquisition rate as on of the rateId indicated by the acqPeriodValuesIndex enum variable - */ - void setAcquisitionRate(int rateIndex); - - /** - Prints the homogeneous transformation matrix used to convert data from ECEF-WGS to local map. - */ - void printTM(); - - /** - Get data ... - TimeStamp is set by the computer running the driver. - Tow is the GPS "time of week". - PVTerror codes are explained in the device manual, pag XX. - Lat and Lon are expressed in radians by default. Pass "inDEGREES" if degree values are required. - *Wgs is data with respect to the ECEF-WGS coordinate frame. - *Map is data with respect to the local (map) coordinate frame. - */ - unsigned int getStatus(); - double getTimeStamp(); - unsigned short int getWnc(); - unsigned int getTow(); - unsigned int getNumSatellites(); - float getPDOP(); - float getTDOP(); - float getHDOP(); - float getVDOP(); - float getUndulation(); - unsigned short int getPVTerror(); - double getLat(bool units=inRADS); - double getLon(bool units=inRADS); - double getAlt(); - double getXWgs(); - double getYWgs(); - double getZWgs(); - double getXMap(); - double getYMap(); - double getZMap(); - double getVxWgs(); - double getVyWgs(); - double getVzWgs(); - double getVxMap(); - double getVyMap(); - double getVzMap(); - double getCxxWgs(); - double getCyyWgs(); - double getCzzWgs(); - double getCxyWgs(); - double getCxxMap(); - double getCyyMap(); - double getCzzMap(); - double getCxyMap(); - double getCxxEnu(); - double getCyyEnu(); - double getCzzEnu(); - double getCxyEnu(); - double getCxzEnu(); - double getCyzEnu(); - - protected: - CRS232 *serialPort; /**<Object for serial comms. This object launch an independent thread managing byte I/O through serial port (USB or RS232)*/ - asterx1DeviceConfig config; /**<Devices configuration. Currently a single string with serial port name*/ + public: + /** \brief Default constructor + * + * Constructor. Requires port file name and, optionally, acquisition rate. + * + */ + CasteRx1(const std::string &name,const std::string &hwPortName = "/dev/ttyACM0"); + /** \brief Destructor + * + * Destructor: Stops acquisition in case it was running and closes serial Port in case it was opened. + * + */ + virtual ~CasteRx1(); + /** \brief Open and configure serial device. + * + * Open and configure serial device to 8N1 Byte transmission. + * Launches a thread for serial in/out comms + */ + void openDevice(); + /** \brief Closes serial comm + * + * Closes serial comm's , stops comm thread and deletes comm object. + * If success , resets status bit DEVICE_OPEN. + */ + void closeDevice(); + /** \brief Starts basic data acquisition + * + * Configures the device to perform some signal processing basics for mobile robotics. + * Starts a mode of operation of continuos data flow from the device at a rate of 2Hz. + */ + void startAcquisition(); + /** \brief Stops acquisition + * + * Stops continuous acquisition mode + */ + void stopAcquisition(); + /** + * \brief + * + */ + std::string get_new_meas_data_event_id(void); + /** + * \brief + * + */ + void get_meas_data(TMeasEpoch &meas_epoch, TMeasExtra &meas_extra); + /** + * \brief + * + */ + std::string get_new_gps_nav_data_event_id(void); + /** + * \brief + * + */ + void get_gps_nav_data(TGPSNav &gps_nav); + /** + * \brief + * + */ + std::string get_new_gps_alm_data_event_id(void); + /** + * \brief + * + */ + void get_gps_alm_data(TGPSAlm &gps_alm); + /** + * \brief + * + */ + std::string get_new_gps_ion_data_event_id(void); + /** + * \brief + * + */ + void get_gps_ion_data(TGPSIon &gps_ion); + /** + * \brief + * + */ + std::string get_new_gps_utc_data_event_id(void); + /** + * \brief + * + */ + void get_gps_utc_data(TGPSUtc &gps_utc); + /** + * \brief + * + */ + std::string get_new_pvt_data_event_id(void); + /** + * \brief + * + */ + void get_pvt_data(TPVTCartesian &pvt_cart,TPVTGeodetic &pvt_geo); + /** + * \brief + * + */ + void get_pvt_cov_data(TPVTCov &pvt_pos_cov_cart,TPVTCov &pvt_pos_cov_geo,TPVTCov &pvt_vel_cov_cart,TPVTCov &pvt_vel_cov_geo); + /** + * \brief + * + */ + void get_pvt_dop_data(TPVTDOP &pvt_dop); + private: + CRS232 *serialPort; /**<Object for serial comms. This object launch an independent thread managing byte I/O through serial port (USB or RS232)*/ + std::string serial_device; + /* internal queue for command replies */ + std::queue<std::string> reply_queue; + /* event server and events */ + CEventServer *event_server; + std::string finish_thread_event_id; + std::string new_reply_event_id; + /* thread server and threads */ + CThreadServer *thread_server; + std::string gps_process_data_thread_id; + bool gps_running; + CTime local_time; - //variables for device operation and configuration - unsigned int status;/**<Status related to the execution of this process*/ - list<sbfBlockManager> blockList; /**<this list manages which data blocks are requested and has been (or not) received in the current iteration*/ - double lat0, lon0, alt0, alpha0; /**<coordinates of the map origin. Alpha is the orientation of the north vector wrt the map X axis*/ - double TM[4][4]; /**homogeneous transformation matrix to convert from ecef-wgs84 to map coordinates*/ - double TMenu[3][3]; /**Rotation transformation matrix to convert from ecef-wgs84 to local tangential ENU (east north up) coordinates. Useful to output covariances following current ENU axis*/ - - //GPS data to be published - double timeStamp; /**<time stamp set by the computer executing the process (not GPS time)*/ - unsigned short int wnc; /**<gps week number*/ - unsigned int tow; /**<gps time of week in milliseconds*/ - unsigned int numSatellites; /**<number of visible satellites*/ - double PDOP, TDOP, HDOP, VDOP; /**<Dillution of precsion DOP's*/ - double undulation; /**<local geoid undulation between Datum ellipsoide and reference geoide*/ - unsigned short int pvtError; /**<error codes related to GPS position computation. (see page 50 of Firmware User Manual)*/ - double lat, lon, alt; /**<position in geodetic frame*/ - double xWgs, yWgs, zWgs; /**<position in WGS frame*/ - double xMap, yMap, zMap; /**<position in Map frame, a given reference frame*/ - double vxWgs,vyWgs,vzWgs; /**<velocities referred to WGS*/ - double vxMap, vyMap, vzMap; /**<velocities in Map frame, a given reference frame*/ - double cxxWgs,cyyWgs,czzWgs,cxyWgs,cxzWgs,cyzWgs; /**<covariance parameters of WGS position*/ - double cxxMap, cyyMap, czzMap, cxyMap; /**<covariance parameters in Map frame, a given reference frame*/ - double cxxEnu,cyyEnu,czzEnu,cxyEnu,cxzEnu,cyzEnu; /**<covariance parameters in the local tangential plane of the current position following the East North Up axis*/ + /* header of the message currently being received */ + TGPSBlockHeader current_header; + TReceiverStatus receiver_status; + + /* Meas blocks attributes */ + CMutex meas_access; + std::string new_meas_block_event_id; + TMeasEpoch current_meas_epoch; + TMeasExtra current_meas_extra; - /** - Reads nn bytes from the serial communication. If there are no bytes available, this function blocks up to timeout is reached. - Success when ALL bytes have been received, it returns BASIC_SUCCESS - If timeout, it returns PORT_READ_TIMEOUT. - */ - int readNbytes(unsigned char *buffer, unsigned int nn, unsigned int msecTimeOut); - - /** - Synchronizes data reading with a given header mark. (markSixe in bytes). - Return values are: - BASIC_SUCCESS if success: the mark is found at the ffdd file descriptor input - PORT_READ_TIMEOUT if timeout is reached and the mark is not found - */ - int synchronizeHeader(const unsigned char *mark, int msecTimeOut=1000, unsigned int markSize=2); - - /** - Sends a command to the AsteRx1 device. - Return values are : - BASIC_SUCCESS if device has acknowledged the command. - PORT_READ_TIMEOUT if timeout is reached and the receiver has not replied with an acknowledment. - ASTERX1_INVALID_COMMAND when device doesn't know the command. - ASTERX1_CONFIG_ERROR otherwise. - */ - int sendCommand(const string & cmnd); - - /** - Returns 1 byte integer in buffer (little-endian reading) - */ - unsigned short int getUI1(unsigned char *buf); + /* GPS naviagtion blocks attributes */ + CMutex nav_access; + std::string new_gps_nav_block_event_id; + TGPSNav current_gps_nav; + std::string new_gps_alm_block_event_id; + TGPSAlm current_gps_alm; + std::string new_gps_ion_block_event_id; + TGPSIon current_gps_ion; + std::string new_gps_utc_block_event_id; + TGPSUtc current_gps_utc; - /** - Returns 2 bytes integer in buffer (little-endian reading) - */ - unsigned short int getUI2(unsigned char *buf); - - /** - Returns 4 bytes integer in buffer (little-endian reading) - */ - unsigned int getUI4(unsigned char *buf); - - /** - Returns 4 byte float in buffer (little-endian reading) - */ - float getFloat(unsigned char *buf); - - /** - Returns 8 byte float in buffer (little-endian reading) - */ - double getDouble(unsigned char *buf); + /* PVT blocks attributes */ + CMutex pvt_access; + std::string new_pvt_block_event_id; + TPVTCartesian current_pvt_cartesian; + TPVTGeodetic current_pvt_geodetic; + TPVTCov current_pvt_pos_cov_cartesian; + TPVTCov current_pvt_vel_cov_cartesian; + TPVTCov current_pvt_pos_cov_geodetic; + TPVTCov current_pvt_vel_cov_geodetic; + TPVTDOP current_pvt_dop; + protected: + /** + * \brief + * + */ + static void *gps_process_data_thread(void *param); + /** + * \brief + * + */ + void process_block(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_channel_status(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_receiver_status(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_sat_visibility(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_gps_nav(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_gps_alm(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_gps_ion(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_gps_utc(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_meas_epoch(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_meas_extra(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_end_of_meas(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_pvt_cartesian(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_pos_cov_cartesian(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_pos_cov_geodetic(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_vel_cov_cartesian(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_vel_cov_geodetic(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_pvt_geodetic(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_dop(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void process_end_of_pvt(unsigned char *data,unsigned short int length); + /** + * \brief + * + */ + void configureStreams(void); + /** + * \brief + * + */ + void sendCommand(const std::string &cmnd); - /** - Decodes PVTCartesian data block. Implementation of the SBF data transfer protocol. - */ - int decodePVTCartesian(unsigned char *sbfMsg); - - /** - Decodes PVTGeodetic data block. Implementation of the SBF data transfer protocol. - */ - int decodePVTGeodetic(unsigned char *sbfMsg); - - /** - Decodes PosCovCartesian data block. Implementation of the SBF data transfer protocol. - */ - int decodePosCovCartesian(unsigned char *sbfMsg); - - /** - Decodes DOP data block. Implementation of the SBF data transfer protocol. - */ - int decodeDOP(unsigned char *sbfMsg); - - /** - computes the crc-ccitt of buf with polynomic 0x1021 - */ - //unsigned short int computeCrc(unsigned char *buf, unsigned short int nBytes); - //unsigned short int CRC_compute16CCITT(const void * buf, size_t buf_length); - unsigned short int CRC_compute16CCITT(unsigned char *buf, unsigned short int nBytes); - - /** - Computes the matrix to transform positions from ECEF-WGS to a local coordinate frame. - Local coordinate frame origin should be set by public function setMapOrigin(). - */ - void computeTM(); - - /** - Computes the matrix to transform positions from ECEF-WGS to the local tangential plane of the current position folloing the East North Up (ENU) axis - This matris is useful to output a covariance matrix of the WGS position following the ENU local tangential coordinates - */ - void computeTMenu(); - - /** - Transforms ECEF-WGS positions, velocities and covariances to local coordinate frame. - Local coordinate frame origin shouold be set by public function setMapOrigin(). - */ - void fromWgsToMap(); - - /** - Computes covariance elements of the position referenced to the ENU axis of the current local tangential plane - */ - void computeENUcovs(); - - /** - Sets to true the received field of the member in blockList that have blockId = id - */ - void markBlockAsReceived(unsigned short int id); + /** + computes the crc-ccitt of buf with polynomic 0x1021 + */ + unsigned short int compute_crc(unsigned char *data,unsigned short int length); }; + #endif diff --git a/src/examples/testasterx1.cpp b/src/examples/testasterx1.cpp index 0ef7afd7dab8a5f1fa0a8c619a7f9e605579acc8..a64735ddd6b0a862ff32a31a909c0be80dff3765 100644 --- a/src/examples/testasterx1.cpp +++ b/src/examples/testasterx1.cpp @@ -16,119 +16,179 @@ USB any port */ #include <stdlib.h> -#include <asterx1_gps.h> - -using namespace std; +#include "asterx1_gps.h" +#include "stream_gps.h" int main(int argc, char **argv) { - int opt; - int ii; - int retValue; - int nIterations = 10; - int rate = MSEC500; //ONCHANGE, MSEC20, ... , MSEC100, ... SEC1, SEC5 - string serial_device="/dev/ttyACM0"; - streamsize tsDigits; - CasteRx1 *myGps; + CasteRx1 myGps("gps","/dev/ttyACM0"); + CEventServer *event_server=CEventServer::instance(); + std::list<std::string> events; + unsigned int i=0,index; + TMeasEpoch meas_epoch; + TMeasExtra meas_extra; + TGPSNav gps_nav; + TGPSAlm gps_alm; + TGPSIon gps_ion; + TGPSUtc gps_utc; + TPVTCartesian pvt_cartesian; + TPVTGeodetic pvt_geodetic; + TPVTCov pvt_pos_cov_cartesian; + TPVTCov pvt_vel_cov_cartesian; + TPVTCov pvt_pos_cov_geodetic; + TPVTCov pvt_vel_cov_geodetic; + TPVTDOP pvt_dop; + + std::cout << "\n\n TEST AsteRx1 GPS RECEIVER \n\n" << std::endl; - cout << "\n\n TEST AsteRx1 GPS RECEIVER \n\n" << endl; + try{ + myGps.openDevice(); + events.push_back(myGps.get_new_meas_data_event_id()); + events.push_back(myGps.get_new_gps_nav_data_event_id()); + events.push_back(myGps.get_new_gps_alm_data_event_id()); + events.push_back(myGps.get_new_gps_ion_data_event_id()); + events.push_back(myGps.get_new_gps_utc_data_event_id()); + events.push_back(myGps.get_new_pvt_data_event_id()); + myGps.startAcquisition(); + //for(i=0;i<100;i++) + for(;;) + { + index=event_server->wait_first(events,10000); + if(index==0) + { + myGps.get_meas_data(meas_epoch,meas_extra); +// std::cout << meas_epoch << std::endl; +// std::cout << meas_extra << std::endl; + } + else if(index==1) + { + myGps.get_gps_nav_data(gps_nav); + std::cout << gps_nav << std::endl; + } + else if(index==2) + { + myGps.get_gps_alm_data(gps_alm); + std::cout << gps_alm << std::endl; + } + else if(index==3) + { + myGps.get_gps_ion_data(gps_ion); + std::cout << gps_ion << std::endl; + } + else if(index==4) + { + myGps.get_gps_utc_data(gps_utc); + std::cout << gps_utc << std::endl; + } + else if(index==5) + { + std::cout << "GPS PVT" << std::endl; + myGps.get_pvt_data(pvt_cartesian,pvt_geodetic); + myGps.get_pvt_cov_data(pvt_pos_cov_cartesian,pvt_pos_cov_geodetic,pvt_vel_cov_cartesian,pvt_vel_cov_geodetic); + myGps.get_pvt_dop_data(pvt_dop); + } + } + myGps.stopAcquisition(); + }catch(CException &e){ + std::cout << e.what() << std::endl; + } - //cout << "acqPeriodValues[ONCHANGE]: " << acqPeriodValues[ONCHANGE] << endl; - - // Argument management - while ((opt = getopt(argc, argv, "u:n:r:h?"))!= -1) + //cout << "acqPeriodValues[ONCHANGE]: " << acqPeriodValues[ONCHANGE] << endl; + + // Argument management +/* while ((opt = getopt(argc, argv, "u:n:r:h?"))!= -1) + { + switch (opt) + { + case 'u': // change USB device + serial_device = optarg; + break; + case 'n': + nIterations = atoi(optarg); + break; + case 'r': + rate = atoi(optarg); + break; + case '?': // help + case 'h': + default: + cout << " USAGE" << endl + << " " << argv[0] << " [options]" << endl + << " OPTIONS" << endl + << " -u SERIAL_DEVICE (default: " << serial_device << ")" << endl + << " -n NUMBER OF ITERATIONS (default: " << nIterations << ")" << endl + << " -r ACQUISITION RATE: (default: " << rate << ")" << endl; + for (ii=0; ii<10; ii++) { - switch (opt) - { - case 'u': // change USB device - serial_device = optarg; - break; - case 'n': - nIterations = atoi(optarg); - break; - case 'r': - rate = atoi(optarg); - break; - case '?': // help - case 'h': - default: - cout << " USAGE" << endl - << " " << argv[0] << " [options]" << endl - << " OPTIONS" << endl - << " -u SERIAL_DEVICE (default: " << serial_device << ")" << endl - << " -n NUMBER OF ITERATIONS (default: " << nIterations << ")" << endl - << " -r ACQUISITION RATE: (default: " << rate << ")" << endl; - for (ii=0; ii<10; ii++) - { - cout << " " << ii << ": " << acqPeriodValues[ii] << endl; - } - cout << endl; - return 1; - } + cout << " " << ii << ": " << acqPeriodValues[ii] << endl; } - - myGps = new CasteRx1(serial_device,rate); - - myGps->setMapOrigin(41.388595, 2.113133, 120, 44.2); //sets map origin for coordinate transformation - //myGps->printTM(); //prints to stdout the transformation matrix - - retValue = myGps->openDevice();//open device comm's - - retValue = myGps->closeDevice();//close device comm's (stressing tests ...) - retValue = myGps->openDevice();//open device comm's, again - - myGps->setPortName("/dev/ttyS1"); //checking that when device is open, port configuration can't be achieved - myGps->setAcquisitionRate(56); //checking that when invalid rate indexes prdouces an error and don't change the rate - myGps->setAcquisitionRate(SEC2); //checking that when device is open rate configuration can be achieved - myGps->setAcquisitionRate(rate); //checking that when device is open rate configuration can be achieved - - if ( retValue == BASIC_SUCCESS ) + cout << endl; + return 1; + } + } + + myGps = new CasteRx1(serial_device,rate); + + myGps->setMapOrigin(41.388595, 2.113133, 120, 44.2); //sets map origin for coordinate transformation + //myGps->printTM(); //prints to stdout the transformation matrix + + retValue = myGps->openDevice();//open device comm's + + retValue = myGps->closeDevice();//close device comm's (stressing tests ...) + retValue = myGps->openDevice();//open device comm's, again + + myGps->setPortName("/dev/ttyS1"); //checking that when device is open, port configuration can't be achieved + myGps->setAcquisitionRate(56); //checking that when invalid rate indexes prdouces an error and don't change the rate + myGps->setAcquisitionRate(SEC2); //checking that when device is open rate configuration can be achieved + myGps->setAcquisitionRate(rate); //checking that when device is open rate configuration can be achieved + + if ( retValue == BASIC_SUCCESS ) + { + retValue = myGps->startAcquisition();//start data acquisition + retValue = myGps->stopAcquisition();//stop data acquisition (stressing tests ...) + retValue = myGps->startAcquisition();//start data acquisition, again + if ( retValue == BASIC_SUCCESS ) + { + for (ii=0; ii<nIterations; ii++) + { + cout << endl; + myGps->readDataFromDevice(); + //myGps->printData(cout); //prints to cout all current data in a single row. (cout can be repolaced by another ostream object reference) + cout << "Status = " << myGps->getStatus() << endl; + tsDigits=cout.precision(12); + cout << "TimeStamp = " << myGps->getTimeStamp() << endl; + cout.precision(tsDigits); + cout << "PVT error = " << myGps->getPVTerror() << endl; + cout << "TOW = " << myGps->getTow() << endl; + + if ( myGps->getStatus() == ALL_OK ) { - retValue = myGps->startAcquisition();//start data acquisition - retValue = myGps->stopAcquisition();//stop data acquisition (stressing tests ...) - retValue = myGps->startAcquisition();//start data acquisition, again - if ( retValue == BASIC_SUCCESS ) - { - for (ii=0; ii<nIterations; ii++) - { - cout << endl; - myGps->readDataFromDevice(); - //myGps->printData(cout); //prints to cout all current data in a single row. (cout can be repolaced by another ostream object reference) - cout << "Status = " << myGps->getStatus() << endl; - tsDigits=cout.precision(12); - cout << "TimeStamp = " << myGps->getTimeStamp() << endl; - cout.precision(tsDigits); - cout << "PVT error = " << myGps->getPVTerror() << endl; - cout << "TOW = " << myGps->getTow() << endl; - - if ( myGps->getStatus() == ALL_OK ) - { - cout << "Num Of Satellites = " << myGps->getNumSatellites() << endl; - tsDigits=cout.precision(12); - cout << "lat = " << myGps->getLat(inDEGREES) << endl; - cout << "lon = " << myGps->getLon(inDEGREES) << endl; - cout.precision(tsDigits); - cout << "alt = " << myGps->getAlt() << endl; - cout << "xWgs = " << myGps->getXWgs() << endl; - cout << "yWgs = " << myGps->getYWgs() << endl; - cout << "zWgs = " << myGps->getZWgs() << endl; - cout << "xMap = " << myGps->getXMap() << endl; - cout << "yMap = " << myGps->getYMap() << endl; - cout << "zMap = " << myGps->getZMap() << endl; - cout << "vxMap = " << myGps->getVxMap() << endl; - cout << "vyMap = " << myGps->getVyMap() << endl; - cout << "vzMap = " << myGps->getVzMap() << endl; - cout << "PDOP = " << myGps->getPDOP() << endl; - } - } - - retValue = myGps->stopAcquisition(); - } - - retValue = myGps->closeDevice(); + cout << "Num Of Satellites = " << myGps->getNumSatellites() << endl; + tsDigits=cout.precision(12); + cout << "lat = " << myGps->getLat(inDEGREES) << endl; + cout << "lon = " << myGps->getLon(inDEGREES) << endl; + cout.precision(tsDigits); + cout << "alt = " << myGps->getAlt() << endl; + cout << "xWgs = " << myGps->getXWgs() << endl; + cout << "yWgs = " << myGps->getYWgs() << endl; + cout << "zWgs = " << myGps->getZWgs() << endl; + cout << "xMap = " << myGps->getXMap() << endl; + cout << "yMap = " << myGps->getYMap() << endl; + cout << "zMap = " << myGps->getZMap() << endl; + cout << "vxMap = " << myGps->getVxMap() << endl; + cout << "vyMap = " << myGps->getVyMap() << endl; + cout << "vzMap = " << myGps->getVzMap() << endl; + cout << "PDOP = " << myGps->getPDOP() << endl; } + } + + retValue = myGps->stopAcquisition(); + } + + retValue = myGps->closeDevice(); + } + + delete myGps;*/ - delete myGps; - - return 0; + return 0; } diff --git a/src/gps_types.h b/src/gps_types.h new file mode 100644 index 0000000000000000000000000000000000000000..cd5ec73fd315e3e2287e02574187a472ab025229 --- /dev/null +++ b/src/gps_types.h @@ -0,0 +1,870 @@ +#ifndef _GPS_TYPES_H +#define _GPS_TYPES_H + +// global satellite information +typedef struct{ + unsigned int tow; + unsigned short int wnc; +}TBlockTimeStamp; + +// User data structures +typedef enum {elev_setting=0,elev_rising=1,elev_unknown=3} rise_set_t; + +typedef enum {health_unknown=0, healthy=1, unhealthy=3} health_t; + +typedef enum {track_idle=0, track_search=1, track_sync=2, tracking=3} track_status_t; + +typedef enum {pvt_not_used=0, pvt_waiting=1,pvt_used=2, pvt_rejected=3} pvt_status_t; + +typedef enum {main_antenna=0,aux1_antenna=1,aux2_antenna=2} antenna_t; + +typedef struct { + antenna_t antenna_id; + track_status_t track_status; + pvt_status_t pvt_status; +}TChannelStateInfo; + +typedef struct { + int sat_id; + unsigned int azimuth; + rise_set_t rise_set; + health_t health; + int elevation; + std::vector<TChannelStateInfo> state; +}TChannelSatInfo; + +typedef struct { + TBlockTimeStamp gps_timestamp; + double local_timestamp; + std::vector<TChannelSatInfo> info; +}TChannelStatus; + +typedef enum {gps_sbas_galileo_l1=0,glonass_l1=1,galileo_e6=2,gps_l2=3,glonass_l2=4,gps_sbas_galileo_l5_e5a=5,galileo_e5b=6,galileo_e5a_b=7} frontend_t; + +enum {vbat_ok=0x00000001, + antenna_connected=0x00000001, + ext_ref=0x00000002, + pps_in=0x00000004, + wn_set=0x00000008, + tow_set=0x00000010, + fine_time=0x00000020, + disk_activity=0x00000040, + disk_full=0x00000080, + disk_mounted=0x00000100}; + +enum {nvram=0x00000001, + baseband=0x00000002, + rtc=0x00000004, + software=0x00000008, + watchdog=0x00000010, + antenna_ok=0x00000020, + congestion=0x00000040, + sis_error=0x00000080, + missed_event=0x00000100, + cpu_overload=0x00000200, + invalid_config=0x00000400}; + +typedef struct { + frontend_t frontend_id; + antenna_t antenna_id; + int gain; + int sample_var; + int blanking_stat; +}TAGCData; + +typedef struct { + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int cpu_load; + unsigned int up_time; + unsigned int state; + unsigned int error; + std::vector<TAGCData> agc; +}TReceiverStatus; + +typedef enum {almanac=1, ephemeris=2, unkown_info=255} sat_info_t; + +typedef struct { + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int sat_id; + double azimuth; + double elevation; + rise_set_t rise_set; + sat_info_t sat_info; +}TSatInfo; + +typedef enum {GPS_L1_CA=0,GPS_L1_PY=1,GPS_L2_PY=2,GPS_L2C=3,GPS_L5=4,GLO_L1_CA=8,GLO_L1_P=9,GLO_L2_P=10,GLO_L2_CA=11,GAL_L1A=16, + GAL_L1BC=17,GAL_E6B=18,GAL_E6BC=19,GAL_E5a=20,GAL_E5b=21,GAL_E5=22,GEO_L1CA=24} signal_t; + +const std::string signal_type_name[] = {"GPS_L1_CA (1575.42 MHz)", + "GPS_L1_P(Y) (1575.42 MHz)", + "GPS_L2_P(Y) (1227.60 MHz)", + "GPS_L2C (1227.60 MHz)", + "GPS_L5 (1176.45 MHz)", + "", + "", + "", + "GLO_L1_CA", + "GLO_L1_P", + "GLO_L2_P", + "GLO_L1_CA", + "", + "", + "", + "", + "GAL_L1A (1575.42 MHz)", + "GAL_L1BC (1575.42 MHz)", + "GAL_E6A (1278.75 MHz)", + "GAL_E6BC (1278.75 MHz)", + "GAL_E5a (1176.45 MHz)", + "GAL_E5b (1207.14 MHz)", + "GAL_E5 (1191.795 MHz)", + "", + "GEO_L1CA (1575.42 MHz)"}; + +typedef struct{ + signal_t signal_type; + antenna_t antenna_id; + unsigned int lock_time; + double cn0; + double pseudo_range; + double doppler; + double carrier_phase; + bool pseudorange_smoothed; + bool smoothing_int_reached; + bool half_cycle_ambiguity; +}TMeasEpochType2; + +typedef struct{ + unsigned int rx_channel; + signal_t signal_type; + antenna_t antenna_id; + unsigned int sat_id; + double pseudo_range; + double doppler; + double carrier_phase; + double cn0; + unsigned int lock_time; + bool pseudorange_smoothed; + bool smoothing_int_reached; + bool half_cycle_ambiguity; + std::vector<TMeasEpochType2> type2_data; +}TMeasEpochType1; + +enum {multipath_mitigation=0x01,smoothing_of_code=0x02}; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int flags; + std::vector<TMeasEpochType1> type1_data; +}TMeasEpoch; + +typedef struct{ + unsigned int rx_channel; + signal_t signal_type; + antenna_t antenna_id; + int mp_correction; + int smoothing_correction; + unsigned int code_var; + unsigned int carrier_var; + unsigned int lock_time; + unsigned int cum_lost_cont; +}TMeasExtraBlock; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + float doppler_var_factor; + std::vector<TMeasExtraBlock> blocks; +}TMeasExtra; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int sat_id; + int wn; + unsigned int ca_or_pon_l2; + unsigned int ura; + unsigned int health; + unsigned int l2_data_flag; + unsigned int iodc; + unsigned int iode2; + unsigned int iode3; + unsigned int fit_int_flag; + double t_gd; + unsigned int t_oc; + double a_f2; + double a_f1; + double a_f0; + double c_rs; + double delta_n; + double m_0; + double c_uc; + double e; + double c_us; + double sqrt_a; + unsigned int t_oe; + double c_ic; + double omega_0; + double c_is; + double i_0; + double c_rc; + double omega; + double omega_dot; + double i_dot; + unsigned int wnt_oc; + unsigned int wnt_oe; +}TGPSNav; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int sat_id; + double e; + unsigned int t_oa; + double delta_i; + double omega_dot; + double sqrt_a; + double omega_0; + double omega; + double m_0; + double a_f1; + double a_f0; + unsigned int wn_a; + unsigned int as_config; + unsigned int health8; + unsigned int health6; +}TGPSAlm; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int sat_id; + double alpha_0; + double alpha_1; + double alpha_2; + double alpha_3; + double beta_0; + double beta_1; + double beta_2; + double beta_3; +}TGPSIon; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int sat_id; + double a_1; + double a_0; + unsigned int t_ot; + unsigned int wn_t; + int del_t_ls; + unsigned int wn_lsf; + unsigned int dn; + int del_t_lsf; +}TGPSUtc; + +typedef enum {no_pvt=0,stand_alone_pvt=1,diff_pvt=2,fixed_loc=3,rtk_fixed_amb=4,rtk_float_amb=5,sbas_pvt=6} pvt_mode_t; + +typedef enum {pvt_3d=0,pvt_2d=1} solution_t; + +enum {no_error=0,not_enough_meas=1,not_enough_eph=2,dop_too_large=3,res_too_large=4,no_conv=5,not_enough_meas_outliers=6,export_laws=7,not_enough_diff_corr=8,no_base_coord=9}; + +typedef enum {gps_time=0,galileo_time=1} sys_time_t; + +typedef enum {wgs_84=0,galileo=1,pz_90_02=2,user_datum1=250,user_datum2=251} datum_t; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + pvt_mode_t mode; + solution_t solution; + unsigned int error; + double x; + double y; + double z; + double undulation; + double vx; + double vy; + double vz; + double cog; + double rx_clk_bias; + double rx_clk_drift; + sys_time_t time_system; + datum_t datum; + unsigned int num_sat; + unsigned int wa_corr_info; + bool orbit_sat_clock_corr; + bool range_corr_info; + bool ion_info; + bool orbit_accuracy_info; + bool DO299_used; + unsigned int reference_id; + unsigned int mean_corr_age; + unsigned int signal_info; + bool integrity_mon; + bool integrity_failed_RAIM; + bool integrity_failed_HPCA; +}TPVTCartesian; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + pvt_mode_t mode; + solution_t solution; + unsigned int error; + double latitude; + double longitude; + double h; + double undulation; + double vn; + double ve; + double vu; + double cog; + double rx_clk_bias; + double rx_clk_drift; + sys_time_t time_system; + datum_t datum; + unsigned int num_sat; + unsigned int wa_corr_info; + bool orbit_sat_clock_corr; + bool range_corr_info; + bool ion_info; + bool orbit_accuracy_info; + bool DO299_used; + unsigned int reference_id; + unsigned int mean_corr_age; + unsigned int signal_info; + bool integrity_mon; + bool integrity_failed_RAIM; + bool integrity_failed_HPCA; +}TPVTGeodetic; + +typedef struct{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + pvt_mode_t mode; + solution_t solution; + unsigned int error; + double cov_00; + double cov_11; + double cov_22; + double cov_33; + double cov_01; + double cov_02; + double cov_03; + double cov_12; + double cov_13; + double cov_23; +}TPVTCov; + +typedef struct +{ + TBlockTimeStamp gps_timestamp; + double local_timestamp; + unsigned int num_sat; + unsigned int p_dop; + unsigned int t_dop; + unsigned int h_dop; + unsigned int v_dop; + double hpl; + double vpl; +}TPVTDOP; + +// these precompiler commands force the byte aligment in memory of the data structures +//#pragma pack (push, 1) +//#pragma pack (pop) + +// block ID structure +#pragma pack (push, 1) +typedef struct{ + uint16_t id:13; + uint16_t rev:3; +}TGPSBlockId; +#pragma pack (pop) + +// header structure +#pragma pack (push, 1) +typedef struct{ + uint8_t sync[2]; + uint16_t crc; + TGPSBlockId id; + uint16_t length; +}TGPSBlockHeader; +#pragma pack (pop) + +// block time stamp structure +#pragma pack (push, 1) +typedef struct{ + uint32_t tow; + uint16_t wnc; +}TGPSBlockTimeStamp; +#pragma pack (pop) + +// Measure Epoch structure +#pragma pack (push, 1) +typedef struct{ + uint8_t master_signal_type:5; + uint8_t antenna_id:3; +}TGPSMeasBlockType; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t smoothed:1; + uint8_t smoothing_int_reached:1; + uint8_t phase_ambiguity:1; + uint8_t freq_nr:5; +}TGPSMeasBlockObsInfo; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t code_offset_msb:3; + uint8_t doppler_offset_msb:5; +}TGPSMeasBlockType2Offsets; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSMeasBlockType type; + uint8_t lock_time; + uint8_t cn0; + TGPSMeasBlockType2Offsets offsets_msb; + int8_t carrier_msb; + TGPSMeasBlockObsInfo info; + uint16_t code_offset_lsb; + uint16_t carrier_lsb; + uint16_t doppler_offset_lsb; +}TGPSMeasBlockType2; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t msb:4; + uint8_t reserved:4; + uint32_t lsb; +}TGPSMeasBlockType1Code; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint16_t lsb; + int8_t msb; +}TGPSMeasBlockType1Carrier; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t rx_channel; + TGPSMeasBlockType type; + uint8_t svid; + TGPSMeasBlockType1Code code; + int32_t doppler; + TGPSMeasBlockType1Carrier carrier; + uint8_t cn0; + uint16_t lock_time; + TGPSMeasBlockObsInfo info; + uint8_t num_type2; +}TGPSMeasBlockType1; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t num_type1; + uint8_t length_type1; + uint8_t length_type2; + uint8_t common_flags; + uint8_t reserved[2]; +}TGPSMeasEpoch; +#pragma pack (pop) + +// Measurement extra structure +#pragma pack (push, 1) +typedef struct{ + uint8_t rx_channel; + TGPSMeasBlockType type; + int16_t mp_correction; + int16_t smoothing_correction; + uint16_t code_var; + uint16_t carrier_var; + uint16_t lock_time; + uint8_t cum_lost_cont; + uint8_t reserved[3]; +}TGPSMeasExtraBlock; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t num_blocks; + uint8_t length_blocks; + float doppler_var_factor; +}TGPSMeasExtra; +#pragma pack (pop) + +// measurement end structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; +}TGPSEndOfMeas; +#pragma pack (pop) + +// GPS NAV structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t prn; + uint8_t reserved1; + int16_t wn; + uint8_t ca_or_pon_l2; + uint8_t ura; + uint8_t health; + uint8_t l2_data_flag; + uint16_t iodc; + uint8_t iode2; + uint8_t iode3; + uint8_t fit_int_flag; + uint8_t reserved2; + float t_gd; + uint32_t t_oc; + float a_f2; + float a_f1; + float a_f0; + float c_rs; + float delta_n; + double m_0; + float c_uc; + double e; + float c_us; + double sqrt_a; + uint32_t t_oe; + float c_ic; + double omega_0; + float c_is; + double i_0; + float c_rc; + double omega; + float omega_dot; + float i_dot; + uint16_t wnt_oc; + uint16_t wnt_oe; +}TGPSGPSNav; +#pragma pack (pop) + +// APG Alm structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t prn; + uint8_t reserved1; + float e; + uint32_t t_oa; + float delta_i; + float omega_dot; + float sqrt_a; + float omega_0; + float omega; + float m_0; + float a_f1; + float a_f0; + uint8_t wn_a; + uint8_t as_config; + uint8_t health8; + uint8_t health6; +}TGPSGPSAlm; +#pragma pack (pop) + +// GPS Ion structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t prn; + uint8_t reserved1; + float alpha_0; + float alpha_1; + float alpha_2; + float alpha_3; + float beta_0; + float beta_1; + float beta_2; + float beta_3; +}TGPSGPSIon; +#pragma pack (pop) + +// GPs UTC structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t prn; + uint8_t reserved1; + float a_1; + double a_0; + uint32_t t_ot; + uint8_t wn_t; + int8_t del_t_ls; + uint8_t wn_lsf; + uint8_t dn; + int8_t del_t_lsf; +}TGPSGPSUtc; +#pragma pack (pop) + +// Position, velocity and time Cartesian structure +#pragma pack (push, 1) +typedef struct{ + uint8_t mode:4; + uint8_t reserved:3; + uint8_t solution_type:1; +}TGPSPVTMode; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t orbit_clock_corr:1; + uint8_t range_corr:1; + uint8_t ion_info:1; + uint8_t orbit_acc_info:1; + uint8_t do229_mode:1; + uint8_t reserver:3; +}TGPSPVTInfo; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t int_mon:1; + uint8_t int_failed_raim:1; + uint8_t int_failed_hpca:1; + uint8_t galileo_storm_flag:1; + uint8_t reserved:4; +}TGPSPVTAlert; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + TGPSPVTMode mode; + uint8_t error; + double x; + double y; + double z; + float undulation; + float vx; + float vy; + float vz; + float cog; + double rx_clk_bias; + float rx_clk_drift; + uint8_t time_system; + uint8_t datum; + uint8_t num_sat; + uint8_t wa_corr_info; + TGPSPVTInfo corr_info; + uint16_t reference_id; + uint16_t mean_corr_age; + uint32_t signal_info; + TGPSPVTAlert alert_flag; + uint8_t reserved[3]; +}TGPSPVTCartesian; +#pragma pack (pop) + +// Position, velocity and time Geodetic structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + TGPSPVTMode mode; + uint8_t error; + double latitude; + double longitude; + double h; + float undulation; + float vn; + float ve; + float vu; + float cog; + double rx_clk_bias; + float rx_clk_drift; + uint8_t time_system; + uint8_t datum; + uint8_t num_sat; + uint8_t wa_corr_info; + TGPSPVTInfo corr_info; + uint16_t reference_id; + uint16_t mean_corr_age; + uint32_t signal_info; + TGPSPVTAlert alert_flag; + uint8_t reserved[3]; +}TGPSPVTGeodetic; +#pragma pack (pop) + +// Position, velocity and time Covariance Cartesian structure +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + TGPSPVTMode mode; + uint8_t error; + float cov_00; + float cov_11; + float cov_22; + float cov_33; + float cov_01; + float cov_02; + float cov_03; + float cov_12; + float cov_13; + float cov_23; +}TGPSPVTCov; +#pragma pack (pop) + +// Position, velocity and time DOP structure +#pragma pack (push, 1) +typedef struct +{ + TGPSBlockTimeStamp timestamp; + uint8_t num_sat; + uint8_t reserved; + uint16_t p_dop; + uint16_t t_dop; + uint16_t h_dop; + uint16_t v_dop; + float hpl; + float vpl; +}TGPSPVTDOP; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; +}TGPSEndOfPVT; +#pragma pack (pop) + +// channel status structure +#pragma pack (push, 1) +typedef struct{ + uint8_t antenna; + uint8_t reserved; + uint16_t tracking_status; + uint16_t pvt_status; + uint16_t pvy_info; +}TGPSChannelStateInfo; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint16_t azimuth:9; + uint16_t reserved:5; + uint16_t rise_set:2; +}TGPSAzimuthRiseSet; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t sat_id; + uint8_t freq_nr; + uint16_t reserved1; + TGPSAzimuthRiseSet azimuth_rise_set; + uint16_t health; + int8_t elevation; + uint8_t num_state_info; + uint8_t rx_channel; + uint8_t reserved2; +}TGPSChannelSatInfo; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t num_ch; + uint8_t length_ch_sat_info; + uint8_t length_ch_state_info; + uint8_t reserved[3]; +}TGPSChannelStatus; +#pragma pack (pop) + +// Receiver status structure +#pragma pack (push, 1) +typedef struct{ + uint32_t vbat_ok:1; + uint32_t antenna_connected:1; + uint32_t ext_ref:1; + uint32_t pps_in:1; + uint32_t wn_set:1; + uint32_t tow_set:1; + uint32_t fine_time:1; + uint32_t disk_activity:1; + uint32_t disk_full:1; + uint32_t disk_mounted:1; + uint32_t reserved:22; +}TGPSReceiverStatusRxState; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint32_t nvram:1; + uint32_t baseband:1; + uint32_t rtc:1; + uint32_t software:1; + uint32_t watchdog:1; + uint32_t antenna_ok:1; + uint32_t congestion:1; + uint32_t sis_error:1; + uint32_t missed_event:1; + uint32_t cpu_overload:1; + uint32_t invalid_config:1; + uint32_t reserved:21; +}TGPSReceiverStatusRxError; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + uint8_t code:4; + uint8_t antenna_id:4; +}TGPSAGCDataFrontendId; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSAGCDataFrontendId frontend_id; + int8_t gain; + uint8_t sample_var; + uint8_t blanking_stat; +}TGPSAGCData; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t cpu_load; + uint8_t reserved1; + uint32_t up_time; + TGPSReceiverStatusRxState rx_state; + TGPSReceiverStatusRxError rx_error; + uint8_t num_agc_states; + uint8_t length_agc_states; + uint8_t reserved2[2]; +}TGPSReceiverStatus; +#pragma pack (pop) + +// satellite visibility structure +#pragma pack (push, 1) +typedef struct{ + uint8_t sat_id; + uint8_t freq_nr; + uint16_t azimuth; + int16_t elevation; + uint8_t rise_set; + uint8_t sat_info; +}TGPSSatInfo; +#pragma pack (pop) + +#pragma pack (push, 1) +typedef struct{ + TGPSBlockTimeStamp timestamp; + uint8_t num_sat; + uint8_t length_sat; +}TGPSSatVisibility; +#pragma pack (pop) + +#endif diff --git a/src/stream_gps.cpp b/src/stream_gps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d02a4b01bcc0ccce57fc3a7f75441d94099064f1 --- /dev/null +++ b/src/stream_gps.cpp @@ -0,0 +1,213 @@ +#include "stream_gps.h" + +std::ostream& operator<< (std::ostream& out, TMeasEpoch &meas_epoch) +{ + unsigned int i,j; + + out << "Common flags: " << std::endl; + if(meas_epoch.flags&multipath_mitigation) + out << " Multipath mitigation enabled" << std::endl; + else + out << " Multipath mitigation disabled" << std::endl; + if(meas_epoch.flags&smoothing_of_code) + out << " At least one of the code measurements is smoothed" << std::endl; + else + out << " None of the code measurements are smoothed" << std::endl; + for(i=0;i<meas_epoch.type1_data.size();i++) + { + out << "Sattelite " << meas_epoch.type1_data[i].sat_id << " on channel " << meas_epoch.type1_data[i].rx_channel << std::endl; + out << " Master signal: " << signal_type_name[meas_epoch.type1_data[i].signal_type] << std::endl; + out << " Antenna: " << (int)meas_epoch.type1_data[i].antenna_id << std::endl; + out << " Pseudo range: " << meas_epoch.type1_data[i].pseudo_range << " m" << std::endl; + out << " Doppler: " << meas_epoch.type1_data[i].doppler << " Hz" << std::endl; + out << " Carrier phase: " << meas_epoch.type1_data[i].carrier_phase << " cycles" << std::endl; + out << " Carrier/noise ratio: " << meas_epoch.type1_data[i].cn0 << " dB-Hz" << std::endl; + out << " Lock time: " << meas_epoch.type1_data[i].lock_time << " s" << std::endl; + if(meas_epoch.type1_data[i].pseudorange_smoothed) + out << " Pseudo ranfe measurement is smoothed" << std::endl; + else + out << " Pseudo ranfe measurement is not smoothed" << std::endl; + if(meas_epoch.type1_data[i].smoothing_int_reached) + out << " The smoothing filter has reached the requested smoothing interval" << std::endl; + else + out << " The smoothing filter has not reached the requested smoothing interval" << std::endl; + if(meas_epoch.type1_data[i].half_cycle_ambiguity) + out << " Carrier phase has a half-cycle ambiguity" << std::endl; + else + out << " Carrier phase does not have a half-cycle ambiguity" << std::endl; + if(meas_epoch.type1_data[i].type2_data.size()>0) + { + for(j=0;j<meas_epoch.type1_data[i].type2_data.size();j++) + { + out << " Inter-channel differences" << std::endl; + out << " Master signal: " << signal_type_name[meas_epoch.type1_data[i].type2_data[j].signal_type] << std::endl; + out << " Antenna: " << (int)meas_epoch.type1_data[i].type2_data[j].antenna_id << std::endl; + out << " Pseudo range: " << meas_epoch.type1_data[i].type2_data[j].pseudo_range << " m" << std::endl; + out << " Doppler: " << meas_epoch.type1_data[i].type2_data[j].doppler << " Hz" << std::endl; + out << " Carrier phase: " << meas_epoch.type1_data[i].type2_data[j].carrier_phase << " cycles" << std::endl; + out << " Carrier/noise ratio: " << meas_epoch.type1_data[i].type2_data[j].cn0 << " dB-Hz" << std::endl; + out << " Lock time: " << meas_epoch.type1_data[i].type2_data[j].lock_time << " s" << std::endl; + if(meas_epoch.type1_data[i].type2_data[j].pseudorange_smoothed) + out << " Pseudo ranfe measurement is smoothed" << std::endl; + else + out << " Pseudo ranfe measurement is not smoothed" << std::endl; + if(meas_epoch.type1_data[i].type2_data[j].smoothing_int_reached) + out << " The smoothing filter has reached the requested smoothing interval" << std::endl; + else + out << " The smoothing filter has not reached the requested smoothing interval" << std::endl; + if(meas_epoch.type1_data[i].type2_data[j].half_cycle_ambiguity) + out << " Carrier phase has a half-cycle ambiguity" << std::endl; + else + out << " Carrier phase does not have a half-cycle ambiguity" << std::endl; + } + } + } + + return out; +} + +std::ostream& operator<< (std::ostream& out, TMeasExtra &meas_extra) +{ + unsigned int i; + + out << "Doppler variance factor: " << meas_extra.doppler_var_factor << " Hz2/cycles2" << std::endl; + for(i=0;i<meas_extra.blocks.size();i++) + { + out << "Block:" << std::endl; + out << " Receiver channel: " << meas_extra.blocks[i].rx_channel << std::endl; + out << " Master signal: " << signal_type_name[meas_extra.blocks[i].signal_type] << std::endl; + out << " Antenna: " << meas_extra.blocks[i].antenna_id << std::endl; + out << " Multipath correction: " << meas_extra.blocks[i].mp_correction << " m" << std::endl; + out << " Smoothing correction: " << meas_extra.blocks[i].smoothing_correction << " m" << std::endl; + out << " Code tracking noise variance: " << meas_extra.blocks[i].code_var << " m2" << std::endl; + out << " Carrier tracking noise variance: " << meas_extra.blocks[i].carrier_var << " mcycle2" << std::endl; + out << " Lock time: " << meas_extra.blocks[i].lock_time << " s" << std::endl; + } + + return out; +} + +std::ostream& operator<< (std::ostream& out, TGPSNav &gps_nav) +{ + out << "GPSNav block for satellite " << gps_nav.sat_id << std::endl; + out << " Code on L2 channel: " << gps_nav.ca_or_pon_l2 << std::endl; + out << " User range accuracy index: " << gps_nav.ura << std::endl; + out << " Health: " << gps_nav.health << std::endl; + out << " Data flag for L2 p-code: " << gps_nav.l2_data_flag << std::endl; + out << " Issue of data, clock: " << gps_nav.iodc << std::endl; + out << " Issue of data, ephemeris (subframe 2): " << gps_nav.iode2 << std::endl; + out << " Issue of data, ephemeris (subframe 3): " << gps_nav.iode3 << std::endl; + out << " Curve fit interval: " << gps_nav.fit_int_flag << std::endl; + out << " Estimated group delay differential (Tgd): " << gps_nav.t_gd << " s" << std::endl; + out << " Clock data reference time (Toc): " << gps_nav.t_oc << " s" << std::endl; + out << " SV clock aging" << gps_nav.a_f2 << " s/s2" << std::endl; + out << " SV clock drift: " << gps_nav.a_f1 << " s/s" << std::endl; + out << " SV clock bias: " << gps_nav.a_f0 << " s" << std::endl; + out << " Amplitude of the sine harmonic correction term to the orbit radius (Crs): " << gps_nav.c_rs << " m" << std::endl; + out << " Mean motion difference: " << gps_nav.delta_n << " semi-circle/s" << std::endl; + out << " Mean anomaly at reference time: " << gps_nav.m_0 << " semi-circle" << std::endl; + out << " Amplitude of the cosine harmonic correction term to the argument of latitude (Cuc): " << gps_nav.c_uc << " rad" << std::endl; + out << " Eccentricity: " << gps_nav.e << std::endl; + out << " Amplitude of the cosine harmonic correction term to the argument of latitude (Cus): " << gps_nav.c_us << " rad" << std::endl; + out << " Square root of the semi-major axis: " << gps_nav.sqrt_a << " m1/2" << std::endl; + out << " Reference time ephemeris (Toe): " << gps_nav.t_oe << " s" << std::endl; + out << " Amplitude of the cosine harmonic correction term to the angle of inclination (Cic): " << gps_nav.c_ic << " rad" << std::endl; + out << " Longitude of ascending node of orbit plane at weekly epoch: " << gps_nav.omega_0 << " semi-circle" << std::endl; + out << " Amplitude of the sine harmonic correction term to the angle of inclination (Cis): " << gps_nav.c_is << " rad" << std::endl; + out << " Inclination angle at reference time: " << gps_nav.i_0 << " semi-circle" << std::endl; + out << " Amplitude of the cosine harmonic correction term to the orbit radius (Crc): " << gps_nav.c_rc << " m" << std::endl; + out << " Argument of peregee: " << gps_nav.omega << " semi-circle" << std::endl; + out << " Rate of right ascension: " << gps_nav.omega_dot << " semi-circle/s" << std::endl; + out << " Rate of inclination angle: " << gps_nav.i_dot << " semi-circle/s" << std::endl; + + return out; +} + +std::ostream& operator<< (std::ostream& out, TGPSAlm &gps_alm) +{ + out << "GPSAlm block for satellite: " << gps_alm.sat_id << std::endl; + out << "Eccentricity: " << gps_alm.e << std::endl; + out << "Almanac reference time of week (Toa): " << gps_alm.t_oa << " s" << std::endl; + out << "Inclinationa ngle at reference time: " << gps_alm.delta_i << " semi-circle" << std::endl; + out << "Rate of right ascension: " << gps_alm.omega_dot << " semi-circle/s" << std::endl; + out << "Square root of the semi-major axis: " << gps_alm.sqrt_a << " m1/2" << std::endl; + out << "Longitude of ascending node of orbit plane at weekly epoch: " << gps_alm.omega_0 << " semi-circle" << std::endl; + out << "Argument of peregee: " << gps_alm.omega << " semi-circle" << std::endl; + out << "Mean anomaly at reference time: " << gps_alm.m_0 << " semi-circle" << std::endl; + out << "SV clock drift: " << gps_alm.a_f1 << " s/s" << std::endl; + out << "SV clock bias: " << gps_alm.a_f0 << " s" << std::endl; + + return out; +} + +std::ostream& operator<< (std::ostream& out, TGPSIon &gps_ion) +{ + out << "GPSIon block for satellite: " << gps_ion.sat_id << std::endl; + out << "Vertical delay coefficient 0: " << gps_ion.alpha_0 << " s" << std::endl; + out << "Vertical delay coefficient 1: " << gps_ion.alpha_1 << " s/semi-circle" << std::endl; + out << "Vertical delay coefficient 2: " << gps_ion.alpha_2 << " s/semi-circle2" << std::endl; + out << "Vertical delay coefficient 3: " << gps_ion.alpha_3 << " s/semi-circle3" << std::endl; + out << "Model period coefficient 0: " << gps_ion.beta_0 << " s" << std::endl; + out << "Model period coefficient 1: " << gps_ion.beta_1 << " s/semi-circle" << std::endl; + out << "Model period coefficient 2: " << gps_ion.beta_2 << " s/semi-circle2" << std::endl; + out << "Model period coefficient 3: " << gps_ion.beta_3 << " s/semi-circle3" << std::endl; + + return out; +} + +std::ostream& operator<< (std::ostream& out, TGPSUtc &gps_utc) +{ + out << "GPSUtc block for satellite: " << gps_utc.sat_id << std::endl; + out << "First order term of polynomial: " << gps_utc.a_1 << " s/s" << std::endl; + out << "constant term of polynomial: " << gps_utc.a_0 << " s" << std::endl; + out << "Reference time for UTC data (Tot): " << gps_utc.t_ot << " s" << std::endl; + out << "Delta time due to leap seconds when effectivity time is not in the past: " << gps_utc.del_t_ls << " s" << std::endl; + out << "Effectivity time of leap seconds (week): " << gps_utc.wn_lsf << " weelk" << std::endl; + out << "Effectivity time of leap seconds (day): " << gps_utc.dn << " day" << std::endl; + out << "Delta time due to leap seconds when effectivity time is not in the past: " << gps_utc.del_t_lsf << " s" << std::endl; + + return out; +} + +// ChannelStatus +/* std::cout << "gps timestamp: " << this->channel_status.gps_timestamp << std::endl; + std::cout << "num channles: " << this->channel_status.info.size() << std::endl; + for(i=0;i<this->channel_status.info.size();i++) + { + std::cout << " Sat ID: " << (int)this->channel_status.info[i].sat_id << std::endl; + std::cout << " Azimuth: " << this->channel_status.info[i].azimuth << std::endl; + std::cout << " rise/set: " << this->channel_status.info[i].rise_set << std::endl; + std::cout << " Health: " << this->channel_status.info[i].health << std::endl; + std::cout << " Elevation: " << this->channel_status.info[i].elevation << std::endl; + for(j=0;j<this->channel_status.info[i].state.size();j++) + { + std::cout << " Antenna ID: " << (int)this->channel_status.info[i].state[j].antenna_id << std::endl; + std::cout << " Tracking status: " << this->channel_status.info[i].state[j].track_status << std::endl; + std::cout << " PVT status: " << this->channel_status.info[i].state[j].pvt_status << std::endl; + } + }*/ + +//ReceiverStatus +/* std::cout << "gps timestamp: " << this->receiver_status.gps_timestamp << std::endl; + std::cout << "CPU load: " << this->receiver_status.cpu_load << std::endl; + std::cout << "up time: " << this->receiver_status.up_time << std::endl; + for(i=0;i<this->receiver_status.agc.size();i++) + { + std::cout << " Frontend: " << this->receiver_status.agc[i].frontend_id << std::endl;; + std::cout << " Antenna: " << this->receiver_status.agc[i].antenna_id << std::endl;; + std::cout << " Gain: " << this->receiver_status.agc[i].gain << std::endl;; + std::cout << " Sample var: " << this->receiver_status.agc[i].sample_var << std::endl;; + std::cout << " Blanking stat: " << this->receiver_status.agc[i].blanking_stat << std::endl;; + }*/ + +// SatVisibility +/* std::cout << "Num sat: " << this->sat_info.size() << std::endl; + for(i=0;i<this->sat_info.size();i++) + { + std::cout << "Sat ID: " << this->sat_info[i].sat_id << std::endl; + std::cout << "Azmimuth: " << this->sat_info[i].azimuth << std::endl; + std::cout << "Elevation: " << this->sat_info[i].elevation << std::endl; + std::cout << "rise/set: " << this->sat_info[i].rise_set << std::endl; + std::cout << "Sat info: " << this->sat_info[i].sat_info << std::endl; + }*/ + diff --git a/src/stream_gps.h b/src/stream_gps.h new file mode 100644 index 0000000000000000000000000000000000000000..597aacd827249f34b3920968e554490be63bf263 --- /dev/null +++ b/src/stream_gps.h @@ -0,0 +1,16 @@ +#ifndef _STREAM_GPS_H +#define _STREAM_GPS_H + +#include <iostream> +#include <vector> +#include <stdint.h> +#include "gps_types.h" + +std::ostream& operator<< (std::ostream& out, TMeasEpoch &meas_epoch); +std::ostream& operator<< (std::ostream& out, TMeasExtra &meas_extra); +std::ostream& operator<< (std::ostream& out, TGPSNav &gps_nav); +std::ostream& operator<< (std::ostream& out, TGPSAlm &gps_alm); +std::ostream& operator<< (std::ostream& out, TGPSIon &gps_ion); +std::ostream& operator<< (std::ostream& out, TGPSUtc &gps_utc); + +#endif