etsi_its_messages v3.3.0
 
Loading...
Searching...
No Matches
spatem_ts_utils.h
Go to the documentation of this file.
1/*
2=============================================================================
3MIT License
4
5Copyright (c) 2023-2025 Institute for Automotive Engineering (ika), RWTH Aachen University
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24=============================================================================
25*/
26
31
32#include <ctime>
33
34#pragma once
35
36namespace etsi_its_spatem_ts_msgs {
37
38namespace access {
39
40static constexpr std::array<float, 4> COLOR_GREY{0.5, 0.5, 0.5, 1.0};
41static constexpr std::array<float, 4> COLOR_GREEN{0.18, 0.79, 0.21, 1.0};
42static constexpr std::array<float, 4> COLOR_ORANGE{0.9, 0.7, 0.09, 1.0};
43static constexpr std::array<float, 4> COLOR_RED{0.8, 0.2, 0.2, 1.0};
44
45static constexpr int HOUR_IN_SECONDS = 3600;
46static constexpr int64_t FACTOR_SECONDS_TO_NANOSECONDS = 1000000000LL;
47
48// ETSI Timemark value equals 0.1 seconds and 10e8 nanoseconds
49static constexpr int64_t FACTOR_ETSI_TIMEMARK_TO_NANOSECONDS = 100000000LL;
50static constexpr float FACTOR_ETSI_TIMEMARK_TO_SECONDS = 0.1f;
51
52enum time_mark_value_interpretation { normal, undefined, over_an_hour, leap_second };
53
60inline uint64_t getUnixSecondsOfYear(const uint64_t unixSecond) {
61 // Get current time as a time_point
62 time_t ts = static_cast<time_t>(unixSecond); // Convert uint64_t to time_t
63
64 struct tm* timeinfo;
65 timeinfo = gmtime(&ts);
66
67 // Set the timeinfo to the beginning of the year
68 timeinfo->tm_sec = 0;
69 timeinfo->tm_min = 0;
70 timeinfo->tm_hour = 0;
71 timeinfo->tm_mday = 1;
72 timeinfo->tm_mon = 0;
73
74 return timegm(timeinfo); // Convert struct tm back to Unix timestamp
75}
76
84inline uint64_t getUnixNanosecondsFromMinuteOfTheYear(const MinuteOfTheYear& moy,
85 const uint64_t unix_nanoseconds_estimate) {
86 return ((uint64_t)(moy.value * 60) + getUnixSecondsOfYear(unix_nanoseconds_estimate * 1e-9)) * 1e9;
87}
88
95inline float interpretTimeIntervalConfidenceAsFloat(const uint16_t encoded_probability) {
96 float probability = 0;
97
98 switch (encoded_probability) {
99 case 0:
100 probability = 0.21;
101 break;
102 case 1:
103 probability = 0.36;
104 break;
105 case 2:
106 probability = 0.47;
107 break;
108 case 3:
109 probability = 0.56;
110 break;
111 case 4:
112 probability = 0.62;
113 break;
114 case 5:
115 probability = 0.68;
116 break;
117 case 6:
118 probability = 0.73;
119 break;
120 case 7:
121 probability = 0.77;
122 break;
123 case 8:
124 probability = 0.81;
125 break;
126 case 9:
127 probability = 0.85;
128 break;
129 case 10:
130 probability = 0.88;
131 break;
132 case 11:
133 probability = 0.91;
134 break;
135 case 12:
136 probability = 0.94;
137 break;
138 case 13:
139 probability = 0.96;
140 break;
141 case 14:
142 probability = 0.98;
143 break;
144 case 15:
145 probability = 1.0;
146 break;
147 }
148
149 return probability;
150}
151
158inline std::array<float, 4> interpretMovementPhaseStateAsColor(const uint8_t value) {
159 std::array<float, 4> color;
160
161 switch (value) {
162 case MovementPhaseState::UNAVAILABLE:
163 color = COLOR_GREY;
164 break;
165
166 case MovementPhaseState::DARK:
167 color = COLOR_GREY;
168 break;
169 case MovementPhaseState::STOP_THEN_PROCEED:
170 color = COLOR_RED;
171 break;
172 case MovementPhaseState::STOP_AND_REMAIN:
173 color = COLOR_RED;
174 break;
175 case MovementPhaseState::PRE_MOVEMENT:
176 color = COLOR_ORANGE;
177 break;
178 case MovementPhaseState::PERMISSIVE_MOVEMENT_ALLOWED:
179 color = COLOR_GREEN;
180 break;
181 case MovementPhaseState::PROTECTED_MOVEMENT_ALLOWED:
182 color = COLOR_GREEN;
183 break;
184 case MovementPhaseState::PERMISSIVE_CLEARANCE:
185 color = COLOR_ORANGE;
186 break;
187 case MovementPhaseState::PROTECTED_CLEARANCE:
188 color = COLOR_ORANGE;
189 break;
190 case MovementPhaseState::CAUTION_CONFLICTING_TRAFFIC:
191 color = COLOR_ORANGE;
192 break;
193 default:
194 color = COLOR_GREY;
195 break;
196 }
197
198 return color;
199}
200
207inline time_mark_value_interpretation interpretTimeMarkValueType(const uint16_t time) {
208 time_mark_value_interpretation type;
209
210 if (time == 36001) {
211 // value is undefined or unknown
212 type = time_mark_value_interpretation::undefined;
213 } else if (time == 36000) {
214 // used to indicate time >3600 seconds
215 type = time_mark_value_interpretation::over_an_hour;
216 } else if (time >= 35991 && time <= 35999) {
217 // leap second
218 type = time_mark_value_interpretation::leap_second;
219 } else { // time >= 0 && time <= 36000
220 type = time_mark_value_interpretation::normal;
221 }
222
223 return type;
224}
225
233inline int64_t interpretTimeMarkDeltaTimeAsNanoSeconds(const uint16_t time, const uint64_t nanosec) {
234 // calculate elapsed nanoseconds since the start of the last full hour
235 int64_t timestamp_hour_nanosec = ((nanosec) % (HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS));
236 // convert TimeMark value to nanoseconds
237 int64_t timemark_in_nanosec =
238 static_cast<int64_t>(time) * FACTOR_ETSI_TIMEMARK_TO_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS;
239 // calculate relative time until the next change occurs
240 int64_t rel_time_until_change = timemark_in_nanosec - timestamp_hour_nanosec;
241
242 // adjust relative time if a jump to the next hour occurs (relative time should be inside the interval [0, 3600e9) )
243 if (rel_time_until_change < 0) {
244 rel_time_until_change += HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS;
245 }
246
247 return rel_time_until_change;
248}
249
258inline float interpretTimeMarkDeltaTimeValueAsSeconds(const uint16_t time, const int32_t seconds,
259 const uint32_t nanosec) {
260 uint64_t timestamp_in_nanoseconds = seconds * FACTOR_SECONDS_TO_NANOSECONDS + nanosec;
261 return interpretTimeMarkDeltaTimeAsNanoSeconds(time, timestamp_in_nanoseconds) /
262 static_cast<float>(FACTOR_SECONDS_TO_NANOSECONDS);
263}
264
273inline std::string parseTimeMarkValueToString(const uint16_t time, const int32_t seconds, const uint32_t nanosec) {
274 time_mark_value_interpretation time_type = interpretTimeMarkValueType(time);
275
276 std::string text_content;
277
278 switch (time_type) {
279 case time_mark_value_interpretation::undefined:
280 text_content = "undefined";
281 break;
282 case time_mark_value_interpretation::over_an_hour:
283 text_content = ">36000s";
284 break;
285 case time_mark_value_interpretation::leap_second:
286 text_content = "leap second";
287 break;
288 case time_mark_value_interpretation::normal:
289 float rel_time_until_change = interpretTimeMarkDeltaTimeValueAsSeconds(time, seconds, nanosec);
290
291 // set displayed precision to 0.1
292 std::stringstream ss;
293 ss << std::fixed << std::setprecision(1) << rel_time_until_change << "s";
294 text_content = ss.str();
295 break;
296 }
297
298 return text_content;
299}
300
301} // namespace access
302
303} // 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.