18#include <wgs84_utils/proj_tools.h>
19#include <lanelet2_core/geometry/Point.h>
20#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
25 std::string map_frame_id, std::string base_link_frame_id,
26 std::string heading_frame_id,
27 std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode> nh)
29 , tf_lookup_(tf_lookup)
30 , map_frame_id_(map_frame_id)
31 , base_link_frame_id_(base_link_frame_id)
32 , heading_frame_id_(heading_frame_id)
45 RCLCPP_WARN_STREAM_THROTTLE(
nh_->get_logger(), *
nh_->get_clock(), 1000,
46 "Throttled Log 1s: Ignoring fix message: Could not locate static transform between "
63 RCLCPP_WARN_STREAM_THROTTLE(
nh_->get_logger(), *
nh_->get_clock(), 1000,
64 "Throttled Log 1s: Ignoring fix message: Could not locate static transform between "
66 << fix_msg->header.frame_id);
73 if (tf.getOrigin().x() != 0.0 || tf.getOrigin().y() != 0.0 || tf.getOrigin().z() != 0.0)
75 RCLCPP_WARN_STREAM(
nh_->get_logger(),
"Heading frame does not have rotation only transform with sensor frame. The translation will not "
76 "be handled by the GNSS convertor");
84 RCLCPP_WARN_STREAM_THROTTLE(
nh_->get_logger(), *
nh_->get_clock(), 1000,
85 "Throttled Log 1s: Ignoring fix message as no map projection has been received.");
89 geometry_msgs::msg::PoseWithCovarianceStamped pose_msg =
92 geometry_msgs::msg::PoseStamped msg;
93 msg.header = pose_msg.header;
95 msg.pose = pose_msg.pose.pose;
105 map_projector_ = std::make_shared<lanelet::projection::LocalFrameProjector>(
106 geo_ref->data.c_str());
108 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"Received map georeference: " << geo_ref->data);
110 std::string axis = wgs84_utils::proj_tools::getAxisFromProjString(geo_ref->data);
112 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"Extracted Axis: " << axis);
116 RCLCPP_INFO_STREAM(
nh_->get_logger(),
"Extracted NED in Map Rotation (x,y,z,w) : ( "
134 const tf2::Transform& baselink_in_sensor,
135 const tf2::Quaternion& sensor_in_ned_heading_rotation,
136 const lanelet::projection::LocalFrameProjector& projector,
137 const tf2::Quaternion& ned_in_map_rotation,
138 gps_msgs::msg::GPSFix fix_msg)
141 const double lat = fix_msg.latitude;
142 const double lon = fix_msg.longitude;
143 const double alt = fix_msg.altitude;
145 lanelet::BasicPoint3d map_point = projector.forward({
lat,
lon, alt });
146 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"map_point: " << map_point.x() <<
", " << map_point.y() <<
", " << map_point.z());
148 if (fabs(map_point.x()) > 10000.0 || fabs(map_point.y()) > 10000.0)
151 RCLCPP_WARN_STREAM(
nh_->get_logger(),
"Distance from map origin is larger than supported by system assumptions. Strongly advise "
152 "alternative map origin be used. ");
161 tf2::Quaternion R_m_n(ned_in_map_rotation);
162 tf2::Quaternion R_n_h;
163 R_n_h.setRPY(0, 0, fix_msg.track * wgs84_utils::DEG2RAD);
165 tf2::Quaternion R_h_s = sensor_in_ned_heading_rotation;
167 tf2::Quaternion R_m_s =
168 R_m_n * R_n_h * R_h_s;
171 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"R_m_n (x,y,z,w) : ( "
172 << R_m_n.x() <<
", " << R_m_n.y() <<
", "
173 << R_m_n.z() <<
", " << R_m_n.w());
175 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"R_n_h (x,y,z,w) : ( "
176 << R_n_h.x() <<
", " << R_n_h.y() <<
", "
177 << R_n_h.z() <<
", " << R_n_h.w());
179 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"R_h_s (x,y,z,w) : ( "
180 << R_h_s.x() <<
", " << R_h_s.y() <<
", "
181 << R_h_s.z() <<
", " << R_h_s.w());
183 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"R_m_s (x,y,z,w) : ( "
184 << R_m_s.x() <<
", " << R_m_s.y() <<
", "
185 << R_m_s.z() <<
", " << R_m_s.w());
187 tf2::Transform T_m_s(R_m_s,
188 tf2::Vector3(map_point.x(), map_point.y(), map_point.z()));
190 tf2::Transform T_s_b(baselink_in_sensor);
191 tf2::Transform T_m_b = T_m_s * T_s_b;
193 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"T_m_s (x,y,z,w) : ( "
194 << T_m_s.getRotation().x() <<
", " << T_m_s.getRotation().y() <<
", "
195 << T_m_s.getRotation().z() <<
", " << T_m_s.getRotation().w());
196 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"T_s_b (x,y,z,w) : ( "
197 << T_s_b.getRotation().x() <<
", " << T_s_b.getRotation().y() <<
", "
198 << T_s_b.getRotation().z() <<
", " << T_s_b.getRotation().w());
199 RCLCPP_DEBUG_STREAM(
nh_->get_logger(),
"T_m_b (x,y,z,w) : ( "
200 << T_m_b.getRotation().x() <<
", " << T_m_b.getRotation().y() <<
", "
201 << T_m_b.getRotation().z() <<
", " << T_m_b.getRotation().w());
206 geometry_msgs::msg::PoseWithCovarianceStamped pose;
207 pose.header = fix_msg.header;
209 pose.pose.pose.position.x = T_m_b.getOrigin().getX();
210 pose.pose.pose.position.y = T_m_b.getOrigin().getY();
211 pose.pose.pose.position.z = T_m_b.getOrigin().getZ();
213 pose.pose.pose.orientation.x = T_m_b.getRotation().getX();
214 pose.pose.pose.orientation.y = T_m_b.getRotation().getY();
215 pose.pose.pose.orientation.z = T_m_b.getRotation().getZ();
216 pose.pose.pose.orientation.w = T_m_b.getRotation().getW();
std::string base_link_frame_id_
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
std::function< void(geometry_msgs::msg::PoseStamped)> PosePubCallback
void geoReferenceCallback(std_msgs::msg::String::UniquePtr geo_ref)
Map georeference callback The geodetic description of the map frame should be provided to this callba...
std::function< boost::optional< geometry_msgs::msg::TransformStamped >(const std::string &, const std::string &)> TransformLookupCallback
boost::optional< tf2::Quaternion > sensor_in_ned_heading_rotation_
TransformLookupCallback tf_lookup_
void gnssFixCb(gps_msgs::msg::GPSFix::UniquePtr fix_msg)
GNSS Fix callback which will publish a pose representing that fix in the map frame if the required tr...
std::shared_ptr< lanelet::projection::LocalFrameProjector > getMapProjector()
Get the projector built from the provided georeference via the callback.
std::string heading_frame_id_
std::string georeference_
boost::optional< tf2::Transform > baselink_in_sensor_
boost::optional< tf2::Quaternion > ned_in_map_rotation_
geometry_msgs::msg::PoseWithCovarianceStamped poseFromGnss(const tf2::Transform &baselink_in_sensor, const tf2::Quaternion &sensor_in_ned_heading_rotation, const lanelet::projection::LocalFrameProjector &projector, const tf2::Quaternion &ned_in_map_rotation, gps_msgs::msg::GPSFix fix_msg)
Converts a provided GNSS fix message into a pose message for the map frame describibed by the provide...
GNSSToMapConvertor(PosePubCallback pose_pub, TransformLookupCallback tf_lookup, std::string map_frame_id, std::string base_link_frame_id, std::string heading_frame_id, std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh)
Constructor.
boost::optional< tf2::Quaternion > getNedInMapRotation()
Get the rotation computed from the recieved georeference or boost::none if unset.
std::string map_frame_id_
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_
PosePubCallback pose_pub_
void convert(const carma_v2x_msgs::msg::PSM &in_msg, carma_perception_msgs::msg::ExternalObject &out_msg, const std::string &map_frame_id, double pred_period, double pred_step_size, const lanelet::projection::LocalFrameProjector &map_projector, const tf2::Quaternion &ned_in_map_rotation, rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock)