18#include <wgs84_utils/proj_tools.h>
19#include <lanelet2_core/geometry/Point.h>
20#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
25 std::string map_frame_id, std::string base_link_frame_id,
26 std::string heading_frame_id,rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger)
28 , tf_lookup_(tf_lookup)
29 , map_frame_id_(map_frame_id)
30 , base_link_frame_id_(base_link_frame_id)
31 , heading_frame_id_(heading_frame_id)
44 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Ignoring fix message: Could not locate static transform between "
61 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Ignoring fix message: Could not locate static transform between " <<
heading_frame_id_ <<
" and "
62 << fix_msg->header.frame_id);
69 if (tf.getOrigin().x() != 0.0 || tf.getOrigin().y() != 0.0 || tf.getOrigin().z() != 0.0)
71 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Heading frame does not have rotation only transform with sensor frame. The translation will not "
72 "be handled by the GNSS convertor");
80 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Ignoring fix message as no map projection has been recieved.");
84 geometry_msgs::msg::PoseWithCovarianceStamped pose_msg =
87 geometry_msgs::msg::PoseStamped msg;
88 msg.header = pose_msg.header;
90 msg.pose = pose_msg.pose.pose;
100 map_projector_ = std::make_shared<lanelet::projection::LocalFrameProjector>(
101 geo_ref->data.c_str());
103 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"Received map georeference: " << geo_ref->data);
105 std::string axis = wgs84_utils::proj_tools::getAxisFromProjString(geo_ref->data);
107 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"Extracted Axis: " << axis);
111 RCLCPP_INFO_STREAM(
logger_->get_logger(),
"Extracted NED in Map Rotation (x,y,z,w) : ( "
129 const tf2::Transform& baselink_in_sensor,
130 const tf2::Quaternion& sensor_in_ned_heading_rotation,
131 const lanelet::projection::LocalFrameProjector& projector,
132 const tf2::Quaternion& ned_in_map_rotation,
133 gps_msgs::msg::GPSFix fix_msg)
136 const double lat = fix_msg.latitude;
137 const double lon = fix_msg.longitude;
138 const double alt = fix_msg.altitude;
140 lanelet::BasicPoint3d map_point = projector.forward({ lat, lon, alt });
141 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"map_point: " << map_point.x() <<
", " << map_point.y() <<
", " << map_point.z());
143 if (fabs(map_point.x()) > 10000.0 || fabs(map_point.y()) > 10000.0)
146 RCLCPP_WARN_STREAM(
logger_->get_logger(),
"Distance from map origin is larger than supported by system assumptions. Strongly advise "
147 "alternative map origin be used. ");
156 tf2::Quaternion R_m_n(ned_in_map_rotation);
157 tf2::Quaternion R_n_h;
158 R_n_h.setRPY(0, 0, fix_msg.track * wgs84_utils::DEG2RAD);
160 tf2::Quaternion R_h_s = sensor_in_ned_heading_rotation;
162 tf2::Quaternion R_m_s =
163 R_m_n * R_n_h * R_h_s;
166 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"R_m_n (x,y,z,w) : ( "
167 << R_m_n.x() <<
", " << R_m_n.y() <<
", "
168 << R_m_n.z() <<
", " << R_m_n.w());
170 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"R_n_h (x,y,z,w) : ( "
171 << R_n_h.x() <<
", " << R_n_h.y() <<
", "
172 << R_n_h.z() <<
", " << R_n_h.w());
174 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"R_h_s (x,y,z,w) : ( "
175 << R_h_s.x() <<
", " << R_h_s.y() <<
", "
176 << R_h_s.z() <<
", " << R_h_s.w());
178 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"R_m_s (x,y,z,w) : ( "
179 << R_m_s.x() <<
", " << R_m_s.y() <<
", "
180 << R_m_s.z() <<
", " << R_m_s.w());
182 tf2::Transform T_m_s(R_m_s,
183 tf2::Vector3(map_point.x(), map_point.y(), map_point.z()));
185 tf2::Transform T_s_b(baselink_in_sensor);
186 tf2::Transform T_m_b = T_m_s * T_s_b;
188 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"T_m_s (x,y,z,w) : ( "
189 << T_m_s.getRotation().x() <<
", " << T_m_s.getRotation().y() <<
", "
190 << T_m_s.getRotation().z() <<
", " << T_m_s.getRotation().w());
191 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"T_s_b (x,y,z,w) : ( "
192 << T_s_b.getRotation().x() <<
", " << T_s_b.getRotation().y() <<
", "
193 << T_s_b.getRotation().z() <<
", " << T_s_b.getRotation().w());
194 RCLCPP_DEBUG_STREAM(
logger_->get_logger(),
"T_m_b (x,y,z,w) : ( "
195 << T_m_b.getRotation().x() <<
", " << T_m_b.getRotation().y() <<
", "
196 << T_m_b.getRotation().z() <<
", " << T_m_b.getRotation().w());
201 geometry_msgs::msg::PoseWithCovarianceStamped pose;
202 pose.header = fix_msg.header;
204 pose.pose.pose.position.x = T_m_b.getOrigin().getX();
205 pose.pose.pose.position.y = T_m_b.getOrigin().getY();
206 pose.pose.pose.position.z = T_m_b.getOrigin().getZ();
208 pose.pose.pose.orientation.x = T_m_b.getRotation().getX();
209 pose.pose.pose.orientation.y = T_m_b.getRotation().getY();
210 pose.pose.pose.orientation.z = T_m_b.getRotation().getZ();
211 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_
GNSSToMapConvertor(PosePubCallback pose_pub, TransformLookupCallback tf_lookup, std::string map_frame_id, std::string base_link_frame_id, std::string heading_frame_id, rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger)
Constructor.
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...
boost::optional< tf2::Quaternion > getNedInMapRotation()
Get the rotation computed from the recieved georeference or boost::none if unset.
std::string map_frame_id_
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger_
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)