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.
motion_computation::conversion Namespace Reference

Namespaces

namespace  impl
 

Functions

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)
 
void convert (const carma_v2x_msgs::msg::BSM &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, tf2::Quaternion ned_in_map_rotation)
 
void convert (const carma_v2x_msgs::msg::MobilityPath &in_msg, carma_perception_msgs::msg::ExternalObject &out_msg, const lanelet::projection::LocalFrameProjector &map_projector)
 

Function Documentation

◆ convert() [1/3]

void motion_computation::conversion::convert ( const carma_v2x_msgs::msg::BSM &  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,
tf2::Quaternion  ned_in_map_rotation 
)

Definition at line 28 of file bsm_to_external_object_convertor.cpp.

33{
34 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::BSM_ID_PRESENCE_VECTOR;
35
36 // assume any BSM is a dynamic object since its sent be a vehicle
37 out_msg.dynamic_obj = true;
38 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::DYNAMIC_OBJ_PRESENCE;
39
41 // Generate a unique object id from the bsm id
42 out_msg.id = 0;
43 for (int i = in_msg.core_data.id.size() - 1; i >= 0;
44 i--) { // using signed iterator to handle empty case
45 // each byte of the bsm id gets placed in one byte of the object id.
46 // This should result in very large numbers which will be unlikely to
47 // conflict with standard detections
48 out_msg.id |= in_msg.core_data.id[i] << (8 * i);
49 }
50 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::ID_PRESENCE_VECTOR;
51
53 out_msg.bsm_id = in_msg.core_data.id;
54 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::BSM_ID_PRESENCE_VECTOR;
55
57 // Compute the timestamp
58 out_msg.header.stamp = in_msg.header.stamp;
59 out_msg.header.frame_id = map_frame_id;
60
62
63 if (
64 in_msg.core_data.size.presence_vector &
65 carma_v2x_msgs::msg::VehicleSize::VEHICLE_LENGTH_AVAILABLE) {
66 // ExternalObject size is half of each dimension
67 out_msg.size.x = in_msg.core_data.size.vehicle_length / 2;
68 } else {
69 out_msg.size.x = 1.0; // value from mob path to external obj conversion
70 }
71
72 if (
73 in_msg.core_data.size.presence_vector &
74 carma_v2x_msgs::msg::VehicleSize::VEHICLE_WIDTH_AVAILABLE) {
75 // ExternalObject size is half of each dimension
76 out_msg.size.y = in_msg.core_data.size.vehicle_width / 2;
77 } else {
78 out_msg.size.y = 1.0; // value from mob path to external obj conversion
79 }
80
81 out_msg.size.z = 2.0; // value from mob path to external obj conversion
82
83 out_msg.object_type = carma_perception_msgs::msg::ExternalObject::SMALL_VEHICLE;
84
86 // Set the velocity
87 if (in_msg.core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::SPEED_AVAILABLE) {
88 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::VELOCITY_PRESENCE_VECTOR;
89 float_t speed_mps = in_msg.core_data.speed;
90
91 out_msg.velocity.twist.linear.x = std::min(speed_mps, in_msg.core_data.SPEED_MAX);
92 }
93
94 // NOTE: The velocity covariance is not provided in the BSM. In order to
95 // compute it you need at least two BSM messages
96 // Tracking and associating BSM messages would be an increase in
97 // complexity for this conversion which is not warranted without an
98 // existing use case for the velocity covariance. If a use case is
99 // presented for it, such an addition can be made at that time.
100
102 // Compute the position covariance
103 // For computing confidence we will use the largest provided standard
104 // deviation of position
105 double largest_position_std =
106 std::max(in_msg.core_data.accuracy.semi_major, in_msg.core_data.accuracy.semi_minor);
107
108 double lat_variance = in_msg.core_data.accuracy.semi_minor * in_msg.core_data.accuracy.semi_minor;
109
110 double lon_variance = in_msg.core_data.accuracy.semi_major * in_msg.core_data.accuracy.semi_major;
111
112 double heading_variance =
113 in_msg.core_data.accuracy.orientation * in_msg.core_data.accuracy.orientation;
114
115 double position_confidence = 0.1; // Default will be 10% confidence. If the position accuracy is
116 // available then this value will be updated
117
118 // A standard deviation which is larger than the acceptable value to give
119 // 95% confidence interval on fitting the pedestrian within one 3.7m lane
120 constexpr double MAX_POSITION_STD = 1.85;
121
122 if (
123 (in_msg.core_data.accuracy.presence_vector |
124 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_AVAILABLE) &&
125 (in_msg.core_data.accuracy.presence_vector |
126 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_ORIENTATION_AVAILABLE)) {
127 // Both accuracies available
128
129 // NOTE: ExternalObject.msg does not clearly define what is meant by
130 // position confidence
131 // Here we are providing a linear scale based on the positional accuracy
132 // where 0 confidence would denote A standard deviation which is larger
133 // than the acceptable value to give 95% confidence interval on fitting
134 // the pedestrian within one 3.7m lane
135 // Set the confidence
136 // Without a way of getting the velocity confidence from the BSM we will use
137 // the position confidence for both
138 out_msg.confidence = 1.0 - std::min(1.0, fabs(largest_position_std / MAX_POSITION_STD));
139 out_msg.presence_vector |=
140 carma_perception_msgs::msg::ExternalObject::CONFIDENCE_PRESENCE_VECTOR;
141 } else if (
142 in_msg.core_data.accuracy.presence_vector |
143 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_AVAILABLE) {
144 // Position accuracy available
145
146 heading_variance = 1.0; // Yaw variance is not available so mark as
147 // impossible perfect case
148
149 // Same calculation as shown in above condition. See that for description
150 out_msg.confidence = 1.0 - std::min(1.0, fabs(largest_position_std / MAX_POSITION_STD));
151 out_msg.presence_vector |=
152 carma_perception_msgs::msg::ExternalObject::CONFIDENCE_PRESENCE_VECTOR;
153 } else if (
154 in_msg.core_data.accuracy.presence_vector |
155 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_ORIENTATION_AVAILABLE) {
156 // Orientation accuracy available
157
158 lat_variance = 1.0;
159 lon_variance = 1.0;
160 }
161 // Else: No accuracies available
162
164 // Compute the pose
165
166 if (
167 (in_msg.core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::LATITUDE_AVAILABLE) &&
168 (in_msg.core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::LONGITUDE_AVAILABLE) &&
169 (in_msg.core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::ELEVATION_AVAILABLE) &&
170 (in_msg.core_data.presence_vector & carma_v2x_msgs::msg::BSMCoreData::HEADING_AVAILABLE)) {
171 double longitude = std::min(in_msg.core_data.longitude, in_msg.core_data.LONGITUDE_MAX);
172 longitude = std::max(longitude, in_msg.core_data.LONGITUDE_MIN);
173
174 double latitude = std::min(in_msg.core_data.latitude, in_msg.core_data.LATITUDE_MAX);
175 // latitude = std::max(latitude, in_msg.core_data.LATITUDE_MIN);
176
177 double elev = std::min(in_msg.core_data.elev, in_msg.core_data.ELEVATION_MAX);
178 // elev = std::max(elev, (float)in_msg.core_data.ELEVATION_MIN);
179
180 double heading = std::min(in_msg.core_data.heading, in_msg.core_data.HEADING_MAX);
181 // heading = std::max(heading, in_msg.core_data.HEADING_MIN);
182
183 out_msg.pose = impl::pose_from_gnss(
184 map_projector, ned_in_map_rotation, {latitude, longitude, elev}, heading, lat_variance,
185 lon_variance, heading_variance);
186 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::POSE_PRESENCE_VECTOR;
187 }
188 // Else: No pose available
189
190 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::POSE_PRESENCE_VECTOR;
191
193 // Compute predictions
194 // For prediction, if the prediction is available we will sample it
195 // If not then assume linear motion
196
197 std::vector<geometry_msgs::msg::Pose> predicted_poses;
198
199 predicted_poses = impl::sample_2d_linear_motion(
200 out_msg.pose.pose, out_msg.velocity.twist.linear.x, pred_period, pred_step_size);
201
202 out_msg.predictions = impl::predicted_poses_to_predicted_state(
203 predicted_poses, out_msg.velocity.twist.linear.x, rclcpp::Time(out_msg.header.stamp),
204 rclcpp::Duration(pred_step_size * 1e9), map_frame_id, out_msg.confidence, out_msg.confidence);
205 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::PREDICTION_PRESENCE_VECTOR;
206}
geometry_msgs::msg::PoseWithCovariance pose_from_gnss(const lanelet::projection::LocalFrameProjector &projector, const tf2::Quaternion &ned_in_map_rotation, const lanelet::GPSPoint &gps_point, const double &heading, const double lat_variance, const double lon_variance, const double heading_variance)
std::vector< carma_perception_msgs::msg::PredictedState > predicted_poses_to_predicted_state(const std::vector< geometry_msgs::msg::Pose > &poses, double constant_velocity, const rclcpp::Time &start_time, const rclcpp::Duration &step_size, const std::string &frame, double initial_pose_confidence, double initial_vel_confidence)
std::vector< geometry_msgs::msg::Pose > sample_2d_linear_motion(const geometry_msgs::msg::Pose &pose, double velocity, double period, double step_size)

