Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
gnss_to_map_convertor::GNSSToMapConvertor Class Reference

#include <GNSSToMapConvertor.hpp>

Collaboration diagram for gnss_to_map_convertor::GNSSToMapConvertor:
Collaboration graph

Public Types

using PosePubCallback = std::function< void(geometry_msgs::msg::PoseStamped)>
 
using TransformLookupCallback = std::function< boost::optional< geometry_msgs::msg::TransformStamped >(const std::string &, const std::string &)>
 

Public Member Functions

 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. More...
 
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 transforms are available. More...
 
void geoReferenceCallback (std_msgs::msg::String::UniquePtr geo_ref)
 Map georeference callback The geodetic description of the map frame should be provided to this callback as a proj library string. The frame orientation must be right handed and aligned with lat/lon however the orientation of this alignment does not matter (enu, ned, etc.) More...
 
boost::optional< tf2::Quaternion > getNedInMapRotation ()
 Get the rotation computed from the recieved georeference or boost::none if unset. More...
 
std::shared_ptr< lanelet::projection::LocalFrameProjector > getMapProjector ()
 Get the projector built from the provided georeference via the callback. More...
 
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 provided projector. More...
 

Private Attributes

PosePubCallback pose_pub_
 
TransformLookupCallback tf_lookup_
 
std::string map_frame_id_
 
std::string base_link_frame_id_
 
std::string heading_frame_id_
 
std::string georeference_ {""}
 
boost::optional< tf2::Quaternion > ned_in_map_rotation_
 
boost::optional< tf2::Quaternion > sensor_in_ned_heading_rotation_
 
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
 
boost::optional< tf2::Transform > baselink_in_sensor_
 
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_
 

Detailed Description

Definition at line 50 of file GNSSToMapConvertor.hpp.

Member Typedef Documentation

◆ PosePubCallback

using gnss_to_map_convertor::GNSSToMapConvertor::PosePubCallback = std::function<void(geometry_msgs::msg::PoseStamped)>

Definition at line 53 of file GNSSToMapConvertor.hpp.

◆ TransformLookupCallback

using gnss_to_map_convertor::GNSSToMapConvertor::TransformLookupCallback = std::function<boost::optional<geometry_msgs::msg::TransformStamped>(const std::string&, const std::string&)>

Function which will return the most recent transform between the provided frames First frame is target second is source If the transform does not exist or cannot be computed the optional returns false

Definition at line 60 of file GNSSToMapConvertor.hpp.

Constructor & Destructor Documentation

◆ GNSSToMapConvertor()

GNSSToMapConvertor::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.

Parameters
pose_pubA function to publish a converted gps fix as a pose to the rest of the system
tf_lookupA function which will lookup the most recent transform between the two provided frames
map_frame_idThe frame id of the frame which the output pose should be considered in
base_link_frame_idThe frame id of the frame which the output pose defines the position and orientation of
heading_frame_idThe frame id of the frame which the heading report aligns with an NED frame
nhA shared pointer to the node handle which will be used to log messages and get clock in the map frame.

Definition at line 24 of file GNSSToMapConvertor.cpp.

28 : pose_pub_(pose_pub)
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)
33 , nh_(nh)
34{
35}
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_

Member Function Documentation

◆ geoReferenceCallback()

void GNSSToMapConvertor::geoReferenceCallback ( std_msgs::msg::String::UniquePtr  geo_ref)

Map georeference callback The geodetic description of the map frame should be provided to this callback as a proj library string. The frame orientation must be right handed and aligned with lat/lon however the orientation of this alignment does not matter (enu, ned, etc.)

Parameters
geo_refThe proj string which defines the geodetic projection of the map frame which is used to convert between GNSS and Map.

Definition at line 100 of file GNSSToMapConvertor.cpp.

101{
102 if (georeference_ != geo_ref->data)
103 {
104 georeference_ = geo_ref->data;
105 map_projector_ = std::make_shared<lanelet::projection::LocalFrameProjector>(
106 geo_ref->data.c_str()); // Build projector from proj string
107
108 RCLCPP_INFO_STREAM(nh_->get_logger(), "Received map georeference: " << geo_ref->data);
109
110 std::string axis = wgs84_utils::proj_tools::getAxisFromProjString(geo_ref->data); // Extract axis for orientation calc
111
112 RCLCPP_INFO_STREAM(nh_->get_logger(), "Extracted Axis: " << axis);
113
114 ned_in_map_rotation_ = wgs84_utils::proj_tools::getRotationOfNEDFromProjAxis(axis); // Extract map rotation from axis
115
116 RCLCPP_INFO_STREAM(nh_->get_logger(), "Extracted NED in Map Rotation (x,y,z,w) : ( "
117 << ned_in_map_rotation_.get().x() << ", " << ned_in_map_rotation_.get().y() << ", "
118 << ned_in_map_rotation_.get().z() << ", " << ned_in_map_rotation_.get().w());
119 }
120}
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
boost::optional< tf2::Quaternion > ned_in_map_rotation_

