Skip to content

Commit 6fe76fd

Browse files
Feature: Add support for new HPS firmware and publishing NMEA Sentences (#209)
* Fix for NMEA messages overwhelming publishing queue * Apply suggestions from code review Co-authored-by: Chris Lalancette <[email protected]>
1 parent be4fb7b commit 6fe76fd

File tree

8 files changed

+92
-8
lines changed

8 files changed

+92
-8
lines changed

ublox_gps/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ find_package(asio REQUIRED)
1717
find_package(diagnostic_msgs REQUIRED)
1818
find_package(diagnostic_updater REQUIRED)
1919
find_package(geometry_msgs REQUIRED)
20+
find_package(nmea_msgs REQUIRED)
2021
find_package(rcl_interfaces REQUIRED)
2122
find_package(rclcpp REQUIRED)
2223
find_package(rclcpp_components REQUIRED)
24+
find_package(rtcm_msgs REQUIRED)
2325
find_package(sensor_msgs REQUIRED)
2426
find_package(std_msgs REQUIRED)
2527
find_package(tf2 REQUIRED)
2628
find_package(ublox_msgs REQUIRED)
2729
find_package(ublox_serialization REQUIRED)
28-
find_package(rtcm_msgs REQUIRED)
2930

3031
# build node
3132
add_library(ublox_gps
@@ -58,6 +59,7 @@ target_link_libraries(ublox_gps PUBLIC
5859
${rcl_interfaces_TARGETS}
5960
rclcpp::rclcpp
6061
rclcpp_components::component
62+
${nmea_msgs_TARGETS}
6163
${rtcm_msgs_TARGETS}
6264
${sensor_msgs_TARGETS}
6365
${std_msgs_TARGETS}

ublox_gps/include/ublox_gps/callback.hpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <mutex>
3939
#include <sstream>
4040
#include <stdexcept>
41+
#include <string>
4142
#include <utility>
4243

4344
#include <ublox_msgs/serialization.hpp>
@@ -163,6 +164,15 @@ class CallbackHandlers final {
163164
std::make_shared<CallbackHandler_<T>>(callback, debug_)));
164165
}
165166

167+
/**
168+
* @brief Add a callback handler for nmea messages
169+
* @param callback the callback handler for the message
170+
*/
171+
void set_nmea_callback(std::function<void(const std::string&)> callback) {
172+
std::lock_guard<std::mutex> lock(callback_mutex_);
173+
callback_nmea_ = callback;
174+
}
175+
166176
/**
167177
* @brief Calls the callback handler for the message in the reader.
168178
* @param reader a reader containing a u-blox message
@@ -178,6 +188,28 @@ class CallbackHandlers final {
178188
}
179189
}
180190

191+
/**
192+
* @brief Calls the callback handler for the nmea messages in the reader.
193+
* @param reader a reader containing an nmea message
194+
*/
195+
void handle_nmea(ublox::Reader& reader) {
196+
std::lock_guard<std::mutex> lock(callback_mutex_);
197+
if (callback_nmea_ == nullptr) {
198+
return;
199+
}
200+
201+
const std::string buffer = reader.getExtraData();
202+
size_t nmea_start = buffer.find('$', 0);
203+
size_t nmea_end = buffer.find('\n', nmea_start);
204+
while(nmea_start != std::string::npos && nmea_end != std::string::npos) {
205+
std::string sentence = buffer.substr(nmea_start, nmea_end - nmea_start + 1);
206+
callback_nmea_(sentence);
207+
208+
nmea_start = buffer.find('$', nmea_end + 1);
209+
nmea_end = buffer.find('\n', nmea_start);
210+
}
211+
}
212+
181213
/**
182214
* @brief Read a u-blox message of the given type.
183215
* @param message the received u-blox message
@@ -225,12 +257,13 @@ class CallbackHandlers final {
225257
it != reader.pos() + reader.length() + 8; ++it) {
226258
oss << std::hex << static_cast<unsigned int>(*it) << " ";
227259
}
228-
// RCLCPP_DEBUG("U-blox: reading %d bytes\n%s", reader.length() + 8,
260+
// RCLCPP_DEBUG(logger_, "U-blox: reading %d bytes\n%s", reader.length() + 8,
229261
// oss.str().c_str());
230262
}
231263

232264
handle(reader);
233265
}
266+
handle_nmea(reader);
234267

235268
// delete read bytes from ASIO input buffer
236269
std::copy(reader.pos(), reader.end(), data);
@@ -246,6 +279,9 @@ class CallbackHandlers final {
246279
Callbacks callbacks_;
247280
std::mutex callback_mutex_;
248281
int debug_;
282+
283+
//! Callback handler for nmea messages
284+
std::function<void(const std::string &)> callback_nmea_{nullptr};
249285
};
250286

251287
} // namespace ublox_gps

ublox_gps/include/ublox_gps/gps.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <locale>
3636
#include <map>
3737
#include <stdexcept>
38+
#include <string>
3839
#include <vector>
3940

4041
#include <rclcpp/rclcpp.hpp>
@@ -350,6 +351,12 @@ class Gps final {
350351
template <typename T>
351352
void subscribe(typename CallbackHandler_<T>::Callback callback);
352353

354+
/**
355+
* @brief Subscribe to the given Ublox message.
356+
* @param callback the callback handler for the message
357+
*/
358+
void subscribe_nmea(std::function<void(const std::string &)> callback);
359+
353360
/**
354361
* @brief Subscribe to the message with the given ID. This is used for
355362
* messages which have the same format but different message IDs,

ublox_gps/include/ublox_gps/node.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <ublox_msgs/msg/cfg_dat.hpp>
4343
#include <ublox_msgs/msg/inf.h>
4444
#include <rtcm_msgs/msg/message.hpp>
45+
#include <nmea_msgs/msg/sentence.hpp>
4546
// Ublox GPS includes
4647
#include <ublox_gps/component_interface.hpp>
4748
#include <ublox_gps/fix_diagnostic.hpp>
@@ -269,6 +270,9 @@ class UbloxNode final : public rclcpp::Node {
269270
rclcpp::Publisher<ublox_msgs::msg::AidALM>::SharedPtr aid_alm_pub_;
270271
rclcpp::Publisher<ublox_msgs::msg::AidEPH>::SharedPtr aid_eph_pub_;
271272
rclcpp::Publisher<ublox_msgs::msg::AidHUI>::SharedPtr aid_hui_pub_;
273+
rclcpp::Publisher<nmea_msgs::msg::Sentence>::SharedPtr nmea_pub_;
274+
275+
void publish_nmea(const std::string & sentence, const std::string & topic);
272276

273277
//! Navigation rate in measurement cycles, see CfgRate.msg
274278
uint16_t nav_rate_{0};

ublox_gps/package.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@
1818
<depend>diagnostic_msgs</depend>
1919
<depend>diagnostic_updater</depend>
2020
<depend>geometry_msgs</depend>
21+
<depend>nmea_msgs</depend>
2122
<depend>rcl_interfaces</depend>
2223
<depend>rclcpp</depend>
2324
<depend>rclcpp_components</depend>
25+
<depend>rtcm_msgs</depend>
2426
<depend>sensor_msgs</depend>
2527
<depend>std_msgs</depend>
2628
<depend>tf2</depend>
2729
<depend>ublox_msgs</depend>
2830
<depend>ublox_serialization</depend>
29-
<depend>rtcm_msgs</depend>
3031

3132
<export>
3233
<build_type>ament_cmake</build_type>

ublox_gps/src/gps.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ void Gps::setWorker(const std::shared_ptr<Worker>& worker) {
6969
configured_ = static_cast<bool>(worker);
7070
}
7171

72+
void Gps::subscribe_nmea(std::function<void(const std::string &)> callback) {
73+
callbacks_.set_nmea_callback(callback);
74+
}
75+
7276
void Gps::subscribeAcks() {
7377
// Set NACK handler
7478
subscribeId<ublox_msgs::msg::Ack>(std::bind(&Gps::processNack, this,

ublox_gps/src/node.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
#include <ublox_msgs/msg/nav_posecef.hpp>
5757
#include <ublox_msgs/msg/nav_status.hpp>
5858

59+
#include <nmea_msgs/msg/sentence.hpp>
60+
5961
#include <ublox_gps/adr_udr_product.hpp>
6062
#include <ublox_gps/fix_diagnostic.hpp>
6163
#include <ublox_gps/fts_product.hpp>
@@ -217,11 +219,11 @@ void UbloxNode::addFirmwareInterface() {
217219

218220
void UbloxNode::addProductInterface(const std::string & product_category,
219221
const std::string & ref_rov) {
220-
if (product_category == "HPG" && ref_rov == "REF") {
222+
if ((product_category == "HPG" || product_category == "HPS") && ref_rov == "REF") {
221223
components_.push_back(std::make_shared<HpgRefProduct>(nav_rate_, meas_rate_, updater_, rtcms_, this));
222-
} else if (product_category == "HPG" && ref_rov == "ROV") {
224+
} else if ((product_category == "HPG" || product_category == "HPS") && ref_rov == "ROV") {
223225
components_.push_back(std::make_shared<HpgRovProduct>(nav_rate_, updater_, this));
224-
} else if (product_category == "HPG") {
226+
} else if (product_category == "HPG" || product_category == "HPS") {
225227
components_.push_back(std::make_shared<HpPosRecProduct>(nav_rate_, meas_rate_, frame_id_, updater_, rtcms_, this));
226228
} else if (product_category == "TIM") {
227229
components_.push_back(std::make_shared<TimProduct>(frame_id_, updater_, this));
@@ -441,6 +443,8 @@ void UbloxNode::getRosParams() {
441443

442444
this->declare_parameter("publish.tim.tm2", false);
443445

446+
this->declare_parameter("publish.nmea", true);
447+
444448
// INF parameters
445449
this->declare_parameter("inf.all", true);
446450
this->declare_parameter("inf.debug", false);
@@ -489,6 +493,10 @@ void UbloxNode::getRosParams() {
489493
if (getRosBoolean(this, "publish.aid.hui")) {
490494
aid_hui_pub_ = this->create_publisher<ublox_msgs::msg::AidHUI>("aidhui", 1);
491495
}
496+
if (getRosBoolean(this, "publish.nmea")) {
497+
// Larger queue depth to handle all NMEA strings being published consecutively
498+
nmea_pub_ = this->create_publisher<nmea_msgs::msg::Sentence>("nmea", 20);
499+
}
492500

493501
// Create subscriber for RTCM correction data to enable RTK
494502
this->subscription_ = this->create_subscription<rtcm_msgs::msg::Message>("/rtcm", 10, std::bind(&UbloxNode::rtcmCallback, this, std::placeholders::_1));
@@ -606,6 +614,16 @@ void UbloxNode::subscribe() {
606614
1);
607615
}
608616

617+
if (getRosBoolean(this, "publish.nmea")) {
618+
gps_->subscribe_nmea([this](const std::string &sentence) {
619+
nmea_msgs::msg::Sentence m;
620+
m.header.stamp = this->now();
621+
m.header.frame_id = frame_id_;
622+
m.sentence = sentence;
623+
nmea_pub_->publish(m);
624+
});
625+
}
626+
609627
for (const std::shared_ptr<ComponentInterface> & component : components_) {
610628
component->subscribe(gps_);
611629
}

ublox_serialization/include/ublox_serialization/serialization.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <array>
3434
#include <cstdint>
3535
#include <cstring>
36+
#include <string>
3637
#include <utility>
3738
#include <vector>
3839

@@ -367,7 +368,10 @@ class Reader {
367368
*/
368369
Reader(const uint8_t *data, uint32_t count,
369370
const Options &options = Options()) :
370-
data_(data), count_(count), found_(false), options_(options) {}
371+
data_(data), count_(count), found_(false), options_(options)
372+
{
373+
extra_data_.reserve(1024);
374+
}
371375

372376
using iterator = const uint8_t *;
373377

@@ -386,6 +390,8 @@ class Reader {
386390
if (data_[0] == options_.sync_a &&
387391
(count_ == 1 || data_[1] == options_.sync_b)) {
388392
break;
393+
} else {
394+
extra_data_.push_back(data_[0]);
389395
}
390396
}
391397

@@ -532,9 +538,15 @@ class Reader {
532538
return (classId() == class_id && messageId() == message_id);
533539
}
534540

535-
private:
541+
const std::string &getExtraData() const {
542+
return extra_data_;
543+
}
544+
545+
private:
536546
//! The buffer of message bytes
537547
const uint8_t *data_;
548+
//! Unused data from the read buffer, contains nmea messages.
549+
std::string extra_data_;
538550
//! the number of bytes in the buffer, //! decrement as the buffer is read
539551
uint32_t count_;
540552
//! Whether or not a message has been found

0 commit comments

Comments
 (0)