etsi_its_messages v3.2.1
 
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
40 static constexpr std::array<float, 4> COLOR_GREY {0.5, 0.5, 0.5, 1.0};
41 static constexpr std::array<float, 4> COLOR_GREEN {0.18, 0.79, 0.21, 1.0};
42 static constexpr std::array<float, 4> COLOR_ORANGE {0.9, 0.7, 0.09, 1.0};
43 static constexpr std::array<float, 4> COLOR_RED {0.8, 0.2, 0.2, 1.0};
44
45 static constexpr int HOUR_IN_SECONDS = 3600;
46 static constexpr int HALF_HOUR_IN_SECONDS = 1800;
47 static constexpr int64_t FACTOR_SECONDS_TO_NANOSECONDS = 1000000000LL;
48
49 // ETSI Timemark value equals 0.1 seconds and 10e8 nanoseconds
50 static constexpr int64_t FACTOR_ETSI_TIMEMARK_TO_NANOSECONDS = 100000000LL;
51 static constexpr float FACTOR_ETSI_TIMEMARK_TO_SECONDS = 0.1f;
52
53 enum time_mark_value_interpretation { normal, undefined, over_an_hour, leap_second };
54
61 inline uint64_t getUnixSecondsOfYear(const uint64_t unixSecond) {
62
63 // Get current time as a time_point
64 time_t ts = static_cast<time_t>(unixSecond); // Convert uint64_t to time_t
65
66 struct tm* timeinfo;
67 timeinfo = gmtime(&ts);
68
69 // Set the timeinfo to the beginning of the year
70 timeinfo->tm_sec = 0;
71 timeinfo->tm_min = 0;
72 timeinfo->tm_hour = 0;
73 timeinfo->tm_mday = 1;
74 timeinfo->tm_mon = 0;
75
76 return timegm(timeinfo); // Convert struct tm back to Unix timestamp
77 }
78
86 inline uint64_t getUnixNanosecondsFromMinuteOfTheYear(const MinuteOfTheYear& moy, const uint64_t unix_nanoseconds_estimate) {
87 return ((uint64_t)(moy.value*60) + getUnixSecondsOfYear(unix_nanoseconds_estimate*1e-9))*1e9;
88 }
89
96 inline float interpretTimeIntervalConfidenceAsFloat(const uint16_t encoded_probability) {
97 float probability = 0;
98
99 switch (encoded_probability)
100 {
101 case 0:
102 probability = 0.21;
103 break;
104 case 1:
105 probability = 0.36;
106 break;
107 case 2:
108 probability = 0.47;
109 break;
110 case 3:
111 probability = 0.56;
112 break;
113 case 4:
114 probability = 0.62;
115 break;
116 case 5:
117 probability = 0.68;
118 break;
119 case 6:
120 probability = 0.73;
121 break;
122 case 7:
123 probability = 0.77;
124 break;
125 case 8:
126 probability = 0.81;
127 break;
128 case 9:
129 probability = 0.85;
130 break;
131 case 10:
132 probability = 0.88;
133 break;
134 case 11:
135 probability = 0.91;
136 break;
137 case 12:
138 probability = 0.94;
139 break;
140 case 13:
141 probability = 0.96;
142 break;
143 case 14:
144 probability = 0.98;
145 break;
146 case 15:
147 probability = 1.0;
148 break;
149 }
150
151 return probability;
152 }
153
160 inline std::array<float, 4> interpretMovementPhaseStateAsColor(const uint8_t value)
161 {
162 std::array<float, 4> color;
163
164 switch (value) {
165
166 case MovementPhaseState::UNAVAILABLE:
167 color = COLOR_GREY;
168 break;
169
170 case MovementPhaseState::DARK:
171 color = COLOR_GREY;
172 break;
173 case MovementPhaseState::STOP_THEN_PROCEED:
174 color = COLOR_RED;
175 break;
176 case MovementPhaseState::STOP_AND_REMAIN:
177 color = COLOR_RED;
178 break;
179 case MovementPhaseState::PRE_MOVEMENT:
180 color = COLOR_ORANGE;
181 break;
182 case MovementPhaseState::PERMISSIVE_MOVEMENT_ALLOWED:
183 color = COLOR_GREEN;
184 break;
185 case MovementPhaseState::PROTECTED_MOVEMENT_ALLOWED:
186 color = COLOR_GREEN;
187 break;
188 case MovementPhaseState::PERMISSIVE_CLEARANCE:
189 color = COLOR_ORANGE;
190 break;
191 case MovementPhaseState::PROTECTED_CLEARANCE:
192 color = COLOR_ORANGE;
193 break;
194 case MovementPhaseState::CAUTION_CONFLICTING_TRAFFIC:
195 color = COLOR_ORANGE;
196 break;
197 default:
198 color = COLOR_GREY;
199 break;
200 }
201
202 return color;
203}
204
211inline time_mark_value_interpretation interpretTimeMarkValueType(const uint16_t time) {
212 time_mark_value_interpretation type;
213
214 if (time == 36001) {
215 // value is undefined or unknown
216 type = time_mark_value_interpretation::undefined;
217 } else if (time == 36000) {
218 // used to indicate time >3600 seconds
219 type = time_mark_value_interpretation::over_an_hour;
220 } else if (time >= 35991 && time <= 35999) {
221 // leap second
222 type = time_mark_value_interpretation::leap_second;
223 } else { // time >= 0 && time <= 36000
224 type = time_mark_value_interpretation::normal;
225 }
226
227 return type;
228}
229
237 inline int64_t interpretTimeMarkValueAsNanoSeconds(const uint16_t time, const uint64_t nanosec) {
238 // calculate elapsed nanoseconds since the start of the last full hour in nanoseconds
239 int64_t abs_time_hour_nanosec = ((nanosec) % (HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS));
240 int64_t abs_time_decoded_nanosec = static_cast<int64_t>(time) * FACTOR_ETSI_TIMEMARK_TO_SECONDS;
241 int64_t rel_time_until_change = abs_time_decoded_nanosec - abs_time_hour_nanosec;
242
243 // adjust relative time if a jump to the next hour occurs (relative time inside the interval [-30:00, 30:00] )
244 if (rel_time_until_change < - HALF_HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS) {
245 rel_time_until_change += HOUR_IN_SECONDS * FACTOR_SECONDS_TO_NANOSECONDS;
246 }
247
248 return rel_time_until_change;
249}
250
259inline float interpretTimeMarkValueAsSeconds(const uint16_t time, const int32_t seconds, const uint32_t nanosec) {
260 // calculate elapsed seconds since the start of the last full hour
261 float abs_time_hour = ((int)(seconds)) % HOUR_IN_SECONDS + (float)nanosec * 1e-9;
262 float rel_time_until_change = (float)time * FACTOR_ETSI_TIMEMARK_TO_SECONDS - abs_time_hour;
263
264 // adjust relative time if a jump to the next hour occurs (relative time inside the interval [-30:00, 30:00] )
265 if (rel_time_until_change < - HALF_HOUR_IN_SECONDS) {
266 rel_time_until_change += HOUR_IN_SECONDS;
267 }
268
269 return rel_time_until_change;
270}
271
280inline std::string parseTimeMarkValueToString(const uint16_t time, const int32_t seconds, const uint32_t nanosec)
281{
282 time_mark_value_interpretation time_type = interpretTimeMarkValueType(time);
283
284 std::string text_content;
285
286 switch (time_type) {
287 case time_mark_value_interpretation::undefined:
288 text_content = "undefined";
289 break;
290 case time_mark_value_interpretation::over_an_hour:
291 text_content = ">36000s";
292 break;
293 case time_mark_value_interpretation::leap_second:
294 text_content = "leap second";
295 break;
296 case time_mark_value_interpretation::normal:
297 float rel_time_until_change = interpretTimeMarkValueAsSeconds(time, seconds, nanosec);
298
299 // set displayed precision to 0.1
300 std::stringstream ss;
301 ss << std::fixed << std::setprecision(1) << rel_time_until_change << "s";
302 text_content = ss.str();
303 break;
304 }
305
306 return text_content;
307}
308
309} // namespace etsi_its_spatem_ts_msgs
310
311} // namespace access
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.
int64_t interpretTimeMarkValueAsNanoSeconds(const uint16_t time, const uint64_t nanosec)
Calculates the delta between the encoded time mark and the current timestamp.
float interpretTimeMarkValueAsSeconds(const uint16_t time, const int32_t seconds, const uint32_t nanosec)
Calculates the delta between the encoded time mark and the current 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)