Program Listing for File ublox_firmware7plus.hpp
↰ Return to documentation for file (/tmp/ws/src/ublox/ublox_gps/include/ublox_gps/ublox_firmware7plus.hpp
)
#ifndef UBLOX_GPS_UBLOX_FIRMWARE7PLUS_HPP
#define UBLOX_GPS_UBLOX_FIRMWARE7PLUS_HPP
#include <memory>
#include <string>
#include <diagnostic_msgs/msg/diagnostic_status.hpp>
#include <diagnostic_updater/diagnostic_updater.hpp>
#include <geometry_msgs/msg/twist_with_covariance_stamped.hpp>
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/nav_sat_fix.hpp>
#include <ublox_msgs/msg/nav_pvt.hpp>
#include <ublox_gps/fix_diagnostic.hpp>
#include <ublox_gps/gnss.hpp>
#include <ublox_gps/ublox_firmware.hpp>
#include <ublox_gps/utils.hpp>
namespace ublox_node {
template<typename NavPVT>
class UbloxFirmware7Plus : public UbloxFirmware {
public:
explicit UbloxFirmware7Plus(const std::string & frame_id, std::shared_ptr<diagnostic_updater::Updater> updater, std::shared_ptr<FixDiagnostic> freq_diag, std::shared_ptr<Gnss> gnss, rclcpp::Node* node)
: UbloxFirmware(updater, gnss, node), frame_id_(frame_id), freq_diag_(freq_diag) {
// NavPVT publisher
if (getRosBoolean(node_, "publish.nav.pvt")) {
nav_pvt_pub_ = node_->create_publisher<NavPVT>("~/navpvt", 1);
}
fix_pub_ =
node_->create_publisher<sensor_msgs::msg::NavSatFix>("~/fix", 1);
vel_pub_ =
node_->create_publisher<geometry_msgs::msg::TwistWithCovarianceStamped>("~/fix_velocity",
1);
}
void callbackNavPvt(const NavPVT& m) {
if (getRosBoolean(node_, "publish.nav.pvt")) {
// NavPVT publisher
nav_pvt_pub_->publish(m);
}
//
// NavSatFix message
//
sensor_msgs::msg::NavSatFix fix;
fix.header.frame_id = frame_id_;
// set the timestamp
uint8_t valid_time = m.VALID_DATE | m.VALID_TIME | m.VALID_FULLY_RESOLVED;
if (((m.valid & valid_time) == valid_time) &&
(m.flags2 & m.FLAGS2_CONFIRMED_AVAILABLE)) {
// Use NavPVT timestamp since it is valid
// The time in nanoseconds from the NavPVT message can be between -1e9 and 1e9
// The ros time uses only unsigned values, so a negative nano seconds must be
// converted to a positive value
if (m.nano < 0) {
fix.header.stamp.sec = toUtcSeconds(m) - 1;
fix.header.stamp.nanosec = static_cast<uint32_t>(m.nano + 1e9);
}
else {
fix.header.stamp.sec = toUtcSeconds(m);
fix.header.stamp.nanosec = static_cast<uint32_t>(m.nano);
}
} else {
// Use ROS time since NavPVT timestamp is not valid
fix.header.stamp = node_->now();
}
// Set the LLA
fix.latitude = m.lat * 1e-7; // to deg
fix.longitude = m.lon * 1e-7; // to deg
fix.altitude = m.height * 1e-3; // to [m]
// Set the Fix status
bool fixOk = m.flags & m.FLAGS_GNSS_FIX_OK;
if (fixOk && m.fix_type >= m.FIX_TYPE_2D) {
fix.status.status = sensor_msgs::msg::NavSatStatus::STATUS_FIX;
if (m.flags & m.CARRIER_PHASE_FIXED) {
fix.status.status = sensor_msgs::msg::NavSatStatus::STATUS_GBAS_FIX;
}
} else {
fix.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
}
// Set the service based on GNSS configuration
fix.status.service = fix_status_service_;
// Set the position covariance
const double var_h = pow(m.h_acc / 1000.0, 2); // to [m^2]
const double var_v = pow(m.v_acc / 1000.0, 2); // to [m^2]
fix.position_covariance[0] = var_h;
fix.position_covariance[4] = var_h;
fix.position_covariance[8] = var_v;
fix.position_covariance_type =
sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
fix_pub_->publish(fix);
//
// Twist message
//
geometry_msgs::msg::TwistWithCovarianceStamped velocity;
velocity.header.stamp = fix.header.stamp;
velocity.header.frame_id = frame_id_;
// convert to XYZ linear velocity [m/s] in ENU
velocity.twist.twist.linear.x = m.vel_e * 1e-3;
velocity.twist.twist.linear.y = m.vel_n * 1e-3;
velocity.twist.twist.linear.z = -m.vel_d * 1e-3;
// Set the covariance
const double cov_speed = pow(m.s_acc * 1e-3, 2);
const int cols = 6;
velocity.twist.covariance[cols * 0 + 0] = cov_speed;
velocity.twist.covariance[cols * 1 + 1] = cov_speed;
velocity.twist.covariance[cols * 2 + 2] = cov_speed;
velocity.twist.covariance[cols * 3 + 3] = -1; // angular rate unsupported
vel_pub_->publish(velocity);
//
// Update diagnostics
//
last_nav_pvt_ = m;
freq_diag_->diagnostic->tick(fix.header.stamp);
}
protected:
void fixDiagnostic(diagnostic_updater::DiagnosticStatusWrapper& stat) override {
// check the last message, convert to diagnostic
if (last_nav_pvt_.fix_type ==
ublox_msgs::msg::NavPVT::FIX_TYPE_DEAD_RECKONING_ONLY) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
stat.message = "Dead reckoning only";
} else if (last_nav_pvt_.fix_type == ublox_msgs::msg::NavPVT::FIX_TYPE_2D) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
stat.message = "2D fix";
} else if (last_nav_pvt_.fix_type == ublox_msgs::msg::NavPVT::FIX_TYPE_3D) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
stat.message = "3D fix";
} else if (last_nav_pvt_.fix_type ==
ublox_msgs::msg::NavPVT::FIX_TYPE_GNSS_DEAD_RECKONING_COMBINED) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
stat.message = "GPS and dead reckoning combined";
} else if (last_nav_pvt_.fix_type ==
ublox_msgs::msg::NavPVT::FIX_TYPE_TIME_ONLY) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
stat.message = "Time only fix";
}
// If fix not ok (w/in DOP & Accuracy Masks), raise the diagnostic level
if (!(last_nav_pvt_.flags & ublox_msgs::msg::NavPVT::FLAGS_GNSS_FIX_OK)) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
stat.message += ", fix not ok";
}
// Raise diagnostic level to error if no fix
if (last_nav_pvt_.fix_type == ublox_msgs::msg::NavPVT::FIX_TYPE_NO_FIX) {
stat.level = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
stat.message = "No fix";
}
// append last fix position
stat.add("iTOW [ms]", last_nav_pvt_.i_tow);
stat.add("Latitude [deg]", last_nav_pvt_.lat * 1e-7);
stat.add("Longitude [deg]", last_nav_pvt_.lon * 1e-7);
stat.add("Altitude [m]", last_nav_pvt_.height * 1e-3);
stat.add("Height above MSL [m]", last_nav_pvt_.h_msl * 1e-3);
stat.add("Horizontal Accuracy [m]", last_nav_pvt_.h_acc * 1e-3);
stat.add("Vertical Accuracy [m]", last_nav_pvt_.v_acc * 1e-3);
stat.add("# SVs used", static_cast<int>(last_nav_pvt_.num_sv));
}
NavPVT last_nav_pvt_;
// Whether or not to enable the given GNSS
bool enable_gps_{false};
bool enable_glonass_{false};
bool enable_qzss_{false};
uint32_t qzss_sig_cfg_{0};
typename rclcpp::Publisher<NavPVT>::SharedPtr nav_pvt_pub_;
rclcpp::Publisher<sensor_msgs::msg::NavSatFix>::SharedPtr fix_pub_;
rclcpp::Publisher<geometry_msgs::msg::TwistWithCovarianceStamped>::SharedPtr vel_pub_;
std::string frame_id_;
std::shared_ptr<FixDiagnostic> freq_diag_;
};
} // namespace ublox_node
#endif // UBLOX_GPS_UBLOX_FIRMWARE7PLUS_HPP