References georeference_, map_projector_, ned_in_map_rotation_, and nh_.

Referenced by gnss_to_map_convertor::Node::handle_on_configure().

Here is the caller graph for this function:

◆ getMapProjector()

std::shared_ptr< lanelet::projection::LocalFrameProjector > GNSSToMapConvertor::getMapProjector ( )

Get the projector built from the provided georeference via the callback.

Definition at line 127 of file GNSSToMapConvertor.cpp.

128{
129 return map_projector_;
130}

References map_projector_.

◆ getNedInMapRotation()

boost::optional< tf2::Quaternion > GNSSToMapConvertor::getNedInMapRotation ( )

Get the rotation computed from the recieved georeference or boost::none if unset.

Definition at line 122 of file GNSSToMapConvertor.cpp.

123{
125}

References ned_in_map_rotation_.

◆ gnssFixCb()

void GNSSToMapConvertor::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 transforms are available.

Parameters
fix_msgThe message to convert to the map frame

Definition at line 37 of file GNSSToMapConvertor.cpp.

38{
39 if (!baselink_in_sensor_) // Extract the assumed static transform between baselink and the sensor if it was not
40 // already optained
41 {
42 auto tf_msg = tf_lookup_(fix_msg->header.frame_id, base_link_frame_id_);
43 if (!tf_msg) // Failed to get transform
44 {
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 "
47 << fix_msg->header.frame_id << " and " << base_link_frame_id_);
48 return;
49 }
50
51 tf2::Transform tf;
52 tf2::convert(tf_msg.get().transform, tf);
53
55 }
56
57 if (!sensor_in_ned_heading_rotation_) // Extract the assumed static transform between heading frame and the position
58 // sensor frame if it was not already optained
59 {
60 auto tf_msg = tf_lookup_(fix_msg->header.frame_id, heading_frame_id_);
61 if (!tf_msg) // Failed to get transform
62 {
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 "
65 << heading_frame_id_ << " and "
66 << fix_msg->header.frame_id);
67 return;
68 }
69
70 tf2::Transform tf;
71 tf2::convert(tf_msg.get().transform, tf);
72
73 if (tf.getOrigin().x() != 0.0 || tf.getOrigin().y() != 0.0 || tf.getOrigin().z() != 0.0)
74 {
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");
77 }
78
79 sensor_in_ned_heading_rotation_ = tf.getRotation();
80 }
81
82 if (!map_projector_ || !ned_in_map_rotation_) // Check if map projection is available
83 {
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.");
86 return;
87 }
88
89 geometry_msgs::msg::PoseWithCovarianceStamped pose_msg =
91
92 geometry_msgs::msg::PoseStamped msg; // TODO until covariance is added drop it from the output
93 msg.header = pose_msg.header;
94 msg.header.frame_id = map_frame_id_;
95 msg.pose = pose_msg.pose.pose;
96
97 pose_pub_(msg);
98}
boost::optional< tf2::Quaternion > sensor_in_ned_heading_rotation_
boost::optional< tf2::Transform > baselink_in_sensor_
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...
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)

References base_link_frame_id_, baselink_in_sensor_, motion_computation::conversion::convert(), heading_frame_id_, map_frame_id_, map_projector_, ned_in_map_rotation_, nh_, pose_pub_, poseFromGnss(), sensor_in_ned_heading_rotation_, and tf_lookup_.

Referenced by gnss_to_map_convertor::Node::handle_on_configure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ poseFromGnss()

geometry_msgs::msg::PoseWithCovarianceStamped GNSSToMapConvertor::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 provided projector.

ASSUMPTION: This logic assumes that the orientation difference between an NED frame located at the map origin and an NED frame located at the GNSS point are sufficiently small that they can be ignored. Therefore it is assumed the heading report of the GNSS system reguardless of its poition in the map without change in its orientation will give the same result (as far as we are concered). This assumption will break down as the distance between the GNSS recieved and the map origin grows. It is recommended this distance be kept under 10km. If larger distances are required then the map origin should probably be periodically updated with a new georeference.

Parameters
baselink_in_sensorA transform describing the location of the desried output frame (baselink) with respect to the GNSS sensor frame.
sensor_in_ned_heading_rotationA rotation describing the orientation of the heading frame with respect to the position sensor frame
projectorA projector using the proj library which can convert lat/lon points into the map frame projection
ned_in_map_rotationA rotation describibing the orientation of an NED frame located at the map origin with respect to the map frame.
fix_msgThe GNSS message to be converted into the pose in the map frame
Returns
A pose message describing the location and orientation of the baselink frame in the map frame. TODO handle covariance which is not currently included

