Program Listing for File gps.hpp
↰ Return to documentation for file (/tmp/ws/src/ublox/ublox_gps/include/ublox_gps/gps.hpp
)
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_GPS_GPS_HPP
#define UBLOX_GPS_GPS_HPP
// STL
#include <atomic>
#include <chrono>
#include <locale>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include <rclcpp/rclcpp.hpp>
// Other u-blox packages
#include <ublox_msgs/serialization.hpp>
// u-blox gps
#include <ublox_gps/async_worker.hpp>
#include <ublox_gps/callback.hpp>
#include <ublox_gps/rtcm.hpp>
namespace ublox_gps {
const std::vector<unsigned int> kBaudrates{ 4800,
9600,
19200,
38400,
57600,
115200,
230400,
460800 };
class Gps final {
public:
const int kSetBaudrateSleepMs = 500;
constexpr static double kDefaultAckTimeout = 1.0;
constexpr static int kWriterSize = 2056;
explicit Gps(int debug, const rclcpp::Logger & logger);
~Gps();
Gps(Gps &&c) = delete;
Gps &operator=(Gps &&c) = delete;
Gps(const Gps &c) = delete;
Gps &operator=(const Gps &c) = delete;
void setSaveOnShutdown(bool save_on_shutdown) {
save_on_shutdown_ = save_on_shutdown;
}
void setConfigOnStartup(bool config_on_startup) { config_on_startup_flag_ = config_on_startup; }
void initializeTcp(const std::string & host, const std::string & port);
void initializeUdp(const std::string & host, const std::string & port);
void initializeSerial(const std::string & port, unsigned int baudrate,
uint16_t uart_in, uint16_t uart_out);
void resetSerial(const std::string & port);
bool sendRtcm(const std::vector<uint8_t> &message);
void close();
void reset(const std::chrono::milliseconds& wait);
bool configReset(uint16_t nav_bbr_mask, uint16_t reset_mode);
bool configGnss(ublox_msgs::msg::CfgGNSS gnss,
const std::chrono::milliseconds& wait);
bool clearBbr();
bool configUart1(unsigned int baudrate, uint16_t in_proto_mask,
uint16_t out_proto_mask);
bool disableUart1(ublox_msgs::msg::CfgPRT& prev_config);
bool configUsb(uint16_t tx_ready, uint16_t in_proto_mask,
uint16_t out_proto_mask);
bool configRate(uint16_t meas_rate, uint16_t nav_rate);
bool configRtcm(const std::vector<Rtcm> & rtcms);
bool configSbas(bool enable, uint8_t usage, uint8_t max_sbas);
bool configTmode3Fixed(bool lla_flag,
std::vector<double> arp_position,
std::vector<int8_t> arp_position_hp,
float fixed_pos_acc);
bool configTmode3SurveyIn(unsigned int svin_min_dur, float svin_acc_limit);
bool disableTmode3();
bool setRate(uint8_t class_id, uint8_t message_id, uint8_t rate);
bool setDynamicModel(uint8_t model);
bool setFixMode(uint8_t mode);
bool setDeadReckonLimit(uint8_t limit);
bool setPpp(bool enable);
bool setDgnss(uint8_t mode);
bool setUseAdr(bool enable);
bool setUTCtime();
bool setTimtm2(uint8_t rate);
template <typename T>
void subscribe(typename CallbackHandler_<T>::Callback callback,
unsigned int rate);
template <typename T>
void subscribe(typename CallbackHandler_<T>::Callback callback);
void subscribe_nmea(std::function<void(const std::string &)> callback);
template <typename T>
void subscribeId(typename CallbackHandler_<T>::Callback callback,
unsigned int message_id);
template <typename T>
bool read(T& message,
const std::chrono::milliseconds& timeout = default_timeout_);
bool isInitialized() const { return worker_ != nullptr; }
bool isConfigured() const { return isInitialized() && configured_; }
bool isOpen() const { return worker_->isOpen(); }
template <typename ConfigT>
bool poll(ConfigT& message,
const std::vector<uint8_t>& payload = std::vector<uint8_t>(),
const std::chrono::milliseconds& timeout = default_timeout_);
bool poll(uint8_t class_id, uint8_t message_id,
const std::vector<uint8_t>& payload = std::vector<uint8_t>());
template <typename ConfigT>
bool configure(const ConfigT& message, bool wait = true);
bool waitForAcknowledge(const std::chrono::milliseconds& timeout,
uint8_t class_id, uint8_t msg_id);
void setRawDataCallback(const Worker::WorkerRawCallback& callback);
private:
enum AckType {
NACK,
ACK,
WAIT
};
struct Ack {
AckType type;
uint8_t class_id;
uint8_t msg_id;
};
void setWorker(const std::shared_ptr<Worker>& worker);
void subscribeAcks();
void processAck(const ublox_msgs::msg::Ack &m);
void processNack(const ublox_msgs::msg::Ack &m);
void processUpdSosAck(const ublox_msgs::msg::UpdSOSAck &m);
bool saveOnShutdown();
std::shared_ptr<Worker> worker_;
bool configured_;
bool save_on_shutdown_;
bool config_on_startup_flag_;
static const std::chrono::milliseconds default_timeout_;
std::atomic<Ack> ack_{};
int debug_;
CallbackHandlers callbacks_;
std::string host_, port_;
rclcpp::Logger logger_;
};
template <typename T>
void Gps::subscribe(
typename CallbackHandler_<T>::Callback callback, unsigned int rate) {
if (!setRate(T::CLASS_ID, T::MESSAGE_ID, rate)) {
return;
}
subscribe<T>(callback);
}
template <typename T>
void Gps::subscribe(typename CallbackHandler_<T>::Callback callback) {
callbacks_.insert<T>(callback);
}
template <typename T>
void Gps::subscribeId(typename CallbackHandler_<T>::Callback callback,
unsigned int message_id) {
callbacks_.insert<T>(callback, message_id);
}
template <typename ConfigT>
bool Gps::poll(ConfigT& message,
const std::vector<uint8_t>& payload,
const std::chrono::milliseconds& timeout) {
if (!poll(ConfigT::CLASS_ID, ConfigT::MESSAGE_ID, payload)) {
return false;
}
return read(message, timeout);
}
template <typename T>
bool Gps::read(T& message, const std::chrono::milliseconds& timeout) {
if (!worker_) {
return false;
}
return callbacks_.read(message, timeout);
}
template <typename ConfigT>
bool Gps::configure(const ConfigT& message, bool wait) {
if (!worker_) {
return false;
}
// Reset ack
Ack ack{};
ack.type = WAIT;
ack.class_id = 0;
ack.msg_id = 0;
ack_.store(ack, std::memory_order_seq_cst);
// Encode the message
std::vector<unsigned char> out(kWriterSize);
ublox::Writer writer(out.data(), out.size());
if (!writer.write(message)) {
RCLCPP_ERROR(logger_, "Failed to encode config message 0x%02x / 0x%02x",
message.CLASS_ID, message.MESSAGE_ID);
return false;
}
// Send the message to the device
worker_->send(out.data(), writer.end() - out.data());
if (!wait) {
return true;
}
// Wait for an acknowledgment and return whether or not it was received
return waitForAcknowledge(default_timeout_,
message.CLASS_ID,
message.MESSAGE_ID);
}
} // namespace ublox_gps
#endif // UBLOX_GPS_GPS_HPP