References process_bag::i, motion_computation::conversion::impl::pose_from_gnss(), motion_computation::conversion::impl::predicted_poses_to_predicted_state(), and motion_computation::conversion::impl::sample_2d_linear_motion().

Here is the call graph for this function:

◆ convert() [2/3]

void motion_computation::conversion::convert ( const carma_v2x_msgs::msg::MobilityPath &  in_msg,
carma_perception_msgs::msg::ExternalObject &  out_msg,
const lanelet::projection::LocalFrameProjector &  map_projector 
)

Definition at line 31 of file mobility_path_to_external_object.cpp.

35{
36 constexpr double mobility_path_points_timestep_size =
37 0.1; // Mobility path timestep size per message spec
38
39 out_msg.size.x = 2.5; // TODO(carma) identify better approach for object size in mobility path
40 out_msg.size.y = 2.25;
41 out_msg.size.z = 2.0;
42
43 // get reference origin in ECEF (convert from cm to m)
44 double ecef_x = static_cast<double>(in_msg.trajectory.location.ecef_x) / 100.0;
45 double ecef_y = static_cast<double>(in_msg.trajectory.location.ecef_y) / 100.0;
46 double ecef_z = static_cast<double>(in_msg.trajectory.location.ecef_z) / 100.0;
47
48 // Convert general information
49 // clang-off
50 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::ID_PRESENCE_VECTOR;
51 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::POSE_PRESENCE_VECTOR;
52 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::VELOCITY_PRESENCE_VECTOR;
53 out_msg.presence_vector |=
54 carma_perception_msgs::msg::ExternalObject::OBJECT_TYPE_PRESENCE_VECTOR;
55 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::BSM_ID_PRESENCE_VECTOR;
56 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::DYNAMIC_OBJ_PRESENCE;
57 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::PREDICTION_PRESENCE_VECTOR;
58 // clang-on
59
60 out_msg.object_type = carma_perception_msgs::msg::ExternalObject::SMALL_VEHICLE;
61 std::hash<std::string> hasher;
62
63 // TODO(carma) hasher returns size_t, message accept uint32_t which we might lose info
64 auto hashed = hasher(in_msg.m_header.sender_id);
65 out_msg.id = static_cast<uint32_t>(hashed);
66
67 // convert hex std::string to uint8_t array
68 for (size_t i = 0; i < in_msg.m_header.sender_bsm_id.size(); i += 2) {
69 unsigned int num = 0;
70 sscanf(in_msg.m_header.sender_bsm_id.substr(i, i + 2).c_str(), "%x", &num);
71 out_msg.bsm_id.push_back((uint8_t)num);
72 }
73
74 // first point's timestamp
75 out_msg.header.stamp =
76 rclcpp::Time((uint64_t)in_msg.m_header.timestamp * 1e6); // ms to nanoseconds
77
78 // If it is a static object, we finished processing
79 if (in_msg.trajectory.offsets.size() < 2) {
80 out_msg.dynamic_obj = false;
81 return;
82 }
83 out_msg.dynamic_obj = true;
84
85 // get planned trajectory points
86 carma_perception_msgs::msg::PredictedState prev_state;
87 tf2::Vector3 prev_pt_ecef{ecef_x, ecef_y, ecef_z};
88
89 auto prev_pt_map = impl::transform_to_map_frame(prev_pt_ecef, map_projector);
90 double prev_yaw = 0.0;
91
92 double message_offset_x = 0.0; // units cm
93 double message_offset_y = 0.0;
94 double message_offset_z = 0.0;
95
96 rclcpp::Duration mobility_path_point_delta_t(mobility_path_points_timestep_size * 1e9);
97
98 // Note the usage of current vs previous in this loop can be a bit confusing
99 // The intended behavior is we our always storing our prev_point but using
100 // curr_pt for computing velocity at prev_point
101 for (size_t i = 0; i < in_msg.trajectory.offsets.size(); i++) {
102 auto curr_pt_msg = in_msg.trajectory.offsets[i];
103
104 message_offset_x = static_cast<double>(curr_pt_msg.offset_x) + message_offset_x;
105 message_offset_y = static_cast<double>(curr_pt_msg.offset_y) + message_offset_y;
106 message_offset_z = static_cast<double>(curr_pt_msg.offset_z) + message_offset_z;
107
108 tf2::Vector3 curr_pt_ecef{
109 ecef_x + message_offset_x / 100.0, ecef_y + message_offset_y / 100.0,
110 ecef_z + message_offset_z /
111 100.0}; // ecef_x is in m while message_offset_x is in cm. Want m as final result
112 auto curr_pt_map = impl::transform_to_map_frame(curr_pt_ecef, map_projector);
113
114 carma_perception_msgs::msg::PredictedState curr_state;
115
116 if (i == 0) // First point's state should be stored outside "predictions"
117 {
118 rclcpp::Time prev_stamp_as_time = rclcpp::Time(out_msg.header.stamp);
119 rclcpp::Time updated_time_step = prev_stamp_as_time + mobility_path_point_delta_t;
120
122 curr_pt_map, prev_pt_map, prev_stamp_as_time, updated_time_step,
123 prev_yaw); // Position returned is that of prev_pt_map NOT curr_pt_map
124 curr_state = std::get<0>(res);
125 prev_yaw = std::get<1>(res);
126 // Compute out_msg pose
127 out_msg.pose.pose = curr_state.predicted_position; // Orientation computed from first point
128 // in offsets with location
129 out_msg.velocity.twist = curr_state.predicted_velocity; // Velocity derived from first point
130
131 } else {
132 // NOTE: This is where the time increment happens but it feels incorrect.
133 // since the corresponding data is actually from the original prev_state stamp
134 rclcpp::Time prev_stamp_as_time =
135 rclcpp::Time(prev_state.header.stamp) + mobility_path_point_delta_t;
136 rclcpp::Time updated_time_step = prev_stamp_as_time + mobility_path_point_delta_t;
137
139 curr_pt_map, prev_pt_map, prev_stamp_as_time, updated_time_step, prev_yaw);
140 curr_state = std::get<0>(res);
141 prev_yaw = std::get<1>(res);
142 out_msg.predictions.push_back(curr_state);
143 }
144
145 if (
146 i == in_msg.trajectory.offsets.size() -
147 1) // if last point, copy the prev_state velocity & orientation to the last point too
148 {
149 curr_state.predicted_position.position.x = curr_pt_map.x();
150 curr_state.predicted_position.position.y = curr_pt_map.y();
151 curr_state.predicted_position.position.z = curr_pt_map.z();
152 out_msg.predictions.push_back(curr_state);
153 }
154
155 prev_state = curr_state;
156 prev_pt_map = curr_pt_map;
157 }
158
160
161 return;
162}
tf2::Vector3 transform_to_map_frame(const tf2::Vector3 &ecef_point, const lanelet::projection::LocalFrameProjector &map_projector)
Transforms ecef point to map frame using internally saved map transform.
void calculateAngVelocityOfPredictedStates(carma_perception_msgs::msg::ExternalObject &object)
Helper function to fill in the angular velocity of the external object.
std::pair< carma_perception_msgs::msg::PredictedState, double > composePredictedState(const tf2::Vector3 &curr_pt, const tf2::Vector3 &prev_pt, const rclcpp::Time &prev_time_stamp, const rclcpp::Time &curr_time_stamp, double prev_yaw)
Composes a PredictedState message form a provided current point and previous point....