Definition at line 133 of file GNSSToMapConvertor.cpp.

139{
141 const double lat = fix_msg.latitude;
142 const double lon = fix_msg.longitude;
143 const double alt = fix_msg.altitude;
144
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());
147
148 if (fabs(map_point.x()) > 10000.0 || fabs(map_point.y()) > 10000.0)
149 { // Above 10km from map origin earth curvature will start to have a negative impact on system performance
150
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. ");
153 }
154
156 // This logic assumes that the orientation difference between an NED frame located at the map origin and an NED frame
157 // located at the GNSS point are sufficiently small that they can be ignored. Therefore it is assumed the heading
158 // report of the GNSS system reguardless of its poition in the map without change in its orientation will give the
159 // same result (as far as we are concered).
160
161 tf2::Quaternion R_m_n(ned_in_map_rotation); // Rotation of NED frame in map frame
162 tf2::Quaternion R_n_h; // Rotation of sensor heading report in NED frame
163 R_n_h.setRPY(0, 0, fix_msg.track * wgs84_utils::DEG2RAD);
164
165 tf2::Quaternion R_h_s = sensor_in_ned_heading_rotation; // Rotation of heading report in sensor frame
166
167 tf2::Quaternion R_m_s =
168 R_m_n * R_n_h * R_h_s; // Rotation of sensor in map frame under assumption that distance from map origin is
169 // sufficiently small so as to ignore local changes in NED orientation
170
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());
174
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());
178
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());
182
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());
186
187 tf2::Transform T_m_s(R_m_s,
188 tf2::Vector3(map_point.x(), map_point.y(), map_point.z())); // Reported position and orientation
189 // of sensor frame in map frame
190 tf2::Transform T_s_b(baselink_in_sensor); // Transform between sensor and baselink frame
191 tf2::Transform T_m_b = T_m_s * T_s_b; // Transform between map and baselink frame
192
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());
202
203 // TODO handle covariance
204
205 // Populate message
206 geometry_msgs::msg::PoseWithCovarianceStamped pose;
207 pose.header = fix_msg.header;
208
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();
212
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();
217
218 return pose;
219}

References osm_transform::lat, osm_transform::lon, and nh_.

Referenced by gnssFixCb().

Here is the caller graph for this function:

Member Data Documentation

◆ base_link_frame_id_

std::string gnss_to_map_convertor::GNSSToMapConvertor::base_link_frame_id_
private

Definition at line 139 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ baselink_in_sensor_

boost::optional<tf2::Transform> gnss_to_map_convertor::GNSSToMapConvertor::baselink_in_sensor_
private

Definition at line 154 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ georeference_

std::string gnss_to_map_convertor::GNSSToMapConvertor::georeference_ {""}
private

Definition at line 141 of file GNSSToMapConvertor.hpp.

Referenced by geoReferenceCallback().

◆ heading_frame_id_

std::string gnss_to_map_convertor::GNSSToMapConvertor::heading_frame_id_
private

Definition at line 140 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ map_frame_id_

std::string gnss_to_map_convertor::GNSSToMapConvertor::map_frame_id_
private

Definition at line 138 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ map_projector_

std::shared_ptr<lanelet::projection::LocalFrameProjector> gnss_to_map_convertor::GNSSToMapConvertor::map_projector_
private

Definition at line 150 of file GNSSToMapConvertor.hpp.

Referenced by geoReferenceCallback(), getMapProjector(), and gnssFixCb().

◆ ned_in_map_rotation_

boost::optional<tf2::Quaternion> gnss_to_map_convertor::GNSSToMapConvertor::ned_in_map_rotation_
private

Definition at line 145 of file GNSSToMapConvertor.hpp.

Referenced by geoReferenceCallback(), getNedInMapRotation(), and gnssFixCb().

◆ nh_

std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode> gnss_to_map_convertor::GNSSToMapConvertor::nh_
private

Definition at line 158 of file GNSSToMapConvertor.hpp.

Referenced by geoReferenceCallback(), gnssFixCb(), and poseFromGnss().

◆ pose_pub_

PosePubCallback gnss_to_map_convertor::GNSSToMapConvertor::pose_pub_
private

Definition at line 136 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ sensor_in_ned_heading_rotation_

boost::optional<tf2::Quaternion> gnss_to_map_convertor::GNSSToMapConvertor::sensor_in_ned_heading_rotation_
private

Definition at line 148 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().

◆ tf_lookup_

TransformLookupCallback gnss_to_map_convertor::GNSSToMapConvertor::tf_lookup_
private

Definition at line 137 of file GNSSToMapConvertor.hpp.

Referenced by gnssFixCb().


The documentation for this class was generated from the following files: