1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "GnssRawMeasurementParser.h"
18
19 namespace android {
20 namespace hardware {
21 namespace gnss {
22 namespace common {
23
24 using aidl::android::hardware::gnss::ElapsedRealtime;
25 using aidl::android::hardware::gnss::GnssClock;
26 using aidl::android::hardware::gnss::GnssConstellationType;
27 using aidl::android::hardware::gnss::GnssData;
28 using aidl::android::hardware::gnss::GnssMeasurement;
29 using aidl::android::hardware::gnss::GnssMultipathIndicator;
30 using aidl::android::hardware::gnss::GnssSignalType;
31
32 using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
33
getColumnIdNameMappingFromHeader(const std::string & header)34 std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
35 const std::string& header) {
36 std::vector<std::string> columnNames;
37 std::unordered_map<std::string, int> columnNameIdMapping;
38 std::string s = header;
39 // Trim left spaces
40 s.erase(s.begin(),
41 std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
42 // Trim right spaces
43 s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
44 .base(),
45 s.end());
46 // Remove comment symbol, start from `Raw`.
47 s = s.substr(s.find("Raw"));
48
49 ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
50 int columnId = 0;
51 for (auto& name : columnNames) {
52 columnNameIdMapping[name] = columnId++;
53 }
54
55 return columnNameIdMapping;
56 }
57
getClockFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)58 int GnssRawMeasurementParser::getClockFlags(
59 const std::vector<std::string>& rawMeasurementRecordValues,
60 const std::unordered_map<std::string, int>& columnNameIdMapping) {
61 int clockFlags = 0;
62 if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
63 clockFlags |= GnssClock::HAS_LEAP_SECOND;
64 }
65 if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
66 clockFlags |= GnssClock::HAS_FULL_BIAS;
67 }
68 if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
69 clockFlags |= GnssClock::HAS_BIAS;
70 }
71 if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
72 clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
73 }
74 if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
75 clockFlags |= GnssClock::HAS_DRIFT;
76 }
77 if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
78 .empty()) {
79 clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
80 }
81 return clockFlags;
82 }
83
getElapsedRealtimeFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)84 int GnssRawMeasurementParser::getElapsedRealtimeFlags(
85 const std::vector<std::string>& rawMeasurementRecordValues,
86 const std::unordered_map<std::string, int>& columnNameIdMapping) {
87 int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
88 if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
89 elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
90 }
91 return elapsedRealtimeFlags;
92 }
93
getRawMeasurementFlags(const std::vector<std::string> & rawMeasurementRecordValues,const std::unordered_map<std::string,int> & columnNameIdMapping)94 int GnssRawMeasurementParser::getRawMeasurementFlags(
95 const std::vector<std::string>& rawMeasurementRecordValues,
96 const std::unordered_map<std::string, int>& columnNameIdMapping) {
97 int rawMeasurementFlags = 0;
98 if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
99 rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
100 }
101 if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
102 rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
103 }
104 if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
105 rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
106 }
107 if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
108 rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
109 }
110 if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
111 rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
112 }
113 if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
114 rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
115 }
116 if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
117 rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
118 }
119 if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
120 .empty()) {
121 rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
122 }
123 if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
124 .empty()) {
125 rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
126 }
127 if (!rawMeasurementRecordValues[columnNameIdMapping.at(
128 "SatelliteInterSignalBiasUncertaintyNanos")]
129 .empty()) {
130 rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
131 }
132 // HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
133 // output, need add them later.
134 return rawMeasurementFlags;
135 }
136
getGnssConstellationType(int constellationType)137 GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
138 GnssConstellationType gnssConstellationType =
139 aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
140
141 switch (constellationType) {
142 case 1:
143 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
144 break;
145 case 2:
146 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
147 break;
148 case 3:
149 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
150 break;
151 case 4:
152 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
153 break;
154 case 5:
155 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
156 break;
157 case 6:
158 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
159 break;
160 default:
161 gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
162 }
163
164 return gnssConstellationType;
165 }
166
getMeasurementFromStrs(std::string & rawMeasurementStr)167 std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
168 std::string& rawMeasurementStr) {
169 /*
170 * Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
171 * BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
172 * HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
173 * ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
174 * PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
175 * AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
176 * CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
177 * ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
178 * FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
179 * SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
180 */
181 ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
182 if (rawMeasurementStr.empty()) {
183 return nullptr;
184 }
185 std::vector<std::string> rawMeasurementStrRecords;
186 ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
187 if (rawMeasurementStrRecords.size() <= 1) {
188 ALOGE("Raw GNSS Measurements parser failed. (No records) ");
189 return nullptr;
190 }
191
192 // Get the column name mapping from the header.
193 std::unordered_map<std::string, int> columnNameIdMapping =
194 getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
195
196 if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
197 ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
198 return nullptr;
199 }
200
201 // Set GnssClock from 1st record.
202 std::size_t pointer = 1;
203 std::vector<std::string> firstRecordValues;
204 ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
205 GnssClock clock = {
206 .gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
207 .timeNs = ParseUtils::tryParseLongLong(
208 firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
209 .fullBiasNs = ParseUtils::tryParseLongLong(
210 firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
211 .biasNs = ParseUtils::tryParseDouble(
212 firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
213 .biasUncertaintyNs = ParseUtils::tryParseDouble(
214 firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
215 .driftNsps = ParseUtils::tryParseDouble(
216 firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
217 .driftUncertaintyNsps = ParseUtils::tryParseDouble(
218 firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
219 .hwClockDiscontinuityCount = ParseUtils::tryParseInt(
220 firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
221 0)};
222
223 ElapsedRealtime timestamp = {
224 .flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
225 .timestampNs = ParseUtils::tryParseLongLong(
226 firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
227 .timeUncertaintyNs = ParseUtils::tryParseDouble(
228 firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
229
230 std::vector<GnssMeasurement> measurementsVec;
231 for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
232 std::vector<std::string> rawMeasurementValues;
233 std::string line = rawMeasurementStrRecords[pointer];
234 ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
235 GnssSignalType signalType = {
236 .constellation = getGnssConstellationType(ParseUtils::tryParseInt(
237 rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
238 .carrierFrequencyHz = ParseUtils::tryParseDouble(
239 rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
240 .codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
241 };
242 GnssMeasurement measurement = {
243 .flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
244 .svid = ParseUtils::tryParseInt(
245 rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
246 .signalType = signalType,
247 .receivedSvTimeInNs = ParseUtils::tryParseLongLong(
248 rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
249 .receivedSvTimeUncertaintyInNs =
250 ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
251 "ReceivedSvTimeUncertaintyNanos")],
252 0),
253 .antennaCN0DbHz = ParseUtils::tryParseDouble(
254 rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
255 .basebandCN0DbHz = ParseUtils::tryParseDouble(
256 rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
257 .agcLevelDb = ParseUtils::tryParseDouble(
258 rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
259 .pseudorangeRateMps =
260 ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
261 "PseudorangeRateMetersPerSecond")],
262 0),
263 .pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
264 rawMeasurementValues[columnNameIdMapping.at(
265 "PseudorangeRateUncertaintyMetersPerSecond")],
266 0),
267 .accumulatedDeltaRangeState = ParseUtils::tryParseInt(
268 rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
269 0),
270 .accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
271 rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
272 0),
273 .accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
274 rawMeasurementValues[columnNameIdMapping.at(
275 "AccumulatedDeltaRangeUncertaintyMeters")],
276 0),
277 .multipathIndicator = GnssMultipathIndicator::UNKNOWN, // Not in GnssLogger yet.
278 .state = ParseUtils::tryParseInt(
279 rawMeasurementValues[columnNameIdMapping.at("State")], 0),
280 .fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
281 .fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
282 rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
283 0),
284 .satelliteInterSignalBiasNs =
285 ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
286 "SatelliteInterSignalBiasNanos")],
287 0),
288 .satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
289 rawMeasurementValues[columnNameIdMapping.at(
290 "SatelliteInterSignalBiasUncertaintyNanos")],
291 0),
292 .satellitePvt = {},
293 .correlationVectors = {}};
294 measurementsVec.push_back(measurement);
295 }
296
297 GnssData gnssData = {
298 .measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
299 return std::make_unique<GnssData>(gnssData);
300 }
301
302 } // namespace common
303 } // namespace gnss
304 } // namespace hardware
305 } // namespace android
306