References motion_computation::conversion::impl::calculateAngVelocityOfPredictedStates(), motion_computation::conversion::impl::composePredictedState(), process_bag::i, and motion_computation::conversion::impl::transform_to_map_frame().

Here is the call graph for this function:

◆ convert() [3/3]

void motion_computation::conversion::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 
)

Definition at line 38 of file psm_to_external_object_convertor.cpp.

45{
47 out_msg.dynamic_obj = true; // If a PSM is sent then the object is dynamic
48 // since its a living thing
49 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::DYNAMIC_OBJ_PRESENCE;
50
52 // Generate a unique object id from the psm id
53 out_msg.id = 0;
54 for (int i = in_msg.id.id.size() - 1; i >= 0;
55 i--) { // using signed iterator to handle empty case
56 // each byte of the psm id gets placed in one byte of the object id.
57 // This should result in very large numbers which will be unlikely to
58 // conflict with standard detections
59 out_msg.id |= in_msg.id.id[i] << (8 * i);
60 }
61 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::ID_PRESENCE_VECTOR;
62
64 // Additionally, store the id in the bsm_id field
65 out_msg.bsm_id = in_msg.id.id;
66 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::BSM_ID_PRESENCE_VECTOR;
67
69 // Compute the timestamp
70
71 auto psm_timestamp = impl::get_psm_timestamp(in_msg, node_clock->get_clock());
72 out_msg.header.stamp = builtin_interfaces::msg::Time(psm_timestamp);
73 out_msg.header.frame_id = map_frame_id;
74
76 // Set the type
77
78 if (
79 in_msg.basic_type.type == j2735_v2x_msgs::msg::PersonalDeviceUserType::A_PEDESTRIAN ||
80 in_msg.basic_type.type == j2735_v2x_msgs::msg::PersonalDeviceUserType::A_PUBLIC_SAFETY_WORKER ||
81 in_msg.basic_type.type ==
82 j2735_v2x_msgs::msg::PersonalDeviceUserType::AN_ANIMAL) // Treat animals
83 // like people
84 // since we have
85 // no internal
86 // class for that
87 {
88 out_msg.object_type = carma_perception_msgs::msg::ExternalObject::PEDESTRIAN;
89
90 // Default pedestrian size
91 // Assume a
92 // ExternalObject dimensions are half actual size
93 // Here we assume 1.0, 1.0, 2.0
94 out_msg.size.x = 0.5;
95 out_msg.size.y = 0.5;
96 out_msg.size.z = 1.0;
97
98 } else if (
99 in_msg.basic_type.type == j2735_v2x_msgs::msg::PersonalDeviceUserType::A_PEDALCYCLIST) {
100 out_msg.object_type = carma_perception_msgs::msg::ExternalObject::
101 MOTORCYCLE; // Currently external object cannot represent bicycles,
102 // but motor cycle seems like the next best choice
103
104 // Default bicycle size
105 out_msg.size.x = 1.0;
106 out_msg.size.y = 0.5;
107 out_msg.size.z = 1.0;
108 } else {
109 out_msg.object_type = carma_perception_msgs::msg::ExternalObject::UNKNOWN;
110
111 // Default pedestrian size
112 out_msg.size.x = 0.5;
113 out_msg.size.y = 0.5;
114 out_msg.size.z = 1.0;
115 }
116 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::SIZE_PRESENCE_VECTOR;
117
119 // Set the velocity
120
121 out_msg.velocity.twist.linear.x = in_msg.speed.velocity;
122 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::VELOCITY_PRESENCE_VECTOR;
123 // NOTE: The velocity covariance is not provided in the PSM. In order to
124 // compute it you need at least two PSM messages
125 // Tracking and associating PSM messages would be an increase in
126 // complexity for this conversion which is not warranted without an
127 // existing use case for the velocity covariance. If a use case is
128 // presented for it, such an addition can be made at that time.
129
131
132 double largest_position_std = 0.0;
133 double lat_variance = 0.0;
134 double lon_variance = 0.0;
135 double heading_variance = 0.0; // Yaw variance is not available so mark as
136 // impossible perfect case
137 double position_confidence = 0.0; // Default will be 10% confidence. If the position accuracy is
138 // available then this value will be updated
139
140 // A standard deviation which is larger than the acceptable value to give
141 // 95% confidence interval on fitting the pedestrian within one 3.7m lane
142 constexpr double MAX_POSITION_STD = 1.85;
143
144 if (
145 (in_msg.accuracy.presence_vector |
146 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_AVAILABLE) &&
147 (in_msg.accuracy.presence_vector |
148 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_ORIENTATION_AVAILABLE)) {
149 // Both accuracies available
150
151 // Compute the position covariance
152 // For computing confidence we will use the largest provided standard
153 // deviation of position
154 largest_position_std = std::max(in_msg.accuracy.semi_major, in_msg.accuracy.semi_minor);
155 lat_variance = in_msg.accuracy.semi_minor * in_msg.accuracy.semi_minor;
156 lon_variance = in_msg.accuracy.semi_major * in_msg.accuracy.semi_major;
157 heading_variance = in_msg.accuracy.orientation * in_msg.accuracy.orientation;
158
159 // NOTE: ExternalObject.msg does not clearly define what is meant by
160 // position confidence
161 // Here we are providing a linear scale based on the positional accuracy
162 // where 0 confidence would denote A standard deviation which is larger
163 // than the acceptable value to give 95% confidence interval on fitting
164 // the pedestrian within one 3.7m lane
165 // Set the confidence
166 // Without a way of getting the velocity confidence from the PSM we will use
167 // the position confidence for both
168 out_msg.confidence = 1.0 - std::min(1.0, fabs(largest_position_std / MAX_POSITION_STD));
169 out_msg.presence_vector |=
170 carma_perception_msgs::msg::ExternalObject::CONFIDENCE_PRESENCE_VECTOR;
171 } else if (
172 in_msg.accuracy.presence_vector | carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_AVAILABLE) {
173 // Position accuracy available
174
175 largest_position_std = std::max(in_msg.accuracy.semi_major, in_msg.accuracy.semi_minor);
176 lat_variance = in_msg.accuracy.semi_minor * in_msg.accuracy.semi_minor;
177 lon_variance = in_msg.accuracy.semi_major * in_msg.accuracy.semi_major;
178 heading_variance = 1.0; // Yaw variance is not available so mark as
179 // impossible perfect case
180
181 // Same calculation as shown in above condition. See that for description
182 out_msg.confidence = 1.0 - std::min(1.0, fabs(largest_position_std / MAX_POSITION_STD));
183 out_msg.presence_vector |=
184 carma_perception_msgs::msg::ExternalObject::CONFIDENCE_PRESENCE_VECTOR;
185
186 } else if (
187 in_msg.accuracy.presence_vector |
188 carma_v2x_msgs::msg::PositionalAccuracy::ACCURACY_ORIENTATION_AVAILABLE) {
189 // Orientation accuracy available
190
191 lat_variance = 1.0;
192 lon_variance = 1.0;
193
194 heading_variance = in_msg.accuracy.orientation * in_msg.accuracy.orientation;
195 } else { // No accuracies available
196 lat_variance = 1.0;
197 lon_variance = 1.0;
198 heading_variance = 1.0;
199 }
200
202 // Compute the pose
203 lanelet::GPSPoint gps_point(
204 {in_msg.position.latitude, in_msg.position.longitude, in_msg.position.elevation});
205 out_msg.pose = impl::pose_from_gnss(
206 map_projector, ned_in_map_rotation, gps_point, in_msg.heading.heading, lat_variance,
207 lon_variance, heading_variance);
208 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::POSE_PRESENCE_VECTOR;
209
211 // Compute predictions
212 // For prediction, if the prediction is available we will sample it
213 // If not then assume linear motion
214
215 std::vector<geometry_msgs::msg::Pose> predicted_poses;
216
217 if (in_msg.presence_vector & carma_v2x_msgs::msg::PSM::HAS_PATH_PREDICTION) {
218 // Based on the vehicle frame used in j2735 positive should be to the right
219 // and negative to the left
220 predicted_poses = impl::sample_2d_path_from_radius(
221 out_msg.pose.pose, out_msg.velocity.twist.linear.x,
222 -in_msg.path_prediction.radius_of_curvature, pred_period, pred_step_size);
223 } else {
224 predicted_poses = impl::sample_2d_linear_motion(
225 out_msg.pose.pose, out_msg.velocity.twist.linear.x, pred_period, pred_step_size);
226 }
227
228 out_msg.predictions = impl::predicted_poses_to_predicted_state(
229 predicted_poses, out_msg.velocity.twist.linear.x, rclcpp::Time(out_msg.header.stamp),
230 rclcpp::Duration(pred_step_size * 1e9), map_frame_id, out_msg.confidence, out_msg.confidence);
231 out_msg.presence_vector |= carma_perception_msgs::msg::ExternalObject::PREDICTION_PRESENCE_VECTOR;
232}
std::vector< geometry_msgs::msg::Pose > sample_2d_path_from_radius(const geometry_msgs::msg::Pose &pose, double velocity, double radius_of_curvature, double period, double step_size)
rclcpp::Time get_psm_timestamp(const carma_v2x_msgs::msg::PSM &in_msg, rclcpp::Clock::SharedPtr clock)

References motion_computation::conversion::impl::get_psm_timestamp(), process_bag::i, motion_computation::conversion::impl::pose_from_gnss(), motion_computation::conversion::impl::predicted_poses_to_predicted_state(), motion_computation::conversion::impl::sample_2d_linear_motion(), and motion_computation::conversion::impl::sample_2d_path_from_radius().

Referenced by motion_computation::MotionComputationWorker::bsmCallback(), gnss_to_map_convertor::GNSSToMapConvertor::gnssFixCb(), motion_computation::MotionComputationWorker::mobilityPathCallback(), motion_computation::MotionComputationWorker::psmCallback(), carma_wm::geometry::rpyFromQuaternion(), and carma_cloud_client::CarmaCloudClient::XMLconversion().

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