Skip to content

Commit 5632728

Browse files
dakejahlCopilot
andauthored
lib: gnss: add RTCM parsing library (#26093)
* lib: gnss: add RTCM parsing library. Generated by Claude Code. * lib: gnss: rtcm: use rtcm3_payload_length() * lib: gnss: rtcm: set header year * lib: gnss: rtcm: add units tests * Update src/lib/gnss/rtcm.h Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/lib/gnss/CMakeLists.txt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/lib/gnss/rtcm.h Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove mention of reset() * lib: gnss: rtcm: more effecient preamble search --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 778ad16 commit 5632728

File tree

11 files changed

+1098
-0
lines changed

11 files changed

+1098
-0
lines changed

src/lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ add_subdirectory(dataman_client EXCLUDE_FROM_ALL)
5050
add_subdirectory(drivers EXCLUDE_FROM_ALL)
5151
add_subdirectory(field_sensor_bias_estimator EXCLUDE_FROM_ALL)
5252
add_subdirectory(geo EXCLUDE_FROM_ALL)
53+
add_subdirectory(gnss EXCLUDE_FROM_ALL)
5354
add_subdirectory(heatshrink EXCLUDE_FROM_ALL)
5455
add_subdirectory(hysteresis EXCLUDE_FROM_ALL)
5556
add_subdirectory(lat_lon_alt EXCLUDE_FROM_ALL)

src/lib/gnss/CMakeLists.txt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
############################################################################
2+
#
3+
# Copyright (c) 2025 PX4 Development Team. All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions
7+
# are met:
8+
#
9+
# 1. Redistributions of source code must retain the above copyright
10+
# notice, this list of conditions and the following disclaimer.
11+
# 2. Redistributions in binary form must reproduce the above copyright
12+
# notice, this list of conditions and the following disclaimer in
13+
# the documentation and/or other materials provided with the
14+
# distribution.
15+
# 3. Neither the name PX4 nor the names of its contributors may be
16+
# used to endorse or promote products derived from this software
17+
# without specific prior written permission.
18+
#
19+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23+
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26+
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27+
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29+
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30+
# POSSIBILITY OF SUCH DAMAGE.
31+
#
32+
############################################################################
33+
34+
px4_add_library(gnss rtcm.cpp)
35+
36+
target_include_directories(gnss PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
37+
38+
if(BUILD_TESTING)
39+
add_subdirectory(test)
40+
endif()

src/lib/gnss/rtcm.cpp

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in
13+
* the documentation and/or other materials provided with the
14+
* distribution.
15+
* 3. Neither the name PX4 nor the names of its contributors may be
16+
* used to endorse or promote products derived from this software
17+
* without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30+
* POSSIBILITY OF SUCH DAMAGE.
31+
*
32+
****************************************************************************/
33+
34+
/**
35+
* @file rtcm.cpp
36+
*
37+
* RTCM3 protocol parsing implementation.
38+
*/
39+
40+
#include "rtcm.h"
41+
#include <cstring>
42+
43+
namespace gnss
44+
{
45+
46+
uint32_t rtcm3_crc24q(const uint8_t *data, size_t len)
47+
{
48+
uint32_t crc = 0;
49+
50+
for (size_t i = 0; i < len; i++) {
51+
crc ^= static_cast<uint32_t>(data[i]) << 16;
52+
53+
for (int j = 0; j < 8; j++) {
54+
crc <<= 1;
55+
56+
if (crc & 0x1000000) {
57+
crc ^= RTCM3_CRC24Q_POLY;
58+
}
59+
}
60+
}
61+
62+
return crc & 0xFFFFFF;
63+
}
64+
65+
size_t Rtcm3Parser::addData(const uint8_t *data, size_t len)
66+
{
67+
size_t space_available = BUFFER_SIZE - _buffer_len;
68+
size_t to_copy = (len < space_available) ? len : space_available;
69+
70+
if (to_copy > 0) {
71+
memcpy(&_buffer[_buffer_len], data, to_copy);
72+
_buffer_len += to_copy;
73+
}
74+
75+
return to_copy;
76+
}
77+
78+
const uint8_t *Rtcm3Parser::getNextMessage(size_t *out_len)
79+
{
80+
while (_buffer_len > 0) {
81+
int to_drop = 0;
82+
83+
// Find preamble
84+
for (size_t i = 0; i < _buffer_len; i++) {
85+
if (_buffer[i] == RTCM3_PREAMBLE) {
86+
break;
87+
}
88+
89+
to_drop++;
90+
}
91+
92+
// Drop everything not being the preamble
93+
if (to_drop > 0) {
94+
_bytes_discarded += to_drop;
95+
discardBytes(to_drop);
96+
}
97+
98+
// Need at least header to check length
99+
if (_buffer_len < RTCM3_HEADER_LEN) {
100+
return nullptr;
101+
}
102+
103+
size_t payload_len = rtcm3_payload_length(_buffer);
104+
105+
if (payload_len > RTCM3_MAX_PAYLOAD_LEN) {
106+
// Invalid length - not a valid frame, discard preamble
107+
_bytes_discarded++;
108+
discardBytes(1);
109+
continue;
110+
}
111+
112+
size_t frame_len = RTCM3_HEADER_LEN + payload_len + RTCM3_CRC_LEN;
113+
114+
// Check if we have the complete frame
115+
if (_buffer_len < frame_len) {
116+
return nullptr;
117+
}
118+
119+
uint32_t calculated_crc = rtcm3_crc24q(_buffer, RTCM3_HEADER_LEN + payload_len);
120+
uint32_t received_crc = (static_cast<uint32_t>(_buffer[frame_len - 3]) << 16) |
121+
(static_cast<uint32_t>(_buffer[frame_len - 2]) << 8) |
122+
_buffer[frame_len - 1];
123+
124+
if (calculated_crc != received_crc) {
125+
_crc_errors++;
126+
discardBytes(1);
127+
continue;
128+
}
129+
130+
*out_len = frame_len;
131+
return _buffer;
132+
}
133+
134+
return nullptr;
135+
}
136+
137+
void Rtcm3Parser::consumeMessage(size_t len)
138+
{
139+
discardBytes(len);
140+
_messages_parsed++;
141+
_total_frame_bytes += len;
142+
}
143+
144+
void Rtcm3Parser::discardBytes(size_t count)
145+
{
146+
if (count >= _buffer_len) {
147+
_buffer_len = 0;
148+
149+
} else {
150+
memmove(_buffer, &_buffer[count], _buffer_len - count);
151+
_buffer_len -= count;
152+
}
153+
}
154+
155+
} // namespace gnss

0 commit comments

Comments
 (0)