17#include <carma_cooperative_perception_interfaces/msg/track.hpp>
18#include <carma_cooperative_perception_interfaces/msg/track_list.hpp>
19#include <carma_perception_msgs/msg/external_object.hpp>
20#include <carma_perception_msgs/msg/external_object_list.hpp>
21#include <j2735_v2x_msgs/msg/d_date_time.hpp>
22#include <j2735_v2x_msgs/msg/personal_device_user_type.hpp>
23#include <j2735_v2x_msgs/msg/positional_accuracy.hpp>
24#include <j2735_v2x_msgs/to_floating_point.hpp>
25#include <j3224_v2x_msgs/msg/detected_object_data.hpp>
26#include <j3224_v2x_msgs/msg/equipment_type.hpp>
27#include <j3224_v2x_msgs/msg/measurement_time_offset.hpp>
28#include <j3224_v2x_msgs/msg/object_type.hpp>
29#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
42#include <fmt/format.h>
45#include <gsl/pointers>
53#include <lanelet2_core/geometry/Lanelet.h>
54#include <lanelet2_extension/projection/local_frame_projector.h>
55#include <boost/date_time/posix_time/conversion.hpp>
56#include <boost/date_time/posix_time/posix_time_io.hpp>
57#include "boost/date_time/posix_time/posix_time.hpp"
64 builtin_interfaces::msg::Time msg;
67 std::tm timeinfo = {};
70 if (d_date_time.year){
73 timeinfo.tm_year =
static_cast<int>(
remove_units(d_date_time.year.value())) - 1900;
76 throw std::invalid_argument(
77 "Year must be greater than 1970 for live date/time conversion");
82 if (d_date_time.month &&
static_cast<int>(d_date_time.month.value().get_value()) != 0)
85 timeinfo.tm_mon =
static_cast<int>(d_date_time.month.value().get_value()) - 1;
89 if (d_date_time.day &&
static_cast<int>(d_date_time.day.value()) != 0)
92 timeinfo.tm_mday =
static_cast<int>(d_date_time.day.value());
99 if (d_date_time.hour &&
static_cast<int>(d_date_time.hour.value()) != 31)
102 timeinfo.tm_hour =
static_cast<int>(d_date_time.hour.value());
106 if (d_date_time.minute &&
static_cast<int>(d_date_time.minute.value()) != 60)
109 timeinfo.tm_min =
static_cast<int>(d_date_time.minute.value());
117 if (d_date_time.time_zone_offset)
119 timeinfo.tm_gmtoff =
static_cast<int>(d_date_time.time_zone_offset.value());
120 timeT = std::mktime(&timeinfo);
131 std::time_t currentTime = std::time(
nullptr);
132 std::tm* localTimeInfo = std::localtime(¤tTime);
134 long timezone_offset = localTimeInfo->tm_gmtoff;
136 timeinfo.tm_gmtoff = timezone_offset;
137 timeinfo.tm_isdst = localTimeInfo->tm_isdst;
140 timeT = std::mktime(&timeinfo);
144 auto timePoint = std::chrono::system_clock::from_time_t(timeT);
147 int milliseconds = 0;
148 if (d_date_time.second)
150 milliseconds =
static_cast<int>(d_date_time.second.value());
152 timePoint += std::chrono::milliseconds(milliseconds);
155 auto duration = timePoint.time_since_epoch();
156 auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
157 auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - seconds);
159 msg.sec =
static_cast<int32_t
>(seconds.count());
160 msg.nanosec =
static_cast<uint32_t
>(nanoseconds.count());
167 const auto fractional_secs{std::modf(
168 remove_units(units::time::second_t{d_date_time.hour.value_or(units::time::second_t{0.0})}) +
169 remove_units(units::time::second_t{d_date_time.minute.value_or(units::time::second_t{0.0})}) +
170 remove_units(units::time::second_t{d_date_time.second.value_or(units::time::second_t{0.0})}),
173 msg.sec =
static_cast<std::int32_t
>(seconds);
174 msg.nanosec =
static_cast<std::int32_t
>(fractional_secs * 1e9);
182 sdsm_time.
second.value() += offset.measurement_time_offset;
189 auto offset_enu{offset_ned};
192 offset_enu.offset_x = offset_ned.offset_y;
193 offset_enu.offset_y = offset_ned.offset_x;
195 if (offset_enu.offset_z) {
196 offset_enu.offset_z.value() *= -1;
203 -> j2735_v2x_msgs::msg::DDateTime
205 j2735_v2x_msgs::msg::DDateTime ddate_time_output;
208 boost::posix_time::ptime posix_time = boost::posix_time::from_time_t(builtin_time.sec) +
209 boost::posix_time::nanosec(builtin_time.nanosec);
211 const auto time_stamp_year = posix_time.date().year();
212 const auto time_stamp_month = posix_time.date().month();
213 const auto time_stamp_day = posix_time.date().day();
215 const auto hours_of_day = posix_time.time_of_day().hours();
216 const auto minutes_of_hour = posix_time.time_of_day().minutes();
217 const auto seconds_of_minute = posix_time.time_of_day().seconds();
219 ddate_time_output.presence_vector = 0;
221 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::YEAR;
222 ddate_time_output.year.year = time_stamp_year;
223 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::MONTH;
224 ddate_time_output.month.month = time_stamp_month;
225 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::DAY;
226 ddate_time_output.day.day = time_stamp_day;
227 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::HOUR;
228 ddate_time_output.hour.hour = hours_of_day;
229 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::MINUTE;
230 ddate_time_output.minute.minute = minutes_of_hour;
231 ddate_time_output.presence_vector |= j2735_v2x_msgs::msg::DDateTime::SECOND;
232 ddate_time_output.second.millisecond = seconds_of_minute;
234 return ddate_time_output;
238 const builtin_interfaces::msg::Time & external_object_list_stamp,
239 const builtin_interfaces::msg::Time & external_object_stamp)
240 -> carma_v2x_msgs::msg::MeasurementTimeOffset
242 carma_v2x_msgs::msg::MeasurementTimeOffset time_offset;
244 boost::posix_time::ptime external_object_list_time =
245 boost::posix_time::from_time_t(external_object_list_stamp.sec) +
246 boost::posix_time::nanosec(external_object_list_stamp.nanosec);
248 boost::posix_time::ptime external_object_time =
249 boost::posix_time::from_time_t(external_object_stamp.sec) +
250 boost::posix_time::nanosec(external_object_stamp.nanosec);
252 boost::posix_time::time_duration offset_duration =
253 (external_object_list_time - external_object_time);
255 time_offset.measurement_time_offset = offset_duration.total_seconds();
262 geometry_msgs::msg::Point msg;
273 geometry_msgs::msg::Point msg;
284 return units::angle::degree_t{std::fmod(-(
remove_units(heading) - 90.0) + 360.0, 360.0)};
288 double yaw,
const lanelet::BasicPoint3d & obj_pose,
289 const std::shared_ptr<lanelet::projection::LocalFrameProjector> & map_projection)
290 -> units::angle::degree_t
293 lanelet::GPSPoint wgs_obj_pose = map_projection->reverse(obj_pose);
296 gsl::owner<PJ_CONTEXT *> context = proj_context_create();
297 gsl::owner<PJ *> transform = proj_create(context, map_projection->ECEF_PROJ_STR);
298 units::angle::degree_t grid_heading{std::fmod(90 - yaw + 360, 360)};
300 const auto factors = proj_factors(
301 transform, proj_coord(proj_torad(wgs_obj_pose.lon), proj_torad(wgs_obj_pose.lat), 0, 0));
302 units::angle::degree_t grid_convergence{proj_todeg(factors.meridian_convergence)};
304 auto wgs_heading = grid_convergence + grid_heading;
306 proj_destroy(transform);
307 proj_context_destroy(context);
315 const geometry_msgs::msg::PoseStamped & source_pose,
316 const carma_v2x_msgs::msg::PositionOffsetXYZ & position_offset)
317 -> carma_v2x_msgs::msg::PositionOffsetXYZ
319 carma_v2x_msgs::msg::PositionOffsetXYZ adjusted_offset;
321 adjusted_offset.offset_x.object_distance =
322 position_offset.offset_x.object_distance - source_pose.pose.position.x;
323 adjusted_offset.offset_y.object_distance =
324 position_offset.offset_y.object_distance - source_pose.pose.position.y;
325 adjusted_offset.offset_z.object_distance =
326 position_offset.offset_z.object_distance - source_pose.pose.position.z;
327 adjusted_offset.presence_vector = carma_v2x_msgs::msg::PositionOffsetXYZ::HAS_OFFSET_Z;
329 return adjusted_offset;
333 const geometry_msgs::msg::PoseStamped & source_pose,
334 const std::shared_ptr<lanelet::projection::LocalFrameProjector> & map_projection)
335 -> carma_v2x_msgs::msg::Position3D
337 carma_v2x_msgs::msg::Position3D ref_pos;
338 lanelet::BasicPoint3d source_pose_basicpoint{
339 source_pose.pose.position.x, source_pose.pose.position.y, 0.0};
341 lanelet::GPSPoint wgs84_ref_pose = map_projection->reverse(source_pose_basicpoint);
343 ref_pos.longitude = wgs84_ref_pose.lon;
344 ref_pos.latitude = wgs84_ref_pose.lat;
345 ref_pos.elevation = wgs84_ref_pose.ele;
346 ref_pos.elevation_exists =
true;
353std::string
to_string(
const std::vector<std::uint8_t> & temporary_id) {
355 str.reserve(2 * std::size(temporary_id));
357 std::array<char, 2> buffer;
358 for (
const auto & octet_string : temporary_id) {
359 std::to_chars(std::begin(buffer), std::end(buffer), octet_string, 16);
360 str.push_back(std::toupper(std::get<0>(buffer)));
361 str.push_back(std::toupper(std::get<1>(buffer)));
369 const j3224_v2x_msgs::msg::ObjectType& j3224_obj_type)
371 switch (j3224_obj_type.object_type) {
372 case j3224_obj_type.ANIMAL:
373 detection.motion_model = detection.MOTION_MODEL_CTRV;
375 detection.semantic_class = detection.SEMANTIC_CLASS_UNKNOWN;
377 case j3224_obj_type.VRU:
378 detection.motion_model = detection.MOTION_MODEL_CTRV;
379 detection.semantic_class = detection.SEMANTIC_CLASS_PEDESTRIAN;
381 case j3224_obj_type.VEHICLE:
382 detection.motion_model = detection.MOTION_MODEL_CTRV;
383 detection.semantic_class = detection.SEMANTIC_CLASS_SMALL_VEHICLE;
386 detection.motion_model = detection.MOTION_MODEL_CTRV;
387 detection.semantic_class = detection.SEMANTIC_CLASS_UNKNOWN;
392 const carma_v2x_msgs::msg::DetectedObjectCommonData& common_data,
393 const std::optional<SdsmToDetectionListConfig>& conversion_adjustment)
396 double original_pose_covariance_x = 0.0;
397 double original_pose_covariance_y = 0.0;
398 double original_pose_covariance_z = 0.0;
399 double original_pose_covariance_yaw = 0.0;
400 double original_twist_covariance_x = 0.0;
401 double original_twist_covariance_z = 0.0;
402 double original_twist_covariance_yaw = 0.0;
406 original_pose_covariance_x =
407 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.pos_confidence.pos).value(), 2);
408 original_pose_covariance_y = original_pose_covariance_x;
410 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
411 "Original pose covariance X/Y: " << original_pose_covariance_x);
412 }
catch (
const std::bad_optional_access &) {
413 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
414 "Missing position confidence");
418 original_pose_covariance_z =
419 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.pos_confidence.elevation).value(), 2);
421 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
422 "Original pose covariance Z: " << original_pose_covariance_z);
423 }
catch (
const std::bad_optional_access &) {
424 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
425 "Missing elevation confidence");
430 original_pose_covariance_yaw =
431 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.heading_conf).value(), 2);
433 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
434 "Original pose covariance yaw: " << original_pose_covariance_yaw);
435 }
catch (
const std::bad_optional_access &) {
436 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
437 "Missing heading confidence");
442 original_twist_covariance_x =
443 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.speed_confidence).value(), 2);
445 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
446 "Original twist covariance X: " << original_twist_covariance_x);
447 }
catch (
const std::bad_optional_access &) {
448 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
449 "Missing speed confidence");
452 if (!common_data.speed_z.unavailable){
455 original_twist_covariance_z =
456 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.speed_confidence_z).value(), 2);
458 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
459 "Original twist covariance Z: " << original_twist_covariance_z);
460 }
catch (
const std::bad_optional_access &) {
461 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
462 "Missing z-speed confidence");
466 original_twist_covariance_z = 0.0;
467 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
468 "Original twist covariance Z: 0.0 (speed_z not provided)");
472 if(
static_cast<bool>(common_data.accel_4_way.yaw_rate)){
475 original_twist_covariance_yaw =
476 0.5 * std::pow(j2735_v2x_msgs::to_double(common_data.acc_cfd_yaw).value(), 2);
478 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
479 "Original twist covariance yaw: " << original_twist_covariance_yaw);
480 }
catch (
const std::bad_optional_access &) {
481 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
482 "Missing yaw-rate confidence");
486 original_twist_covariance_yaw = 0.0;
487 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
488 "Original twist covariance yaw: 0.0 (yaw_rate not provided)");
491 if (conversion_adjustment && conversion_adjustment.value().overwrite_covariance)
494 detection.pose.covariance[0] = conversion_adjustment.value().pose_covariance_x;
495 detection.pose.covariance[7] = conversion_adjustment.value().pose_covariance_y;
496 detection.pose.covariance[14] = conversion_adjustment.value().pose_covariance_z;
497 detection.pose.covariance[35] = conversion_adjustment.value().pose_covariance_yaw;
500 detection.twist.covariance[0] = conversion_adjustment.value().twist_covariance_x;
501 detection.twist.covariance[14] = conversion_adjustment.value().twist_covariance_z;
502 detection.twist.covariance[35] = conversion_adjustment.value().twist_covariance_yaw;
505 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
506 "POSE COVARIANCE COMPARISON - Original vs Hardcoded: " <<
507 "X: " << original_pose_covariance_x <<
" -> " << detection.pose.covariance[0] <<
", " <<
508 "Y: " << original_pose_covariance_y <<
" -> " << detection.pose.covariance[7] <<
", " <<
509 "Z: " << original_pose_covariance_z <<
" -> " << detection.pose.covariance[14] <<
", " <<
510 "Yaw: " << original_pose_covariance_yaw <<
" -> " << detection.pose.covariance[35]);
512 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
"sdsm_to_detection_list_node"),
513 "TWIST COVARIANCE COMPARISON - Original vs Hardcoded: " <<
514 "X: " << original_twist_covariance_x <<
" -> , " << detection.twist.covariance[0] <<
", " <<
515 "Z: " << original_twist_covariance_z <<
" -> , " << detection.twist.covariance[14] <<
", " <<
516 "Yaw: " << original_twist_covariance_yaw <<
" -> " << detection.twist.covariance[35]);
521 detection.pose.covariance[0] = original_pose_covariance_x;
522 detection.pose.covariance[7] = original_pose_covariance_y;
523 detection.pose.covariance[14] = original_pose_covariance_z;
524 detection.pose.covariance[35] = original_pose_covariance_yaw;
527 detection.twist.covariance[0] = original_twist_covariance_x;
528 detection.twist.covariance[14] = original_twist_covariance_z;
529 detection.twist.covariance[35] = original_twist_covariance_yaw;
533 for (
size_t i = 0;
i < 36; ++
i) {
534 if (
i != 0 &&
i != 14 &&
i != 35) {
535 detection.twist.covariance[
i] = 0.0;
540 for (
size_t i = 0;
i < 36; ++
i) {
541 if (
i != 0 &&
i != 7 &&
i != 14 &&
i != 35) {
542 detection.pose.covariance[
i] = 0.0;
576 const carma_v2x_msgs::msg::SensorDataSharingMessage & sdsm, std::string_view georeference,
577 bool is_simulation,
const std::optional<SdsmToDetectionListConfig>& conversion_adjustment)
578 -> carma_cooperative_perception_interfaces::msg::DetectionList
580 carma_cooperative_perception_interfaces::msg::DetectionList detection_list;
583 units::length::meter_t elevation(0.0);
584 if(ref_pos_3d.elevation){
585 elevation = ref_pos_3d.elevation.value();
588 ref_pos_3d.
latitude, ref_pos_3d.longitude, elevation};
592 for (
const auto & object_data : sdsm.objects.detected_object_data) {
593 const auto common_data{object_data.detected_object_common_data};
596 detection.header.frame_id =
"map";
602 detection.header.stamp =
to_time_msg(detection_time, is_simulation);
604 detection.id = fmt::format(
"{}-{}",
606 common_data.detected_id.object_id);
610 ref_pos_map.
easting + pos_offset_enu.offset_x, ref_pos_map.northing + pos_offset_enu.offset_y,
611 ref_pos_map.elevation + pos_offset_enu.offset_z.value_or(units::length::meter_t{0.0})});
615 if (conversion_adjustment && conversion_adjustment.value().adjust_pose)
617 detection.pose.pose.position.x += conversion_adjustment.value().x_offset;
618 detection.pose.pose.position.y += conversion_adjustment.value().y_offset;
621 const auto true_heading{units::angle::degree_t{
Heading::from_msg(common_data.heading).heading}};
625 const units::angle::degree_t grid_convergence{
628 const auto grid_heading{true_heading - grid_convergence};
631 tf2::Quaternion quat_tf;
633 if (conversion_adjustment && conversion_adjustment.value().adjust_pose)
637 auto yaw_with_offset = units::angle::radian_t{enu_yaw} +
638 units::angle::radian_t{units::angle::degree_t{conversion_adjustment.value().yaw_offset}};
639 auto new_yaw = std::fmod(
remove_units(yaw_with_offset) + 2 * M_PI, 2 * M_PI);
640 quat_tf.setRPY(0, 0, new_yaw);
645 quat_tf.setRPY(0, 0,
remove_units(units::angle::radian_t{enu_yaw}));
648 detection.pose.pose.orientation = tf2::toMsg(quat_tf);
651 detection.twist.twist.linear.x =
652 remove_units(units::velocity::meters_per_second_t{speed.speed});
654 if (!common_data.speed_z.unavailable){
656 detection.twist.twist.linear.z =
657 remove_units(units::velocity::meters_per_second_t{speed_z.speed});
660 detection.twist.twist.linear.z =
remove_units(units::velocity::meters_per_second_t{0.0});
666 if(
static_cast<bool>(common_data.accel_4_way.yaw_rate)){
668 detection.twist.twist.angular.z =
669 remove_units(units::angular_velocity::degrees_per_second_t{accel_set.yaw_rate});
672 detection.twist.twist.angular.z = 0.0;
679 detection_list.detections.push_back(std::move(detection));
682 return detection_list;
686 const carma_perception_msgs::msg::ExternalObject &
object,
692 detection.header =
object.header;
694 if (
object.presence_vector &
object.BSM_ID_PRESENCE_VECTOR) {
697 std::cbegin(
object.bsm_id), std::cend(
object.bsm_id), std::back_inserter(detection.id),
698 [](
const auto &
i) { return i +
'0'; });
701 if (
object.presence_vector &
object.ID_PRESENCE_VECTOR) {
705 if (
object.presence_vector &
object.POSE_PRESENCE_VECTOR) {
706 detection.pose =
object.pose;
709 if (
object.presence_vector &
object.VELOCITY_PRESENCE_VECTOR) {
710 detection.twist =
object.velocity;
713 if (
object.presence_vector &
object.OBJECT_TYPE_PRESENCE_VECTOR) {
714 switch (
object.object_type) {
715 case object.SMALL_VEHICLE:
716 detection.motion_model = motion_model_mapping.small_vehicle_model;
717 detection.semantic_class = detection.SEMANTIC_CLASS_SMALL_VEHICLE;
719 case object.LARGE_VEHICLE:
720 detection.motion_model = motion_model_mapping.large_vehicle_model;
721 detection.semantic_class = detection.SEMANTIC_CLASS_LARGE_VEHICLE;
723 case object.MOTORCYCLE:
724 detection.motion_model = motion_model_mapping.motorcycle_model;
725 detection.semantic_class = detection.SEMANTIC_CLASS_MOTORCYCLE;
727 case object.PEDESTRIAN:
728 detection.motion_model = motion_model_mapping.pedestrian_model;
729 detection.semantic_class = detection.SEMANTIC_CLASS_PEDESTRIAN;
733 detection.motion_model = motion_model_mapping.unknown_model;
734 detection.semantic_class = detection.SEMANTIC_CLASS_UNKNOWN;
742 const carma_perception_msgs::msg::ExternalObjectList & object_list,
744 -> carma_cooperative_perception_interfaces::msg::DetectionList
746 carma_cooperative_perception_interfaces::msg::DetectionList detection_list;
749 std::cbegin(object_list.objects), std::cend(object_list.objects),
750 std::back_inserter(detection_list.detections),
751 [&motion_model_mapping = std::as_const(motion_model_mapping)](
const auto &
object) {
752 return to_detection_msg(object, motion_model_mapping);
755 return detection_list;
759 -> carma_perception_msgs::msg::ExternalObject
765 const auto to_numeric_id = [](std::string string_id) -> std::optional<uint32_t> {
766 auto non_digit_start = std::remove_if(
767 std::begin(string_id), std::end(string_id),
768 [](
const auto & ch) {
return !std::isdigit(ch); });
770 std::uint32_t numeric_id;
771 const auto digit_substr_size{std::distance(std::begin(string_id), non_digit_start)};
773 std::from_chars(string_id.c_str(), string_id.c_str() + digit_substr_size, numeric_id).ec ==
781 if (
const auto numeric_id{to_numeric_id(track.id)}) {
793 const auto track_longitudinal_velocity{track.twist.twist.linear.x};
794 const auto track_orientation = track.pose.pose.orientation;
797 track_orientation.x, track_orientation.y, track_orientation.z, track_orientation.w);
799 double roll, pitch, yaw;
800 m.getRPY(roll, pitch, yaw);
802 external_object.velocity.twist.linear.x = track_longitudinal_velocity * std::cos(yaw);
803 external_object.velocity.twist.linear.y = track_longitudinal_velocity * std::sin(yaw);
808 switch (track.semantic_class) {
809 case track.SEMANTIC_CLASS_SMALL_VEHICLE:
812 case track.SEMANTIC_CLASS_LARGE_VEHICLE:
815 case track.SEMANTIC_CLASS_MOTORCYCLE:
818 case track.SEMANTIC_CLASS_PEDESTRIAN:
821 case track.SEMANTIC_CLASS_UNKNOWN:
830 const carma_cooperative_perception_interfaces::msg::TrackList & track_list)
831 -> carma_perception_msgs::msg::ExternalObjectList
833 carma_perception_msgs::msg::ExternalObjectList external_object_list;
835 for (
const auto & track : track_list.tracks) {
839 return external_object_list;
843 const carma_perception_msgs::msg::ExternalObjectList & external_object_list,
844 const geometry_msgs::msg::PoseStamped & current_pose,
845 const std::shared_ptr<lanelet::projection::LocalFrameProjector> & map_projection)
846 -> carma_v2x_msgs::msg::SensorDataSharingMessage
848 carma_v2x_msgs::msg::SensorDataSharingMessage sdsm;
849 carma_v2x_msgs::msg::DetectedObjectList detected_object_list;
860 sdsm_detected_object.detected_object_common_data.measurement_time =
864 sdsm_detected_object.detected_object_common_data.pos =
867 detected_object_list.detected_object_data.push_back(sdsm_detected_object);
870 std::vector<uint8_t>
id = {0x00, 0x00, 0x00, 0x01};
871 sdsm.source_id.id = id;
872 sdsm.equipment_type.equipment_type = j3224_v2x_msgs::msg::EquipmentType::OBU;
873 sdsm.ref_pos_xy_conf.semi_major = j2735_v2x_msgs::msg::PositionalAccuracy::ACCURACY_UNAVAILABLE;
874 sdsm.ref_pos_xy_conf.semi_minor = j2735_v2x_msgs::msg::PositionalAccuracy::ACCURACY_UNAVAILABLE;
875 sdsm.ref_pos_xy_conf.orientation =
876 j2735_v2x_msgs::msg::PositionalAccuracy::ACCURACY_ORIENTATION_UNAVAILABLE;
877 sdsm.objects = detected_object_list;
884 const std::shared_ptr<lanelet::projection::LocalFrameProjector> & map_projection)
885 -> carma_v2x_msgs::msg::DetectedObjectData
887 carma_v2x_msgs::msg::DetectedObjectData detected_object_data;
888 detected_object_data.presence_vector = 0;
890 carma_v2x_msgs::msg::DetectedObjectCommonData detected_object_common_data;
891 detected_object_common_data.presence_vector = 0;
897 detected_object_common_data.obj_type_cfd.classification_confidence =
903 detected_object_common_data.detected_id.object_id =
913 detected_object_common_data.pos.offset_x.object_distance =
915 detected_object_common_data.pos.offset_y.object_distance =
917 detected_object_common_data.pos.offset_z.object_distance =
923 detected_object_common_data.speed.speed =
926 detected_object_common_data.presence_vector |=
927 carma_v2x_msgs::msg::DetectedObjectCommonData::HAS_SPEED_Z;
928 detected_object_common_data.speed_z.speed =
external_object.velocity.twist.linear.z;
931 lanelet::BasicPoint3d external_object_position{
936 tf2::Quaternion q(obj_orientation.x, obj_orientation.y, obj_orientation.z, obj_orientation.w);
938 double roll, pitch, yaw;
939 m.getRPY(roll, pitch, yaw);
941 detected_object_common_data.heading.heading =
947 carma_v2x_msgs::msg::DetectedObjectOptionalData detected_object_optional_data;
951 detected_object_common_data.obj_type.object_type = j3224_v2x_msgs::msg::ObjectType::VEHICLE;
954 detected_object_optional_data.det_veh.presence_vector =
955 carma_v2x_msgs::msg::DetectedVehicleData::HAS_SIZE;
956 detected_object_optional_data.det_veh.presence_vector |=
957 carma_v2x_msgs::msg::DetectedVehicleData::HAS_HEIGHT;
959 detected_object_optional_data.det_veh.size.vehicle_width =
external_object.size.y;
960 detected_object_optional_data.det_veh.size.vehicle_length =
external_object.size.x;
961 detected_object_optional_data.det_veh.height.vehicle_height =
external_object.size.z;
965 detected_object_common_data.obj_type.object_type = j3224_v2x_msgs::msg::ObjectType::VEHICLE;
968 detected_object_optional_data.det_veh.presence_vector =
969 carma_v2x_msgs::msg::DetectedVehicleData::HAS_SIZE;
970 detected_object_optional_data.det_veh.presence_vector |=
971 carma_v2x_msgs::msg::DetectedVehicleData::HAS_HEIGHT;
973 detected_object_optional_data.det_veh.size.vehicle_width =
external_object.size.y;
974 detected_object_optional_data.det_veh.size.vehicle_length =
external_object.size.x;
975 detected_object_optional_data.det_veh.height.vehicle_height =
external_object.size.z;
979 detected_object_common_data.obj_type.object_type = j3224_v2x_msgs::msg::ObjectType::VEHICLE;
982 detected_object_optional_data.det_veh.presence_vector =
983 carma_v2x_msgs::msg::DetectedVehicleData::HAS_SIZE;
984 detected_object_optional_data.det_veh.presence_vector |=
985 carma_v2x_msgs::msg::DetectedVehicleData::HAS_HEIGHT;
987 detected_object_optional_data.det_veh.size.vehicle_width =
external_object.size.y;
988 detected_object_optional_data.det_veh.size.vehicle_length =
external_object.size.x;
989 detected_object_optional_data.det_veh.height.vehicle_height =
external_object.size.z;
993 detected_object_common_data.obj_type.object_type = j3224_v2x_msgs::msg::ObjectType::VRU;
995 detected_object_optional_data.det_vru.presence_vector =
996 carma_v2x_msgs::msg::DetectedVRUData::HAS_BASIC_TYPE;
997 detected_object_optional_data.det_vru.basic_type.type |=
998 j2735_v2x_msgs::msg::PersonalDeviceUserType::A_PEDESTRIAN;
1003 detected_object_common_data.obj_type.object_type = j3224_v2x_msgs::msg::ObjectType::UNKNOWN;
1006 detected_object_optional_data.det_obst.obst_size.width.size_value =
external_object.size.y;
1007 detected_object_optional_data.det_obst.obst_size.length.size_value =
external_object.size.x;
1009 detected_object_optional_data.det_obst.obst_size.presence_vector =
1010 carma_v2x_msgs::msg::ObstacleSize::HAS_HEIGHT;
1011 detected_object_optional_data.det_obst.obst_size.height.size_value =
external_object.size.z;
1015 detected_object_data.detected_object_common_data = std::move(detected_object_common_data);
1016 detected_object_data.detected_object_optional_data = std::move(detected_object_optional_data);
1018 return detected_object_data;
auto enu_orientation_to_true_heading(double yaw, const lanelet::BasicPoint3d &obj_pose, const std::shared_ptr< lanelet::projection::LocalFrameProjector > &map_projection) -> units::angle::degree_t
void convert_covariances(carma_cooperative_perception_interfaces::msg::Detection &detection, const carma_v2x_msgs::msg::DetectedObjectCommonData &common_data, const std::optional< SdsmToDetectionListConfig > &conversion_adjustment)
auto to_external_object_list_msg(const carma_cooperative_perception_interfaces::msg::TrackList &track_list) -> carma_perception_msgs::msg::ExternalObjectList
auto calc_sdsm_time_offset(const builtin_interfaces::msg::Time &external_object_list_time, const builtin_interfaces::msg::Time &external_object_time) -> carma_v2x_msgs::msg::MeasurementTimeOffset
std::string to_string(const std::vector< std::uint8_t > &temporary_id)
auto calculate_grid_convergence(const Wgs84Coordinate &position, const UtmZone &zone) -> units::angle::degree_t
Calculate grid convergence at a given position.
auto to_ddate_time_msg(const builtin_interfaces::msg::Time &builtin_time) -> j2735_v2x_msgs::msg::DDateTime
auto calc_detection_time_stamp(DDateTime d_date_time, const MeasurementTimeOffset &offset) -> DDateTime
std::variant< multiple_object_tracking::CtrvDetection, multiple_object_tracking::CtraDetection > Detection
auto project_to_carma_map(const Wgs84Coordinate &coordinate, std::string_view proj_string) -> MapCoordinate
auto to_string(const UtmZone &zone) -> std::string
auto to_detection_msg(const carma_perception_msgs::msg::ExternalObject &object, const MotionModelMapping &motion_model_mapping) -> carma_cooperative_perception_interfaces::msg::Detection
auto to_time_msg(const DDateTime &d_date_time, bool is_simulation) -> builtin_interfaces::msg::Time
auto ned_to_enu(const PositionOffsetXYZ &offset_ned) noexcept
auto to_detected_object_data_msg(const carma_perception_msgs::msg::ExternalObject &external_object, const std::shared_ptr< lanelet::projection::LocalFrameProjector > &map_projection) -> carma_v2x_msgs::msg::DetectedObjectData
void convert_object_type(carma_cooperative_perception_interfaces::msg::Detection &detection, const j3224_v2x_msgs::msg::ObjectType &j3224_obj_type)
auto to_external_object_msg(const carma_cooperative_perception_interfaces::msg::Track &track) -> carma_perception_msgs::msg::ExternalObject
auto heading_to_enu_yaw(const units::angle::degree_t &heading) -> units::angle::degree_t
auto calc_relative_position(const geometry_msgs::msg::PoseStamped ¤t_pose, const carma_v2x_msgs::msg::PositionOffsetXYZ &detected_object_data) -> carma_v2x_msgs::msg::PositionOffsetXYZ
auto to_sdsm_msg(const carma_perception_msgs::msg::ExternalObjectList &external_object_list, const geometry_msgs::msg::PoseStamped ¤t_pose, const std::shared_ptr< lanelet::projection::LocalFrameProjector > &map_projection) -> carma_v2x_msgs::msg::SensorDataSharingMessage
constexpr auto remove_units(const T &value)
auto to_position_msg(const UtmCoordinate &position_utm) -> geometry_msgs::msg::Point
std::variant< multiple_object_tracking::CtrvTrack, multiple_object_tracking::CtraTrack > Track
auto transform_pose_from_map_to_wgs84(const geometry_msgs::msg::PoseStamped &source_pose, const std::shared_ptr< lanelet::projection::LocalFrameProjector > &map_projection) -> carma_v2x_msgs::msg::Position3D
auto to_detection_list_msg(const carma_v2x_msgs::msg::SensorDataSharingMessage &sdsm, std::string_view georeference, bool is_simulation, const std::optional< SdsmToDetectionListConfig > &conversion_adjustment) -> carma_cooperative_perception_interfaces::msg::DetectionList
Converts a carma_v2x_msgs::msg::SensorDataSharingMessage (SDSM) to carma_cooperative_perception_inter...
static auto from_msg(const j2735_v2x_msgs::msg::AccelerationSet4Way &msg) -> AccelerationSet4Way
std::optional< units::time::millisecond_t > second
static auto from_msg(const j2735_v2x_msgs::msg::DDateTime &msg) -> DDateTime
static auto from_msg(const j2735_v2x_msgs::msg::Heading &heading) -> Heading
units::length::meter_t easting
static auto from_msg(const j3224_v2x_msgs::msg::MeasurementTimeOffset &msg) -> MeasurementTimeOffset
static auto from_msg(const j2735_v2x_msgs::msg::Position3D &msg) -> Position3D
static auto from_msg(const j3224_v2x_msgs::msg::PositionOffsetXYZ &msg) -> PositionOffsetXYZ
static auto from_msg(const j2735_v2x_msgs::msg::Speed &speed) -> Speed
Represents a position using UTM coordinates.
Represents a position using WGS-84 coordinates.
units::angle::degree_t latitude