| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
| 2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
| 3 | // the University of Stuttgart, Germany. | ||
| 4 | // | ||
| 5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
| 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| 7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| 8 | |||
| 9 | #include "EmlidUtilities.hpp" | ||
| 10 | #include "EmlidTypes.hpp" | ||
| 11 | |||
| 12 | #include "util/Logger.hpp" | ||
| 13 | #include "util/Time/TimeBase.hpp" | ||
| 14 | |||
| 15 | ✗ | void NAV::vendor::emlid::decryptEmlidObs(const std::shared_ptr<NAV::EmlidObs>& obs, uart::protocol::Packet& packet) | |
| 16 | { | ||
| 17 | ✗ | if (packet.type() == uart::protocol::Packet::Type::TYPE_BINARY) | |
| 18 | { | ||
| 19 | ✗ | obs->msgId = packet.extractUint8(); | |
| 20 | ✗ | obs->payloadLength = packet.extractUint16(); | |
| 21 | |||
| 22 | // Navigation Results Messages: Position | ||
| 23 | ✗ | auto msgId = static_cast<ErbMessageID>(obs->msgId); | |
| 24 | ✗ | if (msgId == ErbMessageID::ERB_MessageId_VER) | |
| 25 | { | ||
| 26 | ✗ | obs->data = ErbVer(); | |
| 27 | |||
| 28 | ✗ | std::get<ErbVer>(obs->data).iTOW = packet.extractUint32(); | |
| 29 | ✗ | std::get<ErbVer>(obs->data).verH = packet.extractUint8(); | |
| 30 | ✗ | std::get<ErbVer>(obs->data).verM = packet.extractUint8(); | |
| 31 | ✗ | std::get<ErbVer>(obs->data).verL = packet.extractUint8(); | |
| 32 | |||
| 33 | // Calculate the insTime with the iTOW | ||
| 34 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 35 | ✗ | if (!currentTime.empty()) | |
| 36 | { | ||
| 37 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 38 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 39 | gpst.gpsWeek, | ||
| 40 | ✗ | static_cast<long double>(std::get<ErbVer>(obs->data).iTOW) / 1000.0L); | |
| 41 | ✗ | obs->insTime = currentTime; | |
| 42 | } | ||
| 43 | |||
| 44 | LOG_DATA("Erb: VER, iTOW {}, verH {}, verH {}, verH {}", | ||
| 45 | std::get<ErbVer>(obs->data).iTOW, | ||
| 46 | std::get<ErbVer>(obs->data).verH, | ||
| 47 | std::get<ErbVer>(obs->data).verM, | ||
| 48 | std::get<ErbVer>(obs->data).verL); | ||
| 49 | } | ||
| 50 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_POS) | |
| 51 | { | ||
| 52 | ✗ | obs->data = ErbPos(); | |
| 53 | |||
| 54 | ✗ | std::get<ErbPos>(obs->data).iTOW = packet.extractUint32(); | |
| 55 | ✗ | std::get<ErbPos>(obs->data).lon = packet.extractDouble(); | |
| 56 | ✗ | std::get<ErbPos>(obs->data).lat = packet.extractDouble(); | |
| 57 | ✗ | std::get<ErbPos>(obs->data).height = packet.extractDouble(); | |
| 58 | ✗ | std::get<ErbPos>(obs->data).hMSL = packet.extractDouble(); | |
| 59 | ✗ | std::get<ErbPos>(obs->data).hAcc = packet.extractUint32(); | |
| 60 | ✗ | std::get<ErbPos>(obs->data).vAcc = packet.extractUint32(); | |
| 61 | |||
| 62 | // Calculate the insTime with the iTOW | ||
| 63 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 64 | ✗ | if (!currentTime.empty()) | |
| 65 | { | ||
| 66 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 67 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 68 | gpst.gpsWeek, | ||
| 69 | ✗ | static_cast<long double>(std::get<ErbPos>(obs->data).iTOW) / 1000.0L); | |
| 70 | ✗ | obs->insTime = currentTime; | |
| 71 | } | ||
| 72 | |||
| 73 | LOG_DATA("Erb: POS, iTOW {}, lon {}, lat {}, height {}", | ||
| 74 | std::get<ErbPos>(obs->data).iTOW, std::get<ErbPos>(obs->data).lon, | ||
| 75 | std::get<ErbPos>(obs->data).lat, std::get<ErbPos>(obs->data).height); | ||
| 76 | } | ||
| 77 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_STAT) | |
| 78 | { | ||
| 79 | ✗ | obs->data = ErbStat(); | |
| 80 | |||
| 81 | ✗ | std::get<ErbStat>(obs->data).iTOW = packet.extractUint32(); | |
| 82 | ✗ | std::get<ErbStat>(obs->data).weekGPS = packet.extractUint16(); | |
| 83 | ✗ | std::get<ErbStat>(obs->data).fixType = packet.extractUint8(); | |
| 84 | ✗ | std::get<ErbStat>(obs->data).fixStatus = packet.extractUint8(); | |
| 85 | ✗ | std::get<ErbStat>(obs->data).numSV = packet.extractUint8(); | |
| 86 | |||
| 87 | // Calculate the insTime with the iTOW | ||
| 88 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 89 | ✗ | if (!currentTime.empty()) | |
| 90 | { | ||
| 91 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 92 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 93 | gpst.gpsWeek, | ||
| 94 | ✗ | static_cast<long double>(std::get<ErbStat>(obs->data).iTOW) / 1000.0L); | |
| 95 | ✗ | obs->insTime = currentTime; | |
| 96 | } | ||
| 97 | |||
| 98 | LOG_DATA("Erb: STAT, iTOW {}, weekGPS {}, fixType {}, fixStatus {}, numSV {}", | ||
| 99 | std::get<ErbStat>(obs->data).iTOW, | ||
| 100 | std::get<ErbStat>(obs->data).weekGPS, std::get<ErbStat>(obs->data).fixType, | ||
| 101 | std::get<ErbStat>(obs->data).fixStatus, std::get<ErbStat>(obs->data).numSV); | ||
| 102 | } | ||
| 103 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_DPOS) | |
| 104 | { | ||
| 105 | ✗ | obs->data = ErbDops(); | |
| 106 | |||
| 107 | ✗ | std::get<ErbDops>(obs->data).iTOW = packet.extractUint32(); | |
| 108 | ✗ | std::get<ErbDops>(obs->data).dopGeo = packet.extractUint16(); | |
| 109 | ✗ | std::get<ErbDops>(obs->data).dopPos = packet.extractUint16(); | |
| 110 | ✗ | std::get<ErbDops>(obs->data).dopVer = packet.extractUint16(); | |
| 111 | ✗ | std::get<ErbDops>(obs->data).dopHor = packet.extractUint16(); | |
| 112 | |||
| 113 | // Calculate the insTime with the iTOW | ||
| 114 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 115 | ✗ | if (!currentTime.empty()) | |
| 116 | { | ||
| 117 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 118 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 119 | gpst.gpsWeek, | ||
| 120 | ✗ | static_cast<long double>(std::get<ErbDops>(obs->data).iTOW) / 1000.0L); | |
| 121 | ✗ | obs->insTime = currentTime; | |
| 122 | } | ||
| 123 | |||
| 124 | LOG_DATA("Erb: DOPS, iTOW {}, dopGeo {}, dopPos {}, dopVer {}, dopHor {}", | ||
| 125 | std::get<ErbDops>(obs->data).iTOW, | ||
| 126 | std::get<ErbDops>(obs->data).dopGeo, std::get<ErbDops>(obs->data).dopPos, | ||
| 127 | std::get<ErbDops>(obs->data).dopVer, std::get<ErbDops>(obs->data).dopHor); | ||
| 128 | } | ||
| 129 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_VEL) | |
| 130 | { | ||
| 131 | ✗ | obs->data = ErbVel(); | |
| 132 | |||
| 133 | ✗ | std::get<ErbVel>(obs->data).iTOW = packet.extractUint32(); | |
| 134 | ✗ | std::get<ErbVel>(obs->data).velN = packet.extractInt32(); | |
| 135 | ✗ | std::get<ErbVel>(obs->data).velE = packet.extractInt32(); | |
| 136 | ✗ | std::get<ErbVel>(obs->data).velD = packet.extractInt32(); | |
| 137 | ✗ | std::get<ErbVel>(obs->data).speed = packet.extractUint32(); | |
| 138 | ✗ | std::get<ErbVel>(obs->data).gSpeed = packet.extractUint32(); | |
| 139 | ✗ | std::get<ErbVel>(obs->data).heading = packet.extractInt32(); | |
| 140 | ✗ | std::get<ErbVel>(obs->data).sAcc = packet.extractUint32(); | |
| 141 | |||
| 142 | // Calculate the insTime with the iTOW | ||
| 143 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 144 | ✗ | if (!currentTime.empty()) | |
| 145 | { | ||
| 146 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 147 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 148 | gpst.gpsWeek, | ||
| 149 | ✗ | static_cast<long double>(std::get<ErbVel>(obs->data).iTOW) / 1000.0L); | |
| 150 | ✗ | obs->insTime = currentTime; | |
| 151 | } | ||
| 152 | |||
| 153 | LOG_DATA("Erb: VEL, iTOW {}, gSpeed {} [cm/s], heading {} [deg*1e-5], velD {} [cm/s]", | ||
| 154 | std::get<ErbVel>(obs->data).iTOW, std::get<ErbVel>(obs->data).gSpeed, | ||
| 155 | std::get<ErbVel>(obs->data).heading, std::get<ErbVel>(obs->data).velD); | ||
| 156 | } | ||
| 157 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_SVI) | |
| 158 | { | ||
| 159 | ✗ | obs->data = ErbSvi(); | |
| 160 | |||
| 161 | ✗ | std::get<ErbSvi>(obs->data).iTOW = packet.extractUint32(); | |
| 162 | ✗ | std::get<ErbSvi>(obs->data).nSV = packet.extractUint8(); | |
| 163 | ✗ | std::get<ErbSvi>(obs->data).idSV = packet.extractUint8(); | |
| 164 | ✗ | std::get<ErbSvi>(obs->data).typeSV = packet.extractUint8(); | |
| 165 | ✗ | std::get<ErbSvi>(obs->data).carPh = packet.extractInt32(); | |
| 166 | ✗ | std::get<ErbSvi>(obs->data).psRan = packet.extractInt32(); | |
| 167 | ✗ | std::get<ErbSvi>(obs->data).freqD = packet.extractInt32(); | |
| 168 | ✗ | std::get<ErbSvi>(obs->data).snr = packet.extractUint16(); | |
| 169 | ✗ | std::get<ErbSvi>(obs->data).azim = packet.extractUint16(); | |
| 170 | ✗ | std::get<ErbSvi>(obs->data).elev = packet.extractUint16(); | |
| 171 | |||
| 172 | // Calculate the insTime with the iTOW | ||
| 173 | ✗ | auto currentTime = util::time::GetCurrentInsTime(); | |
| 174 | ✗ | if (!currentTime.empty()) | |
| 175 | { | ||
| 176 | ✗ | auto gpst = currentTime.toGPSweekTow(); | |
| 177 | ✗ | currentTime = InsTime(gpst.gpsCycle, | |
| 178 | gpst.gpsWeek, | ||
| 179 | ✗ | static_cast<long double>(std::get<ErbSvi>(obs->data).iTOW) / 1000.0L); | |
| 180 | ✗ | obs->insTime = currentTime; | |
| 181 | } | ||
| 182 | |||
| 183 | LOG_DATA("Erb: SVI, iTOW {}, nSV {} , idSV {} , typeSV {} , carPh {}, psRan {} , freqD {} , snr {}, , azim {} , elev {}", | ||
| 184 | std::get<ErbSvi>(obs->data).iTOW, std::get<ErbSvi>(obs->data).nSV, std::get<ErbSvi>(obs->data).idSV, | ||
| 185 | std::get<ErbSvi>(obs->data).typeSV, std::get<ErbSvi>(obs->data).carPh, | ||
| 186 | std::get<ErbSvi>(obs->data).psRan, std::get<ErbSvi>(obs->data).freqD, | ||
| 187 | std::get<ErbSvi>(obs->data).snr, std::get<ErbSvi>(obs->data).azim, | ||
| 188 | std::get<ErbSvi>(obs->data).elev); | ||
| 189 | } | ||
| 190 | ✗ | else if (msgId == ErbMessageID::ERB_MessageId_RTK) | |
| 191 | { | ||
| 192 | ✗ | obs->data = ErbRtk(); | |
| 193 | |||
| 194 | ✗ | std::get<ErbRtk>(obs->data).numSV = packet.extractUint8(); | |
| 195 | ✗ | std::get<ErbRtk>(obs->data).age = packet.extractUint16(); | |
| 196 | ✗ | std::get<ErbRtk>(obs->data).baselineN = packet.extractInt32(); | |
| 197 | ✗ | std::get<ErbRtk>(obs->data).baselineE = packet.extractInt32(); | |
| 198 | ✗ | std::get<ErbRtk>(obs->data).baselineD = packet.extractInt32(); | |
| 199 | ✗ | std::get<ErbRtk>(obs->data).arRatio = packet.extractUint16(); | |
| 200 | ✗ | std::get<ErbRtk>(obs->data).weekGPS = packet.extractUint16(); | |
| 201 | ✗ | std::get<ErbRtk>(obs->data).timeGPS = packet.extractUint32(); | |
| 202 | |||
| 203 | LOG_DATA("Erb: RTK, numSV {}, age {} [s * 1e-2] , baselineN {} , baselineE {} , baselineD {}, arRatio {} [*1e-1] , weekGPS {} , timeGPS {}", | ||
| 204 | std::get<ErbRtk>(obs->data).numSV, std::get<ErbRtk>(obs->data).age, std::get<ErbRtk>(obs->data).baselineN, | ||
| 205 | std::get<ErbRtk>(obs->data).baselineE, std::get<ErbRtk>(obs->data).baselineD, | ||
| 206 | std::get<ErbRtk>(obs->data).arRatio, std::get<ErbRtk>(obs->data).weekGPS, | ||
| 207 | std::get<ErbRtk>(obs->data).timeGPS); | ||
| 208 | } | ||
| 209 | else | ||
| 210 | { | ||
| 211 | LOG_DATA("Erb: {:x}, Size {}, not implemented yet!", obs->msgId, packet.getRawDataLength()); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | ✗ | } | |
| 215 | |||
| 216 | ✗ | std::pair<uint8_t, uint8_t> NAV::vendor::emlid::checksumUBX(const std::vector<uint8_t>& data) | |
| 217 | { | ||
| 218 | ✗ | uint8_t cka = 0; | |
| 219 | ✗ | uint8_t ckb = 0; | |
| 220 | |||
| 221 | ✗ | for (size_t i = 2; i < data.size() - 2; i++) | |
| 222 | { | ||
| 223 | ✗ | cka += data.at(i); | |
| 224 | ✗ | ckb += cka; | |
| 225 | } | ||
| 226 | ✗ | return std::make_pair(cka, ckb); | |
| 227 | } | ||
| 228 |