32 #ifndef ETSI_ITS_MSGS_UTILS_IMPL_CDD_CDD_SETTERS_COMMON_H
33 #define ETSI_ITS_MSGS_UTILS_IMPL_CDD_CDD_SETTERS_COMMON_H
37 #include <GeographicLib/UTMUPS.hpp>
42 #include <type_traits>
53 TimestampIts& timestamp_its,
const uint64_t unix_nanosecs,
57 timestamp_its.value = t_its;
66 inline void setLatitude(Latitude& latitude,
const double deg) {
67 int64_t angle_in_10_micro_degree = (int64_t)std::round(deg * 1e7);
68 throwIfOutOfRange(angle_in_10_micro_degree, Latitude::MIN, Latitude::MAX,
"Latitude");
69 latitude.value = angle_in_10_micro_degree;
79 int64_t angle_in_10_micro_degree = (int64_t)std::round(deg * 1e7);
80 throwIfOutOfRange(angle_in_10_micro_degree, Longitude::MIN, Longitude::MAX,
"Longitude");
81 longitude.value = angle_in_10_micro_degree;
91 int64_t alt_in_cm = (int64_t)std::round(value * 1e2);
92 if (alt_in_cm >= AltitudeValue::MIN && alt_in_cm <= AltitudeValue::MAX) {
93 altitude.value = alt_in_cm;
94 }
else if (alt_in_cm < AltitudeValue::MIN) {
95 altitude.value = AltitudeValue::MIN;
96 }
else if (alt_in_cm > AltitudeValue::MAX) {
97 altitude.value = AltitudeValue::MAX;
110 altitude.altitude_confidence.value = AltitudeConfidence::UNAVAILABLE;
121 auto speed_val = std::round(value * 1e2);
123 speed.value =
static_cast<decltype(speed.value)
>(speed_val);
134 if (speed_conf < SpeedConfidence::MIN && speed_conf > 0.0){
135 speed_conf = SpeedConfidence::MIN;
136 }
else if (speed_conf >= SpeedConfidence::OUT_OF_RANGE || speed_conf <= 0.0) {
137 speed_conf = SpeedConfidence::UNAVAILABLE;
139 speed_confidence.value =
static_cast<decltype(speed_confidence.value)
>(speed_conf);
151 inline void setSpeed(Speed& speed,
const double value,
const double confidence = std::numeric_limits<double>::infinity()) {
162 template <
typename AccelerationConf
idence>
165 if (accel_conf < AccelerationConfidence::MIN && accel_conf > 0.0){
166 accel_conf = AccelerationConfidence::MIN;
167 }
else if (accel_conf >= AccelerationConfidence::OUT_OF_RANGE || accel_conf <= 0.0) {
168 accel_conf = AccelerationConfidence::UNAVAILABLE;
170 accel_confidence.value =
static_cast<decltype(accel_confidence.value)
>(accel_conf);
184 template <
typename T>
186 const double altitude = AltitudeValue::UNAVAILABLE) {
189 if (altitude != AltitudeValue::UNAVAILABLE) {
192 ref_position.altitude.altitude_value.value = AltitudeValue::UNAVAILABLE;
193 ref_position.altitude.altitude_confidence.value = AltitudeConfidence::UNAVAILABLE;
210 template <
typename T>
211 inline void setFromUTMPosition(T& reference_position,
const gm::PointStamped& utm_position,
const int zone,
213 std::string required_frame_prefix =
"utm_";
214 if (utm_position.header.frame_id.rfind(required_frame_prefix, 0) != 0) {
215 throw std::invalid_argument(
"Frame-ID of UTM Position '" + utm_position.header.frame_id +
216 "' does not start with required prefix '" + required_frame_prefix +
"'!");
218 double latitude, longitude;
220 GeographicLib::UTMUPS::Reverse(zone, northp, utm_position.point.x, utm_position.point.y, latitude, longitude);
221 }
catch (GeographicLib::GeographicErr& e) {
222 throw std::invalid_argument(e.what());
235 template <
typename HeadingValue>
237 int64_t deg = (int64_t)std::round(value * 1e1);
248 template<
typename HeadingConf
idence>
251 if (heading_conf < HeadingConfidence::MIN && heading_conf > 0.0){
252 heading_conf = HeadingConfidence::MIN;
253 }
else if (heading_conf >= HeadingConfidence::OUT_OF_RANGE || heading_conf <= 0.0) {
254 heading_conf = HeadingConfidence::UNAVAILABLE;
256 heading_confidence.value =
static_cast<decltype(heading_confidence.value)
>(heading_conf);
269 template <
typename Heading,
typename HeadingConf
idence = decltype(Heading::heading_conf
idence)>
270 void setHeadingCDD(Heading& heading,
const double value,
double confidence = std::numeric_limits<double>::infinity()) {
283 template <
typename SemiAxisLength>
284 inline void setSemiAxis(SemiAxisLength& semi_axis_length,
const double length) {
286 if(semi_axis_length_val < SemiAxisLength::MIN) {
287 semi_axis_length_val = SemiAxisLength::MIN;
288 }
else if(semi_axis_length_val >= SemiAxisLength::OUT_OF_RANGE) {
289 semi_axis_length_val = SemiAxisLength::OUT_OF_RANGE;
291 semi_axis_length.value =
static_cast<uint16_t
>(semi_axis_length_val);
302 template <
typename PosConf
idenceEllipse>
304 const double semi_minor_axis,
const double orientation) {
305 setSemiAxis(position_confidence_ellipse.semi_major_confidence, semi_major_axis);
306 setSemiAxis(position_confidence_ellipse.semi_minor_confidence, semi_minor_axis);
307 setHeadingValue(position_confidence_ellipse.semi_major_orientation, orientation);
321 if(std::abs(covariance_matrix[1] - covariance_matrix[2]) > 1e-6) {
322 throw std::invalid_argument(
"Covariance matrix is not symmetric");
324 double trace = covariance_matrix[0] + covariance_matrix[3];
325 double determinant = covariance_matrix[0] * covariance_matrix[3] - covariance_matrix[1] * covariance_matrix[1];
326 if (determinant <= 0 || covariance_matrix[0] <= 0) {
330 throw std::invalid_argument(
"Covariance matrix is not positive definite");
332 double eigenvalue1 = trace / 2 + std::sqrt(trace * trace / 4 - determinant);
333 double eigenvalue2 = trace / 2 - std::sqrt(trace * trace / 4 - determinant);
337 double orientation = object_heading - 0.5 * std::atan2(2 * covariance_matrix[1], covariance_matrix[0] - covariance_matrix[3]);
338 orientation = orientation * 180 / M_PI;
341 orientation = std::fmod(orientation + 180, 180);
342 while (orientation < 0) {
345 while (orientation >= 180) {
348 return std::make_tuple(semi_major_axis, semi_minor_axis, orientation);
375 template <
typename PosConf
idenceEllipse>
376 inline void setPosConfidenceEllipse(PosConfidenceEllipse& position_confidence_ellipse,
const std::array<double, 4>& covariance_matrix,
const double object_heading){
390 template <
typename PosConf
idenceEllipse>
398 #endif // ETSI_ITS_MSGS_UTILS_IMPL_CDD_CDD_SETTERS_COMMON_H