etsi_its_messages v3.4.0
Loading...
Searching...
No Matches
spatem_ts_utils.h
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Copyright Institute for Automotive Engineering (ika), RWTH Aachen University
3
8
9#include <ctime>
10
11#pragma once
12
13namespace etsi_its_spatem_ts_msgs {
14
15namespace access {
16
17static constexpr std::array<float, 4> COLOR_GREY{0.5, 0.5, 0.5, 1.0};
18static constexpr std::array<float, 4> COLOR_GREEN{0.18, 0.79, 0.21, 1.0};
19static constexpr std::array<float, 4> COLOR_ORANGE{0.9, 0.7, 0.09, 1.0};
20static constexpr std::array<float, 4> COLOR_RED{0.8, 0.2, 0.2, 1.0};
21
22static constexpr int HOUR_IN_SECONDS = 3600;
23static constexpr int64_t FACTOR_SECONDS_TO_NANOSECONDS = 1000000000LL;
24
25// ETSI Timemark value equals 0.1 seconds and 10e8 nanoseconds
26static constexpr int64_t FACTOR_ETSI_TIMEMARK_TO_NANOSECONDS = 100000000LL;
27static constexpr float FACTOR_ETSI_TIMEMARK_TO_SECONDS = 0.1f;
28
29enum time_mark_value_interpretation { normal, undefined, over_an_hour, leap_second };
30
37inline uint64_t getUnixSecondsOfYear(const uint64_t unixSecond) {
38 // Get current time as a time_point
39 time_t ts = static_cast<time_t>(unixSecond); // Convert uint64_t to time_t
40
41 struct tm* timeinfo;
42 timeinfo = gmtime(&ts);
43
44 // Set the timeinfo to the beginning of the year
45 timeinfo->tm_sec = 0;
46 timeinfo->tm_min = 0;
47 timeinfo->tm_hour = 0;
48 timeinfo->tm_mday = 1;
49 timeinfo->tm_mon = 0;
50
51 return timegm(timeinfo); // Convert struct tm back to Unix timestamp
52}
53
61inline uint64_t getUnixNanosecondsFromMinuteOfTheYear(const MinuteOfTheYear& moy,
62 const uint64_t unix_nanoseconds_estimate) {
63 return ((uint64_t)(moy.value * 60) + getUnixSecondsOfYear(unix_nanoseconds_estimate * 1e-9)) * 1e9;
64}
65
72inline float interpretTimeIntervalConfidenceAsFloat(const uint16_t encoded_probability) {
73 float probability = 0;
74
75 switch (encoded_probability) {
76 case 0:
77 probability = 0.21;
78 break;
79 case 1:
80 probability = 0.36;
81 break;
82 case 2:
83 probability = 0.47;
84 break;
85 case 3:
86 probability = 0.56;
87 break;
88 case 4:
89 probability = 0.62;
90 break;
91 case 5:
92 probability = 0.68;
93 break;
94 case 6:
95 probability = 0.73;
96 break;
97 case 7:
98 probability = 0.77;
99 break;
100 case 8:
101 probability = 0.81;
102 break;
103 case 9:
104 probability = 0.85;
105 break;
106 case 10:
107 probability = 0.88;
108 break;
109 case 11:
110 probability = 0.91;
111 break;
112 case 12:
113 probability = 0.94;
114 break;
115 case 13:
116 probability = 0.96;
117 break;
118 case 14:
119 probability = 0.98;
120 break;
121 case 15:
122 probability = 1.0;
123 break;
124 }
125
126 return probability;
127}
128
135inline std::array<float, 4> interpretMovementPhaseStateAsColor(const uint8_t value) {
136 std::array<float, 4> color;
137
138 switch (value) {
139 case MovementPhaseState::UNAVAILABLE:
140 color = COLOR_GREY;
141 break;
142
143 case MovementPhaseState::DARK:
144 color = COLOR_GREY;
145 break;
146 case MovementPhaseState::STOP_THEN_PROCEED:
147 color = COLOR_RED;
148 break;
149 case MovementPhaseState::STOP_AND_REMAIN:
150 color = COLOR_RED;
151 break;
152 case MovementPhaseState::PRE_MOVEMENT:
153 color = COLOR_ORANGE;
154 break;
155 case MovementPhaseState::PERMISSIVE_MOVEMENT_ALLOWED:
156 color = COLOR_GREEN;
157 break;
158 case MovementPhaseState::PROTECTED_MOVEMENT_ALLOWED:
159 color = COLOR_GREEN;
160 break;
161 case MovementPhaseState::PERMISSIVE_CLEARANCE:
162 color = COLOR_ORANGE;
163 break;
164 case MovementPhaseState::PROTECTED_CLEARANCE:
165 color = COLOR_ORANGE;
166 break;
167 case MovementPhaseState::CAUTION_CONFLICTING_TRAFFIC:
168 color = COLOR_ORANGE;
169 break;
170 default:
171 color = COLOR_GREY;
172 break;
173 }
174
175 return color;
176}
177
184inline time_mark_value_interpretation interpretTimeMarkValueType(const uint16_t time) {
185 time_mark_value_interpretation type;
186
187 if (time == 36001) {
188 // value is undefined or unknown
189 type = time_mark_value_interpretation::undefined;
190 } else if (time == 36000) {
191 // used to indicate time >3600 seconds
192 type = time_mark_value_interpretation::over_an_hour;
193 } else if (time >= 35991 && time <= 35999) {
194 // leap second
195 type = time_mark_value_interpretation::leap_second;
196 } else { // time >= 0 && time <= 36000
197 type = time_mark_value_interpretation::normal;
198 }
199
200 return type;
201}
202
210inline int64_t interpretTimeMarkDeltaTimeAsNanoSeconds(const uint16_t time, const uint64_t nanosec) {
211 // calculate elapsed nanoseconds since the start of the last full hour
212 int64_t timestamp_hour_nanosec = ((nanosec) % (HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS));
213 // convert TimeMark value to nanoseconds
214 int64_t timemark_in_nanosec =
215 static_cast<int64_t>(time) * FACTOR_ETSI_TIMEMARK_TO_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS;
216 // calculate relative time until the next change occurs
217 int64_t rel_time_until_change = timemark_in_nanosec - timestamp_hour_nanosec;
218
219 // adjust relative time if a jump to the next hour occurs (relative time should be inside the interval [0, 3600e9) )
220 if (rel_time_until_change < 0) {
221 rel_time_until_change += HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS;
222 }
223
224 return rel_time_until_change;
225}
226
235inline float interpretTimeMarkDeltaTimeValueAsSeconds(const uint16_t time, const int32_t seconds,
236 const uint32_t nanosec) {
237 uint64_t timestamp_in_nanoseconds = seconds * FACTOR_SECONDS_TO_NANOSECONDS + nanosec;
238 return interpretTimeMarkDeltaTimeAsNanoSeconds(time, timestamp_in_nanoseconds) /
239 static_cast<float>(FACTOR_SECONDS_TO_NANOSECONDS);
240}
241
250inline std::string parseTimeMarkValueToString(const uint16_t time, const int32_t seconds, const uint32_t nanosec) {
251 time_mark_value_interpretation time_type = interpretTimeMarkValueType(time);
252
253 std::string text_content;
254
255 switch (time_type) {
256 case time_mark_value_interpretation::undefined:
257 text_content = "undefined";
258 break;
259 case time_mark_value_interpretation::over_an_hour:
260 text_content = ">36000s";
261 break;
262 case time_mark_value_interpretation::leap_second:
263 text_content = "leap second";
264 break;
265 case time_mark_value_interpretation::normal:
266 float rel_time_until_change = interpretTimeMarkDeltaTimeValueAsSeconds(time, seconds, nanosec);
267
268 // set displayed precision to 0.1
269 std::stringstream ss;
270 ss << std::fixed << std::setprecision(1) << rel_time_until_change << "s";
271 text_content = ss.str();
272 break;
273 }
274
275 return text_content;
276}
277
278} // namespace access
279
280} // namespace etsi_its_spatem_ts_msgs
uint64_t getUnixSecondsOfYear(const uint64_t unixSecond)
Get the unix seconds of the beginning of a year that corresponds to a given unix timestamp.
std::array< float, 4 > interpretMovementPhaseStateAsColor(const uint8_t value)
Interprets the MovementPhaseState type as a color (see etsi definition).
uint64_t getUnixNanosecondsFromMinuteOfTheYear(const MinuteOfTheYear &moy, const uint64_t unix_nanoseconds_estimate)
Get the unix nanoseconds from MinuteOfTheYear object.
float interpretTimeMarkDeltaTimeValueAsSeconds(const uint16_t time, const int32_t seconds, const uint32_t nanosec)
Calculates the delta between a TimeMark and a given timestamp.
time_mark_value_interpretation interpretTimeMarkValueType(const uint16_t time)
Interprets the type of a TimeMark message See etsi ASNI1 - IS TS 103 301 documentation for for the en...
std::string parseTimeMarkValueToString(const uint16_t time, const int32_t seconds, const uint32_t nanosec)
Converts a value from message type TimeMarkValue into a string representation.
float interpretTimeIntervalConfidenceAsFloat(const uint16_t encoded_probability)
Interprets the TimeIntervalConfidence type as a float value (see etsi definition).
int64_t interpretTimeMarkDeltaTimeAsNanoSeconds(const uint16_t time, const uint64_t nanosec)
Calculates the delta between a TimeMark and a given unix timestamp in nanoseconds.