VIPRA Documentation
Loading...
Searching...
No Matches
attributes.hpp
1#pragma once
2
3#include <algorithm>
4#include <stdexcept>
5#include <type_traits>
6
7#include "vipra/geometry/f3d.hpp"
8
9#include "vipra/logging/logging.hpp"
10#include "vipra/vipra_behaviors/behavior/exceptions.hpp"
11#include "vipra/vipra_behaviors/definitions/behavior_context.hpp"
12#include "vipra/vipra_behaviors/definitions/dsl_types.hpp"
13#include "vipra/vipra_behaviors/definitions/sim_pack.hpp"
14#include "vipra/vipra_behaviors/events/event.hpp"
15#include "vipra/vipra_behaviors/events/event_status.hpp"
16#include "vipra/vipra_behaviors/targets/target.hpp"
17#include "vipra/vipra_behaviors/values/numeric_value.hpp"
18
19namespace VIPRA::Behaviors {
24enum class Attribute {
25 INVALID = 0,
26 POSITION,
27 DIMENSIONS,
28 VELOCITY,
29 END_GOAL,
30 CURR_GOAL,
31 STATE,
32 LOCATION,
33 STATUS,
34};
35
40enum class Type {
41 INVALID = 0,
42 NUMBER,
43 COORD,
44 STATE,
45 STATUS,
46 LOCATION,
47 TOWARDS_LOC,
48 TOWARDS_ATTR,
49 OBJECTIVE,
50 POSITION
51};
52
57struct CAttributeValue {
58 Type type;
59 void const* value;
60
61 CAttributeValue(Type aType, void const* aVal) : type(aType), value(aVal) {}
62
63 inline void type_check(Type check) const
64 {
65 if ( type != check ) DSLException::error("Invalid Type");
66 }
67
74 template <typename value_t>
75 [[nodiscard]] inline auto as() const -> value_t const&
76 {
77 return *static_cast<value_t const*>(value);
78 }
79
86 template <typename value_t>
87 [[nodiscard]] inline auto as_ptr() const -> value_t const*
88 {
89 return static_cast<value_t const*>(value);
90 }
91};
92
98 Type type;
99 void* value;
100
106 inline void type_check(Type check) const
107 {
108 if ( type != check ) DSLException::error("Invalid Type");
109 }
110
117 template <typename value_t>
118 [[nodiscard]] inline auto as() -> value_t&
119 {
120 return *static_cast<value_t*>(value);
121 }
122
129 template <typename value_t>
130 [[nodiscard]] inline auto as_ptr() const -> value_t*
131 {
132 return static_cast<value_t*>(value);
133 }
134};
135
141 public:
150 [[nodiscard]] inline static auto get_value(Target target, Attribute attr,
151 auto pack) -> CAttributeValue
152 {
153 switch ( target.type ) {
154 case TargetType::PEDESTRIAN:
155 return get_ped_value(target, attr, pack);
156 case TargetType::EVENT:
157 return get_event_value(target, attr, pack);
158 case TargetType::LOCATION:
159 return get_location_value(target, attr, pack);
160 case TargetType::INVALID:
161 return {Type::INVALID, nullptr};
162 }
163
164 return {Type::INVALID, nullptr};
165 }
166
176 inline static void set_value(Target target, Attribute attr, Simpack pack,
177 VIPRA::State& state, CAttributeValue value)
178 {
179 switch ( target.type ) {
180 case TargetType::PEDESTRIAN:
181 set_ped_value(target, attr, pack, state, value);
182 return;
183 case TargetType::EVENT:
184 set_event_value(target, attr, pack, value);
185 return;
186 case TargetType::LOCATION:
187 set_location_value(target, attr, pack, value);
188 return;
189 case TargetType::INVALID:
190 return;
191 }
192 }
193
203 inline static void scale_value(Target target, Attribute attr, Simpack pack,
204 VIPRA::State& state, CAttributeValue value)
205 {
206 switch ( target.type ) {
207 case TargetType::PEDESTRIAN:
208 scale_ped_value(target, attr, pack, state, value);
209 return;
210 case TargetType::EVENT:
211 DSLException::error("Cannot Scale Event Value");
212 return;
213 case TargetType::LOCATION:
214 DSLException::error("Cannot Scale Location Value");
215 return;
216 case TargetType::INVALID:
217 return;
218 }
219 }
220
229 [[nodiscard]] inline static auto is_coord_loc_compare(CAttributeValue value1,
230 CAttributeValue value2) -> bool
231 {
232 return (value1.type == Type::COORD && value2.type == Type::LOCATION) ||
233 (value1.type == Type::LOCATION && value2.type == Type::COORD);
234 }
235
245 [[nodiscard]] inline static auto coord_loc_compare(CAttributeValue value1,
246 CAttributeValue value2,
247 auto pack) -> bool
248 {
249 if ( value1.type == Type::COORD && value2.type == Type::LOCATION ) {
250 return pack.context.locations[value2.as<VIPRA::idx>()].is_point_inside(
251 value1.as<VIPRA::f3d>());
252 }
253
254 if ( value2.type == Type::COORD && value1.type == Type::LOCATION ) {
255 return pack.context.locations[value1.as<VIPRA::idx>()].is_point_inside(
256 value2.as<VIPRA::f3d>());
257 }
258
259 return false;
260 }
261
270 [[nodiscard]] inline static auto is_equal(CAttributeValue value1,
271 CAttributeValue value2, auto pack) -> bool
272 {
273 if ( is_coord_loc_compare(value1, value2) ) {
274 return coord_loc_compare(value1, value2, pack);
275 }
276
277 if ( value1.type != value2.type ) return false;
278
279 switch ( value1.type ) {
280 case Type::INVALID:
281 throw std::runtime_error("Invalid Attribute Type");
282 return false;
283 case Type::NUMBER:
284 return value1.as<VIPRA::f_pnt>() == value2.as<VIPRA::f_pnt>();
285 case Type::COORD:
286 return value1.as<VIPRA::f3d>().distance_to_sqrd(value2.as<VIPRA::f3d>()) <= 0.04;
287 case Type::STATE:
288 return value1.as<stateUID>() == value2.as<stateUID>();
289 case Type::STATUS:
290 return value1.as<EventStatus>() == value2.as<EventStatus>();
291 case Type::LOCATION:
292 return value1.as<VIPRA::idx>() == value2.as<VIPRA::idx>();
293 break;
294 default:
295 break;
296 }
297
298 return false;
299 }
300
309 [[nodiscard]] inline static auto is_not_equal(CAttributeValue value1,
310 CAttributeValue value2, auto pack) -> bool
311 {
312 return ! is_equal(value1, value2, pack);
313 }
314
323 template <typename value_t>
324 [[nodiscard]] inline static auto store_value(Type type,
325 value_t&& value) -> CAttributeValue
326 {
327 auto& valueStore = get_value_store();
328 valueStore.emplace_back(
329 type, new std::remove_cvref_t<value_t>(std::forward<value_t>(value)));
330 return valueStore.back();
331 }
332
333 inline static void cleanup()
334 {
335 for ( auto data : get_value_store() ) {
336 // NOLINTBEGIN(cppcoreguidelines-owning-memory)
337 switch ( data.type ) {
338 case Type::INVALID:
339 // throw std::runtime_error("Invalid Type");
340 break;
341 case Type::NUMBER:
342 delete data.as_ptr<VIPRA::f_pnt>();
343 break;
344 case Type::COORD:
345 delete data.as_ptr<VIPRA::f3d>();
346 break;
347 case Type::STATE:
348 delete data.as_ptr<stateUID>();
349 break;
350 case Type::STATUS:
351 delete data.as_ptr<EventStatus>();
352 break;
353 case Type::LOCATION:
354 [[fallthrough]];
355 case Type::TOWARDS_LOC:
356 delete data.as_ptr<VIPRA::idx>();
357 break;
358 case Type::TOWARDS_ATTR:
359 delete data.as_ptr<Attribute>();
360 break;
361 default:
362 // throw std::runtime_error("Cleanup Error: Unknown Type");
363 break;
364 }
365 // NOLINTEND(cppcoreguidelines-owning-memory)
366 }
367
368 get_value_store().clear();
369 }
370
371 struct DeferedCleanup {
372 DeferedCleanup(DeferedCleanup const&) = default;
373 DeferedCleanup(DeferedCleanup&&) = default;
374 auto operator=(DeferedCleanup const&) -> DeferedCleanup& = default;
375 auto operator=(DeferedCleanup&&) -> DeferedCleanup& = default;
376 DeferedCleanup() = default;
377 ~DeferedCleanup() { AttributeHandling::cleanup(); }
378 };
379
380 private:
381 static const DeferedCleanup CLEANUP;
382
383 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) Bug in clang-tidy (https://bugs.llvm.org/show_bug.cgi?id=48040)
384 static inline auto get_value_store() -> std::vector<CAttributeValue>&
385 {
386 static std::vector<CAttributeValue> valueStore;
387 return valueStore;
388 }
389
398 [[nodiscard]] inline static auto get_ped_value(Target target, Attribute attr,
399 auto pack) -> CAttributeValue
400 {
401 switch ( attr ) {
402 case Attribute::POSITION:
403 return {Type::COORD, &pack.pedset.ped_coords(target.targetIdx)};
404 case Attribute::VELOCITY:
405 return {Type::COORD, &pack.state.velocities[target.targetIdx]};
406 case Attribute::END_GOAL:
407 return {Type::COORD, &pack.goals.end_goal(target.targetIdx)};
408 case Attribute::CURR_GOAL:
409 return {Type::COORD, &pack.goals.current_goal(target.targetIdx)};
410 case Attribute::STATE:
411 return {Type::STATE, &pack.context.pedStates[target.targetIdx]};
412 default:
413 DSLException::error("Invalid Pedestrian Attribute");
414 }
415 }
416
425 [[nodiscard]] inline static auto get_event_value(Target target, Attribute attr,
426 auto pack) -> CAttributeValue
427 {
428 switch ( attr ) {
429 case Attribute::LOCATION:
430 // TODO (rolland) : get this added in when event locations are done
431 DSLException::error("Event Locations Not Implmented");
432 case Attribute::STATUS:
433 return {Type::STATUS, &pack.context.events[target.targetIdx].get_status()};
434 default:
435 DSLException::error("Invalid Event Attribute");
436 }
437 }
438
447 [[nodiscard]] inline static auto get_location_value(Target target, Attribute attr,
448 auto pack) -> CAttributeValue
449 {
450 switch ( attr ) {
451 case Attribute::POSITION:
452 return {Type::COORD, &pack.context.locations[target.targetIdx].center()};
453 case Attribute::DIMENSIONS:
454 default:
455 DSLException::error("Invalid Location Attribute");
456 }
457 }
458
468 inline static void set_ped_value(Target target, Attribute attr, Simpack pack,
469 VIPRA::State& state, CAttributeValue value)
470 {
471 switch ( attr ) {
472 case Attribute::POSITION:
473 set_position(target, state, value);
474 return;
475 case Attribute::VELOCITY:
476 set_velocity(target, pack, state, value);
477 return;
478 case Attribute::END_GOAL:
479 set_goal(target, pack, value);
480 return;
481 case Attribute::CURR_GOAL:
482 DSLException::error("Unable to set Pedestrian Current Goal");
483 return;
484 case Attribute::STATE:
485 set_state(target, pack, value);
486 return;
487 default:
488 DSLException::error("Invalid Pedestrian Attribute");
489 }
490 }
491
500 inline static void set_location_value(Target /*target*/, Attribute attr,
501 Simpack /*pack*/, CAttributeValue /*value*/)
502 {
503 switch ( attr ) {
504 case Attribute::POSITION:
505 case Attribute::DIMENSIONS:
506 default:
507 DSLException::error("Invalid Location Attribute");
508 }
509 }
510
520 inline static void scale_ped_value(Target target, Attribute attr, Simpack pack,
521 VIPRA::State& state, CAttributeValue value)
522 {
523 switch ( attr ) {
524 case Attribute::POSITION:
525 DSLException::error("Cannot Scale Pedestrian Position");
526 return;
527 case Attribute::VELOCITY:
528 scale_velocity(target, pack, state, value);
529 return;
530 case Attribute::CURR_GOAL:
531 case Attribute::END_GOAL:
532 DSLException::error("Cannot Scale Pedestrian Position");
533 return;
534 case Attribute::STATE:
535 set_state(target, pack, value);
536 return;
537 case Attribute::INVALID:
538 case Attribute::LOCATION:
539 case Attribute::STATUS:
540 DSLException::error("Invalid Pedestrian Attribute");
541 break;
542 case Attribute::DIMENSIONS:
543 DSLException::error("Pedestrians Do Not Have Dimensions");
544 break;
545 }
546 }
547
556 inline static void set_event_value(Target target, Attribute attr, Simpack pack,
557 CAttributeValue value)
558 {
559 switch ( attr ) {
560 case Attribute::LOCATION:
561 // TODO (rolland) : get this added in when event locations are done
562 DSLException::error("Event Locations Not Implmented");
563 case Attribute::STATUS:
564 pack.context.events[target.targetIdx].set_status(
565 value.as<Behaviors::EventStatus>());
566 return;
567 default:
568 DSLException::error("Invalid Event Attribute");
569 }
570 }
571
572 // ------------------------------------------- SETTERS ------------------------------------------------------------------------
573
581 static inline void set_position(Target target, VIPRA::State& state,
582 CAttributeValue value)
583 {
584 value.type_check(Type::COORD);
585 state.positions[target.targetIdx] = value.as<VIPRA::f3d>();
586 }
587
595 static inline void set_state(Target target, Simpack pack, CAttributeValue value)
596 {
597 value.type_check(Type::STATE);
598 pack.context.pedStates[target.targetIdx] = value.as<stateUID>();
599 }
600
608 static inline void set_goal(Target target, Simpack pack, CAttributeValue value)
609 {
610 auto& goals = pack.goals;
611 auto& context = pack.context;
612 auto const& pedset = pack.pedset;
613
614 if ( value.type == Type::COORD ) {
615 goals.change_end_goal(target.targetIdx, pedset.ped_coords(target.targetIdx),
616 value.as<VIPRA::f3d>(), context.engine);
617 }
618 else if ( value.type == Type::LOCATION ) {
619 // TODO(rolland): this doesn't take into account two pedestrains going to the same location
620 goals.change_end_goal(
621 target.targetIdx, pedset.ped_coords(target.targetIdx),
622 context.locations[value.as<VIPRA::idx>()].random_point(context.engine),
623 context.engine);
624 }
625 }
626
635 static inline void set_velocity(Target target, Simpack pack, VIPRA::State& state,
636 CAttributeValue value)
637 {
638 value.type_check(Type::COORD);
639
640 state.velocities[target.targetIdx] = value.as<VIPRA::f3d>();
641
642 VIPRA::f3d originalPos = pack.pedset.ped_coords(target.targetIdx);
643 state.positions[target.targetIdx] =
644 originalPos + (state.velocities[target.targetIdx] * pack.dT);
645 }
646
647 // ------------------------------------------- END SETTERS ------------------------------------------------------------------------
648
649 // --------------------------------------------- SCALING ------------------------------------------------------------------------
650
659 static inline void scale_velocity(Target target, Simpack pack, VIPRA::State& state,
660 CAttributeValue value)
661 {
662 value.type_check(Type::NUMBER);
663
664 NumericValue const& scale = *static_cast<NumericValue const*>(value.value);
665 // TODO (rolland): get magnitude, scale that then apply to the unit vector
666 VIPRA::f_pnt scaleVal = scale.value(target.targetIdx);
667 auto tempvel = state.velocities[target.targetIdx];
668 tempvel *= scaleVal;
669 state.positions[target.targetIdx] =
670 pack.pedset.ped_coords(target.targetIdx) + (tempvel * pack.dT);
671 }
672
673 // --------------------------------------------- END SCALING ------------------------------------------------------------------------
674};
675} // namespace VIPRA::Behaviors
Handles all getting/setting of attributes in Behaviors.
Definition attributes.hpp:140
static auto is_coord_loc_compare(CAttributeValue value1, CAttributeValue value2) -> bool
Checks if the values are a coordinate and a value, returns true if so.
Definition attributes.hpp:229
static auto is_equal(CAttributeValue value1, CAttributeValue value2, auto pack) -> bool
Checks if two AttributeValues are equal.
Definition attributes.hpp:270
static void scale_value(Target target, Attribute attr, Simpack pack, VIPRA::State &state, CAttributeValue value)
Scales a targets attribute value.
Definition attributes.hpp:203
static void set_value(Target target, Attribute attr, Simpack pack, VIPRA::State &state, CAttributeValue value)
Sets a targets attribute value.
Definition attributes.hpp:176
static auto get_value(Target target, Attribute attr, auto pack) -> CAttributeValue
Returns the specified attribute value of the target.
Definition attributes.hpp:150
static auto coord_loc_compare(CAttributeValue value1, CAttributeValue value2, auto pack) -> bool
Compares a coordinate and location, returns true if the coordinate is in the location.
Definition attributes.hpp:245
static auto is_not_equal(CAttributeValue value1, CAttributeValue value2, auto pack) -> bool
Checks if two AttributeValues are not equal.
Definition attributes.hpp:309
static auto store_value(Type type, value_t &&value) -> CAttributeValue
Adds an attribute value to the value store, for later use in atoms.
Definition attributes.hpp:324
Holds a mutable attribute value and its type.
Definition attributes.hpp:97
auto as() -> value_t &
Returns a refernce to the value as a given type.
Definition attributes.hpp:118
auto as_ptr() const -> value_t *
Returns a pointer to the value as a given type.
Definition attributes.hpp:130
void type_check(Type check) const
Checks that the value is a given type, throws exception if not correct type.
Definition attributes.hpp:106
Holds an immutable attribute value and its type.
Definition attributes.hpp:57
auto as_ptr() const -> value_t const *
Returns a pointer to the value as a given type.
Definition attributes.hpp:87
auto as() const -> value_t const &
Returns a refernce to the value as a given type.
Definition attributes.hpp:75
Holds references to commonly used parameters for simpler passing.
Definition sim_pack.hpp:23
Holds information about what to target.
Definition target.hpp:18
Struct that holds the updated positions and velocities of all pedestrians.
Definition state.hpp:12
Definition f3d.hpp:27