diff --git a/src/msgs/CMakeLists.txt b/src/msgs/CMakeLists.txt
index 2b9df55b..83a12abd 100644
--- a/src/msgs/CMakeLists.txt
+++ b/src/msgs/CMakeLists.txt
@@ -19,6 +19,7 @@ rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Currentdraw.msg"
"msg/JointReceiver.msg"
"msg/SystemInfo.msg"
+ "msg/Heading.msg"
"srv/SetController.srv"
"action/NavigateToGPS.action"
DEPENDENCIES std_msgs geometry_msgs sensor_msgs builtin_interfaces action_msgs
diff --git a/src/msgs/msg/Heading.msg b/src/msgs/msg/Heading.msg
new file mode 100644
index 00000000..7f2007c9
--- /dev/null
+++ b/src/msgs/msg/Heading.msg
@@ -0,0 +1,8 @@
+# heading: ROS convention (0=East, CCW, radians). Converted from compass bearing,
+# but does not account for magnetic declination.
+# compass_bearing: raw magnetometer reading (0=magnetic North, CW, degrees).
+
+std_msgs/Header header
+float64 heading
+float64 heading_acc
+float64 compass_bearing
diff --git a/src/subsystems/navigation/athena_gps/CMakeLists.txt b/src/subsystems/navigation/athena_gps/CMakeLists.txt
index 33850750..ea72dfae 100644
--- a/src/subsystems/navigation/athena_gps/CMakeLists.txt
+++ b/src/subsystems/navigation/athena_gps/CMakeLists.txt
@@ -14,6 +14,7 @@ find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(sensor_msgs REQUIRED)
+find_package(msgs REQUIRED)
find_package(MAVSDK REQUIRED)
add_executable(athena_gps src/PixhawkNode.cpp)
@@ -26,6 +27,7 @@ ament_target_dependencies(athena_gps
rclcpp
std_msgs
sensor_msgs
+ msgs
)
target_link_libraries(athena_gps
MAVSDK::mavsdk
diff --git a/src/subsystems/navigation/athena_gps/package.xml b/src/subsystems/navigation/athena_gps/package.xml
index 2138e4c3..2cd9b998 100644
--- a/src/subsystems/navigation/athena_gps/package.xml
+++ b/src/subsystems/navigation/athena_gps/package.xml
@@ -12,6 +12,7 @@
rclcpp
std_msgs
sensor_msgs
+ msgs
ament_lint_auto
ament_lint_common
diff --git a/src/subsystems/navigation/athena_gps/src/PixhawkNode.cpp b/src/subsystems/navigation/athena_gps/src/PixhawkNode.cpp
index c6d9a8e9..545129b5 100644
--- a/src/subsystems/navigation/athena_gps/src/PixhawkNode.cpp
+++ b/src/subsystems/navigation/athena_gps/src/PixhawkNode.cpp
@@ -7,7 +7,7 @@
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/imu.hpp"
#include "sensor_msgs/msg/nav_sat_fix.hpp"
-#include "std_msgs/msg/float64.hpp"
+#include "msgs/msg/heading.hpp"
#include
#include
@@ -54,7 +54,7 @@ class PixhawkNode : public rclcpp::Node
// Create publishers unconditionally so they're always valid
imu_publisher_ = this->create_publisher(imu_topic, 10);
gps_publisher_ = this->create_publisher(gps_topic, 10);
- heading_publisher_ = this->create_publisher(heading_topic, 10);
+ heading_publisher_ = this->create_publisher(heading_topic, 10);
// Create MAVSDK instance
mavsdk_ = std::make_unique(Mavsdk::Configuration{
@@ -78,7 +78,7 @@ class PixhawkNode : public rclcpp::Node
rclcpp::Publisher::SharedPtr imu_publisher_;
rclcpp::Publisher::SharedPtr gps_publisher_;
- rclcpp::Publisher::SharedPtr heading_publisher_;
+ rclcpp::Publisher::SharedPtr heading_publisher_;
rclcpp::TimerBase::SharedPtr init_timer_;
Telemetry::GpsInfo last_gps_info_;
@@ -94,12 +94,6 @@ class PixhawkNode : public rclcpp::Node
bool is_initialized_;
bool connection_added_;
- void publish_heading() {
- auto msg = std_msgs::msg::Float64();
- msg.data = last_heading_deg_;
- heading_publisher_->publish(msg);
- }
-
void try_initialize() {
if (is_initialized_) {
return;
@@ -151,7 +145,6 @@ class PixhawkNode : public rclcpp::Node
RCLCPP_INFO(this->get_logger(), "Telemetry rates configured successfully");
- // Subscribe to telemetry streams
telemetry_->subscribe_imu([this](const Telemetry::Imu &imu) {
imu_callback(imu);
});
@@ -160,11 +153,6 @@ class PixhawkNode : public rclcpp::Node
last_attitude_quaternion_ = quaternion;
});
- telemetry_->subscribe_heading([this](Telemetry::Heading heading) {
- last_heading_deg_ = heading.heading_deg;
- publish_heading();
- });
-
telemetry_->subscribe_raw_gps([this](const Telemetry::RawGps &raw_gps) {
raw_gps_callback(raw_gps);
});
@@ -228,39 +216,39 @@ class PixhawkNode : public rclcpp::Node
}
void raw_gps_callback(const Telemetry::RawGps raw_gps) {
- auto msg = sensor_msgs::msg::NavSatFix();
+ auto gps_msg = sensor_msgs::msg::NavSatFix();
- msg.header.stamp = this->now();
- msg.header.frame_id = gps_frame_id_;
+ gps_msg.header.stamp = this->now();
+ gps_msg.header.frame_id = gps_frame_id_;
- msg.latitude = raw_gps.latitude_deg;
- msg.longitude = raw_gps.longitude_deg;
- msg.altitude = raw_gps.altitude_ellipsoid_m;
+ gps_msg.latitude = raw_gps.latitude_deg;
+ gps_msg.longitude = raw_gps.longitude_deg;
+ gps_msg.altitude = raw_gps.altitude_ellipsoid_m;
// Map GPS fix to ROS fix
if (last_gps_info_.num_satellites > 0) {
switch (last_gps_info_.fix_type) {
case Telemetry::FixType::NoGps:
case Telemetry::FixType::NoFix:
- msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
+ gps_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
break;
case Telemetry::FixType::Fix2D:
- msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_FIX;
+ gps_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_FIX;
break;
case Telemetry::FixType::Fix3D:
case Telemetry::FixType::FixDgps:
case Telemetry::FixType::RtkFloat:
case Telemetry::FixType::RtkFixed:
- msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_GBAS_FIX;
+ gps_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_GBAS_FIX;
break;
default:
- msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
+ gps_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
}
} else {
- msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
+ gps_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
}
- msg.status.service = sensor_msgs::msg::NavSatStatus::SERVICE_GPS;
+ gps_msg.status.service = sensor_msgs::msg::NavSatStatus::SERVICE_GPS;
// calcilate variances
if (!std::isnan(raw_gps.horizontal_uncertainty_m) &&
@@ -269,23 +257,30 @@ class PixhawkNode : public rclcpp::Node
double h_variance = raw_gps.horizontal_uncertainty_m * raw_gps.horizontal_uncertainty_m;
double v_variance = raw_gps.vertical_uncertainty_m * raw_gps.vertical_uncertainty_m;
- msg.position_covariance[0] = h_variance;
- msg.position_covariance[4] = h_variance;
- msg.position_covariance[8] = v_variance;
+ gps_msg.position_covariance[0] = h_variance;
+ gps_msg.position_covariance[4] = h_variance;
+ gps_msg.position_covariance[8] = v_variance;
// refine estimate using doppler
if (!std::isnan(raw_gps.hdop) && !std::isnan(raw_gps.vdop)) {
- msg.position_covariance[0] = h_variance * (raw_gps.hdop / 2.0);
- msg.position_covariance[4] = h_variance * (raw_gps.hdop / 2.0);
- msg.position_covariance[8] = v_variance * raw_gps.vdop;
+ gps_msg.position_covariance[0] = h_variance * (raw_gps.hdop / 2.0);
+ gps_msg.position_covariance[4] = h_variance * (raw_gps.hdop / 2.0);
+ gps_msg.position_covariance[8] = v_variance * raw_gps.vdop;
}
- msg.position_covariance_type = sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
+ gps_msg.position_covariance_type = sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
} else {
- msg.position_covariance_type = sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_UNKNOWN;
+ gps_msg.position_covariance_type = sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_UNKNOWN;
}
-
- gps_publisher_->publish(msg);
+ auto heading_msg = msgs::msg::Heading();
+ heading_msg.header.stamp = this->now();
+ heading_msg.compass_bearing = raw_gps.yaw_deg;
+ // Convert from compass bearing (0=magnetic North, CW, degrees) to ROS convention (0=East, CCW, radians)
+ heading_msg.heading = (90.0 - raw_gps.yaw_deg) * M_PI / 180.0;
+ heading_msg.heading_acc = raw_gps.heading_uncertainty_deg * M_PI / 180.0;
+
+ heading_publisher_->publish(heading_msg);
+ gps_publisher_->publish(gps_msg);
}
};