diff --git a/.clang-format b/.clang-format index b580ec9ff78e8322008ec834c3ecfd72d8bbc62a..af2e0944734f3c4221734748cf9e721bb040a1b8 100644 --- a/.clang-format +++ b/.clang-format @@ -7,3 +7,4 @@ BinPackParameters: false BreakBeforeBraces: Allman ColumnLimit: 0 InsertNewlineAtEOF: true +SeparateDefinitionBlocks: Always diff --git a/BUILD.bazel b/BUILD.bazel index d26e88c2fef44b3cf0d6899b8f14a7405c6dceb3..41b9354db4b94cb9d187e74e302ad401668634b2 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -30,6 +30,6 @@ cc_library( cc_test( name = "interface_test", timeout = "short", - srcs = ["test/interface_test.cpp"] + glob(["test/**/*.cc"]), + srcs = glob(["test/**/*.cc"]), deps = [":test_utils"], ) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 5b7684a3eb20e91ffd7fc751b6cf84d62f7c2529..f39e5d5f3a83f9fa96be3c9cd71ed3122156a350 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,5 +1,5 @@ ################################################################################ -# Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2022-2024 Mercedes-Benz Tech Innovation GmbH # 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) # # This program and the accompanying materials are made available under the terms @@ -17,6 +17,7 @@ set(DOXYGEN_BUILTIN_STL_SUPPORT YES) set(DOXYGEN_DISABLE_INDEX NO) set(DOXYGEN_DOT_IMAGE_FORMAT svg) set(DOXYGEN_DOT_TRANSPARENT YES) +set(DOXYGEN_EXCLUDE_SYMBOLS "detail*") set(DOXYGEN_FULL_SIDEBAR NO) set(DOXYGEN_GENERATE_LATEX NO) set(DOXYGEN_GENERATE_TREEVIEW YES) @@ -40,6 +41,7 @@ set(DOXYGEN_QUIET YES) set(DOXYGEN_RECURSIVE YES) set(DOXYGEN_TAB_SIZE 2) set(DOXYGEN_UML_LOOK YES) +set(DOXYGEN_USE_MATHJAX YES) set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${PROJECT_SOURCE_DIR}/README.md) set(DOXYGEN_WARN_LOGFILE ${CMAKE_CURRENT_BINARY_DIR}/DoxygenWarningLog.txt) set(DOXYGEN_WARN_NO_PARAMDOC YES) diff --git a/include/MantleAPI/Common/bounding_box.h b/include/MantleAPI/Common/bounding_box.h index 0160dab467e5021a428f6f38986e56ef3fcf3857..7185e80ecd20fbafba8410ad420d772617cd3048 100644 --- a/include/MantleAPI/Common/bounding_box.h +++ b/include/MantleAPI/Common/bounding_box.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,27 +20,54 @@ #include <MantleAPI/Common/vector.h> #include <units.h> +#include <iosfwd> +#include <tuple> + namespace mantle_api { +/// Bounding box of an entity. +/// /// Each entity has its own local, right-handed coordinate system, where x means "forward" (e.g. driving direction), y means left and z means upwards. /// The origin of the entity coordinate system is determined by specifying the offset of the geometric bounding box center in entity coordinates. /// For vehicles the origin shall be the center of the rear axis. struct BoundingBox { - Vec3<units::length::meter_t> geometric_center{}; ///< Coordinates of bounding box center in local coordinate system - Dimension3 dimension{}; ///< Dimension of the bounding box (i.e. length = x dimension, width = y dimension, height = z dimension) + Vec3<units::length::meter_t> geometric_center; ///< Coordinates of bounding box center in local coordinate system + Dimension3 dimension; ///< Dimension of the bounding box (i.e. length = x dimension, width = y dimension, height = z dimension) }; -/// @brief equality -/// @details Compares the values of two BoundingBoxes. -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the values of lhs exactly equal to the values of rhs. +/// Compare the values of two BoundingBoxes. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two BoundingBoxes are equal, false otherwise constexpr bool operator==(const BoundingBox& lhs, const BoundingBox& rhs) noexcept { - return lhs.geometric_center == rhs.geometric_center && - lhs.dimension == rhs.dimension; + return std::tie(lhs.geometric_center, lhs.dimension) == + std::tie(rhs.geometric_center, rhs.dimension); +} + +/// Compare the values of two BoundingBoxes. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two BoundingBoxes are not equal, false otherwise +constexpr bool operator!=(const BoundingBox& lhs, const BoundingBox& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Output stream operator for BoundingBox. +/// +/// @param[in] os output stream +/// @param[in] bounding_box BoundingBox to be printed +/// @returns output stream with printed BoundingBox +/// +inline std::ostream& operator<<(std::ostream& os, const BoundingBox& bounding_box) +{ + os << "BoundingBox(.geometric_center=" << bounding_box.geometric_center << ", .dimension=" << bounding_box.dimension << ')'; + return os; } } // namespace mantle_api diff --git a/include/MantleAPI/Common/dimension.h b/include/MantleAPI/Common/dimension.h index 16e13c81d15b481bd40fd4e8c504cb20a8d401cf..feb1f7eada2907721a7a4a743d6a55b893bc0060 100644 --- a/include/MantleAPI/Common/dimension.h +++ b/include/MantleAPI/Common/dimension.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -18,37 +19,52 @@ #include <MantleAPI/Common/floating_point_helper.h> #include <units.h> +#include <iosfwd> + namespace mantle_api { -/// This struct represents the dimension of the bounding box +/// Dimension of an object. struct Dimension3 { - units::length::meter_t length{0}; ///< Length of the object’s bounding box - units::length::meter_t width{0}; ///< Width of the object’s bounding box - units::length::meter_t height{0}; ///< Height of the object’s bounding box + units::length::meter_t length; ///< Length of the object + units::length::meter_t width; ///< Width of the object + units::length::meter_t height; ///< Height of the object }; -/// @brief almost-equality -/// @details Compares the values of two dimensions. -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs almost equal to the values of rhs. -constexpr bool operator==(const Dimension3& lhs, const Dimension3& rhs) noexcept +/// Compare the values of two Dimension3. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Dimension3 are equal, false otherwise +constexpr bool +operator==(const Dimension3& lhs, const Dimension3& rhs) noexcept { - return AlmostEqual(lhs.length, rhs.length) && AlmostEqual(lhs.width, rhs.width) && AlmostEqual(lhs.height, rhs.height); + return AlmostEqual(std::tie(lhs.length, lhs.width, lhs.height), std::tie(rhs.length, rhs.width, rhs.height)); } -/// @brief inequality -/// @details Compares the value of two dimensions. -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// Compare the values of two Dimension3. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Dimension3 are not equal, false otherwise constexpr bool operator!=(const Dimension3& lhs, const Dimension3& rhs) noexcept { return !(lhs == rhs); } +/// Output stream operator for Dimension3. +/// +/// @param[in] os output stream +/// @param[in] dimension Dimension3 to be printed +/// @returns output stream with printed Dimension3 +/// +inline std::ostream& operator<<(std::ostream& os, const Dimension3& dimension) +{ + os << "Dimension3(.length=" << dimension.length << ", .width=" << dimension.width << ", .height=" << dimension.height << ')'; + return os; +} + } // namespace mantle_api #endif // MANTLEAPI_COMMON_DIMENSION_H diff --git a/include/MantleAPI/Common/floating_point_helper.h b/include/MantleAPI/Common/floating_point_helper.h index 4824fa058e0c24288d2a44caef1a3e9a8b63946c..3652c1866e1368335217f2dc5fb5265680fabb54 100644 --- a/include/MantleAPI/Common/floating_point_helper.h +++ b/include/MantleAPI/Common/floating_point_helper.h @@ -19,10 +19,12 @@ #include <units.h> #include <cmath> +#include <tuple> #include <type_traits> +#include <utility> #if !defined(MANTLE_API_DEFAULT_EPS) -/// @brief Default epsilon for floating-point comparison. +/// Default epsilon for floating-point comparison. /// /// > The C++ header `<limits>` provides a constant `std::numeric_limits<float>::epsilon()` /// > for this purpose. The “standard†epsilon has the value 1.192092896e-07. This is @@ -41,7 +43,7 @@ namespace mantle_api namespace details { -/// @brief The signum function, that returns the sign of a real number +/// The signum function, that returns the sign of a real number. /// /// @tparam T the value type /// @param[in] value Real number @@ -54,11 +56,11 @@ constexpr int signum(const T value) noexcept } // namespace details -/// @brief Default epsilon for floating-point comparison. +/// Default epsilon for floating-point comparison. /// inline constexpr auto kDefaultEps = MANTLE_API_DEFAULT_EPS; -/// @brief Compare two values for almost-equality. +/// Compare two values for almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -105,7 +107,7 @@ constexpr bool AlmostEqual(const T lhs, const T rhs, const T epsilon = static_ca return false; } -/// @brief Compare two values for greater-or-almost-equality. +/// Compare two values for greater-or-almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -124,7 +126,7 @@ constexpr bool GreaterOrEqual(const T lhs, const T rhs, const T epsilon = static return AlmostEqual(lhs, rhs, epsilon, absolute_comparison_only); } -/// @brief Compare two values for less-or-almost-equality. +/// Compare two values for less-or-almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -143,7 +145,7 @@ constexpr bool LessOrEqual(const T lhs, const T rhs, const T epsilon = static_ca return AlmostEqual(lhs, rhs, epsilon, absolute_comparison_only); } -/// @brief Compare two values for almost-equality. +/// Compare two values for almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -157,7 +159,7 @@ constexpr bool AlmostEqual(const T lhs, const T rhs, const T epsilon = T{kDefaul return AlmostEqual(lhs(), rhs(), epsilon(), absolute_comparison_only); } -/// @brief Compare two values for greater-or-almost-equality. +/// Compare two values for greater-or-almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -171,7 +173,7 @@ constexpr bool GreaterOrEqual(const T lhs, const T rhs, const T epsilon = T{kDef return GreaterOrEqual(lhs(), rhs(), epsilon(), absolute_comparison_only); } -/// @brief Compare two values for less-or-almost-equality. +/// Compare two values for less-or-almost-equality. /// /// @tparam T the value type /// @param[in] lhs The left-hand side value @@ -185,6 +187,34 @@ constexpr bool LessOrEqual(const T lhs, const T rhs, const T epsilon = T{kDefaul return LessOrEqual(lhs(), rhs(), epsilon(), absolute_comparison_only); } +namespace detail +{ + +template <typename Tuple, typename T, std::size_t... I> +constexpr bool AlmostEqualImpl(const Tuple& lhs, const Tuple& rhs, T epsilon, bool absolute_comparison_only, std::index_sequence<I...> /*unused*/) +{ + return (AlmostEqual(std::get<I>(lhs), std::get<I>(rhs), std::decay_t<decltype(std::get<I>(lhs))>(epsilon), absolute_comparison_only) && ...); +} + +} // namespace detail + +/// Compare the values of two tuples for almost-equality. +/// +/// @tparam T the type of epsilon +/// @tparam Ts the types of the tuple elements +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @param[in] epsilon The epsilon for floating-point comparison +/// @param[in] absolute_comparison_only True if only absolute comparison should be used to test large numbers' equality +/// @returns true, if the values of the two tuples are equal, false otherwise +template <typename T = double, typename... Ts> +constexpr bool AlmostEqual(const std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs, // + T epsilon = T{kDefaultEps}, + bool absolute_comparison_only = false) +{ + return detail::AlmostEqualImpl(lhs, rhs, epsilon, absolute_comparison_only, std::index_sequence_for<Ts...>{}); +} + } // namespace mantle_api #endif // MANTLEAPI_COMMON_FLOATING_POINT_HELPER_H diff --git a/include/MantleAPI/Common/i_identifiable.h b/include/MantleAPI/Common/i_identifiable.h index 19b9e821376f05325d7af2ba693106b0d9b13fd8..a61eb8460ccd7f68758a6413070ddb413055cc7f 100644 --- a/include/MantleAPI/Common/i_identifiable.h +++ b/include/MantleAPI/Common/i_identifiable.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,14 +17,14 @@ #define MANTLEAPI_COMMON_I_IDENTIFIABLE_H #include <cstdint> -#include <limits> #include <string> +#include "MantleAPI/Common/identifier.h" + namespace mantle_api { -using UniqueId = std::uint64_t; ///< Container for unique id -constexpr UniqueId InvalidId{std::numeric_limits<UniqueId>::max()}; ///< 'invalid' id +using UniqueId = Identifier<std::uint64_t, struct UniqueIdTag>; ///< Unique identifier type /// Common interface for all classes that can be referenced by an ID or name. class IIdentifiable diff --git a/include/MantleAPI/Common/i_logger.h b/include/MantleAPI/Common/i_logger.h index 58b6f68406e23c9683393a7671551a552580d50a..7e26858abaa83fafa4458d4dfa1a35f530c1f066 100644 --- a/include/MantleAPI/Common/i_logger.h +++ b/include/MantleAPI/Common/i_logger.h @@ -16,6 +16,10 @@ #ifndef MANTLEAPI_COMMON_I_LOGGER_H #define MANTLEAPI_COMMON_I_LOGGER_H +#include <MantleAPI/Common/meta.h> + +#include <array> +#include <cstdint> #include <string_view> /// MantleAPI namespace @@ -32,7 +36,7 @@ namespace mantle_api /// Log level definition for ILogger /// @ingroup logging -enum class LogLevel : int +enum class LogLevel : std::uint8_t { kTrace = 0, ///< Step by step execution messages for intensive debugging kDebug, ///< Messages considered to be useful for debugging @@ -42,6 +46,23 @@ enum class LogLevel : int kCritical ///< Key business functionality is not working, the overall system is impaired }; +/// Meta info for LogLevel +template <> +struct meta::info<LogLevel> +{ + /// Get the enumerators of LogLevel + /// @return The enumerators of LogLevel + [[nodiscard]] static constexpr std::array<meta::enum_info<LogLevel>, 6U> get_enumerators() noexcept + { + return {{{LogLevel::kTrace, "Trace"}, + {LogLevel::kDebug, "Debug"}, + {LogLevel::kInfo, "Info"}, + {LogLevel::kWarning, "Warning"}, + {LogLevel::kError, "Error"}, + {LogLevel::kCritical, "Critical"}}}; + } +}; + /// Interface for logging messages /// @ingroup logging class ILogger diff --git a/include/MantleAPI/Common/identifier.h b/include/MantleAPI/Common/identifier.h new file mode 100644 index 0000000000000000000000000000000000000000..15fc0b10f94b6162a6d8fa34d6d77e5b6b63739b --- /dev/null +++ b/include/MantleAPI/Common/identifier.h @@ -0,0 +1,310 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +//----------------------------------------------------------------------------- +/// @file MantleAPI/Common/identifier.h +//----------------------------------------------------------------------------- + +#ifndef MANTLEAPI_COMMON_IDENTIFIER_H +#define MANTLEAPI_COMMON_IDENTIFIER_H + +#include <iosfwd> // for std::ostream +#include <limits> // for std::numeric_limits +#include <string> // for std::to_string, std::hash +#include <type_traits> // for std::enable_if_t +#include <utility> // for std::exchange, std::move, std::swap + +/// MantleAPI namespace +namespace mantle_api +{ + +/// Identifier class +/// @tparam T Type of the identifier +/// @tparam Tag Tag type +template <typename T, typename Tag, std::enable_if_t<std::numeric_limits<T>::is_specialized, bool> = true> +class Identifier +{ +public: + using ValueType = T; ///< Value type + using TagType = Tag; ///< Tag type + + static constexpr auto kInvalid = std::numeric_limits<ValueType>::max(); ///< Invalid identifier value + + /// Default constructor + constexpr Identifier() noexcept = default; + + /// Constructor from value type + /// @param value Identifier value + constexpr explicit Identifier(ValueType value) noexcept + : value_(value) {} + + /// Copy constructor + /// @param other Other identifier + constexpr Identifier(const Identifier& other) = default; + + /// Move constructor + /// @param other Other identifier + constexpr Identifier(Identifier&& other) noexcept + : value_(std::exchange(other.value_, kInvalid)) {} + + /// Copy assignment operator + /// @param other Other identifier + /// @return Reference to this + constexpr Identifier& operator=(const Identifier& other) noexcept = default; + + /// Copy assignment operator + /// @param other Other identifier + /// @return Reference to this + Identifier& operator=(Identifier& other) noexcept = default; + + /// Move assignment operator + /// @param other Other identifier + /// @return Reference to this + constexpr Identifier& operator=(Identifier&& other) noexcept + { + value_ = std::exchange(other.value_, kInvalid); + return *this; + } + + /// Destructor + ~Identifier() noexcept = default; + + /// Convert to value type + /// @return Value type + [[nodiscard]] constexpr ValueType Value() const noexcept + { + return value_; + } + + /// Conversion operator to value type + /// @return Value type + [[nodiscard]] constexpr explicit operator ValueType() const noexcept + { + return Value(); + } + + /// Check if the identifier has a value + /// @return True if has a value, false otherwise + [[nodiscard]] constexpr bool HasValue() const noexcept + { + return value_ != kInvalid; + } + + /// Conversion operator to bool + /// @return True if has a value, false otherwise + [[nodiscard]] constexpr explicit operator bool() const noexcept { return HasValue(); } + + /// Assignment operator with value type + /// @param value Value type + /// @return Reference to this + constexpr Identifier& operator=(ValueType&& value) noexcept + { + value_ = std::move(value); + return *this; + } + + /// Equality operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if equal, false otherwise + friend constexpr bool operator==(const Identifier& lhs, const Identifier& rhs) noexcept + { + return lhs.value_ == rhs.value_; + } + + /// Inequality operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if not equal, false otherwise + friend constexpr bool operator!=(const Identifier& lhs, const Identifier& rhs) noexcept + { + return !(lhs == rhs); + } + + /// Equality operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if equal, false otherwise + friend constexpr bool operator==(const Identifier& lhs, ValueType rhs) noexcept + { + return lhs.value_ == rhs; + } + + /// Equality operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if equal, false otherwise + friend constexpr bool operator==(ValueType lhs, const Identifier& rhs) noexcept + { + return rhs.value_ == lhs; + } + + /// Inequality operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if not equal, false otherwise + friend constexpr bool operator!=(const Identifier& lhs, ValueType rhs) noexcept + { + return !(lhs == rhs); + } + + /// Inequality operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if not equal, false otherwise + friend constexpr bool operator!=(ValueType lhs, const Identifier& rhs) noexcept + { + return !(lhs == rhs); + } + + /// Less than operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if less, false otherwise + friend constexpr bool operator<(const Identifier& lhs, const Identifier& rhs) noexcept + { + return lhs.value_ < rhs.value_; + } + + /// Less than operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if less, false otherwise + friend constexpr bool operator<(const Identifier& lhs, ValueType rhs) noexcept + { + return lhs.value_ < rhs; + } + + /// Greater than operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if greater, false otherwise + friend constexpr bool operator>(const Identifier& lhs, const Identifier& rhs) noexcept + { + return rhs < lhs; + } + + /// Greater than operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if greater, false otherwise + friend constexpr bool operator>(const Identifier& lhs, ValueType rhs) noexcept + { + return rhs < lhs.value_; + } + + /// Less or equal to operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if less or equal, false otherwise + friend constexpr bool operator<=(const Identifier& lhs, const Identifier& rhs) noexcept + { + return !(lhs > rhs); + } + + /// Less or equal to operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if less or equal, false otherwise + friend constexpr bool operator<=(const Identifier& lhs, ValueType rhs) noexcept + { + return !(lhs.value_ > rhs); + } + + /// Greater or equal to operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if greater or equal, false otherwise + friend constexpr bool operator>=(const Identifier& lhs, const Identifier& rhs) noexcept + { + return !(lhs < rhs); + } + + /// Greater or equal to operator with value type + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return True if greater or equal, false otherwise + friend constexpr bool operator>=(const Identifier& lhs, ValueType rhs) noexcept + { + return !(lhs.value_ < rhs); + } + + /// Prefix increment + /// @return Reference to this + Identifier& operator++() noexcept + { + value_++; + return *this; + } + + /// Postfix increment + /// @return Reference to this + Identifier operator++(int) noexcept + { + Identifier old = *this; + operator++(); + return old; + } + + /// Add operator + /// @param lhs Left-hand side + /// @param rhs Right-hand side + /// @return Identifier with sum of values of lhs and rhs + friend Identifier operator+(Identifier lhs, const Identifier& rhs) noexcept + { + lhs = lhs.Value() + rhs.Value(); + return lhs; + } + + /// Swap two identifiers + /// @param lhs Left-hand side + /// @param rhs Right-hand side + friend constexpr void swap(Identifier& lhs, Identifier& rhs) noexcept + { + using std::swap; + swap(lhs.value_, rhs.value_); + } + + /// Output stream operator + /// @param os Output stream + /// @param identifier Identifier + /// @return Output stream + friend inline std::ostream& operator<<(std::ostream& os, const Identifier& identifier) + { + return os << std::to_string(identifier.Value()); + } + +private: + ValueType value_{kInvalid}; ///< Identifier value +}; + +} // namespace mantle_api + +namespace std +{ + +/// Hash specialization for mantle_api::Identifier +/// @tparam T Type of the identifier +/// @tparam Tag Tag type +template <typename T, typename Tag> +struct hash<mantle_api::Identifier<T, Tag>> +{ + /// Hash function + /// @param identifier Identifier + /// @return Hash value + size_t operator()(const mantle_api::Identifier<T, Tag>& identifier) const + { + return hash<T>{}(identifier.Value()); + } +}; + +} // namespace std + +#endif // MANTLEAPI_COMMON_IDENTIFIER_H diff --git a/include/MantleAPI/Common/log_utils.h b/include/MantleAPI/Common/log_utils.h deleted file mode 100644 index f0293e5f882d20cda7ca557519576200c18d6d85..0000000000000000000000000000000000000000 --- a/include/MantleAPI/Common/log_utils.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH - * Copyright (c) 2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ - -//----------------------------------------------------------------------------- -/// @file MantleAPI/Common/log_utils.h -//----------------------------------------------------------------------------- - -#ifndef MANTLEAPI_COMMON_LOG_UTILS_H -#define MANTLEAPI_COMMON_LOG_UTILS_H - -#include <MantleAPI/Common/i_logger.h> - -#include <array> -#include <cstddef> -#include <ostream> -#include <string_view> - -/// MantleAPI namespace -namespace mantle_api -{ - -/// Log utilities namespace -namespace log_utils -{ - -/// Array of log level names -/// @ingroup logging -static inline constexpr auto kLogLevelNames = std::array<std::string_view, 6U>{"Trace", "Debug", "Info", "Warning", "Error", "Critical"}; - -/// Convert a log level to its name -/// @param[in] level The log level -/// @return The name of the log level -/// @ingroup logging -[[nodiscard]] constexpr std::string_view ToStringView(LogLevel level) noexcept -{ - return (level >= LogLevel::kTrace && level <= LogLevel::kCritical) ? kLogLevelNames.at(static_cast<std::size_t>(level)) : "Log level out of range"; -} - -} // namespace log_utils - -/// Stream operator for log level -/// @param[in] os The output stream -/// @param[in] level The log level -/// @return The output stream -/// @ingroup logging -inline std::ostream& operator<<(std::ostream& os, mantle_api::LogLevel level) noexcept -{ - os << log_utils::ToStringView(level); - return os; -} - -} // namespace mantle_api - -#endif // MANTLEAPI_COMMON_LOG_UTILS_H diff --git a/include/MantleAPI/Common/meta.h b/include/MantleAPI/Common/meta.h new file mode 100644 index 0000000000000000000000000000000000000000..9626659aa85b9b722839df0426f4a35538a3babc --- /dev/null +++ b/include/MantleAPI/Common/meta.h @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +//----------------------------------------------------------------------------- +/// @file meta.h +//----------------------------------------------------------------------------- + +#ifndef MANTLEAPI_COMMON_META_H +#define MANTLEAPI_COMMON_META_H + +#include <cstddef> +#include <iosfwd> +#include <optional> +#include <string_view> +#include <type_traits> +#include <utility> + +namespace mantle_api +{ + +namespace meta +{ + +namespace details +{ + +template <typename InputIt, typename UnaryPredicate> +constexpr InputIt find_if(InputIt first, InputIt last, UnaryPredicate&& pred) noexcept +{ + while (first != last) + { + if (std::forward<UnaryPredicate>(pred)(*first)) + { + return first; + } + ++first; + } + return last; +} + +} // namespace details + +/// Structure to hold the meta info of an enum value +/// +/// @tparam T The enum type +template <typename T, typename = std::enable_if_t<std::is_enum_v<T>>> +struct enum_info +{ + T value; ///< The enum value + std::string_view name; ///< The name of the enum value +}; + +/// Primary template for info +template <typename T, typename Enable = void> +struct info +{ + info() = delete; +}; + +/// Helper template to check for the presence of info<T>::get_enumerators +template <typename, typename = std::void_t<>> +struct has_meta_info : std::false_type +{ +}; + +/// Helper template to check for the presence of info<T>::get_enumerators +template <typename T> +struct has_meta_info<T, std::void_t<decltype(&info<T>::get_enumerators)>> : std::true_type +{ +}; + +/// Helper variable template to check for the presence of info<T>::get_enumerators +template <typename T> +inline constexpr bool has_meta_info_v = has_meta_info<T>::value; + +/// Helper variable template to check if T is an enum with info<T>::get_enumerators +template <typename T> +inline constexpr bool is_enum_with_meta_info_v = std::is_enum_v<T> && has_meta_info_v<T>; + +/// Helper function to get the enumerators of an enum type +/// +/// @tparam T The enum type +/// @return The enumerators of the enum type +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr auto enumerators_of(T /*unused*/ = T{}) noexcept +{ + return info<T>::get_enumerators(); +} + +/// Helper function to get the size of the enum type +/// +/// @tparam T The enum type +/// @return The size of the enum type +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr std::size_t size_of(T /*unused*/ = T{}) noexcept +{ + return enumerators_of(T{}).size(); +} + +/// Get the value of the enum_info +/// +/// @tparam T The enum type +/// @param enumerator The enum_info +/// @return The value of the enum_info +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr T value_of(const enum_info<T>& enumerator) noexcept +{ + return enumerator.value; +} + +/// Get the name of the enum_info +/// +/// @tparam T The enumeration type +/// @param enumerator The enum_info +/// @return The name of the enum_info +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr std::string_view name_of(const enum_info<T>& enumerator) noexcept +{ + return enumerator.name; +} + +/// Get the name of the enum value +/// +/// @tparam T The enum type +/// @param value The enum value +/// @return The name of the enum value +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr std::string_view enum_to_string(const T value) noexcept +{ + const auto enumerators = enumerators_of(T{}); + const auto it = details::find_if(enumerators.begin(), enumerators.end(), [value](const auto& enumerator) noexcept + { return value_of(enumerator) == value; }); + if (it == enumerators.end()) + { + return {}; + } + return name_of(*it); +} + +/// Get the enum value from the name +/// +/// @tparam T The enum type +/// @param name The name of the enum value +/// @return The enum value +template <typename T, typename = std::enable_if_t<is_enum_with_meta_info_v<T>>> +[[nodiscard]] inline constexpr std::optional<T> string_to_enum(const std::string_view name) noexcept +{ + if (name.empty()) + { + return std::nullopt; + } + + const auto enumerators = enumerators_of(T{}); + const auto it = details::find_if(enumerators.begin(), enumerators.end(), [&name](const auto& enumerator) + { return name_of(enumerator) == name; }); + if (it == enumerators.end()) + { + return std::nullopt; + } + return value_of(*it); +} + +} // namespace meta + +/// Output stream operator for enum values +/// +/// @tparam CharT The character type +/// @tparam Traits The character traits +/// @tparam T The enum type +/// @param os The output stream +/// @param value The enum value +/// @return The output stream +template <typename CharT, typename Traits, typename T, typename = std::enable_if_t<meta::is_enum_with_meta_info_v<T>>> +inline std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const T value) noexcept +{ + os << meta::enum_to_string(value); + return os; +} + +} // namespace mantle_api + +#endif // MANTLEAPI_COMMON_META_H diff --git a/include/MantleAPI/Common/orientation.h b/include/MantleAPI/Common/orientation.h index 432bdc11114e158553fbdda08da5d5437efbbcdb..20387579d3d3b5eab02bd5b0892cee1f759e6ad5 100644 --- a/include/MantleAPI/Common/orientation.h +++ b/include/MantleAPI/Common/orientation.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,80 +20,84 @@ #include <MantleAPI/Common/unit_definitions.h> #include <units.h> +#include <iosfwd> +#include <type_traits> + namespace mantle_api { +/// Definition of the orientation in terms of the Yaw/Pitch/Roll orientation angles in the Cartesian coordinate system template <typename T, class = typename std::enable_if_t<units::traits::is_angle_unit<T>::value || units::traits::is_angular_velocity_unit<T>::value || units::traits::is_angular_acceleration_unit<T>::value>> - -/// Definition of the orientation in terms of the Yaw/Pitch/Roll orientation angles in the Cartesian coordinate system struct Orientation3 { - Orientation3() = default; - - /// Constructor - /// - /// @param[in] yaw_in yaw angle - /// @param[in] pitch_in pitch angle - /// @param[in] roll_in roll angle - Orientation3(T yaw_in, T pitch_in, T roll_in) - : yaw{yaw_in}, pitch{pitch_in}, roll{roll_in} - { - } - - T yaw{}; ///< Yaw represents the rotation around the vertical axis (heading angle) - T pitch{}; ///< Pitch represents the rotation around the lateral axis (elevation angle) - T roll{}; ///< Roll represents the rotation around the longitudinal axis (bank angle) + T yaw; ///< Yaw represents the rotation around the vertical axis (heading angle) + T pitch; ///< Pitch represents the rotation around the lateral axis (elevation angle) + T roll; ///< Roll represents the rotation around the longitudinal axis (bank angle) }; -/// @brief almost-equality -/// @details Compares the values of two orientations. +/// Compare the values of two Orientation3. +/// /// @tparam T the value type -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs almost equal to the values of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Orientation3 are equal, false otherwise template <typename T> constexpr bool operator==(const Orientation3<T>& lhs, const Orientation3<T>& rhs) noexcept { - return AlmostEqual(lhs.yaw, rhs.yaw) && AlmostEqual(lhs.pitch, rhs.pitch) && AlmostEqual(lhs.roll, rhs.roll); + return AlmostEqual(std::tie(lhs.yaw, lhs.pitch, lhs.roll), std::tie(rhs.yaw, rhs.pitch, rhs.roll)); } -/// @brief inequality -/// @details Compares the value of two orientations. +/// Compare the values of two Orientation3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Orientation3 are not equal, false otherwise template <typename T> constexpr bool operator!=(const Orientation3<T>& lhs, const Orientation3<T>& rhs) noexcept { return !(lhs == rhs); } -/// @brief addition -/// @details Returns the sum of two orientations +/// Add two Orientation3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the sum -/// @param[in] rhs right-hand side value for the sum -/// @returns sum of lhs and rhs. +/// @param[in] lhs left-hand side value for the sum +/// @param[in] rhs right-hand side value for the sum +/// @returns sum of lhs and rhs template <typename T> constexpr Orientation3<T> operator+(const Orientation3<T>& lhs, const Orientation3<T>& rhs) noexcept { - return Orientation3<T>{lhs.yaw + rhs.yaw, lhs.pitch + rhs.pitch, lhs.roll + rhs.roll}; + return {lhs.yaw + rhs.yaw, lhs.pitch + rhs.pitch, lhs.roll + rhs.roll}; } -/// @brief subtraction -/// @details Returns the difference of two orientations +/// Subtract two Orientation3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the difference -/// @param[in] rhs right-hand side value for the difference -/// @returns difference of lhs and rhs. +/// @param[in] lhs left-hand side value for the difference +/// @param[in] rhs right-hand side value for the difference +/// @returns difference of lhs and rhs template <typename T> constexpr Orientation3<T> operator-(const Orientation3<T>& lhs, const Orientation3<T>& rhs) noexcept { - return Orientation3<T>{lhs.yaw - rhs.yaw, lhs.pitch - rhs.pitch, lhs.roll - rhs.roll}; + return {lhs.yaw - rhs.yaw, lhs.pitch - rhs.pitch, lhs.roll - rhs.roll}; +} + +/// Output stream operator for Orientation3. +/// +/// @tparam T the value type +/// @param[in] os output stream +/// @param[in] orientation Orientation3 to be printed +/// @returns output stream with printed Orientation3 +/// +template <typename T> +inline std::ostream& operator<<(std::ostream& os, const Orientation3<T>& orientation) +{ + os << "Orientation3(.yaw=" << orientation.yaw << ", .pitch=" << orientation.pitch << ", .roll=" << orientation.roll << ')'; + return os; } } // namespace mantle_api diff --git a/include/MantleAPI/Common/pose.h b/include/MantleAPI/Common/pose.h index 5bbaf6a5f6c68152384474a96c3514d767f81ea9..e497012e38354f3e9b124640824c30b98fef3452 100644 --- a/include/MantleAPI/Common/pose.h +++ b/include/MantleAPI/Common/pose.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,50 +20,50 @@ #include <MantleAPI/Common/vector.h> #include <units.h> -#include <iostream> +#include <iosfwd> +#include <tuple> namespace mantle_api { -/// Pose in the Cartesian coordinate system +/// Pose in the Cartesian coordinate system. struct Pose { /// Position defined in terms of the x/y/z coordinates in the Cartesian coordinate system - Vec3<units::length::meter_t> position{}; + Vec3<units::length::meter_t> position; /// Orientation defined in terms of the Yaw/Pitch/Roll orientation angles in the Cartesian coordinate system - Orientation3<units::angle::radian_t> orientation{}; - - /// @brief Equality comparison for Pose. - /// - /// @param[in] other The left-hand side value for the comparison - /// @returns true if the values of `this` exactly equal to the values of other. - bool operator==(const Pose& other) const - { - return other.position == position && other.orientation == orientation; - } - - /// @brief Prints a human-readable representation of 'pose' to 'os'. - /// @param os The output stream - /// @param pose Open scenario pose - /// @returns 'pose' in a human-readable format - friend inline std::ostream& operator<<(std::ostream& os, const Pose& pose); + Orientation3<units::angle::radian_t> orientation; }; -/// @brief Prints a human-readable representation of 'pose' to 'os'. -/// @param os The output stream -/// @param pose Open scenario pose -/// @returns 'pose' in a human-readable format -std::ostream& operator<<(std::ostream& os, const Pose& pose) +/// Compare the values of two Poses. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Poses are equal, false otherwise +constexpr bool operator==(const Pose& lhs, const Pose& rhs) noexcept { - os << "position (" - << pose.position.x - << ", " << pose.position.y - << ", " << pose.position.z - << "), orientation (" << pose.orientation.yaw - << ", " << pose.orientation.pitch - << ", " << pose.orientation.roll - << ")"; + return std::tie(lhs.position, lhs.orientation) == std::tie(rhs.position, rhs.orientation); +} +/// Compare the values of two Poses. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Poses are not equal, false otherwise +constexpr bool operator!=(const Pose& lhs, const Pose& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Output stream operator for Pose. +/// +/// @param[in] os output stream +/// @param[in] pose Pose to be printed +/// @returns output stream with printed Pose +/// +inline std::ostream& operator<<(std::ostream& os, const Pose& pose) +{ + os << "Pose(.position=" << pose.position << ", .orientation=" << pose.orientation << ')'; return os; } diff --git a/include/MantleAPI/Common/position.h b/include/MantleAPI/Common/position.h index 6e9dc2c1bbc4573eed4dec2e3b8d18880355a968..ca993c4feb9edb1ffc2c25f0841e8b68afc41f39 100644 --- a/include/MantleAPI/Common/position.h +++ b/include/MantleAPI/Common/position.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,116 +21,162 @@ #include <units.h> #include <cstdint> +#include <iosfwd> #include <string> #include <variant> namespace mantle_api { -/// Position defined in terms of the road coordinates (t,s) applied to a given road as defined in OpenDRIVE +/// Position in the OpenDRIVE Road coordinate system. +/// +/// This position is determined by a road id as defined in OpenDRIVE, and an offset in s and t direction w.r.t. the road reference line. struct OpenDriveRoadPosition { - /// @brief RoadId as defined in OpenDRIVE - std::string road{}; - /// @brief Offset in s direction w.r.t. road, unit: [m] - units::length::meter_t s_offset{0.0}; - /// @brief Offset in t direction w.r.t. reference line of road, unit: [m] - units::length::meter_t t_offset{0.0}; + std::string road; ///< RoadId as defined in OpenDRIVE + units::length::meter_t s_offset; ///< Offset in longitudinal direction w.r.t. the road reference line, unit: [m] + units::length::meter_t t_offset; ///< Offset in lateral direction w.r.t. the road reference line, unit: [m] }; -/// Position that is determined by a lane (lane ID as defined in OpenDRIVE) and the s coordinate of a given road +/// Position in the OpenDRIVE Lane coordinate system. +/// +/// This position is determined by a road and lane id as defined in OpenDRIVE, and an offset in s and t direction w.r.t. the lane center line. struct OpenDriveLanePosition { - /// @brief RoadId as defined in OpenDRIVE - std::string road{}; - /// @brief LaneId as defined in OpenDRIVE (e.g. -1 for right lane) - std::int32_t lane{0}; - /// @brief Offset in s direction w.r.t lane (same as road), unit: [m] - units::length::meter_t s_offset{0.0}; - /// @brief Offset in t direction w.r.t center line of lane, unit: [m] - units::length::meter_t t_offset{0.0}; + std::string road; ///< RoadId as defined in OpenDRIVE + std::int32_t lane; ///< LaneId as defined in OpenDRIVE (e.g. -1 for right lane) + units::length::meter_t s_offset; ///< Offset in longitudinal direction w.r.t lane center line, unit: [m] + units::length::meter_t t_offset; ///< Offset in lateral direction w.r.t lane center line, unit: [m] }; -/// Position defined in terms of the spherical geographic coordinates (angular Longitude and Latitude) +/// Position in the spherical geographic coordinate system. +/// +/// This position is defined in terms of the latitude and longitude in the spherical geographic coordinate system. struct LatLonPosition { - /// @brief GPS latitude, unit: [rad] - units::angle::radian_t latitude{0.0}; - /// @brief GPS longitude, unit: [rad] - units::angle::radian_t longitude{0.0}; + units::angle::radian_t latitude; ///< GPS latitude, unit: [rad] + units::angle::radian_t longitude; ///< GPS longitude, unit: [rad] }; -/// Variant of possible definitions of position (e.g. in terms of the road coordinates, spherical geographic coordinates etc.) +/// A variant type for different position representations. using Position = std::variant<OpenDriveRoadPosition, OpenDriveLanePosition, LatLonPosition, Vec3<units::length::meter_t>>; -/// @brief Equality comparison for OpenDriveRoadPosition. +/// Compare the values of two OpenDriveRoadPositions. /// -/// **Attention** Floating-point comparision may require tweaks in precision. -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs (almost) equal to the values of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two OpenDriveRoadPositions are equal, false otherwise +/// @note The floating-point comparision may require tweaks in precision. inline bool operator==(const OpenDriveRoadPosition& lhs, const OpenDriveRoadPosition& rhs) noexcept { return lhs.road == rhs.road && - AlmostEqual(lhs.s_offset, rhs.s_offset) && - AlmostEqual(lhs.t_offset, rhs.t_offset); + AlmostEqual(std::tie(lhs.s_offset, lhs.t_offset), std::tie(rhs.s_offset, rhs.t_offset)); } -/// @brief Inequality comparison for OpenDriveLanePosition. +/// Compare the values of two OpenDriveRoadPositions. /// -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two OpenDriveRoadPositions are not equal, false otherwise inline bool operator!=(const OpenDriveRoadPosition& lhs, const OpenDriveRoadPosition& rhs) noexcept { return !(lhs == rhs); } -/// @brief Equality comparison for OpenDriveLanePosition. +/// Compare the values of two OpenDriveLanePositions. /// -/// **Attention** Floating-point comparision may require tweaks in precision. -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs (almost) equal to the values of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two OpenDriveLanePositions are equal, false otherwise +/// @note The floating-point comparision may require tweaks in precision. inline bool operator==(const OpenDriveLanePosition& lhs, const OpenDriveLanePosition& rhs) noexcept { return lhs.road == rhs.road && lhs.lane == rhs.lane && - AlmostEqual(lhs.s_offset, rhs.s_offset) && - AlmostEqual(lhs.t_offset, rhs.t_offset); + AlmostEqual(std::tie(lhs.s_offset, lhs.t_offset), std::tie(rhs.s_offset, rhs.t_offset)); } -/// @brief Inequality comparison for OpenDriveLanePosition. +/// Compare the values of two OpenDriveLanePositions. /// -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two OpenDriveLanePositions are not equal, false otherwise inline bool operator!=(const OpenDriveLanePosition& lhs, const OpenDriveLanePosition& rhs) noexcept { return !(lhs == rhs); } -/// @brief Equality comparison for LatLonPosition. +/// Compare the values of two LatLonPositions. /// -/// **Attention** Floating-point comparision may require tweaks in precision. -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs almost equal to the values of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two LatLonPositions are equal, false otherwise +/// @note The floating-point comparision may require tweaks in precision. constexpr bool operator==(const LatLonPosition& lhs, const LatLonPosition& rhs) noexcept { - return AlmostEqual(lhs.latitude, rhs.latitude) && AlmostEqual(lhs.longitude, rhs.longitude); + return AlmostEqual(std::tie(lhs.latitude, lhs.longitude), std::tie(rhs.latitude, rhs.longitude)); } -/// @brief Inequality comparison for LatLonPosition. +/// Compare the values of two LatLonPositions. /// -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two LatLonPositions are not equal, false otherwise constexpr bool operator!=(const LatLonPosition& lhs, const LatLonPosition& rhs) noexcept { return !(lhs == rhs); } +/// Output stream operator for OpenDriveRoadPosition. +/// +/// @param[in] os output stream +/// @param[in] position OpenDriveRoadPosition to be printed +/// @returns output stream with printed OpenDriveRoadPosition +/// +inline std::ostream& operator<<(std::ostream& os, const OpenDriveRoadPosition& position) +{ + os << "OpenDriveRoadPosition(.road=" << position.road << ", .s_offset=" << position.s_offset << ", .t_offset=" << position.t_offset << ')'; + return os; +} + +/// Output stream operator for OpenDriveLanePosition. +/// +/// @param[in] os output stream +/// @param[in] position OpenDriveLanePosition to be printed +/// @returns output stream with printed OpenDriveLanePosition +/// +inline std::ostream& operator<<(std::ostream& os, const OpenDriveLanePosition& position) +{ + os << "OpenDriveLanePosition(.road=" << position.road << ", .lane=" << position.lane << ", .s_offset=" << position.s_offset << ", .t_offset=" << position.t_offset << ')'; + return os; +} + +/// Output stream operator for LatLonPosition. +/// +/// @param[in] os output stream +/// @param[in] position LatLonPosition to be printed +/// @returns output stream with printed LatLonPosition +/// +inline std::ostream& operator<<(std::ostream& os, const LatLonPosition& position) +{ + os << "LatLonPosition(.latitude=" << position.latitude << ", .longitude=" << position.longitude << ')'; + return os; +} + +/// Output stream operator for Position. +/// +/// @param[in] os output stream +/// @param[in] position Position to be printed +/// @returns output stream with printed Position +/// +inline std::ostream& operator<<(std::ostream& os, const Position& position) +{ + std::visit([&os](const auto& pos) + { os << pos; }, + position); + return os; +} + } // namespace mantle_api #endif // MANTLEAPI_COMMON_POSITION_H diff --git a/include/MantleAPI/Common/route_definition.h b/include/MantleAPI/Common/route_definition.h deleted file mode 100644 index 6dfc890b46465cfb1a19509d344d945977bfbe2e..0000000000000000000000000000000000000000 --- a/include/MantleAPI/Common/route_definition.h +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2022-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ - -//----------------------------------------------------------------------------- -/// @file route_definition.h -//----------------------------------------------------------------------------- - -#ifndef MANTLEAPI_COMMON_ROUTE_DEFINITION_H -#define MANTLEAPI_COMMON_ROUTE_DEFINITION_H - -#include <MantleAPI/Common/vector.h> -#include <units.h> - -#include <tuple> -#include <vector> - -namespace mantle_api -{ - -/// Define how the route from a waypoint forward should be calculated. -enum class RouteStrategy -{ - kUndefined = 0, - kFastest, - kLeastIntersections, - kShortest -}; - -/// Group a Waypoint with a RouteStrategy. -struct RouteWaypoint -{ - /// Reference position used to form a route - mantle_api::Vec3<units::length::meter_t> waypoint{}; - /// Defines how a route should be calculated - RouteStrategy route_strategy{}; -}; - -/// Equality comparison for RouteWaypoint. -/// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs and rhs are equal -inline bool operator==(const RouteWaypoint& lhs, const RouteWaypoint& rhs) noexcept -{ - return std::tie(lhs.waypoint, lhs.route_strategy) == std::tie(rhs.waypoint, rhs.route_strategy); -} - -/// Inequality comparison for RouteWaypoint. -/// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs and rhs are not equal -inline bool operator!=(const RouteWaypoint& lhs, const RouteWaypoint& rhs) noexcept -{ - return !(lhs == rhs); -} - -/// A raw set of global coordinates and information for -/// linking them, from which the actual route can be calculated. -struct RouteDefinition -{ - /// The list of waypoints with associated RouteStrategies - std::vector<mantle_api::RouteWaypoint> waypoints; -}; - -/// Equality comparison for RouteDefinition. -/// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs and rhs are equal -inline bool operator==(const RouteDefinition& lhs, const RouteDefinition& rhs) noexcept -{ - return lhs.waypoints == rhs.waypoints; -} - -/// Inequality comparison for RouteDefinition. -/// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs and rhs are not equal -inline bool operator!=(const RouteDefinition& lhs, const RouteDefinition& rhs) noexcept -{ - return !(lhs == rhs); -} - -} // namespace mantle_api - -#endif // MANTLEAPI_COMMON_ROUTE_DEFINITION_H diff --git a/include/MantleAPI/Common/spline.h b/include/MantleAPI/Common/spline.h index 250e7d6f335fdbab68190aec7015699e97a8ca72..04a5a6356a61f98c4db1526e44e8d741c6b26533 100644 --- a/include/MantleAPI/Common/spline.h +++ b/include/MantleAPI/Common/spline.h @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (c) 2021-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,64 +18,153 @@ #define MANTLEAPI_COMMON_SPLINE_H #include <MantleAPI/Common/floating_point_helper.h> -#include <MantleAPI/Common/orientation.h> #include <MantleAPI/Common/time_utils.h> -#include <MantleAPI/Common/unit_definitions.h> #include <MantleAPI/Common/vector.h> #include <units.h> +#include <iosfwd> #include <tuple> namespace mantle_api { -/// Definition of a spline segment represented by the polynomial parameters a, b, c, d +/// Definition of a spline segment represented by the polynomial parameters a, b, c, d. +/// /// @tparam T Type of polynomial parameters template <typename T> struct SplineSegment { - Vec3<T> a; ///< Polynom parameter a, e.g. unit: [m] - Vec3<T> b; ///< Polynom parameter b, e.g. unit: [1/m] - Vec3<T> c; ///< Polynom parameter c, e.g. unit: [1/m²] - Vec3<T> d; ///< Polynom parameter d, e.g. unit: [1/m³] + Vec3<T> a; ///< Polynomial parameter a, e.g. unit: [m] + Vec3<T> b; ///< Polynomial parameter b, e.g. unit: [1/m] + Vec3<T> c; ///< Polynomial parameter c, e.g. unit: [1/m²] + Vec3<T> d; ///< Polynomial parameter d, e.g. unit: [1/m³] }; -/// Definition of the section of the spline curve +/// Compare the values of two SplineSegments. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two SplineSegments are equal, false otherwise +template <typename T> +constexpr bool operator==(const SplineSegment<T>& lhs, const SplineSegment<T>& rhs) noexcept +{ + return std::tie(lhs.a, lhs.b, lhs.c, lhs.d) == std::tie(rhs.a, rhs.b, rhs.c, rhs.d); +} + +/// Compare the values of two SplineSegments. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two SplineSegments are not equal, false otherwise +template <typename T> +constexpr bool operator!=(const SplineSegment<T>& lhs, const SplineSegment<T>& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Definition of the section of the spline curve. +/// /// @tparam T the value type template <typename T, class = typename std::enable_if_t<units::traits::is_unit<T>::value>> struct SplineSection { - /// Time specification at the start of the section of the spline curve - Time start_time{0}; - /// Time specification at the end of the section of the spline curve - Time end_time{0}; - /// @brief Represents the polynomial. - /// - /// The tuple stores in format \f$[a_3, a_2, a_1, a_0]\f$ for a polynomial in form - /// @f[ - /// P(x) = \sum_{i=0}^{3} a_{i} x^{i} = a_3 x^3 + a_2 x^2 + a_1 x + a_0 - /// @f] - std::tuple<units::unit_t<units::compound_unit<T, units::inverse<units::cubed<units::time::second>>>>, - units::unit_t<units::compound_unit<T, units::inverse<units::squared<units::time::second>>>>, - units::unit_t<units::compound_unit<T, units::inverse<units::time::second>>>, - units::unit_t<T>> - polynomial{ - units::unit_t<units::compound_unit<T, units::inverse<units::cubed<units::time::second>>>>(0), - units::unit_t<units::compound_unit<T, units::inverse<units::squared<units::time::second>>>>(0), - units::unit_t<units::compound_unit<T, units::inverse<units::time::second>>>(0), - units::unit_t<T>(0)}; + /// Definition of a polynomial in form \f$P(x) = a_3 x^3 + a_2 x^2 + a_1 x + a_0\f$. + struct Polynomial + { + using A3Type = units::unit_t<units::compound_unit<T, units::inverse<units::cubed<units::time::second>>>>; ///< Type of polynomial parameter a3 + using A2Type = units::unit_t<units::compound_unit<T, units::inverse<units::squared<units::time::second>>>>; ///< Type of polynomial parameter a2 + using A1Type = units::unit_t<units::compound_unit<T, units::inverse<units::time::second>>>; ///< Type of polynomial parameter a1 + using A0Type = units::unit_t<T>; ///< Type of polynomial parameter a0 + + A3Type a3; ///< Polynomial parameter a3 + A2Type a2; ///< Polynomial parameter a2 + A1Type a1; ///< Polynomial parameter a1 + A0Type a0; ///< Polynomial parameter a0 + + /// Compare the values of two Polynomials. + /// + /// @param[in] other right-hand side value for the comparison + /// @returns true, if the values of the two Polynomials are almost equal, false otherwise + constexpr bool operator==(const Polynomial& other) const noexcept + { + return AlmostEqual(std::tie(a3, a2, a1, a0), std::tie(other.a3, other.a2, other.a1, other.a0)); + } + + /// Compare the values of two Polynomials. + /// + /// @param[in] other right-hand side value for the comparison + /// @returns true, if the values of the two Polynomials are not almost equal, false otherwise + constexpr bool operator!=(const Polynomial& other) const noexcept + { + return !(*this == other); + } + + /// Output stream operator for Polynomial. + /// + /// @param[in] os output stream + /// @param[in] polynomial Polynomial to be printed + /// @returns output stream with printed Polynomial + /// + friend std::ostream& operator<<(std::ostream& os, const Polynomial& polynomial) + { + os << "Polynomial(.a3=" << polynomial.a3 << ", .a2=" << polynomial.a2 << ", .a1=" << polynomial.a1 << ", .a0=" << polynomial.a0 << ')'; + return os; + } + }; + + Time start_time; ///< Time specification at the start of the section of the spline curve + Time end_time; ///< Time specification at the end of the section of the spline curve + Polynomial polynomial; ///< Polynomial parameters of the spline curve }; -/// @brief Equality comparison for SplineSection. +/// Compare the values of two SplineSections. /// -/// @tparam T the value type -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs (almost) equal to the values of rhs. -template <typename T, class = typename std::enable_if_t<units::traits::is_unit<T>::value>> +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two SplineSections are equal, false otherwise +template <typename T> constexpr bool operator==(const SplineSection<T>& lhs, const SplineSection<T>& rhs) noexcept { - return lhs.start_time == rhs.start_time && lhs.end_time == rhs.end_time && AlmostEqual(std::get<0>(lhs.polynomial), std::get<0>(rhs.polynomial)) && AlmostEqual(std::get<1>(lhs.polynomial), std::get<1>(rhs.polynomial)) && AlmostEqual(std::get<2>(lhs.polynomial), std::get<2>(rhs.polynomial)) && AlmostEqual(std::get<3>(lhs.polynomial), std::get<3>(rhs.polynomial)); + return std::tie(lhs.start_time, lhs.end_time, lhs.polynomial) == std::tie(rhs.start_time, rhs.end_time, rhs.polynomial); +} + +/// Compare the values of two SplineSections. +/// +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two SplineSections are not equal, false otherwise +template <typename T> +constexpr bool operator!=(const SplineSection<T>& lhs, const SplineSection<T>& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Output stream operator for SplineSegment. +/// +/// @tparam T the value type +/// @param[in] os output stream +/// @param[in] segment SplineSegment to be printed +/// @returns output stream with printed SplineSegment +/// +template <typename T> +inline std::ostream& operator<<(std::ostream& os, const SplineSegment<T>& segment) +{ + os << "SplineSegment(.a=" << segment.a << ", .b=" << segment.b << ", .c=" << segment.c << ", .d=" << segment.d << ')'; + return os; +} + +/// Output stream operator for SplineSection. +/// +/// @tparam T the value type +/// @param[in] os output stream +/// @param[in] section SplineSection to be printed +/// @returns output stream with printed SplineSection +/// +template <typename T> +inline std::ostream& operator<<(std::ostream& os, const SplineSection<T>& section) +{ + os << "SplineSection(.start_time=" << section.start_time << ", .end_time=" << section.end_time << ", .polynomial=" << section.polynomial << ')'; + return os; } } // namespace mantle_api diff --git a/include/MantleAPI/Common/trajectory.h b/include/MantleAPI/Common/trajectory.h index e4598bef778f4cc4c07466a5f9e10bf18b2cada3..7c56de4638b761f85a3aaeacc8028deaac83e2d9 100644 --- a/include/MantleAPI/Common/trajectory.h +++ b/include/MantleAPI/Common/trajectory.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -18,8 +19,7 @@ #include <MantleAPI/Common/clothoid_spline.h> #include <MantleAPI/Common/poly_line.h> -#include <cstdint> -#include <optional> +#include <iosfwd> #include <string> #include <tuple> #include <variant> @@ -37,7 +37,7 @@ enum class TrajectoryReferencePoint : std::uint8_t kBoundingBoxCenter ///< Reference point is the center of the bounding box of the object }; -/// Definition of a trajectory type in terms of shape +/// Definition of a trajectory type in terms of shape. struct Trajectory { std::string name; ///< Name of the trajectory type @@ -45,21 +45,32 @@ struct Trajectory TrajectoryReferencePoint reference; ///< Reference point of object, which is used in trajectory }; -/// Compare two objects of Trajectory. +/// Compare the values of two Trajectory objects. /// -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the values of lhs exactly equals to rhs values -constexpr bool operator==(const Trajectory& lhs, const Trajectory& rhs) noexcept +/// @param lhs left-hand side Trajectory object +/// @param rhs right-hand side Trajectory object +/// @return true if the Trajectory objects are equal, false otherwise +inline bool operator==(const Trajectory& lhs, const Trajectory& rhs) noexcept { return std::tie(lhs.name, lhs.type, lhs.reference) == std::tie(rhs.name, rhs.type, rhs.reference); } -/// Print a human-readable representation of 'trajectory' to 'os'. +/// Compare the values of two Trajectory objects. +/// +/// @param lhs left-hand side Trajectory object +/// @param rhs right-hand side Trajectory object +/// @return true if the Trajectory objects are not equal, false otherwise +inline bool operator!=(const Trajectory& lhs, const Trajectory& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Output stream operator for Trajectory. +/// +/// @param os output stream +/// @param trajectory Trajectory to be printed +/// @return output stream with printed Trajectory /// -/// @param os The output stream -/// @param trajectory Open scenario trajectory -/// @returns 'trajectory' in a human-readable format inline std::ostream& operator<<(std::ostream& os, const Trajectory& trajectory) { os << "Trajectory(.name=" << trajectory.name << ", .type="; diff --git a/include/MantleAPI/Common/vector.h b/include/MantleAPI/Common/vector.h index 8b878f51cd1f3668dd5152c9fac62b664100fcc6..51b2ad92be4efe0edf3ddd6607640ccf00e6929b 100644 --- a/include/MantleAPI/Common/vector.h +++ b/include/MantleAPI/Common/vector.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,98 +17,94 @@ #define MANTLEAPI_COMMON_VECTOR_H #include <MantleAPI/Common/floating_point_helper.h> +#include <units.h> + +#include <iosfwd> +#include <tuple> +#include <type_traits> namespace mantle_api { +/// 3-dimensional vector in the right-handed Cartesian coordinate system. template <typename T, class = typename std::enable_if_t<units::traits::is_unit_t<T>::value>> - -/// 3-dimensional vector that contains three components (x, y, z) in the right-handed Cartesian coordinate system struct Vec3 { - Vec3() = default; - - /// Constructor - /// - /// @param[in] x_in x-value - /// @param[in] y_in y-value - /// @param[in] z_in z-value - Vec3(T x_in, T y_in, T z_in) - : x{x_in}, y{y_in}, z{z_in} - { - } + T x; ///< x-component + T y; ///< y-component + T z; ///< z-component - T x{0}; ///< x-component - T y{0}; ///< y-component - T z{0}; ///< z-component - - /// @brief Returns length of the vector + /// Calculate the length of the vector. /// - /// @returns length of the vector + /// @returns the length of the vector inline T Length() const { return units::math::sqrt((x * x) + (y * y) + (z * z)); } - /// @brief Changes the sign of the 3d vector + /// Change the sign of the vector. /// - /// @returns 3d vector - inline Vec3<T> operator-() const noexcept + /// @returns the vector with the sign changed + constexpr Vec3 operator-() const noexcept { return {-x, -y, -z}; } }; -/// @brief almost-equality -/// @details Compares the values of two 3d vectors. +/// Deduction guide for Vec3. +template <typename T> +Vec3(T, T, T) -> Vec3<T>; + +/// Compare the values of two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs almost equal to the values of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Vec3 are equal, false otherwise template <typename T> constexpr bool operator==(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { - return AlmostEqual(lhs.x, rhs.x) && AlmostEqual(lhs.y, rhs.y) && AlmostEqual(lhs.z, rhs.z); + return AlmostEqual(std::tie(lhs.x, lhs.y, lhs.z), std::tie(rhs.x, rhs.y, rhs.z)); } -/// @brief inequality -/// @details Compares the value of two 3d vectors. +/// Compare the values of two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the comparison -/// @param[in] rhs right-hand side value for the comparison -/// @returns true if the value of lhs is not almost equal to the value of rhs. +/// @param[in] lhs left-hand side value for the comparison +/// @param[in] rhs right-hand side value for the comparison +/// @returns true, if the values of the two Vec3 are not equal, false otherwise template <typename T> constexpr bool operator!=(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { return !(lhs == rhs); } -/// @brief subtraction -/// @details Returns the difference of two 3d vectors +/// Add two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the difference -/// @param[in] rhs right-hand side value for the difference -/// @returns difference of lhs and rhs. +/// @param[in] lhs left-hand side value for the sum +/// @param[in] rhs right-hand side value for the sum +/// @returns the sum of the two Vec3 template <typename T> -constexpr Vec3<T> operator-(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept +constexpr Vec3<T> operator+(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { - return {lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z}; + return {lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z}; } -/// @brief addition -/// @details Returns the sum of two 3d vectors +/// Subtract two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the sum -/// @param[in] rhs right-hand side value for the sum -/// @returns sum of lhs and rhs. +/// @param[in] lhs left-hand side value for the difference +/// @param[in] rhs right-hand side value for the difference +/// @returns the difference of the two Vec3 template <typename T> -constexpr Vec3<T> operator+(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept +constexpr Vec3<T> operator-(const Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { - return {lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z}; + return {lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z}; } -/// @brief multiplication -/// @details Multiplication by a scalar for 3d vector +/// Multiply a Vec3 by a scalar. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the multiplication -/// @param[in] d scalar +/// @param[in] lhs left-hand side value for the multiplication +/// @param[in] d scalar for the multiplication /// @returns the scalar multiplied vector template <typename T> constexpr Vec3<T> operator*(const Vec3<T>& lhs, double d) noexcept @@ -115,11 +112,11 @@ constexpr Vec3<T> operator*(const Vec3<T>& lhs, double d) noexcept return {lhs.x * d, lhs.y * d, lhs.z * d}; } -/// @brief multiplication -/// @details Multiplication by a scalar for 3d vector +/// Multiply a scalar by a Vec3. +/// /// @tparam T the value type -/// @param[in] d scalar -/// @param[in] rhs right-hand side value for the multiplication +/// @param[in] d scalar for the multiplication +/// @param[in] rhs right-hand side value for the multiplication /// @returns the scalar multiplied vector template <typename T> constexpr Vec3<T> operator*(double d, const Vec3<T>& rhs) noexcept @@ -127,24 +124,24 @@ constexpr Vec3<T> operator*(double d, const Vec3<T>& rhs) noexcept return rhs * d; } -/// @brief division -/// @details Division by a scalar for 3d vector +/// Divide a Vec3 by a scalar. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value for the division -/// @param[in] d scalar -/// @returns the lhs divided by d +/// @param[in] lhs left-hand side value for the division +/// @param[in] d scalar for the division +/// @returns the scalar divided vector template <typename T> constexpr Vec3<T> operator/(const Vec3<T>& lhs, double d) noexcept { return {lhs.x / d, lhs.y / d, lhs.z / d}; } -/// @brief addable -/// @details Add a 3d vector to a 3d vector +/// AddAssign two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value -/// @param[in] rhs right-hand side value, which will be added -/// @returns the lhs where rhs is added +/// @param[in] lhs left-hand side value for the sum +/// @param[in] rhs right-hand side value for the sum +/// @returns lhs after adding rhs template <typename T> constexpr Vec3<T> operator+=(Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { @@ -154,12 +151,12 @@ constexpr Vec3<T> operator+=(Vec3<T>& lhs, const Vec3<T>& rhs) noexcept return lhs; } -/// @brief subtractable -/// @details Subtract a 3d vector from a 3d vector +/// SubtractAssign two Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value -/// @param[in] rhs right-hand side value -/// @returns the lhs from where rhs is subtracted +/// @param[in] lhs left-hand side value for the difference +/// @param[in] rhs right-hand side value for the difference +/// @returns lhs after subtracting rhs template <typename T> constexpr Vec3<T> operator-=(Vec3<T>& lhs, const Vec3<T>& rhs) noexcept { @@ -169,14 +166,14 @@ constexpr Vec3<T> operator-=(Vec3<T>& lhs, const Vec3<T>& rhs) noexcept return lhs; } -/// @brief addable -/// @details Add a scalar to a 3d vector +/// AddAssign a scalar to each component of a Vec3. +/// /// @tparam T the value type -/// @param[in] lhs left-hand side value -/// @param[in] d scalar -/// @returns the lhs where d is added +/// @param[in] lhs left-hand side value for the sum +/// @param[in] d scalar for the sum +/// @returns lhs after adding d to each component template <typename T> -constexpr Vec3<T> operator+=(Vec3<T>& lhs, double d) noexcept +constexpr Vec3<T> operator+=(Vec3<T>& lhs, T d) noexcept { lhs.x += d; lhs.y += d; @@ -184,14 +181,14 @@ constexpr Vec3<T> operator+=(Vec3<T>& lhs, double d) noexcept return lhs; } -/// @brief subtractable -/// @details Subtract a scalar from a 3d vector -/// @tparam T Type of vector components -/// @param[in] lhs left-hand side value -/// @param[in] d scalar -/// @returns the lhs from where d is subtracted +/// SubtractAssign a scalar from each component of a Vec3. +/// +/// @tparam T the value type +/// @param[in] lhs left-hand side value for the difference +/// @param[in] d scalar for the difference +/// @returns lhs after subtracting d from each component template <typename T> -constexpr Vec3<T> operator-=(Vec3<T>& lhs, double d) noexcept +constexpr Vec3<T> operator-=(Vec3<T>& lhs, T d) noexcept { lhs.x -= d; lhs.y -= d; @@ -199,6 +196,20 @@ constexpr Vec3<T> operator-=(Vec3<T>& lhs, double d) noexcept return lhs; } +/// Output stream operator for Vec3. +/// +/// @tparam T the value type +/// @param[in] os output stream +/// @param[in] vector Vec3 to be printed +/// @returns output stream with printed Vec3 +/// +template <typename T> +inline std::ostream& operator<<(std::ostream& os, const Vec3<T>& vector) +{ + os << "Vec3(.x=" << vector.x << ", .y=" << vector.y << ", .z=" << vector.z << ')'; + return os; +} + } // namespace mantle_api #endif // MANTLEAPI_COMMON_VECTOR_H diff --git a/include/MantleAPI/EnvironmentalConditions/weather.h b/include/MantleAPI/EnvironmentalConditions/weather.h index af3200b090c44b76664c4d134d45b1bf876c639c..df6587e8072d58eae1719e3fe2dd1b4cb0a5ee55 100644 --- a/include/MantleAPI/EnvironmentalConditions/weather.h +++ b/include/MantleAPI/EnvironmentalConditions/weather.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,52 +18,54 @@ #include <units.h> +#include <cstdint> + namespace mantle_api { /// Specify the amount of the precipitation. -enum class Precipitation +enum class Precipitation : std::uint8_t { - kUnknown, - kOther, - kNone, - kVeryLight, - kLight, - kModerate, - kHeavy, - kVeryHeavy, - kExtreme + kUnknown = 0, ///< The amount of precipitation is unknown. + kOther, ///< The amount of precipitation is known, but unspecified. + kNone, ///< There is no precipitation. + kVeryLight, ///< There is very light precipitation. + kLight, ///< There is light precipitation. + kModerate, ///< There is moderate precipitation. + kHeavy, ///< There is heavy precipitation. + kVeryHeavy, ///< There is very heavy precipitation. + kExtreme ///< There is extreme precipitation. }; /// Specify the amount of the fog. -enum class Fog +enum class Fog : std::uint8_t { - kUnknown, - kOther, - kExcellentVisibility, - kGoodVisibility, - kModerateVisibility, - kPoorVisibility, - kMist, - kLight, - kThick, - kDense + kUnknown = 0, ///< The amount of fog is unknown. + kOther, ///< The amount of fog is known, but unspecified. + kExcellentVisibility, ///< Visibility is excellent. There is no fog. + kGoodVisibility, ///< Visibility is good. There is light fog. + kModerateVisibility, ///< Visibility is moderate. There is thick fog. + kPoorVisibility, ///< Visibility is poor. There is dense fog. + kMist, ///< Visibility is moderate. It is misty. + kLight, ///< Visibility is good. There is light fog. + kThick, ///< Visibility is moderate. There is thick fog. + kDense ///< Visibility is poor. There is dense fog. }; /// Specify the level of illumination. -enum class Illumination +enum class Illumination : std::uint8_t { - kUnknown, - kOther, - kLevel1, - kLevel2, - kLevel3, - kLevel4, - kLevel5, - kLevel6, - kLevel7, - kLevel8, - kLevel9 + kUnknown = 0, ///< The level of illumination is unknown. + kOther, ///< The level of illumination is known, but unspecified. + kLevel1, ///< The level of illumination is 1. + kLevel2, ///< The level of illumination is 2. + kLevel3, ///< The level of illumination is 3. + kLevel4, ///< The level of illumination is 4. + kLevel5, ///< The level of illumination is 5. + kLevel6, ///< The level of illumination is 6. + kLevel7, ///< The level of illumination is 7. + kLevel8, ///< The level of illumination is 8. + kLevel9 ///< The level of illumination is 9. }; /// Specification of sun properties. diff --git a/include/MantleAPI/Execution/i_environment.h b/include/MantleAPI/Execution/i_environment.h index 3837f85873ddadfedf28aa0bbf26dc790ff12fa6..06de70a8d07a8113a63d5608e5be1f224fb9979a 100644 --- a/include/MantleAPI/Execution/i_environment.h +++ b/include/MantleAPI/Execution/i_environment.h @@ -17,12 +17,12 @@ #define MANTLEAPI_EXECUTION_I_ENVIRONMENT_H #include <MantleAPI/Common/i_geometry_helper.h> -#include <MantleAPI/Common/route_definition.h> #include <MantleAPI/Common/time_utils.h> #include <MantleAPI/EnvironmentalConditions/road_condition.h> #include <MantleAPI/EnvironmentalConditions/weather.h> #include <MantleAPI/Map/i_coord_converter.h> #include <MantleAPI/Map/i_lane_location_query_service.h> +#include <MantleAPI/Map/i_route_repository.h> #include <MantleAPI/Map/map_details.h> #include <MantleAPI/Traffic/default_routing_behavior.h> #include <MantleAPI/Traffic/i_controller_repository.h> @@ -31,6 +31,7 @@ #include <MantleAPI/Traffic/i_traffic_swarm_service.h> #include <cstdint> +#include <memory> #include <optional> #include <string> #include <variant> @@ -39,7 +40,7 @@ namespace mantle_api { /// @brief Allowed data types for parameters defined in a parameter declaration. -using ParameterType = std::variant<bool, mantle_api::Time, double, std::string, std::uint32_t, std::uint16_t, std::int32_t>; +using ParameterType = std::variant<bool, Time, double, std::string, std::uint32_t, std::uint16_t, std::int32_t>; /// Base interface for the environment conditions (e.g. time of day, weather, road condition) of a scenario class IEnvironment @@ -53,7 +54,7 @@ public: /// environment must do so. /// @param map_details Area of the map /// @param map_model_reference File path of a 3D model representing the virtual environment - virtual void CreateMap(const std::string& map_file_path, const mantle_api::MapDetails& map_details, const std::string& map_model_reference) = 0; + virtual void CreateMap(const std::string& map_file_path, const MapDetails& map_details, const std::string& map_model_reference) = 0; /// Assigns an entity to the specified controller. This controller needs to be created beforehand. /// @@ -72,14 +73,14 @@ public: /// @param entity_id Specifies the entity to be updated /// @param control_strategies Specifies the desired movement behavior for the entity virtual void UpdateControlStrategies( - UniqueId entity_id, std::vector<std::shared_ptr<mantle_api::ControlStrategy>> control_strategies) = 0; + UniqueId entity_id, std::vector<std::shared_ptr<ControlStrategy>> control_strategies) = 0; /// Checks, if a control strategy of a certain type for a specific entity has been fulfilled /// /// @param entity_id The entity to check /// @param type The control strategy type /// @return true if a control strategy of a certain type for a specific entity has been fulfilled - [[nodiscard]] virtual bool HasControlStrategyGoalBeenReached(UniqueId entity_id, mantle_api::ControlStrategyType type) const = 0; + [[nodiscard]] virtual bool HasControlStrategyGoalBeenReached(UniqueId entity_id, ControlStrategyType type) const = 0; /// @brief Retrieves the ILaneLocationQueryService that provides abstraction layer for all map related functions /// @@ -116,20 +117,30 @@ public: /// @return const reference to the controller repository interface [[nodiscard]] virtual const IControllerRepository& GetControllerRepository() const = 0; + /// @brief Retrieves the route repository that provides CRUD functionality for routes + /// + /// @return const reference to the route repository interface + [[nodiscard]] virtual IRouteRepository& GetRouteRepository() = 0; + + /// @brief Retrieves the route repository that provides CRUD functionality for routes + /// + /// @return const reference to the route repository interface + [[nodiscard]] virtual const IRouteRepository& GetRouteRepository() const = 0; + /// @brief Sets the DateTime in UTC (converted from RFC 3339 standard) /// /// @param time Time in ms - virtual void SetDateTime(mantle_api::Time time) = 0; + virtual void SetDateTime(Time time) = 0; /// @brief Gets the DateTime in UTC /// /// @return time in ms - virtual mantle_api::Time GetDateTime() = 0; + virtual Time GetDateTime() = 0; /// @brief Gets the time since start of simulation /// /// @return time since start of simulation in ms - virtual mantle_api::Time GetSimulationTime() = 0; + virtual Time GetSimulationTime() = 0; /// @brief Sets the weather conditions /// @@ -164,7 +175,7 @@ public: /// /// @param name The name of the user defined value /// @return The user defined value. No value if it doesn't exist. - virtual std::optional<std::string> GetUserDefinedValue(const std::string& name) = 0; + [[nodiscard]] virtual std::optional<std::string> GetUserDefinedValue(const std::string& name) const = 0; /// @brief Sets a named variable /// @@ -182,13 +193,7 @@ public: /// or if an entity has reached the end of a route /// /// @param default_routing_behavior selects the behavior - virtual void SetDefaultRoutingBehavior(mantle_api::DefaultRoutingBehavior default_routing_behavior) = 0; - - /// Assigns a route to an entity - /// - /// @param entity_id specifies the entity - /// @param route_definition specifies how the route shall be constructed - virtual void AssignRoute(mantle_api::UniqueId entity_id, mantle_api::RouteDefinition route_definition) = 0; + virtual void SetDefaultRoutingBehavior(DefaultRoutingBehavior default_routing_behavior) = 0; /// @brief Initializes the traffic swarm service with the scenario parameters /// diff --git a/include/MantleAPI/Map/i_coord_converter.h b/include/MantleAPI/Map/i_coord_converter.h index 6bbc8e43a79f33f7799a83ed1aaf1954aebf0c2b..0d878d95aff798b7d0bf1ccbd6deb5695bac587a 100644 --- a/include/MantleAPI/Map/i_coord_converter.h +++ b/include/MantleAPI/Map/i_coord_converter.h @@ -30,20 +30,20 @@ class ICoordConverter public: virtual ~ICoordConverter() = default; - /// Converts a position of any kind to its corresponding inertial position. + /// Convert a position of any kind to its corresponding inertial position. /// /// @param position The input position. Coordinate system is implicitly defined by underlying type of Position /// @return Inertial position [[nodiscard]] virtual Vec3<units::length::meter_t> Convert(Position position) = 0; - /// Calculates the orientation of the lane center line at a given lane position. + /// Calculate the orientation of the lane center line at a given lane position. /// /// @param open_drive_lane_position Position specified in a lane coordinate system (road id, local lane id, s) /// @return Orientation of the lane center line at the specified position in inertial coordinates [[nodiscard]] virtual Orientation3<units::angle::radian_t> GetLaneOrientation( const OpenDriveLanePosition& open_drive_lane_position) = 0; - /// Calculates the orientation of the road reference line at a given road position. + /// Calculate the orientation of the road reference line at a given road position. /// /// @param open_drive_road_position Position specified in a road coordinate system (road id, s) /// @return Orientation of the road reference line at the specified position in inertial coordinates diff --git a/include/MantleAPI/Map/i_lane_location_query_service.h b/include/MantleAPI/Map/i_lane_location_query_service.h index 73687219d34ab13c17a0bcb0891802466cb7059a..9cecc0edb238e7884e2cc78cd190a52d1efca591 100644 --- a/include/MantleAPI/Map/i_lane_location_query_service.h +++ b/include/MantleAPI/Map/i_lane_location_query_service.h @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2022 Ansys, Inc. + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -23,6 +24,7 @@ #include <MantleAPI/Map/lane_definition.h> #include <units.h> +#include <cstdint> #include <optional> #include <vector> @@ -30,19 +32,19 @@ namespace mantle_api { /// Specifiy the direction of the lane relative to the reference pose. -enum class Direction +enum class Direction : std::uint8_t { - kForward = 0, - kBackwards = 1 + kForward = 0, ///< The lane has the same direction as the reference pose. + kBackwards ///< The lane has the opposite direction of the reference pose. }; /// Definiton of the lateral displacement direction either to the left or right w.r.t the reference pose. /// "Any" means that the position calculation to the left is executed first and, in case of an an invalid result, to the right next. -enum class LateralDisplacementDirection +enum class LateralDisplacementDirection : std::uint8_t { - kAny = 0, - kLeft = 1, - kRight = 2 + kAny = 0, ///< The lateral displacement direction is not specified. + kLeft, ///< The lateral displacement direction is to the left. + kRight ///< The lateral displacement direction is to the right. }; /// Abstraction layer for all map related functions. @@ -121,8 +123,8 @@ public: /// @return Position at the given lateral distance in the given displacement direction from the reference pose. /// If the calculated position is not on a lane, no value is returned. If the position is on multiple /// lanes at the same time, the first lane in the list is considered. - [[nodiscard]] virtual std::optional<Vec3<units::length::meter_t>> GetPosition(const mantle_api::Pose& reference_pose, - mantle_api::LateralDisplacementDirection direction, + [[nodiscard]] virtual std::optional<Vec3<units::length::meter_t>> GetPosition(const Pose& reference_pose, + LateralDisplacementDirection direction, units::length::meter_t distance) const = 0; /// @brief Calculate the longitudinal distance of two given positions on a lane. @@ -135,8 +137,8 @@ public: /// No value returned if the distance is not calculable. [[nodiscard]] virtual std::optional<units::length::meter_t> GetLongitudinalLaneDistanceBetweenPositions( - const mantle_api::Vec3<units::length::meter_t>& start_position, - const mantle_api::Vec3<units::length::meter_t>& target_position) const = 0; + const Vec3<units::length::meter_t>& start_position, + const Vec3<units::length::meter_t>& target_position) const = 0; /// @brief Calculate a new pose which is at a certain longitudinal distance in a relative lane from the /// reference_pose_on_lane. @@ -166,8 +168,8 @@ public: /// @return Lane id that is at the given lateral shift (relative_lane_target) from given position /// (reference_pose_on_lane). No value, if reference pose is not on a lane or if the lane doesn't have a /// suitable adjacent lane. - [[nodiscard]] virtual std::optional<mantle_api::LaneId> GetRelativeLaneId(const mantle_api::Pose& reference_pose_on_lane, - int relative_lane_target) const = 0; + [[nodiscard]] virtual std::optional<LaneId> GetRelativeLaneId(const Pose& reference_pose_on_lane, + int relative_lane_target) const = 0; /// @brief Calculate pose projected from a given position to a target lane centerline /// @@ -175,8 +177,8 @@ public: /// @param target_lane_id The id of the target lane that the reference position is projected to. /// @return The projected pose on the target lane centerline. No value, if the projection pose cannot be calculated, /// e.g. reference position not projectable, or target lane does not exist, etc. - [[nodiscard]] virtual std::optional<mantle_api::Pose> GetProjectedPoseAtLane(const Vec3<units::length::meter_t>& reference_position_on_lane, - mantle_api::LaneId target_lane_id) const = 0; + [[nodiscard]] virtual std::optional<Pose> GetProjectedPoseAtLane(const Vec3<units::length::meter_t>& reference_position_on_lane, + UniqueId target_lane_id) const = 0; /// @brief Tries to map a given position to a lane and then returns the projected center line point of the lane from the /// given position diff --git a/include/MantleAPI/Map/i_route.h b/include/MantleAPI/Map/i_route.h index 80357e6910983a0b5d21b74feeaa756fe5963983..99cb4d7a7fdf1bac76df3e605cfcf06754557b19 100644 --- a/include/MantleAPI/Map/i_route.h +++ b/include/MantleAPI/Map/i_route.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,61 +17,46 @@ #define MANTLEAPI_MAP_I_ROUTE_H #include <MantleAPI/Common/i_identifiable.h> +#include <MantleAPI/Common/position.h> #include <MantleAPI/Common/vector.h> #include <MantleAPI/Map/lane_definition.h> +#include <optional> #include <units.h> namespace mantle_api { -/// Base interface for route -/// It represents continuous path throughout the road network, defined by a series of waypoints +/// Base interface for routes. +/// It represents a path through the road network, following the reference lines of road tracks. class IRoute : public virtual IIdentifiable { public: - /// Adds a waypoint to the route + /// Check whether the route is looped. + /// A looped route connects the end with the start of a route resulting in a repeatably drivable path. /// - /// @param inert_pos Waypoint to add - /// @return created route defined by a series of waypoints - virtual IRoute& AddWaypoint(const Vec3<units::length::meter_t>& inert_pos) = 0; + /// @return true, if the route is looped, otherwise false + [[nodiscard]] virtual bool IsLooped() const = 0; - /// Adds a waypoint to the route + /// Return a road position along the route reference line given a longitudinal and lateral offset. + /// If the provided longitudinal offset is longer than the length of the route, it returns a road + /// position at the end of the route. For looped routes, the projection takes potential repetitions + /// into account. /// - /// @param inert_pos Waypoint to add - /// @return created route defined by a series of waypoints - virtual IRoute& AddWaypoint(Vec3<units::length::meter_t>&& inert_pos) = 0; + /// @param longitudinal_offset Provided longitudinal offset + /// @param lateral_offset Provided lateral offset + /// @return Road position at provided offsets along the route reference line + [[nodiscard]] virtual OpenDriveRoadPosition ProjectAlongReferenceLine(units::length::meter_t longitudinal_offset, units::length::meter_t lateral_offset) const = 0; - /// Returns inertial position from track position + /// Return the longitudinal offset from its start to the given position along the route reference line. + /// The returned offset is always less or equal the length of the route. + /// Returns a std::nullopt if the provided position could not be mapped onto any road of the route. /// - /// @param route_pos s coordinate on lane - /// @param lane_id ID of lane - /// @param lane_offset t coordinate on lane - /// @return position in Cartesian coordinate system - [[nodiscard]] virtual Vec3<units::length::meter_t> GetInertPos(units::length::meter_t route_pos, - LaneId lane_id, - units::length::meter_t lane_offset = units::length::meter_t{ - 0.0}) const = 0; + /// @param position End position + /// @return The longitudinal offset from start to the provided position, if position is valid + [[nodiscard]] virtual std::optional<units::length::meter_t> GetOffsetAlongReferenceLine(const Position &position) const = 0; - /// Returns interpolated value for the width of the lane at the given position - /// - /// @param lane_id ID of lane to search in - /// @param route_pos s coordinate of search start - /// @return width at position - [[nodiscard]] virtual units::length::meter_t GetLaneWidth(units::length::meter_t route_pos, LaneId lane_id) const = 0; - - /// Returns ID of the lane that encloses the passed in position within its shape - /// - /// @param inert_pos Position to search for the Lane ID - /// @return ID of the lane - [[nodiscard]] virtual LaneId GetLaneId(const Vec3<units::length::meter_t>& inert_pos) const = 0; - - /// Returns distance from start to the given position along the set route - /// - /// @param inert_pos End position - /// @return distance from start to the given position - [[nodiscard]] virtual units::length::meter_t GetDistanceFromStartTo(const Vec3<units::length::meter_t>& inert_pos) const = 0; - - /// Returns the length of the route + /// Return the length of the route. + /// If the route is looped the length of only one loop shall be returned. /// /// @return length of the route [[nodiscard]] virtual units::length::meter_t GetLength() const = 0; diff --git a/include/MantleAPI/Map/i_route_repository.h b/include/MantleAPI/Map/i_route_repository.h new file mode 100644 index 0000000000000000000000000000000000000000..521a5fc449fc6a544762308aa7b37817feacfa43 --- /dev/null +++ b/include/MantleAPI/Map/i_route_repository.h @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +//----------------------------------------------------------------------------- +/** @file i_route_repository.h */ +//----------------------------------------------------------------------------- + +#ifndef MANTLEAPI_TRAFFIC_I_ROUTE_REPOSITORY +#define MANTLEAPI_TRAFFIC_I_ROUTE_REPOSITORY + +#include <MantleAPI/Map/i_route.h> +#include <MantleAPI/Map/routing_definition.h> + +#include <memory> +#include <string> + +namespace mantle_api +{ + +/// This interface provides CRUD functionality for routes. +class IRouteRepository +{ +public: + virtual ~IRouteRepository() = default; + /// Create a new route. + /// + /// @param name Name of the route + /// @param definition Routing definition used for building the route + /// @return A newly created route + virtual std::weak_ptr<IRoute> Create(const std::string& name, const RoutingDefinition& definition) = 0; + + /// Get the route by the given name. + /// Returns an unassigned pointer if no such route exists. + /// + /// @param name The name of the route + /// @return Route according to the given name (may be ambiguous) + [[nodiscard]] virtual std::weak_ptr<const IRoute> Get(const std::string& name) const = 0; + + /// Get the route by the given unique ID. + /// Returns an unassigned pointer if no such route exists. + /// + /// @param route_id Unique ID of the route + /// @return Route according to the given unique ID + [[nodiscard]] virtual std::weak_ptr<const IRoute> Get(UniqueId route_id) const = 0; + + /// Check whether the repository contains a route with the given ID. + /// + /// @param route_id Unique ID to be searched for + /// @return true, if route with given ID exists, otherwise false + [[nodiscard]] virtual bool Contains(UniqueId route_id) const = 0; + + /// Delete the route with the given unique ID. + /// + /// @param route_id The ID of the route to be deleted + virtual void Delete(UniqueId route_id) = 0; + + /// Delete the route with the given name. + /// + /// @param name The name of the route to be deleted + virtual void Delete(const std::string& name) = 0; + + /// Reset the route repository. + /// + /// Establishes a defined initial state, such as removing all routes + virtual void Reset() = 0; +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_I_ROUTE_REPOSITORY diff --git a/include/MantleAPI/Map/lane_definition.h b/include/MantleAPI/Map/lane_definition.h index 13d278a5b2c2060ceee2c77616839a9a94e70474..e72d205d9fa7ae543a55708961030c886901e1f6 100644 --- a/include/MantleAPI/Map/lane_definition.h +++ b/include/MantleAPI/Map/lane_definition.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2022, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -24,7 +25,7 @@ namespace mantle_api /// A LaneId does not necessarily have to be unique. /// Depending on the scenario description it can repeat, /// as e.g. for every uniqulely identifiable road (i.e. OpenDRIVE). -using LaneId = int64_t; +using LaneId = std::int64_t; } // namespace mantle_api diff --git a/include/MantleAPI/Map/map_details.h b/include/MantleAPI/Map/map_details.h index 8e9895be2bce18f6c5dbce11607562ee40d7c623..a08ec417ae237f6b10477b1c8c3f09004a019119 100644 --- a/include/MantleAPI/Map/map_details.h +++ b/include/MantleAPI/Map/map_details.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,6 +17,7 @@ #include <MantleAPI/Common/position.h> +#include <cstdint> #include <memory> #include <vector> @@ -24,11 +25,11 @@ namespace mantle_api { /// Specify the interpretation of the vector of points in the map region. -enum class MapRegionType +enum class MapRegionType : std::uint8_t { - kUndefined = 0, ///< Undefined interpretation of the vector of points in the map region. - kRoute, ///< Route interpretation of the vector of points in the map region. - kPolygon ///< Polygon interpretation of the vector of points in the map region. + kUndefined = 0, ///< Undefined interpretation of the vector of points in the map region. + kRoute, ///< Route interpretation of the vector of points in the map region. + kPolygon ///< Polygon interpretation of the vector of points in the map region. }; /// Definition of the map area @@ -43,11 +44,8 @@ struct MapDetails return std::make_unique<MapDetails>(*this); } - /// Area of the map (e.g. GPS latitude, GPS longitude) - std::vector<Position> map_region; - - /// Type of map region. - MapRegionType map_region_type; + std::vector<Position> map_region; ///< Area of the map (e.g. GPS latitude, GPS longitude) + MapRegionType map_region_type; ///< Type of map region. }; } // namespace mantle_api diff --git a/include/MantleAPI/Map/routing_definition.h b/include/MantleAPI/Map/routing_definition.h new file mode 100644 index 0000000000000000000000000000000000000000..feb9ac4cfb3d48568fd183a5802dea79ba013eb9 --- /dev/null +++ b/include/MantleAPI/Map/routing_definition.h @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2022-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +//----------------------------------------------------------------------------- +/// @file routing_definition.h +//----------------------------------------------------------------------------- + +#ifndef MANTLEAPI_MAP_ROUTING_DEFINITION_H +#define MANTLEAPI_MAP_ROUTING_DEFINITION_H + +#include <MantleAPI/Common/vector.h> +#include <units.h> + +#include <cstdint> +#include <tuple> +#include <vector> + +#include "MantleAPI/Common/position.h" + +namespace mantle_api +{ + +/// Define how the route from a waypoint forward should be calculated. +enum class RoutingStrategy : std::uint8_t +{ + kUnknown = 0, ///< Invalid initialization value + kUndefined, ///< Use the default route of the simulator + kFastest, ///< Use fastest path routing + kLeastIntersections, ///< Use least intersection routing + kShortest ///< Use shortest path routing +}; + +/// Group a Waypoint with a RoutingStrategy. +struct RoutingWaypoint +{ + Position position; ///< Position defined for the routing waypoint + RoutingStrategy routing_strategy; ///< Routing strategy defined for the routing waypoint +}; + +/// A raw set of positions and routing strategy for +/// linking them, from which the actual route can be calculated +struct RoutingDefinition +{ + std::vector<RoutingWaypoint> routing_waypoints; ///< The list of waypoints with associated RoutingStrategies + bool is_looped = false; ///< Flag indicating whether the resulting route shall be looped +}; + +/// Equality comparison for RoutingWaypoint. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs and rhs are equal +constexpr bool operator==(const RoutingWaypoint& lhs, const RoutingWaypoint& rhs) noexcept +{ + return std::tie(lhs.position, lhs.routing_strategy) == std::tie(rhs.position, rhs.routing_strategy); +} + +/// Inequality comparison for RoutingWaypoint. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs and rhs are not equal +constexpr bool operator!=(const RoutingWaypoint& lhs, const RoutingWaypoint& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Equality comparison for RoutingDefinition. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs and rhs are equal +inline bool operator==(const RoutingDefinition& lhs, const RoutingDefinition& rhs) noexcept +{ + return std::tie(lhs.routing_waypoints, lhs.is_looped) == std::tie(rhs.routing_waypoints, rhs.is_looped); +} + +/// Inequality comparison for RoutingDefinition. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs and rhs are not equal +inline bool operator!=(const RoutingDefinition& lhs, const RoutingDefinition& rhs) noexcept +{ + return !(lhs == rhs); +} + + +/// Output stream operator for RoutingWaypoint. +/// +/// @param[in] os The output stream +/// @param[in] waypoint The RoutingWaypoint to be printed +/// @returns The output stream with the printed RoutingWaypoint +/// +inline std::ostream& operator<<(std::ostream& os, const RoutingWaypoint& waypoint) +{ + os << "RoutingWaypoint(.position=" << waypoint.position << ", .routing_strategy=" << static_cast<int>(waypoint.routing_strategy) << ')'; + return os; +} + +/// Output stream operator for RoutingDefinition. +/// +/// @param[in] os The output stream +/// @param[in] routing_definition The RoutingDefinition to be printed +/// @returns The output stream with the printed RoutingDefinition +/// +inline std::ostream& operator<<(std::ostream& os, const RoutingDefinition& routing_definition) +{ + os << "RoutingDefinition("; + for (auto idx = 0U; idx < routing_definition.routing_waypoints.size(); ++idx) + { + os << (idx == 0U ? "[" : ", [") << std::to_string(idx) << "]=" << routing_definition.routing_waypoints.at(idx); + } + os << ')'; + return os; +} +} // namespace mantle_api + +#endif // MANTLEAPI_COMMON_ROUTING_DEFINITION_H diff --git a/include/MantleAPI/Traffic/control_strategy.h b/include/MantleAPI/Traffic/control_strategy.h index bbd59dab7b53b9f236631e2a41a89b144d6c30ef..a3a3fc5e31ccae5574a2172e62e5112a2bb83b7e 100644 --- a/include/MantleAPI/Traffic/control_strategy.h +++ b/include/MantleAPI/Traffic/control_strategy.h @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2022-2025 Ansys, Inc. + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -24,6 +25,8 @@ #include <MantleAPI/Traffic/traffic_light_properties.h> #include <MantleAPI/Traffic/vehicle_light_properties.h> +#include <cstdint> +#include <optional> #include <utility> // std::move #include <vector> @@ -31,29 +34,29 @@ namespace mantle_api { /// Movement domain of the control strategy, which specifies the desired movement behavior for the entity -enum class MovementDomain +enum class MovementDomain : std::uint8_t { - kUndefined = 0, - kLateral, - kLongitudinal, - kBoth, - kNone + kUndefined = 0, ///< The movement domain is undefined. + kLateral, ///< The movement domain is lateral. + kLongitudinal, ///< The movement domain is longitudinal. + kBoth, ///< The movement domain is both lateral and longitudinal. + kNone ///< The movement domain is none. }; /// Type of the control strategy -enum class ControlStrategyType +enum class ControlStrategyType : std::uint8_t { - kUndefined = 0, - kKeepVelocity, - kKeepLaneOffset, - kFollowHeadingSpline, - kFollowLateralOffsetSpline, - kFollowVelocitySpline, - kAcquireLaneOffset, - kFollowTrajectory, - kUpdateTrafficLightStates, - kPerformLaneChange, - kUpdateVehicleLightStates, + kUndefined = 0, ///< The control strategy type is undefined. + kKeepVelocity, ///< The control strategy type is to keep the current velocity. + kKeepLaneOffset, ///< The control strategy type is to keep the current lane offset. + kFollowHeadingSpline, ///< The control strategy type is to follow a heading angle from spline. + kFollowLateralOffsetSpline, ///< The control strategy type is to follow a lateral offset from spline. + kFollowVelocitySpline, ///< The control strategy type is to follow a velocity from spline. + kAcquireLaneOffset, ///< The control strategy type is to acquire a lane offset. + kFollowTrajectory, ///< The control strategy type is to follow a trajectory. + kUpdateTrafficLightStates, ///< The control strategy type is to update traffic light states. + kPerformLaneChange, ///< The control strategy type is to perform a lane change. + kUpdateVehicleLightStates, ///< The control strategy type is to update the vehicle light states. }; /// Defintion of all control strategies for a single entity. @@ -102,6 +105,7 @@ struct KeepVelocityControlStrategy : public ControlStrategy /// @brief Constructs a KeepVelocityControlStrategy as a ControlStrategy with predefined values KeepVelocityControlStrategy() : ControlStrategy{MovementDomain::kLongitudinal, ControlStrategyType::kKeepVelocity} {} + // Doesn't need configuration attributes. Controller keeps current velocity on adding entity or update }; @@ -111,6 +115,7 @@ struct KeepLaneOffsetControlStrategy : public ControlStrategy /// @brief Constructs a KeepLaneOffsetControlStrategy as a ControlStrategy with predefined values KeepLaneOffsetControlStrategy() : ControlStrategy{MovementDomain::kLateral, ControlStrategyType::kKeepLaneOffset} {} + // Doesn't need configuration attributes. Controller keeps current lane offset on adding entity or update }; @@ -195,22 +200,22 @@ struct FollowLateralOffsetSplineControlStrategy : public ControlStrategy }; /// Defines how a target value will be acquired (with a constant rate, in a defined distance, within a defined time). -enum class Dimension +enum class Dimension : std::uint8_t { - kUndefined = 0, - kDistance, - kRate, - kTime + kUndefined = 0, ///< The dimension of the transition function is undefined. + kDistance, ///< The target value will be acquired within a defined distance. + kRate, ///< The target value will be acquired with a constant rate. + kTime ///< The target value will be acquired within a defined time. }; /// Function type used to represent the change of a given variable over time or distance. -enum class Shape +enum class Shape : std::uint8_t { - kUndefined = 0, - kStep, - kCubic, - kLinear, - kSinusoidal + kUndefined = 0, ///< The shape of the transition function is undefined. + kStep, ///< The transition function is a step function. + kCubic, ///< The transition function is a cubic function. + kLinear, ///< The transition function is a linear function. + kSinusoidal ///< The transition function is a sinusoidal function. }; /// Specifies the dynamics of a value transition and defines how the value changes over time or distance. @@ -248,9 +253,12 @@ struct AcquireLaneOffsetControlStrategy : public ControlStrategy continuous{continuous}, lane_offset_action_dynamics{lane_offset_action_dynamics} {} - units::length::meter_t offset; ///< Lane offset - bool continuous; ///< If false, the action ends when the target lane-offset is reached. If true it does not end but has to be stopped. - LaneOffsetActionDynamics lane_offset_action_dynamics; ///< Parameters defining the dynamics of the LaneOffsetAction + /// Lane offset + units::length::meter_t offset; + /// If false, the action ends when the target lane-offset is reached. If true it does not end but has to be stopped. + bool continuous; + /// Parameters defining the dynamics of the LaneOffsetAction + LaneOffsetActionDynamics lane_offset_action_dynamics; }; /// Controls the transition of a vehicle light state to the target light state @@ -286,8 +294,8 @@ struct TrafficLightStateControlStrategy : public ControlStrategy bool repeat_states; }; -/// Definition of time value context as either absolute or relative -enum class ReferenceContext +/// Definition of time value context as either absolute or relative. +enum class ReferenceContext : std::uint8_t { kAbsolute = 0, kRelative diff --git a/include/MantleAPI/Traffic/default_routing_behavior.h b/include/MantleAPI/Traffic/default_routing_behavior.h index 215a845491c9de4f9e2123a283b685ee1a93b1fb..e5e86fe657afa191ccd9f2143edb8f6003893161 100644 --- a/include/MantleAPI/Traffic/default_routing_behavior.h +++ b/include/MantleAPI/Traffic/default_routing_behavior.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2022, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,14 +16,16 @@ #ifndef MANTLEAPI_TRAFFIC_DEFAULT_ROUTING_BEHAVIOR_H #define MANTLEAPI_TRAFFIC_DEFAULT_ROUTING_BEHAVIOR_H +#include <cstdint> + /// MantleAPI namespace namespace mantle_api { -/// Specify behavior to end of route -enum class DefaultRoutingBehavior +/// Specify behavior to end of route. +enum class DefaultRoutingBehavior : std::uint8_t { - kStop, ///< Do nothing + kStop = 0, ///< Do nothing kRandomRoute ///< Randomly select where to go next }; diff --git a/include/MantleAPI/Traffic/entity_properties.h b/include/MantleAPI/Traffic/entity_properties.h index ff44e4a3daa67814feffac621eac37aa69c59a09..92dea5163d2ec0addafbf3a85ee365d93792bd9e 100644 --- a/include/MantleAPI/Traffic/entity_properties.h +++ b/include/MantleAPI/Traffic/entity_properties.h @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2022 Ansys, Inc. + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,264 +20,437 @@ #include <MantleAPI/Common/bounding_box.h> #include <MantleAPI/Common/floating_point_helper.h> #include <MantleAPI/Common/spline.h> +#include <MantleAPI/Common/unit_definitions.h> #include <MantleAPI/Common/vector.h> +#include <units.h> -#include <limits> +#include <cstdint> #include <map> #include <string> +#include <utility> namespace mantle_api { /// Specify the type of an entity. -enum class EntityType +enum class EntityType : std::uint8_t { - // Other (unspecified but known) - kOther = 1, - // Object is a vehicle. - kVehicle = 2, - // Object is a pedestrian. - kPedestrian = 3, - // Object is an animal. - kAnimal = 4, - // Object is static and does not move - kStatic = 5 + kUnknown = 0, ///< The type of the entity is unknown. + kOther, ///< The type of the entity is known, but unspecified. + kVehicle, ///< The entity is a vehicle. + kPedestrian, ///< The entity is a pedestrian. + kAnimal, ///< The entity is an animal. + kStatic ///< The entity is static and does not move. }; /// Basic properties that describe scenario entities. struct EntityProperties { - /// @brief Constructs EntityProperties from its members + /// Destructor + virtual ~EntityProperties() = default; + + BoundingBox bounding_box{}; ///< The three dimensional bounding box that encloses the entity. + EntityType type{}; ///< Type of the entity object (e.g. vehicle, pedestrian). + std::string model; ///< Definition of the model of the entity. + std::map<std::string, std::string> properties; ///< Additional properties as name value pairs. + units::mass::kilogram_t mass{}; ///< The mass of the entity in kg. + +protected: + /// Default constructor + /// + /// @param[in] type Type of the entity object (e.g. vehicle, pedestrian) + explicit EntityProperties(EntityType type) noexcept + : type{type} {} + + /// Construct EntityProperties from its members /// /// @param[in] bounding_box The three dimensional bounding box that encloses the entity - /// @param[in] type Type of the entity object (e.g. vehicle, pedestrian) - /// @param[in] model Definition of the model of the entity - /// @param[in] properties Additional properties as name value pairs - /// @param[in] mass The mass of the entity in kg - explicit EntityProperties(BoundingBox bounding_box = {}, - EntityType type = EntityType::kOther, - std::string model = {}, - std::map<std::string, std::string> properties = {}, - units::mass::kilogram_t mass = {}) + /// @param[in] type Type of the entity object (e.g. vehicle, pedestrian) + /// @param[in] model Definition of the model of the entity + /// @param[in] properties Additional properties as name value pairs + /// @param[in] mass The mass of the entity in kg + explicit EntityProperties(BoundingBox bounding_box, + EntityType type, + std::string model, + std::map<std::string, std::string> properties, + units::mass::kilogram_t mass) noexcept : bounding_box{bounding_box}, type{type}, model{std::move(model)}, properties{std::move(properties)}, mass{mass} {} - virtual ~EntityProperties() = default; + /// Copy constructor + /// @param[in] other The object to copy from + EntityProperties(const EntityProperties& other) = default; + + /// Copy assignment operator + /// @param[in] other The object to copy from + /// @returns A reference to this object + EntityProperties& operator=(const EntityProperties& other) noexcept = default; - /// The three dimensional bounding box that encloses the entity - BoundingBox bounding_box; - /// Type of the entity object (e.g. vehicle, pedestrian) - EntityType type; - /// Definition of the model of the entity - std::string model; - /// Additional properties as name value pairs - std::map<std::string, std::string> properties; - /// The mass of the entity in kg - units::mass::kilogram_t mass; + /// Move constructor + /// @param[in] other The object to move from + EntityProperties(EntityProperties&& other) noexcept = default; + + /// Move assignment operator + /// @param[in] other The object to move from + /// @returns A reference to this object + EntityProperties& operator=(EntityProperties&& other) noexcept = default; }; -/// @brief Equality comparison for EntityProperties. +/// Equality comparison for EntityProperties. /// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs exactly equal to the values of rhs. +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs exactly equal to the values of rhs. constexpr bool operator==(const EntityProperties& lhs, const EntityProperties& rhs) noexcept { - return lhs.bounding_box == rhs.bounding_box && lhs.type == rhs.type && lhs.model == rhs.model; + return std::tie(lhs.bounding_box, lhs.type, lhs.model, lhs.properties, lhs.mass) == + std::tie(rhs.bounding_box, rhs.type, rhs.model, rhs.properties, rhs.mass); +} + +/// Inequality comparison for EntityProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const EntityProperties& lhs, const EntityProperties& rhs) noexcept +{ + return !(lhs == rhs); } /// Specify the class of a vehicle. -enum class VehicleClass +enum class VehicleClass : std::uint8_t { - kOther = 1, // Other (unspecified but known) type of vehicle. - // Vehicle is a small car. - // Definition: Hatchback car with maximum length 4 m. - kSmall_car = 2, - // Vehicle is a compact car. - // Definition: Hatchback car with length between 4 and 4.5 m. - kCompact_car = 3, - // Vehicle is a medium car. - // Definition: Hatchback or sedan with length between 4.5 and 5 m. - kMedium_car = 4, - // Vehicle is a luxury car. - // Definition: Sedan or coupe that is longer then 5 m. - kLuxury_car = 5, - // Vehicle is a delivery van. - // Definition: A delivery van. - kDelivery_van = 6, - // Vehicle is a heavy truck. - kHeavy_truck = 7, - // Vehicle is a truck with semitrailer. - kSemitrailer = 8, - // Vehicle is a trailer (possibly attached to another vehicle). - kTrailer = 9, - // Vehicle is a motorbike or moped. - kMotorbike = 10, - // Vehicle is a bicycle (without motor and specific lights). - kBicycle = 11, - // Vehicle is a bus. - kBus = 12, - // Vehicle is a tram. - kTram = 13, - // Vehicle is a train. - kTrain = 14, - // Vehicle is a wheelchair. - kWheelchair = 15, - // Vehicle type not specified properly. - kInvalid = -1 + kUnknown = 0, ///< The type of the vehicle is unknown. + kOther, ///< The type of the vehicle is known, but unspecified. + kSmallCar, ///< The vehicle is a small car. Definition: Hatchback car with maximum length 4 m. + kCompactCar, ///< The vehicle is a compact car. Definition: Hatchback car with length between 4 and 4.5 m. + kMediumCar, ///< The vehicle is a medium car. Definition: Hatchback or sedan with length between 4.5 and 5 m. + kLuxuryCar, ///< The vehicle is a luxury car. Definition: Sedan or coupe that is longer then 5 m. + kDeliveryVan, ///< The vehicle is a delivery van. + kHeavyTruck, ///< The vehicle is a heavy truck. + kSemiTrailer, ///< The vehicle is a truck with semi-trailer. + kTrailer, ///< The vehicle is a trailer. The trailer may be attached to another vehicle. + kMotorcycle, ///< The vehicle is a motorcycle or moped. + kBicycle, ///< The vehicle is a bicycle (without motor and specific lights). + kBus, ///< The vehicle is a bus. + kTram, ///< The vehicle is a tram. + kTrain, ///< The vehicle is a train. + kWheelchair, ///< The vehicle is a wheelchair. + kStandupScooter ///< The vehicle is a stand-up scooter. }; /// This struct represents the performance properties of the vehicle struct Performance { - /// Maximum speed of the vehicle - units::velocity::meters_per_second_t max_speed{std::numeric_limits<double>::infinity()}; - /// Maximum acceleration of the vehicle - units::acceleration::meters_per_second_squared_t max_acceleration{std::numeric_limits<double>::infinity()}; - /// Maximum deceleration of the vehicle - units::acceleration::meters_per_second_squared_t max_deceleration{std::numeric_limits<double>::infinity()}; - /// Maximum acceleration rate of the vehicle. If omitted then infinity is assumed - units::jerk::meters_per_second_cubed_t max_acceleration_rate{std::numeric_limits<double>::infinity()}; - /// Maximum deceleration rate of the vehicle. If omitted then infinity is assumed - units::jerk::meters_per_second_cubed_t max_deceleration_rate{std::numeric_limits<double>::infinity()}; + units::velocity::meters_per_second_t max_speed; ///< Maximum speed of the vehicle + units::acceleration::meters_per_second_squared_t max_acceleration; ///< Maximum acceleration of the vehicle + units::acceleration::meters_per_second_squared_t max_deceleration; ///< Maximum deceleration of the vehicle + units::jerk::meters_per_second_cubed_t max_acceleration_rate; ///< Maximum acceleration rate of the vehicle. If omitted, infinity is assumed. + units::jerk::meters_per_second_cubed_t max_deceleration_rate; ///< Maximum deceleration rate of the vehicle. If omitted, infinity is assumed. }; -/// @brief Equality comparison for Performance. +/// Equality comparison for Performance. /// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs almost equal to the values of rhs. +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs almost equal to the values of rhs. constexpr bool operator==(const Performance& lhs, const Performance& rhs) noexcept { - return AlmostEqual(lhs.max_speed, rhs.max_speed) && - AlmostEqual(lhs.max_acceleration, rhs.max_acceleration) && - AlmostEqual(lhs.max_deceleration, rhs.max_deceleration) && - AlmostEqual(lhs.max_acceleration_rate, rhs.max_acceleration_rate) && - AlmostEqual(lhs.max_deceleration_rate, rhs.max_deceleration_rate); + return AlmostEqual(std::tie(lhs.max_speed, lhs.max_acceleration, lhs.max_deceleration, lhs.max_acceleration_rate, lhs.max_deceleration_rate), + std::tie(rhs.max_speed, rhs.max_acceleration, rhs.max_deceleration, rhs.max_acceleration_rate, rhs.max_deceleration_rate)); +} + +/// Inequality comparison for Performance. +/// +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const Performance& lhs, const Performance& rhs) noexcept +{ + return !(lhs == rhs); } -/// This struct represents the definition of vehicle axle +/// Definition of a vehicle axle. struct Axle { - /// Maximum steering angle which can be performed by the wheels on this axle - units::angle::radian_t max_steering{0.0}; - /// Diameter of the wheels on this axle - units::length::meter_t wheel_diameter{0.0}; - /// Distance of the wheels center lines at zero steering - units::length::meter_t track_width{0.0}; - /// Position of the axle with respect to the center of vehicles bounding box - Vec3<units::length::meter_t> bb_center_to_axle_center{}; + units::angle::radian_t max_steering; ///< Maximum steering angle which can be performed by the wheels on this axle. + units::length::meter_t wheel_diameter; ///< Diameter of the wheels on this axle. + units::length::meter_t track_width; ///< Distance of the wheels center lines at zero steering. + Vec3<units::length::meter_t> bb_center_to_axle_center; ///< Position of the axle with respect to the center of vehicles bounding box. }; -/// @brief Equality comparison for Axle. +/// Equality comparison for Axle. /// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs (almost) equal to the values of rhs. +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs (almost) equal to the values of rhs. constexpr bool operator==(const Axle& lhs, const Axle& rhs) noexcept { - return AlmostEqual(lhs.max_steering, rhs.max_steering) && - AlmostEqual(lhs.wheel_diameter, rhs.wheel_diameter) && - AlmostEqual(lhs.track_width, rhs.track_width) && + return AlmostEqual(std::tie(lhs.max_steering, lhs.wheel_diameter, lhs.track_width), + std::tie(rhs.max_steering, rhs.wheel_diameter, rhs.track_width)) && lhs.bb_center_to_axle_center == rhs.bb_center_to_axle_center; } +/// Inequality comparison for Axle. +/// +/// @param[in] lhs The left-hand side value for the comparison. +/// @param[in] rhs The right-hand side value for the comparison. +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const Axle& lhs, const Axle& rhs) noexcept +{ + return !(lhs == rhs); +} + /// Additional properties for entity objects of type vehicle struct VehicleProperties : public EntityProperties { - /// Category of the vehicle (bicycle, train,...) - VehicleClass classification{VehicleClass::kOther}; + /// Default constructor + VehicleProperties() noexcept + : EntityProperties{EntityType::kVehicle} {}; + + /// Construct VehicleProperties from its members + /// + /// @param[in] bounding_box The three dimensional bounding box that encloses the entity + /// @param[in] model Definition of the model of the entity + /// @param[in] properties Additional properties as name value pairs + /// @param[in] mass The mass of the entity in kg + /// @param[in] classification Class of the vehicle + /// @param[in] performance Performance properties of the vehicle + /// @param[in] front_axle Front axle of the vehicle + /// @param[in] rear_axle Rear axle of the vehicle + /// @param[in] is_host Determines, if the vehicle is host or not + /// @param[in] is_controlled_externally Determines, if the vehicle is controlled externally or not + explicit VehicleProperties(BoundingBox bounding_box, + std::string model, + std::map<std::string, std::string> properties, + units::mass::kilogram_t mass, + VehicleClass classification, + Performance performance, + Axle front_axle, + Axle rear_axle, + bool is_host, + bool is_controlled_externally) noexcept + : EntityProperties{bounding_box, EntityType::kVehicle, std::move(model), std::move(properties), mass}, classification{classification}, performance{performance}, front_axle{front_axle}, rear_axle{rear_axle}, is_host{is_host}, is_controlled_externally{is_controlled_externally} {} + + /// Destructor + ~VehicleProperties() noexcept override = default; + + /// Copy constructor + /// @param[in] other The object to copy from + VehicleProperties(const VehicleProperties& other) = default; - /// Performance properties of the vehicle - Performance performance{}; + /// Copy assignment operator + /// @param[in] other The object to copy from + /// @returns A reference to this object + VehicleProperties& operator=(const VehicleProperties& other) noexcept = default; - /// Front axle of the vehicle - Axle front_axle{}; - /// Rear axle of the vehicle - Axle rear_axle{}; + /// Move constructor + /// @param[in] other The object to move from + VehicleProperties(VehicleProperties&& other) noexcept = default; + + /// Move assignment operator + /// @param[in] other The object to move from + /// @returns A reference to this object + VehicleProperties& operator=(VehicleProperties&& other) noexcept = default; + + VehicleClass classification{}; ///< Class of the vehicle + Performance performance{}; ///< Performance properties of the vehicle + Axle front_axle{}; ///< Front axle of the vehicle + Axle rear_axle{}; ///< Rear axle of the vehicle + bool is_host{}; ///< Determines, if the vehicle is host or not - /// The "is_host" flag determines, if the vehicle is host or not - bool is_host{false}; // TODO: remove, once external control for traffic is implemented through controllers - /// The "is_controlled_externally" flag determines, if the vehicle is controlled externally or not - bool is_controlled_externally{false}; + bool is_controlled_externally{}; ///< Determines, if the vehicle is controlled externally or not }; -/// @brief Equality comparison for VehicleProperties. +/// Equality comparison for VehicleProperties. /// -/// @param[in] lhs The left-hand side value for the comparison -/// @param[in] rhs The right-hand side value for the comparison -/// @returns true if the values of lhs exactly equal to the values of rhs. +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs exactly equal to the values of rhs. constexpr bool operator==(const VehicleProperties& lhs, const VehicleProperties& rhs) noexcept { - return lhs.bounding_box == rhs.bounding_box && lhs.type == rhs.type && lhs.model == rhs.model && - lhs.classification == rhs.classification && lhs.performance == rhs.performance && - lhs.front_axle == rhs.front_axle && lhs.rear_axle == rhs.rear_axle && - lhs.is_host == rhs.is_host; + return std::tie(static_cast<const EntityProperties&>(lhs), lhs.classification, lhs.performance, lhs.front_axle, lhs.rear_axle, lhs.is_host, lhs.is_controlled_externally) == + std::tie(static_cast<const EntityProperties&>(rhs), rhs.classification, rhs.performance, rhs.front_axle, rhs.rear_axle, rhs.is_host, rhs.is_controlled_externally); +} + +/// Inequality comparison for VehicleProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const VehicleProperties& lhs, const VehicleProperties& rhs) noexcept +{ + return !(lhs == rhs); } +/// Specify the class of a pedestrian. struct PedestrianProperties : public EntityProperties { + /// Default constructor + PedestrianProperties() noexcept + : EntityProperties{EntityType::kPedestrian} {}; + + /// Construct PedestrianProperties from its members + /// + /// @param[in] bounding_box The three dimensional bounding box that encloses the entity + /// @param[in] model Definition of the model of the entity + /// @param[in] properties Additional properties as name value pairs + /// @param[in] mass The mass of the entity in kg + explicit PedestrianProperties(BoundingBox bounding_box, + std::string model, + std::map<std::string, std::string> properties, + units::mass::kilogram_t mass) noexcept + : EntityProperties{bounding_box, EntityType::kPedestrian, std::move(model), std::move(properties), mass} {} + + /// Destructor + ~PedestrianProperties() noexcept override = default; + + /// Copy constructor + /// @param[in] other The object to copy from + PedestrianProperties(const PedestrianProperties& other) = default; + + /// Copy assignment operator + /// @param[in] other The object to copy from + /// @returns A reference to this object + PedestrianProperties& operator=(const PedestrianProperties& other) noexcept = default; + + /// Move constructor + /// @param[in] other The object to move from + PedestrianProperties(PedestrianProperties&& other) noexcept = default; + + /// Move assignment operator + /// @param[in] other The object to move from + /// @returns A reference to this object + PedestrianProperties& operator=(PedestrianProperties&& other) noexcept = default; + + // TODO: Add pedestrian specific properties }; -/// Specifies the type of a static object. -/// The values are derived from ASAM OSI stationary object type -enum class StaticObjectType +/// Equality comparison for PedestrianProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs exactly equal to the values of rhs. +constexpr bool operator==(const PedestrianProperties& lhs, const PedestrianProperties& rhs) noexcept { - kOther = 1, // Other (unspecified but known) type of static object. - // Object is a bridge. - kBridge = 2, - // Object is a building. - kBuilding = 3, - // Object is a pole (e.g. from a traffic light). - kPole = 4, - // Object is a pylon. - kPylon = 5, - // Object is a delineator (e.g. at a construction site). - kDelineator = 6, - // Object is a tree. - kTree = 7, - // Object is a barrier. - kBarrier = 8, - // Object is vegetation. - kVegetation = 9, - // Object is a curbstone. - kCurbstone = 10, - // Object is a wall. - kWall = 11, - // Landmarks corresponding to vertical structures in the environment. - kVerticalStructure = 12, - // Landmarks corresponding to rectangular structures in the environment, like walls. - kRectangularStructure = 13, - // Landmarks corresponding to overhead structures in the environment, like sign bridges. - kOverheadStructure = 14, - // Landmarks corresponding to reflective structures in the environment, like reflective poles on the road boarder. - kReflectiveStructure = 15, - // Landmarks corresponding to construction site elements in the environment, like beacons. - kConstructionSiteElement = 16, - // Object is a speed bump. - kSpeedBump = 17, - // Landmarks corresponding to sources of electromagnetic waves in the environment, like street lights. - kEmittingStructure = 18, - // Static object type not specified properly. - kInvalid = -1 + return static_cast<const EntityProperties&>(lhs) == static_cast<const EntityProperties&>(rhs); +} + +/// Inequality comparison for PedestrianProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const PedestrianProperties& lhs, const PedestrianProperties& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// Static object types. +/// +/// The values are derived from ASAM OSI stationary object type. +enum class StaticObjectType : std::uint8_t +{ + kUnknown = 0, ///< The type of the static object is unknown. + kOther, ///< The type of the static object is known, but unspecified. + kBridge, ///< The object is a bridge. + kBuilding, ///< The object is a building. + kPole, ///< The object is a pole (e.g., from a traffic light). + kPylon, ///< The object is a pylon. + kDelineator, ///< The object is a delineator (e.g., at a construction site). + kTree, ///< The object is a tree. + kBarrier, ///< The object is a barrier. + kVegetation, ///< The object is vegetation. + kCurbstone, ///< The object is a curbstone. + kWall, ///< The object is a wall. + kVerticalStructure, ///< Landmarks corresponding to vertical structures in the environment. + kRectangularStructure, ///< Landmarks corresponding to rectangular structures in the environment, like walls. + kOverheadStructure, ///< Landmarks corresponding to overhead structures in the environment, like sign bridges. + kReflectiveStructure, ///< Landmarks corresponding to reflective structures in the environment, like reflective poles on the road border. + kConstructionSiteElement, ///< Landmarks corresponding to construction site elements in the environment, like beacons. + kSpeedBump, ///< The object is a speed bump. + kEmittingStructure ///< Landmarks corresponding to sources of electromagnetic waves in the environment, like street lights. }; /// Additional properties for entity objects of type static struct StaticObjectProperties : public EntityProperties { - /// Type of the static object (bridge, pole,...) - StaticObjectType static_object_type{StaticObjectType::kOther}; + /// Default constructor + StaticObjectProperties() noexcept + : EntityProperties{EntityType::kStatic} {} + + /// Construct StaticObjectProperties from its members + /// + /// @param[in] bounding_box The three dimensional bounding box that encloses the entity + /// @param[in] model Definition of the model of the entity + /// @param[in] properties Additional properties as name value pairs + /// @param[in] mass The mass of the entity in kg + /// @param[in] static_object_type Type of the static object (bridge, pole,...) + /// @param[in] vertical_offset Amount to shift position along lane normal + explicit StaticObjectProperties(BoundingBox bounding_box, + std::string model, + std::map<std::string, std::string> properties, + units::mass::kilogram_t mass, + StaticObjectType static_object_type, + units::length::meter_t vertical_offset) noexcept + : EntityProperties{bounding_box, EntityType::kStatic, std::move(model), std::move(properties), mass}, static_object_type{static_object_type}, vertical_offset{vertical_offset} + { + } + + /// Destructor + ~StaticObjectProperties() noexcept override = default; + + /// Copy constructor + /// @param[in] other The object to copy from + StaticObjectProperties(const StaticObjectProperties& other) = default; + + /// Copy assignment operator + /// @param[in] other The object to copy from + /// @returns A reference to this object + StaticObjectProperties& operator=(const StaticObjectProperties& other) noexcept = default; + + /// Move constructor + /// @param[in] other The object to move from + StaticObjectProperties(StaticObjectProperties&& other) noexcept = default; + + /// Move assignment operator + /// @param[in] other The object to move from + /// @returns A reference to this object + StaticObjectProperties& operator=(StaticObjectProperties&& other) noexcept = default; + + StaticObjectType static_object_type{}; ///< Type of the static object (bridge, pole,...) /// Amount to shift position along lane normal. /// It allows static objects like traffic signs to be placed at certain amount above the road. /// It is considered when the position of the entity is set. - units::length::meter_t vertical_offset{0.0}; + units::length::meter_t vertical_offset{}; }; +/// Equality comparison for StaticObjectProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs exactly equal to the values of rhs. +constexpr bool operator==(const StaticObjectProperties& lhs, const StaticObjectProperties& rhs) noexcept +{ + return std::tie(static_cast<const EntityProperties&>(lhs), lhs.static_object_type, lhs.vertical_offset) == + std::tie(static_cast<const EntityProperties&>(rhs), rhs.static_object_type, rhs.vertical_offset); +} + +/// Inequality comparison for StaticObjectProperties. +/// +/// @param[in] lhs The left-hand side value for the comparison +/// @param[in] rhs The right-hand side value for the comparison +/// @returns true if the values of lhs do not exactly equal to the values of rhs. +constexpr bool operator!=(const StaticObjectProperties& lhs, const StaticObjectProperties& rhs) noexcept +{ + return !(lhs == rhs); +} + } // namespace mantle_api #endif // MANTLEAPI_TRAFFIC_ENTITY_PROPERTIES_H diff --git a/include/MantleAPI/Traffic/i_controller.h b/include/MantleAPI/Traffic/i_controller.h index 4afd7b91f1e00c6a27a145bc99bd6229718d2a35..f4b5d9f417b582c28102de0f91c9353f1d0592e6 100644 --- a/include/MantleAPI/Traffic/i_controller.h +++ b/include/MantleAPI/Traffic/i_controller.h @@ -1,6 +1,7 @@ /******************************************************************************** * Copyright (c) 2021 in-tech GmbH * 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -17,6 +18,8 @@ #define MANTLEAPI_TRAFFIC_I_CONTROLLER_H #pragma once +#include <cstdint> + #include "MantleAPI/Common/i_identifiable.h" namespace mantle_api @@ -26,23 +29,23 @@ namespace mantle_api class IController : public virtual IIdentifiable { public: - /// Desired state of lateral domain - enum class LateralState + /// Desired state of lateral domain. + enum class LateralState : std::uint8_t { - kNoChange = 0, - kActivate, - kDeactivate + kNoChange = 0, ///< No change in the state of the lateral domain + kActivate, ///< Activate the lateral domain + kDeactivate ///< Deactivate the lateral domain }; - /// Desired state of longitudinal domain - enum class LongitudinalState + /// Desired state of longitudinal domain. + enum class LongitudinalState : std::uint8_t { - kNoChange = 0, - kActivate, - kDeactivate + kNoChange = 0, ///< No change in the state of the longitudinal domain + kActivate, ///< Activate the longitudinal domain + kDeactivate ///< Deactivate the longitudinal domain }; - /// Change the state of a controller + /// Change the state of a controller. /// @param[in] lateral_state New state of the lateral domain /// @param[in] longitudinal_state New state of the longituindal domain virtual void ChangeState(LateralState lateral_state, LongitudinalState longitudinal_state) = 0; diff --git a/include/MantleAPI/Traffic/i_controller_config.h b/include/MantleAPI/Traffic/i_controller_config.h index c3f765ffc73e53f963d7a435b853c17f39b0f593..4fbb9218d69cba95a6fbced9423dc942544c84c3 100644 --- a/include/MantleAPI/Traffic/i_controller_config.h +++ b/include/MantleAPI/Traffic/i_controller_config.h @@ -16,10 +16,10 @@ #ifndef MANTLEAPI_TRAFFIC_I_CONTROLLER_CONFIG_H #define MANTLEAPI_TRAFFIC_I_CONTROLLER_CONFIG_H -#include <MantleAPI/Common/route_definition.h> #include <MantleAPI/Common/spline.h> #include <MantleAPI/Common/vector.h> #include <MantleAPI/Map/i_lane_location_query_service.h> +#include <MantleAPI/Map/routing_definition.h> #include <MantleAPI/Traffic/control_strategy.h> #include <map> @@ -37,15 +37,15 @@ struct IControllerConfig /// @param[in] name Name of the controller. Might be ignored by the environment. /// @param[in] map_query_service Pointer to the map query service /// @param[in] control_strategies List of active control strategies - /// @param[in] route_definition Specifies the route behavior for the control stratgies + /// @param[in] routing_definition Specifies the route behavior for the control stratgies explicit IControllerConfig(std::string name = {}, ILaneLocationQueryService* map_query_service = nullptr, std::vector<std::shared_ptr<mantle_api::ControlStrategy>> control_strategies = {}, - RouteDefinition route_definition = {}) + RoutingDefinition routing_definition = {}) : name{std::move(name)}, map_query_service{map_query_service}, control_strategies{std::move(control_strategies)}, - route_definition{std::move(route_definition)} {} + routing_definition{std::move(routing_definition)} {} /// @brief default destructor virtual ~IControllerConfig() = default; @@ -56,8 +56,8 @@ struct IControllerConfig ILaneLocationQueryService* map_query_service; /// List of active control strategies std::vector<std::shared_ptr<mantle_api::ControlStrategy>> control_strategies; - /// Specifies the route behavior for the control stratgies - RouteDefinition route_definition; + /// Specifies the routing behavior for the control stratgies + RoutingDefinition routing_definition; }; /// @brief Equality comparison for IControllerConfig. @@ -86,7 +86,7 @@ inline bool operator==(const IControllerConfig& lhs, const IControllerConfig& rh return lhs.name == rhs.name && lhs.map_query_service == rhs.map_query_service && std::equal(lhs.control_strategies.begin(), lhs.control_strategies.end(), rhs.control_strategies.begin(), rhs.control_strategies.end(), compare_control_strategy) && - lhs.route_definition == rhs.route_definition; + lhs.routing_definition == rhs.routing_definition; } /// @brief Check for not equal diff --git a/include/MantleAPI/Traffic/i_controller_repository.h b/include/MantleAPI/Traffic/i_controller_repository.h index 13c0d672330d6ea7b448e017aa59fc94c6a7759d..77dc13b2ffb59329b2464de697568f2420933ffd 100644 --- a/include/MantleAPI/Traffic/i_controller_repository.h +++ b/include/MantleAPI/Traffic/i_controller_repository.h @@ -1,6 +1,7 @@ /******************************************************************************** * Copyright (c) 2021 in-tech GmbH * 2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -17,54 +18,55 @@ #define MANTLEAPI_TRAFFIC_I_CONTROLLER_REPOSITORY_H #pragma once +#include <memory> + #include "MantleAPI/Traffic/i_controller.h" #include "MantleAPI/Traffic/i_controller_config.h" namespace mantle_api { -/// This interface provides CRUD functionality for controllers. -/// Controller, which is assigned to exactly one entity, controls that one entity by enforcing the behavior prescribed by -/// the control strategies assigned to that entity. -/// Multiple controllers can be assigned to an entity, but only one controller can be activated for an entity at a time. +/// This interface provides CRUD functionality for IControllers. +/// An IController, which is assigned to exactly one IEntity, controls that one IEntity by enforcing the behavior prescribed by +/// the ControlStrategies assigned to that IEntity. +/// Multiple controllers can be assigned to one IEntity, but only one controller can be activated for an IEntity at any time. class IControllerRepository { public: virtual ~IControllerRepository() = default; - /// Creates a new controller for the entity + /// Create a new IController. /// - /// @param config Controller config - /// @return newly created controller for the entity - virtual IController& Create(std::unique_ptr<IControllerConfig> config) = 0; + /// @param config IControllerConfig + /// @return The newly created IController + virtual std::weak_ptr<IController> Create(std::unique_ptr<IControllerConfig> config) = 0; - /// @deprecated Creates a new controller for the entity + /// @deprecated Create a new IController. /// - /// @param id Unique ID of the controller - /// @param config Controller config - /// @return newly created controller for the entity - [[deprecated]] virtual IController& Create(UniqueId id, std::unique_ptr<IControllerConfig> config) = 0; // deprecated + /// @param id UniqueId of the controller + /// @param config IControllerConfig + /// @return The newly created IController + [[deprecated]] virtual std::weak_ptr<IController> Create(UniqueId id, std::unique_ptr<IControllerConfig> config) = 0; // deprecated - /// Gets the controller by the given unique ID + /// Get the IController by the given UniqueId. /// - /// @param id Unique ID of the controller - /// @return controller according to the given unique ID - virtual std::optional<std::reference_wrapper<IController>> Get(UniqueId id) = 0; + /// @param id UniqueId of the IController + /// @return IController with to the given UniqueId + virtual std::weak_ptr<IController> Get(UniqueId id) = 0; - /// Checks whether the internal management container contains a controller with the given ID + /// Check whether the repository contains an IController with the given UniqueId. /// - /// @param id Unique ID to be searched for - /// @return true, if controller with given ID exists, otherwise false + /// @param id UniqueId to be searched for + /// @return true, if an IController with given UniqueId exists, false otherwise [[nodiscard]] virtual bool Contains(UniqueId id) const = 0; - /// Deletes the controller + /// Delete the IController from the scenario. /// - /// @param id The Identifier of the controller to be deleted + /// @param id The UniqueId of the IController to be deleted virtual void Delete(UniqueId id) = 0; - /// Resets the controller repository + /// Reset the IControllerRepository. /// - /// Establishes a defined initial state, - /// such as removing all controllers + /// Establish a defined initial state, such as removing all IControllers. virtual void Reset() = 0; }; diff --git a/include/MantleAPI/Traffic/i_entity.h b/include/MantleAPI/Traffic/i_entity.h index fd4ab6da19b307618b925803b43169087284ab9f..5b8a315944eba817abd6838be08498fb0adaa611 100644 --- a/include/MantleAPI/Traffic/i_entity.h +++ b/include/MantleAPI/Traffic/i_entity.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,11 +18,16 @@ #include <MantleAPI/Common/bounding_box.h> #include <MantleAPI/Common/i_identifiable.h> +#include <MantleAPI/Common/orientation.h> #include <MantleAPI/Common/pose.h> +#include <MantleAPI/Map/i_route.h> #include <MantleAPI/Traffic/entity_properties.h> #include <MantleAPI/Traffic/i_controller_config.h> +#include <units.h> +#include <cstdint> #include <memory> +#include <string> #include <vector> namespace mantle_api @@ -45,7 +51,7 @@ struct EntityVisibilityConfig /// sensor the entity would be not visible / not contained in its OSI Sensor View. /// - When "sensor_names" is not specified (empty vector) then the "sensors" flag applies to /// all sensors. - std::vector<std::string> sensor_names{}; + std::vector<std::string> sensor_names; }; /// Base interface for all static and dynamic scenario entities. @@ -97,8 +103,7 @@ public: /// @brief Sets the orientation rate (angular velocity) of the scenario entity /// /// @param orientation_rate Rate of change of a scenario entity's orientation over time - virtual void SetOrientationRate( - const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate) = 0; + virtual void SetOrientationRate(const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate) = 0; /// @brief Get the orientation rate (angular velocity) of the scenario entity /// @@ -108,14 +113,12 @@ public: /// @brief Sets the orientation acceleration (angular acceleration) of the scenario entity /// /// @param orientation_acceleration Rate of change of a scenario entity's orientation rate with respect to time - virtual void SetOrientationAcceleration( - const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration) = 0; + virtual void SetOrientationAcceleration(const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration) = 0; /// @brief Get the orientation acceleration (angular acceleration) of the scenario entity /// /// @return Orientation acceleration (angular acceleration) - [[nodiscard]] virtual Orientation3<units::angular_acceleration::radians_per_second_squared_t> GetOrientationAcceleration() - const = 0; + [[nodiscard]] virtual Orientation3<units::angular_acceleration::radians_per_second_squared_t> GetOrientationAcceleration() const = 0; /// @brief Sets the properties that describe scenario entity /// @@ -130,12 +133,12 @@ public: /// @brief Sets the IDs of the lanes that scenario entity is assigned to /// /// @param assigned_lane_ids The IDs of the lanes that scenario entity is assigned to - virtual void SetAssignedLaneIds(const std::vector<std::uint64_t>& assigned_lane_ids) = 0; + virtual void SetAssignedLaneIds(const std::vector<mantle_api::UniqueId>& assigned_lane_ids) = 0; /// @brief Get the IDs of the lanes that scenario entity is assigned to /// /// @return IDs of the lanes that scenario entity is assigned to - [[nodiscard]] virtual std::vector<std::uint64_t> GetAssignedLaneIds() const = 0; + [[nodiscard]] virtual std::vector<mantle_api::UniqueId> GetAssignedLaneIds() const = 0; /// @brief Sets the visibility of the scenario entity /// @@ -146,6 +149,22 @@ public: /// /// @return Visibility of the scenario entity [[nodiscard]] virtual EntityVisibilityConfig GetVisibility() const = 0; + + /// Set the route for the scenario entity. + /// + /// If the entities' position is on the route, + /// the entity should follow the route from this position. + /// If the entities' position is NOT on the route, + /// the entity should navigate towards the beginning of the route. + /// TODO: we loose RoutingStrategy of first RoutingWaypoint + /// + /// @param route Route of the scenario entity + virtual void SetRoute(const std::weak_ptr<const IRoute>& route) = 0; + + /// Get the route of the scenario entity. + /// + /// @return Route of the scenario entity if one has been assigned + [[nodiscard]] virtual std::weak_ptr<const IRoute> GetRoute() const = 0; }; /// Interface for dynamic scenario entities of vehicle type diff --git a/include/MantleAPI/Traffic/i_entity_repository.h b/include/MantleAPI/Traffic/i_entity_repository.h index cfaeafb9b6fc982599d1615c174cf1372ffd583f..80dac079fec22f5ad77fe67c2820cc314cfab2b9 100644 --- a/include/MantleAPI/Traffic/i_entity_repository.h +++ b/include/MantleAPI/Traffic/i_entity_repository.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,133 +20,126 @@ #include <MantleAPI/Traffic/i_entity.h> #include <functional> -#include <optional> +#include <memory> #include <string> #include <vector> namespace mantle_api { -/// This interface provides CRUD functionality for scenario entities. +/// This interface provides CRUD functionality for IEntities. class IEntityRepository { public: virtual ~IEntityRepository() = default; - /// Creates a new dynamic scenario entity of vehicle type + /// Create a new IVehicle. /// - /// @param name The name of the entity to be created - /// @param properties Vehicle properties - /// @return newly created dynamic scenario entity of vehicle type - virtual IVehicle& Create(const std::string& name, const VehicleProperties& properties) = 0; + /// @param name The name of the IVehicle to be created + /// @param properties VehicleProperties + /// @return The newly created IVehicle + virtual std::weak_ptr<IVehicle> Create(const std::string& name, const VehicleProperties& properties) = 0; - /// @deprecated Creates a new dynamic scenario entity of vehicle type + /// @deprecated Create a new IVehicle. /// - /// @param id Unique ID of the entity - /// @param name The name of the entity to be created - /// @param properties Vehicle properties - /// @return newly created dynamic scenario entity of vehicle type - [[deprecated]] virtual IVehicle& Create(UniqueId id, const std::string& name, const VehicleProperties& properties) = 0; + /// @param id UniqueId of the IVehicle + /// @param name The name of the IVehicle to be created + /// @param properties VehicleProperties + /// @return The newly created IVehicle + [[deprecated]] virtual std::weak_ptr<IVehicle> Create(UniqueId id, const std::string& name, const VehicleProperties& properties) = 0; - /// Creates a new scenario entity of pedestrian type + /// Create a new IPedestrian. /// - /// @param name The name of the entity to be created - /// @param properties Pedestrian properties - /// @return newly created scenario entity of pedestrian type - virtual IPedestrian& Create(const std::string& name, const PedestrianProperties& properties) = 0; + /// @param name The name of the IPedestrian to be created + /// @param properties PedestrianProperties + /// @return The newly created IPedestrian + virtual std::weak_ptr<IPedestrian> Create(const std::string& name, const PedestrianProperties& properties) = 0; - /// @deprecated Creates a new scenario entity of pedestrian type + /// @deprecated Create a new IPedestrian. /// - /// @param id Unique ID of the entity - /// @param name The name of the entity to be created - /// @param properties Pedestrian properties - /// @return newly created scenario entity of pedestrian type - [[deprecated]] virtual IPedestrian& Create(UniqueId id, const std::string& name, const PedestrianProperties& properties) = 0; + /// @param id UniqueId of the IPedestrian + /// @param name The name of the IPedestrian to be created + /// @param properties PedestrianProperties + /// @return The newly created IPedestrian + [[deprecated]] virtual std::weak_ptr<IPedestrian> Create(UniqueId id, const std::string& name, const PedestrianProperties& properties) = 0; - /// Creates a new scenario entity of static object type + /// Create a new IStaticObject. /// - /// @param name The name of the entity to be created - /// @param properties Static object properties - /// @return newly created scenario entity of static object type - virtual IStaticObject& Create(const std::string& name, const mantle_api::StaticObjectProperties& properties) = 0; + /// @param name The name of the IStaticObject to be created + /// @param properties StaticObjectProperties + /// @return The newly created IStaticObject + virtual std::weak_ptr<IStaticObject> Create(const std::string& name, const mantle_api::StaticObjectProperties& properties) = 0; - /// @deprecated Creates a new scenario entity of static object type + /// @deprecated Create a new IStaticObject. /// - /// @param id Unique ID of the entity - /// @param name The name of the entity to be created - /// @param properties Static object properties - /// @return newly created scenario entity of static object type - [[deprecated]] virtual IStaticObject& Create(UniqueId id, const std::string& name, const StaticObjectProperties& properties) = 0; + /// @param id UniqueId of the IStaticObject + /// @param name The name of the IStaticObject to be created + /// @param properties StaticObjectProperties + /// @return The newly created IStaticObject + [[deprecated]] virtual std::weak_ptr<IStaticObject> Create(UniqueId id, const std::string& name, const StaticObjectProperties& properties) = 0; - /// Gets the host vehicle + /// Get the host vehicle. /// - /// @return host vehicle - virtual IVehicle& GetHost() = 0; + /// @return The host vehicle + virtual std::weak_ptr<IVehicle> GetHost() = 0; - /// Gets the entity by the given name + /// Get the IEntity by the given name. /// - /// @param name The name of the entity - /// @return entity according to the given name - virtual std::optional<std::reference_wrapper<IEntity>> Get(const std::string& name) = 0; + /// @param name The name of the IEntity + /// @return The IEntity with the given name + virtual std::weak_ptr<IEntity> Get(const std::string& name) = 0; - /// Gets the const entity by the given name - /// - /// @param name The name of the entity - /// @return const entity according to the given name - [[nodiscard]] virtual std::optional<std::reference_wrapper<const IEntity>> Get(const std::string& name) const = 0; + /// @copydoc Get(const std::string&) + [[nodiscard]] virtual std::weak_ptr<const IEntity> Get(const std::string& name) const = 0; - /// Gets the entity by the given unique ID + /// Get the IEntity by the given UniqueId. /// - /// @param id Unique ID of the entity - /// @return entity according to the given unique ID - virtual std::optional<std::reference_wrapper<IEntity>> Get(UniqueId id) = 0; + /// @param id The UniqueId of the IEntity + /// @return The IEntity with the given UniqueId + virtual std::weak_ptr<IEntity> Get(UniqueId id) = 0; - /// Gets the const entity by the given unique ID - /// - /// @param id Unique ID of the entity - /// @return const entity according to the given unique ID - [[nodiscard]] virtual std::optional<std::reference_wrapper<const IEntity>> Get(UniqueId id) const = 0; + /// @copydoc Get(UniqueId) + [[nodiscard]] virtual std::weak_ptr<const IEntity> Get(UniqueId id) const = 0; - /// Checks whether the internal management container contains an scenario entity with the given ID + /// Check whether the repository contains an IEntity with the given UniqueId. /// - /// @param id Unique ID to be searched for - /// @return true, if scenario entity with given ID exists, otherwise false + /// @param id The UniqueId to be searched for + /// @return true, if an IEntity with given UniqueId exists, false otherwise [[nodiscard]] virtual bool Contains(UniqueId id) const = 0; - /// Deletes the reference entity from the scenario + /// Delete the IEntity from the scenario. /// - /// @param name The name of the entity to be deleted + /// @param name The name of the IEntity to be deleted virtual void Delete(const std::string& name) = 0; - /// Resets the entity repository + /// Reset the IEntityRepository. /// - /// Establishes a defined initial state, - /// such as removing all entities + /// Establish a defined initial state, such as removing all IEntities. virtual void Reset() = 0; - /// Deletes the reference entity from the scenario + /// Delete the IEntity from the scenario. /// - /// @param id The Identifier of the scenario entity to be deleted + /// @param id The UniqueId of the IEntity to be deleted virtual void Delete(UniqueId id) = 0; - /// Gets all scenario entities + /// Get all IEntities. /// - /// @returns all scenario entities - [[nodiscard]] virtual const std::vector<std::unique_ptr<mantle_api::IEntity>>& GetEntities() const = 0; + /// @returns All IEntities + [[nodiscard]] virtual std::vector<std::weak_ptr<IEntity>> GetEntities() const = 0; - /// Allows an external component to react on creation of an entity, such as establishing additional references pointing to it + /// Allow an external component to react to the creation of an IEntity, such as establishing additional references pointing to it. /// - /// @param callback Function to be called when creating an entity - virtual void RegisterEntityCreatedCallback(const std::function<void(IEntity&)>& callback) = 0; + /// @param callback Function to be called when creating an IEntity + virtual void RegisterEntityCreatedCallback(const std::function<void(std::weak_ptr<IEntity>)>& callback) = 0; - /// Allows an external component to react on deletion of an entity, such as cleaning up invalid references pointing to it + /// Allow an external component to react to the deletion of an IEntity, such as cleaning up invalid references pointing to it. /// - /// @param callback Function to be called when deleting an entity with string parameter + /// @param callback Function to be called when deleting an IEntity with string parameter virtual void RegisterEntityDeletedCallback(const std::function<void(const std::string&)>& callback) = 0; - /// Allows an external component to react on deletion of an entity, such as cleaning up invalid references pointing to it + /// Allow an external component to react to the deletion of an IEntity, such as cleaning up invalid references pointing to it. /// - /// @param callback Function to be called when deleting an entity with UniqueId parameter + /// @param callback Function to be called when deleting an IEntity with UniqueId parameter virtual void RegisterEntityDeletedCallback(const std::function<void(UniqueId)>& callback) = 0; }; diff --git a/include/MantleAPI/Traffic/i_traffic_area_stream.h b/include/MantleAPI/Traffic/i_traffic_area_stream.h index d9f0565bc1bd9e1fa844d23e98e2795608a39a40..7b919aa1586d02219aff7f07dac1fab4bd712390 100644 --- a/include/MantleAPI/Traffic/i_traffic_area_stream.h +++ b/include/MantleAPI/Traffic/i_traffic_area_stream.h @@ -65,7 +65,7 @@ public: /// @param start_distance Distance from which to start the search /// @param search_distance Distance to search for in the search_direction /// @returns Entity or empty if no entity was found - virtual const IEntity* GetEntity( + virtual std::weak_ptr<IEntity> GetEntity( SearchDirection search_direction, units::length::meter_t start_distance, units::length::meter_t search_distance) const = 0; diff --git a/include/MantleAPI/Traffic/i_traffic_swarm_service.h b/include/MantleAPI/Traffic/i_traffic_swarm_service.h index 59fdb07eb87facb64702f0cc798df79faa629589..311946b82e470fb85bedff017853b70b8ff830f5 100644 --- a/include/MantleAPI/Traffic/i_traffic_swarm_service.h +++ b/include/MantleAPI/Traffic/i_traffic_swarm_service.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,7 +20,11 @@ #include <MantleAPI/Common/vector.h> #include <units.h> +#include <cstddef> +#include <cstdint> #include <memory> +#include <string> +#include <utility> #include <vector> #include "MantleAPI/Traffic/entity_properties.h" @@ -41,7 +46,7 @@ struct TrafficSwarmParameters /// Name of the central entity the swarm traffic is created around std::string central_entity_name; /// The maximum number of vehicles surrounding the central entity - size_t maximum_number_of_vehicles; + std::size_t maximum_number_of_vehicles; /// The starting speeds of the spawned entities SpeedRange speed_range; /// Radius of the inner circular area around the central entity @@ -62,11 +67,11 @@ class ITrafficSwarmService public: virtual ~ITrafficSwarmService() = default; - /// Specify the relative position of the spawned vehicle to the central entity - enum class RelativePosition + /// Specify the relative position of the spawned vehicle to the central entity. + enum class RelativePosition : std::uint8_t { - kInFront = 0, - kBehind + kInFront = 0, ///< The spawned vehicle is in front of the central entity + kBehind ///< The spawned vehicle is behind the central entity }; /// Specify the position of the spawned vehicle @@ -92,7 +97,7 @@ public: /// Sets the number of swarm entities /// /// @param count number of swarm entities - virtual void SetSwarmEntitiesCount(size_t count) = 0; + virtual void SetSwarmEntitiesCount(std::size_t count) = 0; }; } // namespace mantle_api diff --git a/include/MantleAPI/Traffic/traffic_light_properties.h b/include/MantleAPI/Traffic/traffic_light_properties.h index cb13783542537794dca77657338a937fb9438b02..3114a9c28c87572f01d5c0fc9f9c48dcea2b244d 100644 --- a/include/MantleAPI/Traffic/traffic_light_properties.h +++ b/include/MantleAPI/Traffic/traffic_light_properties.h @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2023, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,32 +18,33 @@ #include <MantleAPI/Common/time_utils.h> +#include <cstdint> #include <vector> namespace mantle_api { /// Specify the color of a traffic light bulb. -enum class TrafficLightBulbColor +enum class TrafficLightBulbColor : std::uint8_t { - kUnknown = 0, - kOther = 1, - kRed = 2, - kYellow = 3, - kGreen = 4, - kBlue = 5, - kWhite = 6 + kUnknown = 0, ///< The color of the traffic light bulb is unknown. + kOther, ///< The color of the traffic light bulb is known, but unspecified. + kRed, ///< The color of the traffic light bulb is red. + kYellow, ///< The color of the traffic light bulb is yellow. + kGreen, ///< The color of the traffic light bulb is green. + kBlue, ///< The color of the traffic light bulb is blue. + kWhite ///< The color of the traffic light bulb is white. }; /// Specify the mode of a traffic light bulb. -enum class TrafficLightBulbMode +enum class TrafficLightBulbMode : std::uint8_t { - kUnknown = 0, - kOther = 1, - kOff = 2, - kConstant = 3, - kFlashing = 4, - kCounting = 5 + kUnknown = 0, ///< The mode of the traffic light bulb is unknown. + kOther, ///< The mode of the traffic light bulb is known, but unspecified. + kOff, ///< The traffic light bulb is off. + kConstant, ///< The traffic light bulb is constantly glowing. + kFlashing, ///< The traffic light bulb is flashing. + kCounting ///< The traffic light bulb is counting, i.e. pedestrian traffic lights in the US. }; /// Definition of the traffic light state diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 263bd52d3833294186b635d385cae18ca0fd5a9f..2a67193e1a7451d89d027686a473ce7abb8d2607 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,21 +15,20 @@ CPMAddPackage( OPTIONS "INSTALL_GTEST ${MantleAPI_INSTALL_MOCKS}" "gtest_force_shared_crt ON" ) -# Generate a translation unit that includes all interface headers -list(TRANSFORM INTERFACE_HEADER_SET PREPEND "#include \"") -list(TRANSFORM INTERFACE_HEADER_SET APPEND "\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/verify_interface_header_set.cpp" ${INTERFACE_HEADER_SET}) - -add_executable(MantleAPITest) - -target_sources(MantleAPITest PUBLIC interface_test.cpp "${CMAKE_CURRENT_BINARY_DIR}/verify_interface_header_set.cpp") - -target_include_directories(MantleAPITest PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/test>) - -target_link_libraries(MantleAPITest PUBLIC MantleAPI::MantleAPI GTest::gmock_main) - -include(GoogleTest) -gtest_discover_tests(MantleAPITest) +# Generate translation units for the interface headers to ensure that they are self-contained. +# +# FIXME: Replace with CMake 3.24's VERIFY_INTERFACE_HEADER_SETS property when available. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +set(VERIFIY_HEADER_SET_SOURCE_FILES) +foreach(INTERFACE_HEADER IN LISTS INTERFACE_HEADER_SET) + get_filename_component(INTERFACE_HEADER_NAME ${INTERFACE_HEADER} NAME_WLE) + set(SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/verify_interface_header_set/${INTERFACE_HEADER_NAME}.cc") + file(WRITE "${SOURCE_FILE}" "#include \"${INTERFACE_HEADER}\"\n") + list(APPEND VERIFIY_HEADER_SET_SOURCE_FILES "${SOURCE_FILE}") +endforeach() +add_library(verify_interface_header_set OBJECT EXCLUDE_FROM_ALL) +target_sources(verify_interface_header_set PRIVATE "${VERIFIY_HEADER_SET_SOURCE_FILES}") +target_link_libraries(verify_interface_header_set PUBLIC MantleAPI::MantleAPI) add_subdirectory(MantleAPI) diff --git a/test/MantleAPI/CMakeLists.txt b/test/MantleAPI/CMakeLists.txt index 98b494b97e35f2c68a46bc878cb5c36ed9b86229..905d44fbf94bdb20d8aa385d0a2836666e99f902 100644 --- a/test/MantleAPI/CMakeLists.txt +++ b/test/MantleAPI/CMakeLists.txt @@ -10,3 +10,5 @@ add_subdirectory(Common) add_subdirectory(Execution) +add_subdirectory(Map) +add_subdirectory(Traffic) diff --git a/test/MantleAPI/Common/CMakeLists.txt b/test/MantleAPI/Common/CMakeLists.txt index 9920800bd3dbf30b6b20f750bede30a74655355f..3a0d5005631c524831b7f663861771af89637004 100644 --- a/test/MantleAPI/Common/CMakeLists.txt +++ b/test/MantleAPI/Common/CMakeLists.txt @@ -1,5 +1,5 @@ ################################################################################ -# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023-2024 Mercedes-Benz Tech Innovation GmbH # # This program and the accompanying materials are made available under the terms # of the Eclipse Public License 2.0 which is available at @@ -9,7 +9,25 @@ ################################################################################ add_executable(CommonTest) -target_sources(CommonTest PUBLIC floating_point_helper_test.cc logger_test.cc log_utils_test.cc clothoid_spline_test.cc trajectory_test.cc) +target_sources( + CommonTest + PUBLIC bounding_box_test.cc + clothoid_spline_test.cc + dimension_test.cc + meta_test.cc + floating_point_helper_test.cc + geometry_helper_test.cc + identifiable_test.cc + identifier_test.cc + logger_test.cc + orientation_test.cc + poly_line_test.cc + pose_test.cc + position_test.cc + spline_test.cc + trajectory_test.cc + vector_test.cc +) target_include_directories(CommonTest PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/test>) target_link_libraries(CommonTest PUBLIC MantleAPI::MantleAPI GTest::gmock_main) diff --git a/test/MantleAPI/Common/bounding_box_test.cc b/test/MantleAPI/Common/bounding_box_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..a6cef9625887fb2d948cc99aedacf414d5fa1ee6 --- /dev/null +++ b/test/MantleAPI/Common/bounding_box_test.cc @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/bounding_box.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; + +static_assert(std::is_trivial_v<BoundingBox>); + +TEST(BoundingBoxTest, OperatorEqual) +{ + constexpr const auto lhs = BoundingBox{{1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + constexpr const auto rhs = BoundingBox{{1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(BoundingBoxTest, OperatorNotEqual) +{ + constexpr const auto lhs = BoundingBox{{1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + constexpr const auto rhs = BoundingBox{{2_m, 2_m, 2_m}, {2_m, 2_m, 2_m}}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(BoundingBoxTest, OutputStreamOperator) +{ + const auto bbox = BoundingBox{{1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + + auto oss = std::ostringstream{}; + oss << bbox; + + ASSERT_EQ(oss.str(), "BoundingBox(.geometric_center=Vec3(.x=1 m, .y=1 m, .z=1 m), .dimension=Dimension3(.length=1 m, .width=1 m, .height=1 m))"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/dimension_test.cc b/test/MantleAPI/Common/dimension_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..4ccbd92618a6a72221198bb00e1eb55cbed2bbf9 --- /dev/null +++ b/test/MantleAPI/Common/dimension_test.cc @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/dimension.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; + +static_assert(std::is_trivial_v<Dimension3>); + +TEST(Dimension3Test, OperatorEqual) +{ + constexpr const auto lhs = Dimension3{1_m, 1_m, 1_m}; + constexpr const auto rhs = Dimension3{1_m, 1_m, 1_m}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(Dimension3Test, OperatorNotEqual) +{ + constexpr const auto lhs = Dimension3{1_m, 1_m, 1_m}; + constexpr const auto rhs = Dimension3{2_m, 2_m, 2_m}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(Dimension3Test, OutputStreamOperator) +{ + const auto dim = Dimension3{1_m, 1_m, 1_m}; + + auto oss = std::ostringstream{}; + oss << dim; + + ASSERT_EQ(oss.str(), "Dimension3(.length=1 m, .width=1 m, .height=1 m)"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/floating_point_helper_test.cc b/test/MantleAPI/Common/floating_point_helper_test.cc index ef9922aec0469aeb6ca47f370388ec8b7403849b..2915fab412ab6ed3dddd7760efc05e3c98643bbf 100644 --- a/test/MantleAPI/Common/floating_point_helper_test.cc +++ b/test/MantleAPI/Common/floating_point_helper_test.cc @@ -14,13 +14,11 @@ #include <units.h> #include <limits> +#include <tuple> -namespace +namespace mantle_api { -using mantle_api::AlmostEqual; -using mantle_api::GreaterOrEqual; -using mantle_api::LessOrEqual; using units::length::meter_t; // @@ -82,6 +80,19 @@ static_assert(LessOrEqual(-kDoubleInfinity, kDoubleLowest)); static_assert(LessOrEqual(kDoubleLargeWithFractional, kDoubleLarge, kDoubleCustomEpsilon)); static_assert(!LessOrEqual(kDoubleLargeWithFractional, kDoubleLarge, kDoubleCustomEpsilon, true)); +// AlmostEqual with tuples +static_assert(AlmostEqual(std::tie(kDoubleZero), std::tie(kDoubleZero))); +static_assert(AlmostEqual(std::tie(kDoubleZero, kDoubleZero), std::tie(kDoubleZero, kDoubleZero))); +static_assert(AlmostEqual(std::tie(kDoubleZero, kDoubleZero, kDoubleZero), std::tie(kDoubleZero, kDoubleZero, kDoubleZero))); + +static_assert(!AlmostEqual(std::tie(kDoubleMax), std::tie(kDoubleZero))); +static_assert(!AlmostEqual(std::tie(kDoubleZero, kDoubleMax), std::tie(kDoubleZero, kDoubleZero))); +static_assert(!AlmostEqual(std::tie(kDoubleZero, kDoubleZero, kDoubleMax), std::tie(kDoubleZero, kDoubleZero, kDoubleZero))); + +static_assert(AlmostEqual(std::tie(kDoubleZero), std::tie(kDoubleZero), kDoubleCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kDoubleZero, kDoubleZero), std::tie(kDoubleZero, kDoubleZero), kDoubleCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kDoubleZero, kDoubleZero, kDoubleZero), std::tie(kDoubleZero, kDoubleZero, kDoubleZero), kDoubleCustomEpsilon, true)); + // // float // @@ -141,6 +152,19 @@ static_assert(LessOrEqual(-kFloatInfinity, kFloatLowest)); static_assert(LessOrEqual(kFloatLargeWithFractional, kFloatLarge, kFloatCustomEpsilon)); static_assert(!LessOrEqual(kFloatLargeWithFractional, kFloatLarge, kFloatCustomEpsilon, true)); +// AlmostEqual with tuples +static_assert(AlmostEqual(std::tie(kFloatZero), std::tie(kFloatZero))); +static_assert(AlmostEqual(std::tie(kFloatZero, kFloatZero), std::tie(kFloatZero, kFloatZero))); +static_assert(AlmostEqual(std::tie(kFloatZero, kFloatZero, kFloatZero), std::tie(kFloatZero, kFloatZero, kFloatZero))); + +static_assert(!AlmostEqual(std::tie(kFloatMax), std::tie(kFloatZero))); +static_assert(!AlmostEqual(std::tie(kFloatZero, kFloatMax), std::tie(kFloatZero, kFloatZero))); +static_assert(!AlmostEqual(std::tie(kFloatZero, kFloatZero, kFloatMax), std::tie(kFloatZero, kFloatZero, kFloatZero))); + +static_assert(AlmostEqual(std::tie(kFloatZero), std::tie(kFloatZero), kFloatCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kFloatZero, kFloatZero), std::tie(kFloatZero, kFloatZero), kFloatCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kFloatZero, kFloatZero, kFloatZero), std::tie(kFloatZero, kFloatZero, kFloatZero), kFloatCustomEpsilon, true)); + // // meter_t // @@ -200,4 +224,22 @@ static_assert(LessOrEqual(-kMeterInfinity, kMeterLowest)); static_assert(LessOrEqual(kMeterLargeWithFractional, kMeterLarge, kMeterCustomEpsilon)); static_assert(!LessOrEqual(kMeterLargeWithFractional, kMeterLarge, kMeterCustomEpsilon, true)); -} // namespace +// AlmostEqual with tuples +static_assert(AlmostEqual(std::tie(kMeterZero), std::tie(kMeterZero))); +static_assert(AlmostEqual(std::tie(kMeterZero, kMeterZero), std::tie(kMeterZero, kMeterZero))); +static_assert(AlmostEqual(std::tie(kMeterZero, kMeterZero, kMeterZero), std::tie(kMeterZero, kMeterZero, kMeterZero))); + +static_assert(!AlmostEqual(std::tie(kMeterMax), std::tie(kMeterZero))); +static_assert(!AlmostEqual(std::tie(kMeterZero, kMeterMax), std::tie(kMeterZero, kMeterZero))); +static_assert(!AlmostEqual(std::tie(kMeterZero, kMeterZero, kMeterMax), std::tie(kMeterZero, kMeterZero, kMeterZero))); + +static_assert(AlmostEqual(std::tie(kMeterZero), std::tie(kMeterZero), kMeterCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kMeterZero, kMeterZero), std::tie(kMeterZero, kMeterZero), kMeterCustomEpsilon, true)); +static_assert(AlmostEqual(std::tie(kMeterZero, kMeterZero, kMeterZero), std::tie(kMeterZero, kMeterZero, kMeterZero), kMeterCustomEpsilon, true)); + +// AlmostEqual with tuples of different types +static_assert(AlmostEqual(std::tie(kDoubleZero, kFloatZero, kMeterZero), std::tie(kDoubleZero, kFloatZero, kMeterZero))); +static_assert(AlmostEqual(std::tie(kMeterZero, kDoubleZero, kFloatZero), std::tie(kMeterZero, kDoubleZero, kFloatZero), kDoubleCustomEpsilon)); +static_assert(AlmostEqual(std::tie(kFloatZero, kMeterZero, kDoubleZero), std::tie(kFloatZero, kMeterZero, kDoubleZero), kDoubleCustomEpsilon)); + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/geometry_helper_test.cc b/test/MantleAPI/Common/geometry_helper_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..122e7647fdd4d7611f70a1cb17fe57826f27f540 --- /dev/null +++ b/test/MantleAPI/Common/geometry_helper_test.cc @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <units.h> + +#include <vector> + +#include "MantleAPI/Common/i_geometry_helper.h" +#include "MantleAPI/Common/mock_geometry_helper.h" +#include "MantleAPI/Common/orientation.h" +#include "MantleAPI/Common/vector.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class GeometryHelperTest : public testing::Test +{ +protected: + MockGeometryHelper mock_geometry_helper_; + IGeometryHelper& geometry_helper_{mock_geometry_helper_}; +}; + +TEST_F(GeometryHelperTest, TranslateGlobalPositionLocally) +{ + static const auto kGlobalPosition = Vec3<units::length::meter_t>{}; + static const auto kLocalOrientation = Orientation3<units::angle::radian_t>{}; + static const auto kLocalTranslation = Vec3<units::length::meter_t>{}; + static const auto kReturnValue = Vec3<units::length::meter_t>{}; + + EXPECT_CALL(mock_geometry_helper_, TranslateGlobalPositionLocally(_, _, _)) + .Times(1) + .WillOnce(Return(kReturnValue)); + + std::ignore = geometry_helper_.TranslateGlobalPositionLocally(kGlobalPosition, kLocalOrientation, kLocalTranslation); +} + +TEST_F(GeometryHelperTest, TransformPolylinePointsFromWorldToLocal) +{ + static const auto kPolylinePoints = std::vector<Vec3<units::length::meter_t>>{}; + static const auto kLocalOrigin = Vec3<units::length::meter_t>{}; + static const auto kLocalOrientation = Orientation3<units::angle::radian_t>{}; + static const auto kReturnValue = std::vector<Vec3<units::length::meter_t>>{}; + + EXPECT_CALL(mock_geometry_helper_, TransformPolylinePointsFromWorldToLocal(_, _, _)) + .Times(1) + .WillOnce(Return(kReturnValue)); + + std::ignore = geometry_helper_.TransformPolylinePointsFromWorldToLocal(kPolylinePoints, kLocalOrigin, kLocalOrientation); +} + +TEST_F(GeometryHelperTest, TransformPositionFromWorldToLocal) +{ + static const auto kWorldPosition = Vec3<units::length::meter_t>{}; + static const auto kLocalOrigin = Vec3<units::length::meter_t>{}; + static const auto kLocalOrientation = Orientation3<units::angle::radian_t>{}; + static const auto kReturnValue = Vec3<units::length::meter_t>{}; + + EXPECT_CALL(mock_geometry_helper_, TransformPositionFromWorldToLocal(_, _, _)) + .Times(1) + .WillOnce(Return(kReturnValue)); + + std::ignore = geometry_helper_.TransformPositionFromWorldToLocal(kWorldPosition, kLocalOrigin, kLocalOrientation); +} + +TEST_F(GeometryHelperTest, AreOrientedSimilarly) +{ + static const auto kOrientation1 = Orientation3<units::angle::radian_t>{}; + static const auto kOrientation2 = Orientation3<units::angle::radian_t>{}; + static const auto kReturnValue = true; + + EXPECT_CALL(mock_geometry_helper_, AreOrientedSimilarly(_, _)) + .Times(1) + .WillOnce(Return(kReturnValue)); + + std::ignore = geometry_helper_.AreOrientedSimilarly(kOrientation1, kOrientation2); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/identifiable_test.cc b/test/MantleAPI/Common/identifiable_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..b36cdf06fded47cc7169f171b7a55b30944b7370 --- /dev/null +++ b/test/MantleAPI/Common/identifiable_test.cc @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <string> +#include <tuple> +#include <utility> + +#include "MantleAPI/Common/i_identifiable.h" +#include "MantleAPI/Common/mock_identifiable.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; +using testing::ReturnRef; + +class IdentifiableTest : public testing::Test +{ +protected: + MockIdentifiable mock_identifiable_; + IIdentifiable& identifiable_{mock_identifiable_}; +}; + +TEST_F(IdentifiableTest, GetUniqueId) +{ + EXPECT_CALL(std::as_const(mock_identifiable_), GetUniqueId()) + .Times(1) + .WillOnce(Return(UniqueId{})); + + std::ignore = std::as_const(identifiable_).GetUniqueId(); +} + +TEST_F(IdentifiableTest, SetName) +{ + EXPECT_CALL(mock_identifiable_, SetName(_)) + .Times(1); + + identifiable_.SetName({}); +} + +TEST_F(IdentifiableTest, GetName) +{ + const auto default_string = std::string{"default_string"}; + + EXPECT_CALL(std::as_const(mock_identifiable_), GetName()) + .Times(1) + .WillOnce(ReturnRef(default_string)); + + std::ignore = std::as_const(identifiable_).GetName(); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/identifier_test.cc b/test/MantleAPI/Common/identifier_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a664260e73ef4f2922c0b19bffa8a30b6928d41 --- /dev/null +++ b/test/MantleAPI/Common/identifier_test.cc @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/identifier.h" + +#include <gtest/gtest.h> + +#include <cstdint> +#include <functional> +#include <sstream> +#include <type_traits> +#include <utility> + +namespace mantle_api +{ + +using TestIdentifier = Identifier<std::uint64_t, struct TestIdentifierTag>; + +static_assert(std::is_nothrow_default_constructible_v<TestIdentifier>); +static_assert(std::is_nothrow_constructible_v<TestIdentifier, TestIdentifier::ValueType>); +static_assert(std::is_nothrow_copy_constructible_v<TestIdentifier>); +static_assert(std::is_nothrow_move_constructible_v<TestIdentifier>); +static_assert(std::is_nothrow_copy_assignable_v<TestIdentifier>); +static_assert(std::is_nothrow_move_assignable_v<TestIdentifier>); +static_assert(std::is_nothrow_destructible_v<TestIdentifier>); +static_assert(std::is_nothrow_swappable_v<TestIdentifier>); + +TEST(IdentifierTest, DefaultConstruction) +{ + constexpr auto id = TestIdentifier{}; + + EXPECT_EQ(id, TestIdentifier::kInvalid); + + static_assert(id == TestIdentifier::kInvalid); +} + +TEST(IdentifierTest, Construction) +{ + constexpr auto id = TestIdentifier{1}; + + EXPECT_EQ(id, 1); + + static_assert(id == 1); +} + +TEST(IdentifierTest, CopyConstruction) +{ + constexpr auto id1 = TestIdentifier{1}; + constexpr auto id2 = TestIdentifier{id1}; + + EXPECT_EQ(id2, id1); + + static_assert(id2 == id1); +} + +TEST(IdentifierTest, MoveConstruction) +{ + auto id1 = TestIdentifier{1}; + const auto id2 = TestIdentifier{std::move(id1)}; + + EXPECT_EQ(id1, TestIdentifier::kInvalid); // NOLINT(bugprone-use-after-move) + EXPECT_EQ(id2, 1); +} + +TEST(IdentifierTest, CopyAssignment) +{ + const auto id1 = TestIdentifier{1}; + const auto id2 = id1; + + EXPECT_EQ(id1, 1); + EXPECT_EQ(id2, 1); +} + +TEST(IdentifierTest, NonConstCopyAssignment) +{ + auto id1 = TestIdentifier{1}; + auto id2 = id1; + + EXPECT_EQ(id1, 1); + EXPECT_EQ(id2, 1); +} + +TEST(IdentifierTest, MoveAssignment) +{ + auto id1 = TestIdentifier{1}; + auto id2 = TestIdentifier{2}; + id2 = std::move(id1); + + EXPECT_EQ(id1, TestIdentifier::kInvalid); // NOLINT(bugprone-use-after-move) + EXPECT_EQ(id2, 1); +} + +TEST(IdentifierTest, Value) +{ + constexpr auto id = TestIdentifier{1}; + constexpr auto value = id.Value(); + + EXPECT_EQ(id, value); + + static_assert(id == value); +} + +TEST(IdentifierTest, ConversionOperator) +{ + constexpr auto id = TestIdentifier{1}; + constexpr auto value = static_cast<TestIdentifier::ValueType>(id); + + EXPECT_EQ(id.Value(), value); + + static_assert(id.Value() == value); +} + +TEST(IdentifierTest, HasValue) +{ + constexpr auto id = TestIdentifier{1}; + constexpr auto has_value = id.HasValue(); + + EXPECT_TRUE(has_value); + EXPECT_TRUE(id); + + static_assert(has_value); + static_assert(id); +} + +TEST(IdentifierTest, HasNoValue) +{ + constexpr auto id = TestIdentifier{}; + constexpr auto has_value = id.HasValue(); + + EXPECT_FALSE(has_value); + EXPECT_FALSE(id); + + static_assert(!has_value); + static_assert(!id); +} + +TEST(IdentifierTest, AssignmentOperatorValueType) +{ + auto id = TestIdentifier{}; + id = 1; + + EXPECT_EQ(id, 1); +} + +TEST(IdentifierTest, OperatorEqual) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{1}; + + EXPECT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(IdentifierTest, OperatorNotEqual) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{2}; + + EXPECT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(IdentifierTest, OperatorEqualValueType) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{1}; + + EXPECT_EQ(lhs, rhs.Value()); + EXPECT_EQ(lhs.Value(), rhs); + + static_assert(lhs == rhs.Value()); + static_assert(lhs.Value() == rhs); +} + +TEST(IdentifierTest, OperatorNotEqualValueType) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{2}; + + EXPECT_NE(lhs, rhs.Value()); + EXPECT_NE(lhs.Value(), rhs); + + static_assert(lhs != rhs.Value()); + static_assert(lhs.Value() != rhs); +} + +TEST(IdentifierTest, OperatorLessThan) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{2}; + + EXPECT_LT(lhs, rhs); + + static_assert(lhs < rhs); +} + +TEST(IdentifierTest, OperatorLessThanWithValueType) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{2}; + + EXPECT_LT(lhs, rhs.Value()); + + static_assert(lhs < rhs.Value()); +} + +TEST(IdentifierTest, OperatorGreaterThan) +{ + constexpr auto lhs = TestIdentifier{2}; + constexpr auto rhs = TestIdentifier{1}; + + EXPECT_GT(lhs, rhs); + + static_assert(lhs > rhs); +} + +TEST(IdentifierTest, OperatorGreaterThanWithValueType) +{ + constexpr auto lhs = TestIdentifier{2}; + constexpr auto rhs = TestIdentifier{1}; + + EXPECT_GT(lhs, rhs.Value()); + + static_assert(lhs > rhs.Value()); +} + +TEST(IdentifierTest, OperatorLessOrEqual) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{1}; + constexpr auto rhs_2 = TestIdentifier{2}; + + EXPECT_LE(lhs, rhs); + EXPECT_LE(lhs, rhs_2); + + static_assert(lhs <= rhs); + static_assert(lhs <= rhs_2); +} + +TEST(IdentifierTest, OperatorLessOrEqualWithValueType) +{ + constexpr auto lhs = TestIdentifier{1}; + constexpr auto rhs = TestIdentifier{1}; + constexpr auto rhs_2 = TestIdentifier{2}; + + EXPECT_LE(lhs, rhs.Value()); + EXPECT_LE(lhs, rhs_2.Value()); + + static_assert(lhs <= rhs.Value()); + static_assert(lhs <= rhs_2.Value()); +} + +TEST(IdentifierTest, OperatorGreaterOrEqual) +{ + constexpr auto lhs = TestIdentifier{2}; + constexpr auto rhs = TestIdentifier{2}; + constexpr auto rhs_2 = TestIdentifier{1}; + + EXPECT_GE(lhs, rhs); + EXPECT_GE(lhs, rhs_2); + + static_assert(lhs >= rhs); + static_assert(lhs >= rhs_2); +} + +TEST(IdentifierTest, OperatorGreaterOrEqualWithValueType) +{ + constexpr auto lhs = TestIdentifier{2}; + constexpr auto rhs = TestIdentifier{2}; + constexpr auto rhs_2 = TestIdentifier{1}; + + EXPECT_GE(lhs, rhs.Value()); + EXPECT_GE(lhs, rhs_2.Value()); + + static_assert(lhs >= rhs.Value()); + static_assert(lhs >= rhs_2.Value()); +} + +TEST(IdentifierTest, PrefixIncrement) +{ + auto id = TestIdentifier{1}; + + EXPECT_EQ(++id, 2); +} + +TEST(IdentifierTest, PostfixIncrement) +{ + auto id = TestIdentifier{1}; + + EXPECT_EQ(id++, 1); + EXPECT_EQ(id, 2); +} + +TEST(IdentifierTest, Add) +{ + constexpr auto id1 = TestIdentifier{1}; + constexpr auto id2 = TestIdentifier{1}; + + const auto id3 = id1 + id2; + + EXPECT_EQ(id3, 2); +} + +TEST(IdentifierTest, Swap) +{ + auto id1 = TestIdentifier{1}; + auto id2 = TestIdentifier{2}; + + std::swap(id1, id2); + + EXPECT_EQ(id1, 2); + EXPECT_EQ(id2, 1); +} + +TEST(IdentifierTest, OutputStreamOperator) +{ + constexpr auto id = TestIdentifier{1}; + + std::ostringstream oss; + oss << id; + + EXPECT_STREQ(oss.str().c_str(), "1"); +} + +TEST(IdentifierTest, Hash) +{ + constexpr auto id = TestIdentifier{1}; + const auto hash = std::hash<TestIdentifier>{}(id); + + EXPECT_EQ(hash, std::hash<TestIdentifier::ValueType>{}(id.Value())); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/log_utils_test.cc b/test/MantleAPI/Common/log_utils_test.cc deleted file mode 100644 index 7a376fa284a39c1f7a542aae7def849bf72f7e58..0000000000000000000000000000000000000000 --- a/test/MantleAPI/Common/log_utils_test.cc +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ - -#include "MantleAPI/Common/log_utils.h" - -#include <gtest/gtest.h> - -#include <limits> -#include <sstream> -#include <type_traits> - -#include "MantleAPI/Common/i_logger.h" - -namespace -{ - -using mantle_api::LogLevel; -using mantle_api::log_utils::ToStringView; - -static_assert(ToStringView(LogLevel::kTrace) == "Trace"); -static_assert(ToStringView(LogLevel::kDebug) == "Debug"); -static_assert(ToStringView(LogLevel::kInfo) == "Info"); -static_assert(ToStringView(LogLevel::kWarning) == "Warning"); -static_assert(ToStringView(LogLevel::kError) == "Error"); -static_assert(ToStringView(LogLevel::kCritical) == "Critical"); - -TEST(LogUtilsTest, ToStringView) -{ - ASSERT_STREQ(ToStringView(LogLevel::kTrace).data(), "Trace"); - ASSERT_STREQ(ToStringView(LogLevel::kDebug).data(), "Debug"); - ASSERT_STREQ(ToStringView(LogLevel::kInfo).data(), "Info"); - ASSERT_STREQ(ToStringView(LogLevel::kWarning).data(), "Warning"); - ASSERT_STREQ(ToStringView(LogLevel::kError).data(), "Error"); - ASSERT_STREQ(ToStringView(LogLevel::kCritical).data(), "Critical"); - - ASSERT_STREQ(ToStringView(static_cast<LogLevel>(std::numeric_limits<std::underlying_type_t<LogLevel>>::min())).data(), "Log level out of range"); - ASSERT_STREQ(ToStringView(static_cast<LogLevel>(std::numeric_limits<std::underlying_type_t<LogLevel>>::max())).data(), "Log level out of range"); -} - -TEST(LogUtilsTest, OutputStreamOperator) -{ - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kTrace); - ASSERT_STREQ(stream.str().c_str(), "Trace"); - } - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kDebug); - ASSERT_STREQ(stream.str().c_str(), "Debug"); - } - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kInfo); - ASSERT_STREQ(stream.str().c_str(), "Info"); - } - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kWarning); - ASSERT_STREQ(stream.str().c_str(), "Warning"); - } - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kError); - ASSERT_STREQ(stream.str().c_str(), "Error"); - } - { - auto stream = std::ostringstream{}; - ASSERT_NO_THROW(stream << LogLevel::kCritical); - ASSERT_STREQ(stream.str().c_str(), "Critical"); - } -} - -} // namespace diff --git a/test/MantleAPI/Common/logger_test.cc b/test/MantleAPI/Common/logger_test.cc index d9f780ae4a20de23c46845c7dad0af222ad816a1..62402add9500a108a357b468b3d58e456b46a504 100644 --- a/test/MantleAPI/Common/logger_test.cc +++ b/test/MantleAPI/Common/logger_test.cc @@ -11,15 +11,16 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <utility> + #include "MantleAPI/Common/i_logger.h" +#include "MantleAPI/Common/meta.h" #include "MantleAPI/Common/mock_logger.h" -namespace +namespace mantle_api { -using mantle_api::LogLevel; using testing::_; -using testing::Const; using testing::Return; class LoggerTest : public testing::Test @@ -30,16 +31,16 @@ protected: mock_logger_.DelegateToFake(); } - mantle_api::MockLogger mock_logger_; - mantle_api::ILogger &logger_{mock_logger_}; + MockLogger mock_logger_; + ILogger &logger_{mock_logger_}; }; TEST_F(LoggerTest, GetCurrentLogLevel) { - EXPECT_CALL(Const(mock_logger_), GetCurrentLogLevel()) // - .Times(1) // + EXPECT_CALL(std::as_const(mock_logger_), GetCurrentLogLevel()) + .Times(1) .WillRepeatedly(Return(LogLevel::kTrace)); - ASSERT_NO_THROW(std::ignore = logger_.GetCurrentLogLevel()); + ASSERT_NO_THROW(std::ignore = std::as_const(logger_).GetCurrentLogLevel()); } TEST_F(LoggerTest, Log) @@ -84,4 +85,14 @@ TEST_F(LoggerTest, Critical) ASSERT_NO_THROW(logger_.Critical("LoggerTest_Critical")); } -} // namespace +TEST_F(LoggerTest, LogLevel) +{ + static_assert(meta::enum_to_string(LogLevel::kTrace) == "Trace"); + static_assert(meta::enum_to_string(LogLevel::kDebug) == "Debug"); + static_assert(meta::enum_to_string(LogLevel::kInfo) == "Info"); + static_assert(meta::enum_to_string(LogLevel::kWarning) == "Warning"); + static_assert(meta::enum_to_string(LogLevel::kError) == "Error"); + static_assert(meta::enum_to_string(LogLevel::kCritical) == "Critical"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/meta_test.cc b/test/MantleAPI/Common/meta_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..c29235547fbb3e1b881b021b6c6b1de197494cd1 --- /dev/null +++ b/test/MantleAPI/Common/meta_test.cc @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/meta.h" + +#include <gtest/gtest.h> + +#include <array> +#include <cstdint> +#include <sstream> + +namespace mantle_api +{ + +inline constexpr auto kEnumSize = 3U; + +enum class EnumUnsigned : std::uint8_t +{ + k1st = 0, + k2nd, + k3rd +}; + +template <> +struct meta::info<EnumUnsigned> +{ + [[nodiscard]] static constexpr std::array<enum_info<EnumUnsigned>, kEnumSize> get_enumerators() noexcept + { + return {{{EnumUnsigned::k1st, "1st"}, + {EnumUnsigned::k2nd, "2nd"}, + {EnumUnsigned::k3rd, "3rd"}}}; + } +}; + +enum class EnumSigned : std::int8_t +{ + k1st = -1, + k2nd, + k3rd +}; + +template <> +struct meta::info<EnumSigned> +{ + [[nodiscard]] static constexpr std::array<enum_info<EnumSigned>, kEnumSize> get_enumerators() noexcept + { + return {{{EnumSigned::k1st, "1st"}, + {EnumSigned::k2nd, "2nd"}, + {EnumSigned::k3rd, "3rd"}}}; + } +}; + +template <typename T> +class MetaTest : public testing::Test +{ +}; + +using EnumTypes = ::testing::Types<EnumUnsigned, EnumSigned>; +TYPED_TEST_SUITE(MetaTest, EnumTypes); + +TYPED_TEST(MetaTest, ValueOf) +{ + constexpr auto enumerators = meta::enumerators_of(TypeParam{}); + static_assert(meta::value_of(enumerators[0]) == TypeParam::k1st); + static_assert(meta::value_of(enumerators[1]) == TypeParam::k2nd); + static_assert(meta::value_of(enumerators[2]) == TypeParam::k3rd); +} + +TYPED_TEST(MetaTest, NameOf) +{ + constexpr auto enumerators = meta::enumerators_of(TypeParam{}); + static_assert(meta::name_of(enumerators[0]) == "1st"); + static_assert(meta::name_of(enumerators[1]) == "2nd"); + static_assert(meta::name_of(enumerators[2]) == "3rd"); +} + +TYPED_TEST(MetaTest, EnumeratorsOf) +{ + { + constexpr auto enumerators = meta::enumerators_of(TypeParam{}); + static_assert(enumerators.size() == kEnumSize); + } + { + constexpr auto enumerators = meta::enumerators_of<TypeParam>(); + static_assert(enumerators.size() == kEnumSize); + } +} + +TYPED_TEST(MetaTest, SizeOf) +{ + static_assert(meta::size_of(TypeParam{}) == kEnumSize); + static_assert(meta::size_of<TypeParam>() == kEnumSize); +} + +TYPED_TEST(MetaTest, EnumToString) +{ + static_assert(meta::enum_to_string(TypeParam::k1st) == "1st"); + static_assert(meta::enum_to_string(TypeParam::k2nd) == "2nd"); + static_assert(meta::enum_to_string(TypeParam::k3rd) == "3rd"); +} + +TYPED_TEST(MetaTest, EnumToStringOutOfRange) +{ + static_assert(meta::enum_to_string(static_cast<TypeParam>(-10)).empty()); + static_assert(meta::enum_to_string(static_cast<TypeParam>(10)).empty()); +} + +TYPED_TEST(MetaTest, StringToEnum) +{ + static_assert(meta::string_to_enum<TypeParam>("1st") == TypeParam::k1st); + static_assert(meta::string_to_enum<TypeParam>("2nd") == TypeParam::k2nd); + static_assert(meta::string_to_enum<TypeParam>("3rd") == TypeParam::k3rd); +} + +TYPED_TEST(MetaTest, StringToEnumUndefined) +{ + static_assert(!meta::string_to_enum<TypeParam>("Undef")); +} + +TYPED_TEST(MetaTest, StringToEnumEmpty) +{ + static_assert(!meta::string_to_enum<TypeParam>("")); +} + +TYPED_TEST(MetaTest, OutputStreamOperator) +{ + std::ostringstream oss; + + oss << TypeParam::k1st; + EXPECT_EQ(oss.str(), "1st"); + + oss.str(""); + oss << TypeParam::k2nd; + EXPECT_EQ(oss.str(), "2nd"); + + oss.str(""); + oss << TypeParam::k3rd; + EXPECT_EQ(oss.str(), "3rd"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/mock_geometry_helper.h b/test/MantleAPI/Common/mock_geometry_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..343c4e3ad1a5aea417878061d37c6c9401b71f33 --- /dev/null +++ b/test/MantleAPI/Common/mock_geometry_helper.h @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_COMMON_MOCK_GEOMETRY_HELPER_H +#define MANTLEAPI_COMMON_MOCK_GEOMETRY_HELPER_H + +#include <gmock/gmock.h> +#include <units.h> + +#include "MantleAPI/Common/i_geometry_helper.h" +#include "MantleAPI/Common/orientation.h" +#include "MantleAPI/Common/vector.h" + +namespace mantle_api +{ + +class MockGeometryHelper : public IGeometryHelper +{ +public: + MOCK_METHOD(Vec3<units::length::meter_t>, TranslateGlobalPositionLocally, (const Vec3<units::length::meter_t>& global_position, const Orientation3<units::angle::radian_t>& local_orientation, const Vec3<units::length::meter_t>& local_translation), (const, override)); + MOCK_METHOD(std::vector<Vec3<units::length::meter_t>>, TransformPolylinePointsFromWorldToLocal, (const std::vector<Vec3<units::length::meter_t>>& polyline_points, const Vec3<units::length::meter_t>& local_origin, const Orientation3<units::angle::radian_t>& local_orientation), (const, override)); + MOCK_METHOD(Vec3<units::length::meter_t>, TransformPositionFromWorldToLocal, (const Vec3<units::length::meter_t>& world_position, const Vec3<units::length::meter_t>& local_origin, const Orientation3<units::angle::radian_t>& local_orientation), (const, override)); + MOCK_METHOD(bool, AreOrientedSimilarly, (const Orientation3<units::angle::radian_t>& orientation1, const Orientation3<units::angle::radian_t>& orientation2), (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_COMMON_MOCK_GEOMETRY_HELPER_H diff --git a/test/MantleAPI/Common/mock_identifiable.h b/test/MantleAPI/Common/mock_identifiable.h new file mode 100644 index 0000000000000000000000000000000000000000..f5e243cb075897221b9cd804341905e879320329 --- /dev/null +++ b/test/MantleAPI/Common/mock_identifiable.h @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_COMMON_MOCK_IDENTIFIABLE_H +#define MANTLEAPI_COMMON_MOCK_IDENTIFIABLE_H + +#include <gmock/gmock.h> + +#include "MantleAPI/Common/i_identifiable.h" + +namespace mantle_api +{ + +class MockIdentifiable : public IIdentifiable +{ +public: + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + MOCK_METHOD(const std::string&, GetName, (), (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_COMMON_MOCK_IDENTIFIABLE_H diff --git a/test/MantleAPI/Common/mock_logger.h b/test/MantleAPI/Common/mock_logger.h index 44e2b22ad6551dcfaf0e323b1257d3d3041b1e66..f9785248fd34e12dc227dc0c0f79c6b8def74f00 100644 --- a/test/MantleAPI/Common/mock_logger.h +++ b/test/MantleAPI/Common/mock_logger.h @@ -17,12 +17,11 @@ #include <ostream> #include "MantleAPI/Common/i_logger.h" -#include "MantleAPI/Common/log_utils.h" namespace mantle_api { -class MockLogger final : public ILogger +class MockLogger : public ILogger { public: MOCK_METHOD(LogLevel, GetCurrentLogLevel, (), (const, noexcept, override)); @@ -33,7 +32,7 @@ public: auto print = [](LogLevel level, std::string_view message) { std::cout << "[" - << level // use the ostream operator from log_utils + << level << "] " << std::quoted(message) << '\n'; }; diff --git a/test/MantleAPI/Common/orientation_test.cc b/test/MantleAPI/Common/orientation_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..b2b846df741dd0774d8cbe2631d952635f6feb7a --- /dev/null +++ b/test/MantleAPI/Common/orientation_test.cc @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/orientation.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_rad; +using Orientation3RadianType = Orientation3<units::angle::radian_t>; + +static_assert(std::is_trivial_v<Orientation3RadianType>); + +TEST(Orientation3Test, OperatorEqual) +{ + constexpr const auto lhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + constexpr const auto rhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(Orientation3Test, OperatorNotEqual) +{ + constexpr const auto lhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + constexpr const auto rhs = Orientation3RadianType{2_rad, 2_rad, 2_rad}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(Orientation3Test, Add) +{ + constexpr const auto lhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + constexpr const auto rhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + constexpr const auto expected_result = Orientation3RadianType{2_rad, 2_rad, 2_rad}; + + constexpr const auto result = lhs + rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Orientation3Test, Subtract) +{ + constexpr const auto lhs = Orientation3RadianType{2_rad, 2_rad, 2_rad}; + constexpr const auto rhs = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + constexpr const auto expected_result = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + + constexpr const auto result = lhs - rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Orientation3Test, OutputStreamOperator) +{ + const auto orientation = Orientation3RadianType{1_rad, 1_rad, 1_rad}; + + auto oss = std::ostringstream{}; + oss << orientation; + + ASSERT_EQ(oss.str(), "Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad)"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/poly_line_test.cc b/test/MantleAPI/Common/poly_line_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..ed17aede97ef0633cd8ec52f8acfcaf372a4d34c --- /dev/null +++ b/test/MantleAPI/Common/poly_line_test.cc @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/poly_line.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; +using ::units::literals::operator""_rad; +using ::units::literals::operator""_s; + +static_assert(std::is_aggregate_v<PolyLinePoint>); + +TEST(PolyLinePoint, OperatorEqual) +{ + constexpr const auto lhs = PolyLinePoint{{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}; + constexpr const auto rhs = PolyLinePoint{{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(PolyLinePoint, OperatorNotEqual) +{ + constexpr const auto lhs = PolyLinePoint{{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}; + constexpr const auto rhs = PolyLinePoint{{{2_m, 2_m, 2_m}, {2_rad, 2_rad, 2_rad}}, 2_s}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(PolyLinePoint, OutputStreamOperatorNoTime) +{ + const auto poly_line_point = PolyLinePoint{{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, std::nullopt}; + + auto oss = std::ostringstream{}; + oss << poly_line_point; + + ASSERT_EQ(oss.str(), "PolyLinePoint(.pose=Pose(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .orientation=Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad)), .time=0 s)"); +} + +TEST(PolyLinePoint, OutputStreamOperator) +{ + const auto poly_line_point = PolyLinePoint{{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}; + + auto oss = std::ostringstream{}; + oss << poly_line_point; + + ASSERT_EQ(oss.str(), "PolyLinePoint(.pose=Pose(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .orientation=Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad)), .time=1 s)"); +} + +TEST(PolyLine, OutputStreamOperatorEmpty) +{ + const auto poly_line = PolyLine{}; + + auto oss = std::ostringstream{}; + oss << poly_line; + + ASSERT_EQ(oss.str(), "PolyLine()"); +} + +TEST(PolyLine, OutputStreamOperatorOnePoint) +{ + const auto poly_line = PolyLine{ + {{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}, + }; + + auto oss = std::ostringstream{}; + oss << poly_line; + + ASSERT_EQ(oss.str(), "PolyLine([0]=PolyLinePoint(.pose=Pose(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .orientation=Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad)), .time=1 s))"); +} + +TEST(PolyLine, OutputStreamOperator) +{ + const auto poly_line = PolyLine{ + {{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}, 1_s}, + {{{2_m, 2_m, 2_m}, {2_rad, 2_rad, 2_rad}}, 2_s}}; + + auto oss = std::ostringstream{}; + oss << poly_line; + + ASSERT_EQ(oss.str(), + "PolyLine([0]=PolyLinePoint(.pose=Pose(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .orientation=Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad)), .time=1 s), [1]=PolyLinePoint(.pose=Pose(.position=Vec3(.x=2 m, .y=2 m, .z=2 m), .orientation=Orientation3(.yaw=2 rad, .pitch=2 rad, .roll=2 rad)), .time=2 s))"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/pose_test.cc b/test/MantleAPI/Common/pose_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..d80ead27cc860d8ee137a4e65eaa637d9a010a0f --- /dev/null +++ b/test/MantleAPI/Common/pose_test.cc @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/pose.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; +using ::units::literals::operator""_rad; + +static_assert(std::is_trivial_v<Pose>); + +TEST(PoseTest, OperatorEqual) +{ + constexpr const auto lhs = Pose{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}; + constexpr const auto rhs = Pose{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(PoseTest, OperatorNotEqual) +{ + constexpr const auto lhs = Pose{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}; + constexpr const auto rhs = Pose{{2_m, 2_m, 2_m}, {2_rad, 2_rad, 2_rad}}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(PoseTest, OutputStreamOperator) +{ + const auto pose = Pose{{1_m, 1_m, 1_m}, {1_rad, 1_rad, 1_rad}}; + + auto oss = std::ostringstream{}; + oss << pose; + + ASSERT_EQ(oss.str(), "Pose(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .orientation=Orientation3(.yaw=1 rad, .pitch=1 rad, .roll=1 rad))"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/position_test.cc b/test/MantleAPI/Common/position_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..5436c8d8248759ada74389554ac3cc210ef8c471 --- /dev/null +++ b/test/MantleAPI/Common/position_test.cc @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/position.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; +using ::units::literals::operator""_rad; + +/******************************************************************************* + * OpenDriveRoadPosition + *******************************************************************************/ +static_assert(std::is_aggregate_v<OpenDriveRoadPosition>); + +TEST(OpenDriveRoadPositionTest, OperatorEqual) +{ + auto lhs = OpenDriveRoadPosition{"Road1", 1_m, 1_m}; + auto rhs = OpenDriveRoadPosition{"Road1", 1_m, 1_m}; + + ASSERT_EQ(lhs, rhs); +} + +TEST(OpenDriveRoadPositionTest, OperatorNotEqual) +{ + auto lhs = OpenDriveRoadPosition{"Road1", 1_m, 1_m}; + auto rhs = OpenDriveRoadPosition{"Road2", 2_m, 2_m}; + + ASSERT_NE(lhs, rhs); +} + +TEST(OpenDriveRoadPositionTest, OutputStreamOperator) +{ + const auto position = OpenDriveRoadPosition{"Road1", 1_m, 1_m}; + + auto oss = std::ostringstream{}; + oss << position; + + ASSERT_EQ(oss.str(), "OpenDriveRoadPosition(.road=Road1, .s_offset=1 m, .t_offset=1 m)"); +} + +/******************************************************************************* + * OpenDriveLanePosition + *******************************************************************************/ +static_assert(std::is_aggregate_v<OpenDriveLanePosition>); + +TEST(OpenDriveLanePositionTest, OperatorEqual) +{ + auto lhs = OpenDriveLanePosition{"Road1", -1, 1_m, 1_m}; + auto rhs = OpenDriveLanePosition{"Road1", -1, 1_m, 1_m}; + + ASSERT_EQ(lhs, rhs); +} + +TEST(OpenDriveLanePositionTest, OperatorNotEqual) +{ + auto lhs = OpenDriveLanePosition{"Road1", -1, 1_m, 1_m}; + auto rhs = OpenDriveLanePosition{"Road2", -2, 2_m, 2_m}; + + ASSERT_NE(lhs, rhs); +} + +TEST(OpenDriveLanePositionTest, OutputStreamOperator) +{ + const auto position = OpenDriveLanePosition{"Road1", -1, 1_m, 1_m}; + + auto oss = std::ostringstream{}; + oss << position; + + ASSERT_EQ(oss.str(), "OpenDriveLanePosition(.road=Road1, .lane=-1, .s_offset=1 m, .t_offset=1 m)"); +} + +/******************************************************************************* + * LatLonPosition + *******************************************************************************/ +static_assert(std::is_trivial_v<LatLonPosition>); + +TEST(LatLonPositionTest, OperatorEqual) +{ + constexpr const auto lhs = LatLonPosition{1_rad, 1_rad}; + constexpr const auto rhs = LatLonPosition{1_rad, 1_rad}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(LatLonPositionTest, OperatorNotEqual) +{ + constexpr const auto lhs = LatLonPosition{1_rad, 1_rad}; + constexpr const auto rhs = LatLonPosition{2_rad, 2_rad}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(LatLonPositionTest, OutputStreamOperator) +{ + const auto position = LatLonPosition{1_rad, 1_rad}; + + auto oss = std::ostringstream{}; + oss << position; + + ASSERT_EQ(oss.str(), "LatLonPosition(.latitude=1 rad, .longitude=1 rad)"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/spline_test.cc b/test/MantleAPI/Common/spline_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..2a32297a14781a5bc3c79e0b8e43590b5cf81ad0 --- /dev/null +++ b/test/MantleAPI/Common/spline_test.cc @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/spline.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; +using ::units::literals::operator""_s; + +/******************************************************************************* + * SplineSegment + *******************************************************************************/ +using SplineSegmentMeterType = SplineSegment<units::length::meter_t>; +static_assert(std::is_trivial_v<SplineSegmentMeterType>); + +TEST(SplineSegmentTest, OperatorEqual) +{ + constexpr const auto lhs = SplineSegmentMeterType{ + {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + constexpr const auto rhs = SplineSegmentMeterType{ + {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(SplineSegmentTest, OperatorNotEqual) +{ + constexpr const auto lhs = SplineSegmentMeterType{ + {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + constexpr const auto rhs = SplineSegmentMeterType{ + {2_m, 2_m, 2_m}, {2_m, 2_m, 2_m}, {2_m, 2_m, 2_m}, {2_m, 2_m, 2_m}}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(SplineSegmentTest, OutputStreamOperator) +{ + const auto spline_segment = SplineSegmentMeterType{ + {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}, {1_m, 1_m, 1_m}}; + + auto oss = std::ostringstream{}; + oss << spline_segment; + + ASSERT_EQ(oss.str(), "SplineSegment(.a=Vec3(.x=1 m, .y=1 m, .z=1 m), .b=Vec3(.x=1 m, .y=1 m, .z=1 m), .c=Vec3(.x=1 m, .y=1 m, .z=1 m), .d=Vec3(.x=1 m, .y=1 m, .z=1 m))"); +} + +/******************************************************************************* + * SplineSection + *******************************************************************************/ +using SplineSectionMeterType = SplineSection<units::length::meter>; + +static_assert(std::is_trivial_v<SplineSectionMeterType>); +static_assert(std::is_trivial_v<SplineSectionMeterType::Polynomial>); + +TEST(SplineSectionTest, OperatorEqual) +{ + constexpr const auto a3_value = 1_m / (3_s * 3_s * 3_s); + constexpr const auto a2_value = 1_m / (2_s * 2_s); + constexpr const auto a1_value = 1_m / 1_s; + constexpr const auto a0_value = 1_m; + + constexpr const auto lhs = SplineSectionMeterType{1_s, 2_s, {a3_value, a2_value, a1_value, a0_value}}; + constexpr const auto rhs = SplineSectionMeterType{1_s, 2_s, {a3_value, a2_value, a1_value, a0_value}}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(SplineSectionTest, OperatorNotEqual) +{ + constexpr const auto lhs_a3_value = 1_m / (3_s * 3_s * 3_s); + constexpr const auto lhs_a2_value = 1_m / (2_s * 2_s); + constexpr const auto lhs_a1_value = 1_m / 1_s; + constexpr const auto lhs_a0_value = 1_m; + + constexpr const auto rhs_a3_value = 1_m / (4_s * 4_s * 4_s); + constexpr const auto rhs_a2_value = 1_m / (3_s * 3_s); + constexpr const auto rhs_a1_value = 1_m / 2_s; + constexpr const auto rhs_a0_value = 1_m; + + constexpr const auto lhs = SplineSectionMeterType{1_s, 2_s, {lhs_a3_value, lhs_a2_value, lhs_a1_value, lhs_a0_value}}; + constexpr const auto rhs = SplineSectionMeterType{2_s, 3_s, {rhs_a3_value, rhs_a2_value, rhs_a1_value, rhs_a0_value}}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(SplineSectionTest, OutputStreamOperator) +{ + const auto spline_section = SplineSectionMeterType{1_s, 2_s, {1_m / (3_s * 3_s * 3_s), 1_m / (2_s * 2_s), 1_m / 1_s, 1_m}}; + + auto oss = std::ostringstream{}; + oss << spline_section; + + ASSERT_EQ(oss.str(), "SplineSection(.start_time=1 s, .end_time=2 s, .polynomial=Polynomial(.a3=0.037037 m s^-3, .a2=0.25 m s^-2, .a1=1 m s^-1, .a0=1 m))"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/trajectory_test.cc b/test/MantleAPI/Common/trajectory_test.cc index 684315815fc8b59d863971d4f151587a5c77e115..a535bc84ff3dc9b38d0668228559932f7285ff19 100644 --- a/test/MantleAPI/Common/trajectory_test.cc +++ b/test/MantleAPI/Common/trajectory_test.cc @@ -1,4 +1,5 @@ /******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH * Copyright (c) 2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * This program and the accompanying materials are made @@ -8,12 +9,15 @@ * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -#include <MantleAPI/Common/trajectory.h> +#include "MantleAPI/Common/trajectory.h" + #include <gtest/gtest.h> +#include <units.h> #include <functional> #include <iostream> #include <sstream> +#include <type_traits> #include <variant> using units::literals::operator""_m; @@ -25,12 +29,41 @@ using mantle_api::ClothoidSpline; using mantle_api::PolyLine; using mantle_api::Trajectory; -namespace +namespace mantle_api { -class TrajectoryTest : public ::testing::Test + +static_assert(std::is_aggregate_v<Trajectory>); + +TEST(TrajectoryTest, OperatorEqual) +{ + const auto lhs = Trajectory{"name", {}, {}}; + const auto rhs = Trajectory{"name", {}, {}}; + + ASSERT_EQ(lhs, rhs); +} + +TEST(TrajectoryTest, OperatorNotEqual) +{ + const auto lhs = Trajectory{"name", {}, {}}; + const auto rhs = Trajectory{"other_name", {}, {}}; + + ASSERT_NE(lhs, rhs); +} + +TEST(TrajectoryTest, OutputStreamOperator) +{ + const auto trajectory = Trajectory{"name", {}, {}}; + + auto oss = std::ostringstream{}; + oss << trajectory; + + ASSERT_EQ(oss.str(), "Trajectory(.name=name, .type=PolyLine(), reference=0)"); +} + +class TrajectoryTestFixture : public ::testing::Test { public: - TrajectoryTest() + TrajectoryTestFixture() { clothoid_spline_.segments.push_back({0.0_curv, 6.6_curv, @@ -60,7 +93,7 @@ protected: Trajectory trajectory_right_; }; -TEST_F(TrajectoryTest, GivenTrajectories_WhenTrajectoriesHaveEqualParameters_ThenTrajectoryEqualOperatorReturnsTrue) +TEST_F(TrajectoryTestFixture, GivenTrajectories_WhenTrajectoriesHaveEqualParameters_ThenTrajectoryEqualOperatorReturnsTrue) { trajectory_left_.type = clothoid_spline_; trajectory_right_ = trajectory_left_; @@ -97,7 +130,7 @@ void ChangeReference(Trajectory& trajectory) trajectory.reference = mantle_api::TrajectoryReferencePoint::kRearAxle; } -class TrajectoryTestParam : public ::testing::WithParamInterface<ChangeParam>, public TrajectoryTest +class TrajectoryTestParam : public ::testing::WithParamInterface<ChangeParam>, public TrajectoryTestFixture { }; @@ -121,7 +154,7 @@ TEST_P(TrajectoryTestParam, GivenTrajectories_WhenTrajectoriesHaveDifferentParam EXPECT_FALSE(trajectory_left_ == trajectory_right_); } -TEST_F(TrajectoryTest, GivenTrajectoryWithNoType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) +TEST_F(TrajectoryTestFixture, GivenTrajectoryWithNoType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) { std::stringstream actual_os; auto output_to_stream = [](std::ostream& os, Trajectory& trajectory) @@ -132,7 +165,7 @@ TEST_F(TrajectoryTest, GivenTrajectoryWithNoType_WhenOutputToStream_ThenNoExcept EXPECT_GT(actual_os.str().size(), 0); } -TEST_F(TrajectoryTest, GivenTrajectoryWithPolylineType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) +TEST_F(TrajectoryTestFixture, GivenTrajectoryWithPolylineType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) { std::stringstream actual_os; trajectory_left_.type = polyline_; @@ -144,7 +177,7 @@ TEST_F(TrajectoryTest, GivenTrajectoryWithPolylineType_WhenOutputToStream_ThenNo EXPECT_GT(actual_os.str().size(), 0); } -TEST_F(TrajectoryTest, GivenTrajectoryWithClothoidSplineType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) +TEST_F(TrajectoryTestFixture, GivenTrajectoryWithClothoidSplineType_WhenOutputToStream_ThenNoExceptionAndOutputNotEmpty) { std::stringstream actual_os; trajectory_left_.type = clothoid_spline_; @@ -155,4 +188,5 @@ TEST_F(TrajectoryTest, GivenTrajectoryWithClothoidSplineType_WhenOutputToStream_ ASSERT_NO_THROW(output_to_stream(actual_os, trajectory_left_)); EXPECT_GT(actual_os.str().size(), 0); } -} // namespace + +} // namespace mantle_api diff --git a/test/MantleAPI/Common/vector_test.cc b/test/MantleAPI/Common/vector_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..2898144524dcfd1a0aa2976f6b63a39335900059 --- /dev/null +++ b/test/MantleAPI/Common/vector_test.cc @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Common/vector.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <sstream> +#include <type_traits> + +namespace mantle_api +{ + +using ::units::literals::operator""_m; +using Vector3MeterType = Vec3<units::length::meter_t>; + +static_assert(std::is_trivial_v<Vector3MeterType>); + +TEST(Vec3Test, OperatorEqual) +{ + constexpr const auto lhs = Vector3MeterType{1_m, 1_m, 1_m}; + constexpr const auto rhs = Vector3MeterType{1_m, 1_m, 1_m}; + + ASSERT_EQ(lhs, rhs); + + static_assert(lhs == rhs); +} + +TEST(Vec3Test, OperatorNotEqual) +{ + constexpr const auto lhs = Vector3MeterType{1_m, 1_m, 1_m}; + constexpr const auto rhs = Vector3MeterType{2_m, 2_m, 2_m}; + + ASSERT_NE(lhs, rhs); + + static_assert(lhs != rhs); +} + +TEST(Vec3Test, Length) +{ + constexpr const auto vector = Vector3MeterType{3_m, 4_m, 0_m}; + + const auto length = vector.Length(); + + ASSERT_EQ(length, 5_m); +} + +TEST(Vec3Test, OperatorMinus) +{ + constexpr const auto vector = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto expected_result = Vector3MeterType{-1_m, -2_m, -3_m}; + + constexpr const auto result = -vector; + + ASSERT_EQ(result, expected_result); +} + +TEST(Vec3Test, Add) +{ + constexpr const auto lhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto rhs = Vector3MeterType{4_m, 5_m, 6_m}; + constexpr const auto expected_result = Vector3MeterType{5_m, 7_m, 9_m}; + + constexpr const auto result = lhs + rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Vec3Test, Subtract) +{ + constexpr const auto lhs = Vector3MeterType{4_m, 5_m, 6_m}; + constexpr const auto rhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto expected_result = Vector3MeterType{3_m, 3_m, 3_m}; + + constexpr const auto result = lhs - rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Vec3Test, MultiplyVectorByScalar) +{ + constexpr const auto lhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto rhs = 2.0; + constexpr const auto expected_result = Vector3MeterType{2_m, 4_m, 6_m}; + + constexpr const auto result = lhs * rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Vec3Test, MultiplyScalarByVector) +{ + constexpr const auto lhs = 2.0; + constexpr const auto rhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto expected_result = Vector3MeterType{2_m, 4_m, 6_m}; + + constexpr const auto vec_mul = lhs * rhs; + + ASSERT_EQ(vec_mul, expected_result); + + static_assert(vec_mul == expected_result); +} + +TEST(Vec3Test, DivideVectorByScalar) +{ + constexpr const auto lhs = Vector3MeterType{2_m, 4_m, 6_m}; + constexpr const auto rhs = 2.0; + constexpr const auto expected_result = Vector3MeterType{1_m, 2_m, 3_m}; + + constexpr const auto result = lhs / rhs; + + ASSERT_EQ(result, expected_result); + + static_assert(result == expected_result); +} + +TEST(Vec3Test, AddAssign) +{ + auto lhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto rhs = Vector3MeterType{4_m, 5_m, 6_m}; + constexpr const auto expected_result = Vector3MeterType{5_m, 7_m, 9_m}; + + lhs += rhs; + + ASSERT_EQ(lhs, expected_result); +} + +TEST(Vec3Test, SubtractAssign) +{ + auto lhs = Vector3MeterType{4_m, 5_m, 6_m}; + constexpr const auto rhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto expected_result = Vector3MeterType{3_m, 3_m, 3_m}; + + lhs -= rhs; + + ASSERT_EQ(lhs, expected_result); +} + +TEST(Vec3Test, AddAssignScalar) +{ + auto lhs = Vector3MeterType{1_m, 2_m, 3_m}; + constexpr const auto rhs = 2.0_m; + constexpr const auto expected_result = Vector3MeterType{3_m, 4_m, 5_m}; + + lhs += rhs; + + ASSERT_EQ(lhs, expected_result); +} + +TEST(Vec3Test, SubtractAssignScalar) +{ + auto lhs = Vector3MeterType{4_m, 5_m, 6_m}; + constexpr const auto rhs = 2.0_m; + constexpr const auto expected_result = Vector3MeterType{2_m, 3_m, 4_m}; + + lhs -= rhs; + + ASSERT_EQ(lhs, expected_result); +} + +TEST(Vec3Test, OutputStreamOperator) +{ + const auto vector = Vector3MeterType{1_m, 2_m, 3_m}; + + auto oss = std::ostringstream{}; + oss << vector; + + ASSERT_EQ(oss.str(), "Vec3(.x=1 m, .y=2 m, .z=3 m)"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Execution/CMakeLists.txt b/test/MantleAPI/Execution/CMakeLists.txt index 10fde3f44363c8f0e472d21d4e42ad8a0aa74d83..e64a2e01d3ddcc1946114dde20957b1ead558196 100644 --- a/test/MantleAPI/Execution/CMakeLists.txt +++ b/test/MantleAPI/Execution/CMakeLists.txt @@ -9,7 +9,7 @@ ################################################################################ add_executable(ExecutionTest) -target_sources(ExecutionTest PUBLIC environment_engine_test.cc) +target_sources(ExecutionTest PUBLIC environment_engine_test.cc environment_test.cc scenario_engine_test.cc) target_include_directories(ExecutionTest PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/test>) target_link_libraries(ExecutionTest PUBLIC MantleAPI::MantleAPI GTest::gmock_main) diff --git a/test/MantleAPI/Execution/environment_engine_test.cc b/test/MantleAPI/Execution/environment_engine_test.cc index 390dd414fa5847ed467a614d4c6c405fabf160d3..c09383f5ddeac6a9afdb84a125600842d92a3760 100644 --- a/test/MantleAPI/Execution/environment_engine_test.cc +++ b/test/MantleAPI/Execution/environment_engine_test.cc @@ -11,38 +11,54 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <utility> + #include "MantleAPI/Execution/i_environment_engine.h" +#include "MantleAPI/Execution/mock_environment.h" #include "MantleAPI/Execution/mock_environment_engine.h" -namespace +namespace mantle_api { using testing::_; -using testing::Const; +using testing::Return; class EnvironmentEngineTest : public testing::Test { protected: - mantle_api::MockEnvironmentEngine mock_environment_engine_; - mantle_api::IEnvironmentEngine &environment_engine_{mock_environment_engine_}; + MockEnvironmentEngine mock_environment_engine_; + IEnvironmentEngine& environment_engine_{mock_environment_engine_}; }; TEST_F(EnvironmentEngineTest, GetEnvironment) { - EXPECT_CALL(mock_environment_engine_, GetEnvironment()).Times(1); - ASSERT_FALSE(environment_engine_.GetEnvironment()); + auto mock_environment = MockEnvironment{}; + + EXPECT_CALL(mock_environment_engine_, GetEnvironment()) + .Times(1) + .WillOnce(Return(&mock_environment)); + + const auto* result = environment_engine_.GetEnvironment(); + + ASSERT_TRUE(result); } TEST_F(EnvironmentEngineTest, Step) { - EXPECT_CALL(mock_environment_engine_, Step(_)).Times(1); + EXPECT_CALL(mock_environment_engine_, Step(_)) + .Times(1); + ASSERT_NO_THROW(environment_engine_.Step({})); } TEST_F(EnvironmentEngineTest, GetDesiredDeltaTime) { - EXPECT_CALL(Const(mock_environment_engine_), GetDesiredDeltaTime()).Times(1); - ASSERT_FALSE(environment_engine_.GetDesiredDeltaTime()); + EXPECT_CALL(std::as_const(mock_environment_engine_), GetDesiredDeltaTime()) + .Times(1); + + auto result = std::as_const(environment_engine_).GetDesiredDeltaTime(); + + ASSERT_FALSE(result); } -} // namespace +} // namespace mantle_api diff --git a/test/MantleAPI/Execution/environment_test.cc b/test/MantleAPI/Execution/environment_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..0bb0bb0b1d101dc66e849a8ec8a91f4dea3eb194 --- /dev/null +++ b/test/MantleAPI/Execution/environment_test.cc @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <utility> + +#include "MantleAPI/Common/mock_geometry_helper.h" +#include "MantleAPI/Execution/mock_environment.h" +#include "MantleAPI/Map/mock_coord_converter.h" +#include "MantleAPI/Map/mock_lane_location_query_service.h" +#include "MantleAPI/Map/mock_route_repository.h" +#include "MantleAPI/Traffic/mock_controller_repository.h" +#include "MantleAPI/Traffic/mock_entity.h" +#include "MantleAPI/Traffic/mock_entity_repository.h" +#include "MantleAPI/Traffic/mock_traffic_area_service.h" +#include "MantleAPI/Traffic/mock_traffic_swarm_service.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; +using testing::ReturnRef; + +class EnvironmentTest : public testing::Test +{ +protected: + MockEnvironment mock_environment_; + IEnvironment& environment_{mock_environment_}; +}; + +TEST_F(EnvironmentTest, CreateMap) +{ + EXPECT_CALL(mock_environment_, CreateMap(_, _, _)) + .Times(1); + + environment_.CreateMap({}, {}, {}); +} + +TEST_F(EnvironmentTest, AddEntityToController) +{ + EXPECT_CALL(mock_environment_, AddEntityToController(_, _)) + .Times(1); + + auto entity = MockEntity{}; + + environment_.AddEntityToController(entity, {}); +} + +TEST_F(EnvironmentTest, RemoveEntityFromController) +{ + EXPECT_CALL(mock_environment_, RemoveEntityFromController(_, _)) + .Times(1); + + environment_.RemoveEntityFromController({}, {}); +} + +TEST_F(EnvironmentTest, UpdateControlStrategies) +{ + EXPECT_CALL(mock_environment_, UpdateControlStrategies(_, _)) + .Times(1); + + environment_.UpdateControlStrategies({}, {}); +} + +TEST_F(EnvironmentTest, HasControlStrategyGoalBeenReached) +{ + EXPECT_CALL(std::as_const(mock_environment_), HasControlStrategyGoalBeenReached(_, _)) + .Times(1) + .WillOnce(Return(true)); + + std::ignore = std::as_const(environment_).HasControlStrategyGoalBeenReached({}, {}); +} + +TEST_F(EnvironmentTest, GetQueryService) +{ + const auto mock_lane_location_query_service = MockLaneLocationQueryService{}; + + EXPECT_CALL(std::as_const(mock_environment_), GetQueryService()) + .Times(1) + .WillOnce(ReturnRef(mock_lane_location_query_service)); + + std::ignore = std::as_const(environment_).GetQueryService(); +} + +TEST_F(EnvironmentTest, GetConverter) +{ + auto mock_coord_converter = MockCoordConverter{}; + + EXPECT_CALL(mock_environment_, GetConverter()) + .Times(1) + .WillOnce(Return(&mock_coord_converter)); + + std::ignore = environment_.GetConverter(); +} + +TEST_F(EnvironmentTest, GetGeometryHelper) +{ + auto mock_geometry_helper = MockGeometryHelper{}; + + EXPECT_CALL(std::as_const(mock_environment_), GetGeometryHelper()) + .Times(1) + .WillOnce(Return(&mock_geometry_helper)); + + std::ignore = std::as_const(environment_).GetGeometryHelper(); +} + +TEST_F(EnvironmentTest, GetEntityRepository) +{ + auto mock_entity_repository = MockEntityRepository{}; + + EXPECT_CALL(mock_environment_, GetEntityRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_entity_repository)); + + std::ignore = environment_.GetEntityRepository(); +} + +TEST_F(EnvironmentTest, GetEntityRepositoryConst) +{ + const auto mock_entity_repository = MockEntityRepository{}; + + EXPECT_CALL(std::as_const(mock_environment_), GetEntityRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_entity_repository)); + + std::ignore = std::as_const(environment_).GetEntityRepository(); +} + +TEST_F(EnvironmentTest, GetControllerRepository) +{ + auto mock_controller_repository = MockControllerRepository{}; + + EXPECT_CALL(mock_environment_, GetControllerRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_controller_repository)); + + std::ignore = environment_.GetControllerRepository(); +} + +TEST_F(EnvironmentTest, GetControllerRepositoryConst) +{ + const auto mock_controller_repository = MockControllerRepository{}; + + EXPECT_CALL(std::as_const(mock_environment_), GetControllerRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_controller_repository)); + + std::ignore = std::as_const(environment_).GetControllerRepository(); +} + +TEST_F(EnvironmentTest, GetRouteRepository) +{ + auto mock_route_repository = MockRouteRepository{}; + + EXPECT_CALL(mock_environment_, GetRouteRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_route_repository)); + + std::ignore = environment_.GetRouteRepository(); +} + +TEST_F(EnvironmentTest, GetRouteRepositoryConst) +{ + const auto mock_route_repository = MockRouteRepository{}; + + EXPECT_CALL(std::as_const(mock_environment_), GetRouteRepository()) + .Times(1) + .WillOnce(ReturnRef(mock_route_repository)); + + std::ignore = std::as_const(environment_).GetRouteRepository(); +} + +TEST_F(EnvironmentTest, SetDateTime) +{ + EXPECT_CALL(mock_environment_, SetDateTime(_)) + .Times(1); + environment_.SetDateTime({}); +} + +TEST_F(EnvironmentTest, GetDateTime) +{ + EXPECT_CALL(mock_environment_, GetDateTime()) + .Times(1) + .WillOnce(Return(Time{})); + + std::ignore = environment_.GetDateTime(); +} + +TEST_F(EnvironmentTest, GetSimulationTime) +{ + EXPECT_CALL(mock_environment_, GetSimulationTime()) + .Times(1) + .WillOnce(Return(Time{})); + + std::ignore = environment_.GetSimulationTime(); +} + +TEST_F(EnvironmentTest, SetWeather) +{ + EXPECT_CALL(mock_environment_, SetWeather(_)) + .Times(1); + environment_.SetWeather({}); +} + +TEST_F(EnvironmentTest, SetRoadCondition) +{ + EXPECT_CALL(mock_environment_, SetRoadCondition(_)) + .Times(1); + environment_.SetRoadCondition({}); +} + +TEST_F(EnvironmentTest, SetTrafficSignalState) +{ + EXPECT_CALL(mock_environment_, SetTrafficSignalState(_, _)) + .Times(1); + environment_.SetTrafficSignalState({}, {}); +} + +TEST_F(EnvironmentTest, ExecuteCustomCommand) +{ + EXPECT_CALL(mock_environment_, ExecuteCustomCommand(_, _, _)) + .Times(1); + environment_.ExecuteCustomCommand({}, {}, {}); +} + +TEST_F(EnvironmentTest, SetUserDefinedValue) +{ + EXPECT_CALL(mock_environment_, SetUserDefinedValue(_, _)) + .Times(1); + environment_.SetUserDefinedValue({}, {}); +} + +TEST_F(EnvironmentTest, GetUserDefinedValue) +{ + EXPECT_CALL(std::as_const(mock_environment_), GetUserDefinedValue(_)) + .Times(1) + .WillOnce(Return(std::nullopt)); + std::ignore = std::as_const(environment_).GetUserDefinedValue({}); +} + +TEST_F(EnvironmentTest, SetVariable) +{ + EXPECT_CALL(mock_environment_, SetVariable(_, _)) + .Times(1); + + environment_.SetVariable({}, {}); +} + +TEST_F(EnvironmentTest, GetVariable) +{ + EXPECT_CALL(std::as_const(mock_environment_), GetVariable(_)) + .Times(1) + .WillOnce(Return(std::nullopt)); + std::ignore = std::as_const(environment_).GetVariable({}); +} + +TEST_F(EnvironmentTest, SetDefaultRoutingBehavior) +{ + EXPECT_CALL(mock_environment_, SetDefaultRoutingBehavior(_)) + .Times(1); + + environment_.SetDefaultRoutingBehavior({}); +} + +TEST_F(EnvironmentTest, InitTrafficSwarmService) +{ + EXPECT_CALL(mock_environment_, InitTrafficSwarmService(_)) + .Times(1); + + environment_.InitTrafficSwarmService({}); +} + +TEST_F(EnvironmentTest, GetTrafficSwarmService) +{ + auto mock_traffic_swarm_service = MockTrafficSwarmService{}; + + EXPECT_CALL(mock_environment_, GetTrafficSwarmService()) + .Times(1) + .WillOnce(ReturnRef(mock_traffic_swarm_service)); + + std::ignore = environment_.GetTrafficSwarmService(); +} + +TEST_F(EnvironmentTest, GetTrafficAreaService) +{ + auto mock_traffic_area_service = MockTrafficAreaService{}; + + EXPECT_CALL(mock_environment_, GetTrafficAreaService()) + .Times(1) + .WillOnce(ReturnRef(mock_traffic_area_service)); + + std::ignore = environment_.GetTrafficAreaService(); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Execution/mock_environment.h b/test/MantleAPI/Execution/mock_environment.h new file mode 100644 index 0000000000000000000000000000000000000000..10d7c4877e618d8e7039fa76d66dc9025ec816c3 --- /dev/null +++ b/test/MantleAPI/Execution/mock_environment.h @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_H +#define MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_H + +#include <gmock/gmock.h> + +#include <memory> +#include <optional> +#include <string> +#include <vector> + +#include "MantleAPI/Common/i_identifiable.h" // for UniqueId +#include "MantleAPI/Common/time_utils.h" +#include "MantleAPI/EnvironmentalConditions/road_condition.h" +#include "MantleAPI/EnvironmentalConditions/weather.h" +#include "MantleAPI/Execution/i_environment.h" +#include "MantleAPI/Map/i_route_repository.h" +#include "MantleAPI/Map/map_details.h" +#include "MantleAPI/Traffic/control_strategy.h" +#include "MantleAPI/Traffic/default_routing_behavior.h" +#include "MantleAPI/Traffic/i_controller_repository.h" +#include "MantleAPI/Traffic/i_entity.h" + +namespace mantle_api +{ + +class ILaneLocationQueryService; +class ICoordConverter; +class IGeometryHelper; +class IEntityRepository; +class IControllerRepository; + +class MockEnvironment : public IEnvironment +{ +public: + MOCK_METHOD(void, CreateMap, (const std::string& map_file_path, const MapDetails& map_details, const std::string& map_model_reference), (override)); + MOCK_METHOD(void, AddEntityToController, (IEntity & entity, UniqueId controller_id), (override)); + MOCK_METHOD(void, RemoveEntityFromController, (UniqueId entity_id, UniqueId controller_id), (override)); + MOCK_METHOD(void, UpdateControlStrategies, (UniqueId entity_id, std::vector<std::shared_ptr<ControlStrategy>> control_strategies), (override)); + MOCK_METHOD(bool, HasControlStrategyGoalBeenReached, (UniqueId entity_id, ControlStrategyType type), (const, override)); + MOCK_METHOD(const ILaneLocationQueryService&, GetQueryService, (), (const, override)); + MOCK_METHOD(ICoordConverter*, GetConverter, (), (override)); + MOCK_METHOD(const IGeometryHelper*, GetGeometryHelper, (), (const, override)); + MOCK_METHOD(IEntityRepository&, GetEntityRepository, (), (override)); + MOCK_METHOD(const IEntityRepository&, GetEntityRepository, (), (const, override)); + MOCK_METHOD(IControllerRepository&, GetControllerRepository, (), (override)); + MOCK_METHOD(const IControllerRepository&, GetControllerRepository, (), (const, override)); + MOCK_METHOD(IRouteRepository&, GetRouteRepository, (), (override)); + MOCK_METHOD(const IRouteRepository&, GetRouteRepository, (), (const, override)); + MOCK_METHOD(void, SetDateTime, (Time time), (override)); + MOCK_METHOD(Time, GetDateTime, (), (override)); + MOCK_METHOD(Time, GetSimulationTime, (), (override)); + MOCK_METHOD(void, SetWeather, (Weather weather), (override)); + MOCK_METHOD(void, SetRoadCondition, (std::vector<FrictionPatch> friction_patches), (override)); + MOCK_METHOD(void, SetTrafficSignalState, (const std::string& traffic_signal_name, const std::string& traffic_signal_state), (override)); + MOCK_METHOD(void, ExecuteCustomCommand, (const std::vector<std::string>& actors, const std::string& type, const std::string& command), (override)); + MOCK_METHOD(void, SetUserDefinedValue, (const std::string& name, const std::string& value), (override)); + MOCK_METHOD(std::optional<std::string>, GetUserDefinedValue, (const std::string& name), (const, override)); + MOCK_METHOD(void, SetVariable, (const std::string& name, const ParameterType& value), (override)); + MOCK_METHOD(std::optional<ParameterType>, GetVariable, (const std::string& name), (const, override)); + MOCK_METHOD(void, SetDefaultRoutingBehavior, (DefaultRoutingBehavior default_routing_behavior), (override)); + MOCK_METHOD(void, InitTrafficSwarmService, (const TrafficSwarmParameters& parameters), (override)); + MOCK_METHOD(ITrafficSwarmService&, GetTrafficSwarmService, (), (override)); + MOCK_METHOD(ITrafficAreaService&, GetTrafficAreaService, (), (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_H diff --git a/test/MantleAPI/Execution/mock_environment_engine.h b/test/MantleAPI/Execution/mock_environment_engine.h index d8007f47dd93c47b46030799e384dd5ca3ebee2e..18393358bae0c37fa492dd6a402f1bbf8915de86 100644 --- a/test/MantleAPI/Execution/mock_environment_engine.h +++ b/test/MantleAPI/Execution/mock_environment_engine.h @@ -8,17 +8,21 @@ * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -#ifndef MANTLEAPI_COMMON_MOCK_ENVIRONMENT_ENGINE_H -#define MANTLEAPI_COMMON_MOCK_ENVIRONMENT_ENGINE_H +#ifndef MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_ENGINE_H +#define MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_ENGINE_H #include <gmock/gmock.h> +#include <optional> + #include "MantleAPI/Execution/i_environment_engine.h" namespace mantle_api { -class MockEnvironmentEngine final : public IEnvironmentEngine +class IEnvironment; + +class MockEnvironmentEngine : public IEnvironmentEngine { public: MOCK_METHOD(IEnvironment*, GetEnvironment, (), (noexcept, override)); @@ -28,4 +32,4 @@ public: } // namespace mantle_api -#endif // MANTLEAPI_COMMON_MOCK_ENVIRONMENT_ENGINE_H +#endif // MANTLEAPI_EXECUTION_MOCK_ENVIRONMENT_ENGINE_H diff --git a/test/MantleAPI/Execution/mock_scenario_engine.h b/test/MantleAPI/Execution/mock_scenario_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..400d98e8b35271f457c0723f3768c1f19197c840 --- /dev/null +++ b/test/MantleAPI/Execution/mock_scenario_engine.h @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_EXECUTION_MOCK_SCENARIO_ENGINE_H +#define MANTLEAPI_EXECUTION_MOCK_SCENARIO_ENGINE_H + +#include <gmock/gmock.h> + +#include <optional> + +#include "MantleAPI/Common/time_utils.h" +#include "MantleAPI/Execution/i_scenario_engine.h" +#include "MantleAPI/Execution/scenario_info.h" + +namespace mantle_api +{ + +class IEnvironment; + +class MockScenarioEngine : public IScenarioEngine +{ +public: + MOCK_METHOD(void, Init, (), (override)); + MOCK_METHOD(ScenarioInfo, GetScenarioInfo, (), (const, override)); + MOCK_METHOD(void, SetupDynamicContent, (), (override)); + MOCK_METHOD(bool, IsFinished, (), (const, override)); + MOCK_METHOD(void, ActivateExternalHostControl, (), (override)); + MOCK_METHOD(int, ValidateScenario, (), (override)); + + MOCK_METHOD(void, Step, (Time), (override)); + MOCK_METHOD(std::optional<Time>, GetDesiredDeltaTime, (), (const, noexcept, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_EXECUTION_MOCK_SCENARIO_ENGINE_H diff --git a/test/MantleAPI/Execution/scenario_engine_test.cc b/test/MantleAPI/Execution/scenario_engine_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..2ee773fae5b8a33662ea2c93013d323bd12baac2 --- /dev/null +++ b/test/MantleAPI/Execution/scenario_engine_test.cc @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <utility> + +#include "MantleAPI/Execution/i_scenario_engine.h" +#include "MantleAPI/Execution/mock_scenario_engine.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class ScenarioEngineTest : public testing::Test +{ +protected: + MockScenarioEngine mock_scenario_engine_; + IScenarioEngine& scenario_engine_{mock_scenario_engine_}; +}; + +TEST_F(ScenarioEngineTest, Init) +{ + EXPECT_CALL(mock_scenario_engine_, Init()) + .Times(1); + + scenario_engine_.Init(); +} + +TEST_F(ScenarioEngineTest, GetScenarioInfo) +{ + auto mock_scenario_info = ScenarioInfo{}; + + EXPECT_CALL(std::as_const(mock_scenario_engine_), GetScenarioInfo()) + .Times(1) + .WillOnce(Return(mock_scenario_info)); + + std::ignore = std::as_const(scenario_engine_).GetScenarioInfo(); +} + +TEST_F(ScenarioEngineTest, SetupDynamicContent) +{ + EXPECT_CALL(mock_scenario_engine_, SetupDynamicContent()) + .Times(1); + + scenario_engine_.SetupDynamicContent(); +} + +TEST_F(ScenarioEngineTest, IsFinished) +{ + EXPECT_CALL(std::as_const(mock_scenario_engine_), IsFinished()) + .Times(1); + + auto result = std::as_const(scenario_engine_).IsFinished(); + + ASSERT_FALSE(result); +} + +TEST_F(ScenarioEngineTest, ActivateExternalHostControl) +{ + EXPECT_CALL(mock_scenario_engine_, ActivateExternalHostControl()) + .Times(1); + + scenario_engine_.ActivateExternalHostControl(); +} + +TEST_F(ScenarioEngineTest, ValidateScenario) +{ + EXPECT_CALL(mock_scenario_engine_, ValidateScenario()) + .Times(1); + + auto result = scenario_engine_.ValidateScenario(); + + ASSERT_EQ(result, 0); +} + +TEST_F(ScenarioEngineTest, Step) +{ + EXPECT_CALL(mock_scenario_engine_, Step(_)) + .Times(1); + + scenario_engine_.Step({}); +} + +TEST_F(ScenarioEngineTest, GetDesiredDeltaTime) +{ + EXPECT_CALL(std::as_const(mock_scenario_engine_), GetDesiredDeltaTime()) + .Times(1); + + auto result = std::as_const(scenario_engine_).GetDesiredDeltaTime(); + + ASSERT_FALSE(result); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Map/CMakeLists.txt b/test/MantleAPI/Map/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..19828fa4c125a82518286418f7c1fe8814349081 --- /dev/null +++ b/test/MantleAPI/Map/CMakeLists.txt @@ -0,0 +1,19 @@ +################################################################################ +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License 2.0 which is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +################################################################################ + +add_executable(MapTest) +target_sources( + MapTest PUBLIC coord_converter_test.cc lane_location_query_service_test.cc route_test.cc routing_definition_test.cc +) +target_include_directories(MapTest PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/test>) +target_link_libraries(MapTest PUBLIC MantleAPI::MantleAPI GTest::gmock_main) + +include(GoogleTest) +gtest_discover_tests(MapTest) diff --git a/test/MantleAPI/Map/coord_converter_test.cc b/test/MantleAPI/Map/coord_converter_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..e40a93b7ec72e128652062df75c20a041afd26f3 --- /dev/null +++ b/test/MantleAPI/Map/coord_converter_test.cc @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <units.h> + +#include <tuple> + +#include "MantleAPI/Map/i_coord_converter.h" +#include "MantleAPI/Map/mock_coord_converter.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class CoordConverterTest : public testing::Test +{ +protected: + MockCoordConverter mock_coord_converter_; + ICoordConverter& coord_converter_{mock_coord_converter_}; +}; + +TEST_F(CoordConverterTest, Convert) +{ + static const auto kPosition = Position{}; + static const auto kReturnValue = Vec3<units::length::meter_t>{}; + + EXPECT_CALL(mock_coord_converter_, Convert(_)) + .Times(1) + .WillOnce(Return(kReturnValue)); + + std::ignore = coord_converter_.Convert(kPosition); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Map/lane_location_query_service_test.cc b/test/MantleAPI/Map/lane_location_query_service_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..27ab4b8342ba26f0b8919f7de6aab86700b7364a --- /dev/null +++ b/test/MantleAPI/Map/lane_location_query_service_test.cc @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <units.h> + +#include <optional> +#include <tuple> +#include <vector> + +#include "MantleAPI/Map/mock_lane_location_query_service.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class LaneLocationQueryServiceTest : public testing::Test +{ +protected: + MockLaneLocationQueryService mock_lane_location_query_service_; + ILaneLocationQueryService& lane_location_query_service_{mock_lane_location_query_service_}; +}; + +TEST_F(LaneLocationQueryServiceTest, GetLaneOrientation) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetLaneOrientation(_)) + .Times(1) + .WillOnce(Return(Orientation3<units::angle::radian_t>{})); + + std::ignore = std::as_const(lane_location_query_service_).GetLaneOrientation({}); +} + +TEST_F(LaneLocationQueryServiceTest, GetUpwardsShiftedLanePosition) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetUpwardsShiftedLanePosition(_, _, _)) + .Times(1) + .WillOnce(Return(Vec3<units::length::meter_t>{})); + + std::ignore = std::as_const(lane_location_query_service_).GetUpwardsShiftedLanePosition({}, {}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, IsPositionOnLane) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), IsPositionOnLane(_)) + .Times(1) + .WillOnce(Return(true)); + + std::ignore = std::as_const(lane_location_query_service_).IsPositionOnLane({}); +} + +TEST_F(LaneLocationQueryServiceTest, GetLaneIdsAtPosition) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetLaneIdsAtPosition(_)) + .Times(1) + .WillOnce(Return(std::vector<UniqueId>{})); + + std::ignore = std::as_const(lane_location_query_service_).GetLaneIdsAtPosition({}); +} + +TEST_F(LaneLocationQueryServiceTest, FindLanePoseAtDistanceFrom) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), FindLanePoseAtDistanceFrom(_, _, _)) + .Times(1) + .WillOnce(Return(std::make_optional<Pose>())); + + std::ignore = std::as_const(lane_location_query_service_).FindLanePoseAtDistanceFrom({}, {}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, GetLongitudinalLaneDistanceBetweenPositions) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetLongitudinalLaneDistanceBetweenPositions(_, _)) + .Times(1) + .WillOnce(Return(std::make_optional<units::length::meter_t>())); + + std::ignore = std::as_const(lane_location_query_service_).GetLongitudinalLaneDistanceBetweenPositions({}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, FindRelativeLanePoseAtDistanceFrom) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), FindRelativeLanePoseAtDistanceFrom(_, _, _, _)) + .Times(1) + .WillOnce(Return(std::make_optional<Pose>())); + + std::ignore = std::as_const(lane_location_query_service_).FindRelativeLanePoseAtDistanceFrom({}, {}, {}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, GetRelativeLaneId) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetRelativeLaneId(_, _)) + .Times(1) + .WillOnce(Return(std::make_optional<LaneId>())); + + std::ignore = std::as_const(lane_location_query_service_).GetRelativeLaneId({}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, GetProjectedPoseAtLane) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetProjectedPoseAtLane(_, _)) + .Times(1) + .WillOnce(Return(std::make_optional<Pose>())); + + std::ignore = std::as_const(lane_location_query_service_).GetProjectedPoseAtLane({}, {}); +} + +TEST_F(LaneLocationQueryServiceTest, GetProjectedCenterLinePoint) +{ + EXPECT_CALL(std::as_const(mock_lane_location_query_service_), GetProjectedCenterLinePoint(_)) + .Times(1) + .WillOnce(Return(std::make_optional<Vec3<units::length::meter_t>>())); + + std::ignore = std::as_const(lane_location_query_service_).GetProjectedCenterLinePoint({}); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Map/mock_coord_converter.h b/test/MantleAPI/Map/mock_coord_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..5323ebef808483872b3b6d59880ad2f7e379af5b --- /dev/null +++ b/test/MantleAPI/Map/mock_coord_converter.h @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_MAP_MOCK_COORD_CONVERTER_H +#define MANTLEAPI_MAP_MOCK_COORD_CONVERTER_H + +#include <gmock/gmock.h> +#include <units.h> + +#include "MantleAPI/Common/position.h" +#include "MantleAPI/Map/i_coord_converter.h" + +namespace mantle_api +{ + +class MockCoordConverter : public ICoordConverter +{ +public: + MOCK_METHOD(Vec3<units::length::meter_t>, Convert, (Position position), (override)); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetLaneOrientation, (const OpenDriveLanePosition& open_drive_lane_position), ()); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetRoadOrientation, (const OpenDriveRoadPosition& open_drive_road_position), ()); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_MAP_MOCK_COORD_CONVERTER_H diff --git a/test/MantleAPI/Map/mock_lane_location_query_service.h b/test/MantleAPI/Map/mock_lane_location_query_service.h new file mode 100644 index 0000000000000000000000000000000000000000..25ddefd686e4b773c3b43da6cf497a550dcd0aee --- /dev/null +++ b/test/MantleAPI/Map/mock_lane_location_query_service.h @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_MAP_MOCK_LANE_LOCATION_QUERY_SERVICE_H +#define MANTLEAPI_MAP_MOCK_LANE_LOCATION_QUERY_SERVICE_H + +#include <gmock/gmock.h> +#include <units.h> + +#include <optional> +#include <vector> + +#include "MantleAPI/Common/i_identifiable.h" +#include "MantleAPI/Common/orientation.h" +#include "MantleAPI/Common/pose.h" +#include "MantleAPI/Common/vector.h" +#include "MantleAPI/Map/i_lane_location_query_service.h" +#include "MantleAPI/Map/lane_definition.h" + +namespace mantle_api +{ + +class MockLaneLocationQueryService : public ILaneLocationQueryService +{ +public: + MOCK_METHOD(Orientation3<units::angle::radian_t>, // + GetLaneOrientation, + (const Vec3<units::length::meter_t>& position), + (const, override)); + MOCK_METHOD(Vec3<units::length::meter_t>, // + GetUpwardsShiftedLanePosition, + (const Vec3<units::length::meter_t>& position, double upwards_shift, bool allow_invalid_positions), + (const, override)); + MOCK_METHOD(bool, IsPositionOnLane, // + (const Vec3<units::length::meter_t>& position), + (const, override)); + MOCK_METHOD(std::vector<UniqueId>, // + GetLaneIdsAtPosition, + (const Vec3<units::length::meter_t>& position), + (const, override)); + MOCK_METHOD(std::optional<Pose>, // + FindLanePoseAtDistanceFrom, + (const Pose& reference_pose_on_lane, units::length::meter_t distance, Direction direction), + (const, override)); + MOCK_METHOD(std::optional<Vec3<units::length::meter_t>>, // + GetPosition, + (const mantle_api::Pose& reference_pose, mantle_api::LateralDisplacementDirection direction, units::length::meter_t distance), + (const, override)); + MOCK_METHOD(std::optional<units::length::meter_t>, // + GetLongitudinalLaneDistanceBetweenPositions, + (const mantle_api::Vec3<units::length::meter_t>& start_position, const mantle_api::Vec3<units::length::meter_t>& target_position), + (const, override)); + MOCK_METHOD(std::optional<Pose>, // + FindRelativeLanePoseAtDistanceFrom, + (const Pose& reference_pose_on_lane, int relative_target_lane, units::length::meter_t distance, units::length::meter_t lateral_offset), + (const, override)); + MOCK_METHOD(std::optional<mantle_api::LaneId>, // + GetRelativeLaneId, + (const mantle_api::Pose& reference_pose_on_lane, int relative_lane_target), + (const, override)); + MOCK_METHOD(std::optional<mantle_api::Pose>, // + GetProjectedPoseAtLane, + (const Vec3<units::length::meter_t>& reference_position_on_lane, + mantle_api::UniqueId target_lane_id), + (const, override)); + MOCK_METHOD(std::optional<Vec3<units::length::meter_t>>, // + GetProjectedCenterLinePoint, + (const Vec3<units::length::meter_t>& position), + (const, override)); + MOCK_METHOD(units::length::meter_t, // + GetLaneHeightAtPosition, + (const Vec3<units::length::meter_t>& position), + (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_MAP_MOCK_LANE_LOCATION_QUERY_SERVICE_H diff --git a/test/MantleAPI/Map/mock_route.h b/test/MantleAPI/Map/mock_route.h new file mode 100644 index 0000000000000000000000000000000000000000..0761bd894c2cffb02e661f86baca4c559b1734a4 --- /dev/null +++ b/test/MantleAPI/Map/mock_route.h @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_MAP_MOCK_ROUTE_H +#define MANTLEAPI_MAP_MOCK_ROUTE_H + +#include <gmock/gmock.h> + +#include <memory> + +#include "MantleAPI/Common/position.h" +#include "MantleAPI/Map/i_route.h" + +namespace mantle_api +{ + +class MockRoute : public IRoute +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IRoute + MOCK_METHOD(bool, IsLooped, (), (const, override)); + MOCK_METHOD(std::optional<units::length::meter_t>, GetOffsetAlongReferenceLine, (const Position& position), (const, override)); + MOCK_METHOD(OpenDriveRoadPosition, ProjectAlongReferenceLine, (units::length::meter_t longitudinal_offset, units::length::meter_t lateral_offset), (const, override)); + MOCK_METHOD(units::length::meter_t, GetLength, (), (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_MAP_MOCK_ROUTE_H diff --git a/test/MantleAPI/Map/mock_route_repository.h b/test/MantleAPI/Map/mock_route_repository.h new file mode 100644 index 0000000000000000000000000000000000000000..159b3a8ef9179ee4186c72af35e987da3e8bad00 --- /dev/null +++ b/test/MantleAPI/Map/mock_route_repository.h @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_MAP_MOCK_ROUTE_REPOSITORY_H +#define MANTLEAPI_MAP_MOCK_ROUTE_REPOSITORY_H + +#include <MantleAPI/Map/i_route_repository.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <string> + +namespace mantle_api +{ +class MockRouteRepository : public mantle_api::IRouteRepository +{ +public: + MOCK_METHOD(std::weak_ptr<IRoute>, + Create, + (const std::string& name, const RoutingDefinition& definition), + (override)); + + MOCK_METHOD(std::weak_ptr<const IRoute>, + Get, + (const std::string& name), + (const override)); + + MOCK_METHOD(std::weak_ptr<const IRoute>, + Get, + (UniqueId id), + (const override)); + + MOCK_METHOD(bool, + Contains, + (UniqueId route_id), + (const, override)); + + MOCK_METHOD(void, + Delete, + (UniqueId route_id), + (override)); + + MOCK_METHOD(void, + Delete, + (const std::string& name), + (override)); + + MOCK_METHOD(void, + Reset, + (), + (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_MAP_MOCK_ROUTE_REPOSITORY_H diff --git a/test/MantleAPI/Map/route_test.cc b/test/MantleAPI/Map/route_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..b0fd8eaeb8a561af3263abd70d06be223f1542b8 --- /dev/null +++ b/test/MantleAPI/Map/route_test.cc @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <utility> + +#include "MantleAPI/Common/position.h" +#include "MantleAPI/Map/i_route.h" +#include "MantleAPI/Map/mock_route.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class RouteTest : public testing::Test +{ +protected: + MockRoute mock_route_; + IRoute& route_{mock_route_}; +}; + +TEST_F(RouteTest, GetLength) +{ + EXPECT_CALL(mock_route_, GetLength()) + .Times(1) + .WillOnce(Return(units::length::meter_t{})); + + std::ignore = std::as_const(route_).GetLength(); +} + +TEST_F(RouteTest, IsLooped) +{ + EXPECT_CALL(mock_route_, IsLooped()) + .Times(1) + .WillOnce(Return(bool{})); + + std::ignore = std::as_const(route_).IsLooped(); +} + +TEST_F(RouteTest, ProjectAlongReferenceLine) +{ + EXPECT_CALL(mock_route_, ProjectAlongReferenceLine(_, _)) + .Times(1) + .WillOnce(Return(OpenDriveRoadPosition{})); + + std::ignore = std::as_const(route_).ProjectAlongReferenceLine({}, {}); +} + +TEST_F(RouteTest, GetOffsetAlongReferenceLine) +{ + EXPECT_CALL(mock_route_, GetOffsetAlongReferenceLine(_)) + .Times(1) + .WillOnce(Return(std::optional<units::length::meter_t>{})); + + std::ignore = std::as_const(route_).GetOffsetAlongReferenceLine({}); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Map/routing_definition_test.cc b/test/MantleAPI/Map/routing_definition_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..26367d8e5283c2e923d329b0436f4742f5eef8b0 --- /dev/null +++ b/test/MantleAPI/Map/routing_definition_test.cc @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Map/routing_definition.h" + +#include <gtest/gtest.h> +#include <units.h> +#include <sstream> + +#include <type_traits> + +#include "MantleAPI/Common/vector.h" + +namespace mantle_api { + +using ::units::literals::operator""_m; + +/******************************************************************************* + * RouteWaypoint + *******************************************************************************/ +static_assert(std::is_aggregate_v<RoutingWaypoint>); + +TEST(RoutingWaypointTest, OperatorEqual) { + const auto lhs = + RoutingWaypoint{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}; + const auto rhs = + RoutingWaypoint{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}; + + ASSERT_EQ(lhs, rhs); +} + +TEST(RoutingWaypointTest, OperatorNotEqual) { + const auto lhs = + RoutingWaypoint{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}; + const auto rhs = + RoutingWaypoint{Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}; + + ASSERT_NE(lhs, rhs); +} + +TEST(RoutingWaypointTest, OutputStreamOperator) +{ + const auto routing_waypoint = RoutingWaypoint{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}; + + auto oss = std::ostringstream{}; + oss << routing_waypoint; + + ASSERT_EQ(oss.str(), "RoutingWaypoint(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .routing_strategy=2)"); +} + +/******************************************************************************* + * RouteDefinition + *******************************************************************************/ +static_assert(std::is_aggregate_v<RoutingDefinition>); + +TEST(RoutingDefinitionTest, OperatorEqual) { + const auto lhs = + RoutingDefinition{{{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}, + {Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}, + {Vec3{3_m, 3_m, 3_m}, RoutingStrategy::kFastest}}}; + const auto rhs = + RoutingDefinition{{{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}, + {Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}, + {Vec3{3_m, 3_m, 3_m}, RoutingStrategy::kFastest}}}; + + ASSERT_EQ(lhs, rhs); +} + +TEST(RoutingDefinitionTest, OperatorNotEqual) +{ + const auto lhs = + RoutingDefinition{{{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}, + {Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}, + {Vec3{3_m, 3_m, 3_m}, RoutingStrategy::kFastest}}}; + const auto rhs = + RoutingDefinition{{{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}, + {Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}, + {Vec3{3_m, 3_m, 3_m}, RoutingStrategy::kShortest}}}; + + ASSERT_NE(lhs, rhs); +} + +TEST(RoutingDefinitionTest, OutputStreamOperatorEmpty) +{ + const auto routing_definition = RoutingDefinition{}; + + auto oss = std::ostringstream{}; + oss << routing_definition; + + ASSERT_EQ(oss.str(), "RoutingDefinition()"); +} + +TEST(RoutingDefinitionTest, OutputStreamOperatorOneWaypoint) +{ + const auto routing_definition = RoutingDefinition{ + {{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}}}; + + auto oss = std::ostringstream{}; + oss << routing_definition; + + ASSERT_EQ(oss.str(), "RoutingDefinition([0]=RoutingWaypoint(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .routing_strategy=2))"); +} + +TEST(RoutingDefinitionTest, OutputStreamOperator) +{ + const auto routing_definition = RoutingDefinition{ + {{Vec3{1_m, 1_m, 1_m}, RoutingStrategy::kFastest}, + {Vec3{2_m, 2_m, 2_m}, RoutingStrategy::kFastest}, + {Vec3{3_m, 3_m, 3_m}, RoutingStrategy::kFastest}}}; + + auto oss = std::ostringstream{}; + oss << routing_definition; + + ASSERT_EQ(oss.str(), "RoutingDefinition([0]=RoutingWaypoint(.position=Vec3(.x=1 m, .y=1 m, .z=1 m), .routing_strategy=2), [1]=RoutingWaypoint(.position=Vec3(.x=2 m, .y=2 m, .z=2 m), .routing_strategy=2), [2]=RoutingWaypoint(.position=Vec3(.x=3 m, .y=3 m, .z=3 m), .routing_strategy=2))"); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Test/test_utils.h b/test/MantleAPI/Test/test_utils.h deleted file mode 100644 index e858326b8a76376f43656cdef6028a2ed0ee55f3..0000000000000000000000000000000000000000 --- a/test/MantleAPI/Test/test_utils.h +++ /dev/null @@ -1,661 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021-2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * Copyright (c) 2022 Ansys, Inc. - * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ - -//----------------------------------------------------------------------------- -/** @file test_utils.h */ -//----------------------------------------------------------------------------- - -#pragma once - -#include <MantleAPI/Common/i_identifiable.h> -#include <MantleAPI/Common/position.h> -#include <MantleAPI/EnvironmentalConditions/road_condition.h> -#include <MantleAPI/EnvironmentalConditions/weather.h> -#include <MantleAPI/Execution/i_environment.h> -#include <MantleAPI/Map/i_coord_converter.h> -#include <MantleAPI/Map/i_lane_location_query_service.h> -#include <MantleAPI/Map/lane_definition.h> -#include <MantleAPI/Traffic/entity_properties.h> -#include <MantleAPI/Traffic/i_controller_config.h> -#include <MantleAPI/Traffic/i_controller_repository.h> -#include <MantleAPI/Traffic/i_entity.h> -#include <MantleAPI/Traffic/i_entity_repository.h> -#include <MantleAPI/Traffic/i_traffic_area_service.h> -#include <MantleAPI/Traffic/i_traffic_area_stream.h> -#include <MantleAPI/Traffic/i_traffic_swarm_service.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -namespace mantle_api -{ -class MockGeometryHelper : public mantle_api::IGeometryHelper -{ -public: - MOCK_METHOD(mantle_api::Vec3<units::length::meter_t>, TranslateGlobalPositionLocally, (const Vec3<units::length::meter_t>& global_position, const Orientation3<units::angle::radian_t>& local_orientation, const Vec3<units::length::meter_t>& local_translation), (const override)); - - virtual std::vector<Vec3<units::length::meter_t>> TransformPolylinePointsFromWorldToLocal( - const std::vector<Vec3<units::length::meter_t>>& polyline_points, - const Vec3<units::length::meter_t>& position, - const Orientation3<units::angle::radian_t>& orientation) const - { - // do not transform but return original points - std::ignore = position; - std::ignore = orientation; - return polyline_points; - } - - virtual Vec3<units::length::meter_t> TransformPositionFromWorldToLocal( - const Vec3<units::length::meter_t>& point_position, - const Vec3<units::length::meter_t>& position, - const Orientation3<units::angle::radian_t>& orientation) const - { - // do not transform but return original points - std::ignore = position; - std::ignore = orientation; - return point_position; - } - - MOCK_METHOD(bool, AreOrientedSimilarly, (const Orientation3<units::angle::radian_t>& orientation1, const Orientation3<units::angle::radian_t>& orientation2), (const override)); -}; - -class MockConverter : public mantle_api::ICoordConverter -{ -public: - MOCK_METHOD(mantle_api::Vec3<units::length::meter_t>, Convert, (mantle_api::Position position), (override)); - MOCK_METHOD(Orientation3<units::angle::radian_t>, GetLaneOrientation, (const OpenDriveLanePosition& open_drive_lane_position), (override)); - MOCK_METHOD(Orientation3<units::angle::radian_t>, GetRoadOrientation, (const OpenDriveRoadPosition& open_drive_road_position), (override)); -}; - -class MockVehicle : public mantle_api::IVehicle -{ -public: - MOCK_METHOD(mantle_api::UniqueId, GetUniqueId, (), (const, override)); - - void SetName(const std::string& name) override { name_ = name; } - const std::string& GetName() const override { return name_; } - - MOCK_METHOD(void, SetPosition, (const mantle_api::Vec3<units::length::meter_t>& inert_pos), (override)); - MOCK_METHOD(mantle_api::Vec3<units::length::meter_t>, GetPosition, (), (const, override)); - - MOCK_METHOD(void, SetVelocity, (const mantle_api::Vec3<units::velocity::meters_per_second_t>& velocity), (override)); - MOCK_METHOD(mantle_api::Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); - - MOCK_METHOD(void, SetAcceleration, (const mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); - MOCK_METHOD(mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetOrientation, (const mantle_api::Orientation3<units::angle::radian_t>& orientation), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); - - MOCK_METHOD(void, SetOrientationRate, (const mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); - - MOCK_METHOD(void, - SetOrientationAcceleration, - (const mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), - (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<std::uint64_t>& ids), (override)); - MOCK_METHOD(std::vector<std::uint64_t>, GetAssignedLaneIds, (), (const, override)); - - MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); - MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); - - void SetProperties(std::unique_ptr<mantle_api::EntityProperties> properties) override { properties_ = std::move(properties); } - - MOCK_METHOD(mantle_api::VehicleProperties*, GetPropertiesImpl, (), (const)); - mantle_api::VehicleProperties* GetProperties() const override - { - if (auto* properties = GetPropertiesImpl()) - { - return properties; - } - return static_cast<mantle_api::VehicleProperties*>(properties_.get()); - } - - MOCK_METHOD(void, SetSteeringWheelAngle, (units::angle::radian_t steering_wheel_angle), (override)); - MOCK_METHOD(units::angle::radian_t, GetSteeringWheelAngle, (), (const, override)); - -private: - std::string name_{}; - std::unique_ptr<mantle_api::EntityProperties> properties_{std::make_unique<mantle_api::VehicleProperties>()}; -}; - -class MockQueryService : public mantle_api::ILaneLocationQueryService -{ -public: - MOCK_METHOD(Orientation3<units::angle::radian_t>, GetLaneOrientation, (const Vec3<units::length::meter_t>& position), (const override)); - - MOCK_METHOD(Vec3<units::length::meter_t>, GetUpwardsShiftedLanePosition, (const Vec3<units::length::meter_t>& position, double upwards_shift, bool allowed_to_leave_lane), (const override)); - - MOCK_METHOD(bool, IsPositionOnLane, (const Vec3<units::length::meter_t>& position), (const override)); - - MOCK_METHOD(std::vector<UniqueId>, GetLaneIdsAtPosition, (const Vec3<units::length::meter_t>& position), (const override)); - - MOCK_METHOD(std::optional<Pose>, FindLanePoseAtDistanceFrom, (const Pose&, units::length::meter_t, Direction), (const, override)); - - std::optional<Pose> FindRelativeLanePoseAtDistanceFrom(const Pose& reference_pose_on_lane, int relative_target_lane, units::length::meter_t distance, units::length::meter_t lateral_offset) const override - { - std::ignore = reference_pose_on_lane; - std::ignore = relative_target_lane; - std::ignore = distance; - std::ignore = lateral_offset; - Pose pose{}; - return pose; - } - - std::optional<LaneId> GetRelativeLaneId(const mantle_api::Pose& reference_pose_on_lane, int relative_lane_target) const override - { - std::ignore = reference_pose_on_lane; - std::ignore = relative_lane_target; - return 0; - } - - MOCK_METHOD(std::optional<units::length::meter_t>, - GetLongitudinalLaneDistanceBetweenPositions, - (const mantle_api::Vec3<units::length::meter_t>&, const mantle_api::Vec3<units::length::meter_t>&), - (const, override)); - - MOCK_METHOD(std::optional<Vec3<units::length::meter_t>>, - GetPosition, - (const Pose&, LateralDisplacementDirection, units::length::meter_t), - (const, override)); - - MOCK_METHOD(std::optional<Pose>, - GetProjectedPoseAtLane, - (const mantle_api::Vec3<units::length::meter_t>&, mantle_api::LaneId), - (const, override)); - - MOCK_METHOD(std::optional<Vec3<units::length::meter_t>>, - GetProjectedCenterLinePoint, - (const Vec3<units::length::meter_t>&), - (const, override)); - - MOCK_METHOD(units::length::meter_t, GetLaneHeightAtPosition, (const Vec3<units::length::meter_t>&), (const)); - -private: - MockVehicle test_vehicle_{}; -}; - -class MockPedestrian : public mantle_api::IPedestrian -{ -public: - MOCK_METHOD(mantle_api::UniqueId, GetUniqueId, (), (const, override)); - - void SetName(const std::string& name) override { name_ = name; } - const std::string& GetName() const override { return name_; } - - MOCK_METHOD(void, SetPosition, (const mantle_api::Vec3<units::length::meter_t>& inert_pos), (override)); - MOCK_METHOD(mantle_api::Vec3<units::length::meter_t>, GetPosition, (), (const, override)); - - MOCK_METHOD(void, SetVelocity, (const mantle_api::Vec3<units::velocity::meters_per_second_t>& velocity), (override)); - MOCK_METHOD(mantle_api::Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); - - MOCK_METHOD(void, SetAcceleration, (const mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); - MOCK_METHOD(mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetOrientation, (const mantle_api::Orientation3<units::angle::radian_t>& orientation), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); - - MOCK_METHOD(void, SetOrientationRate, (const mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); - - MOCK_METHOD(void, - SetOrientationAcceleration, - (const mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), - (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<std::uint64_t>& ids), (override)); - MOCK_METHOD(std::vector<std::uint64_t>, GetAssignedLaneIds, (), (const, override)); - - MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); - MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); - - void SetProperties(std::unique_ptr<mantle_api::EntityProperties> properties) override { properties_ = std::move(properties); } - mantle_api::PedestrianProperties* GetProperties() const override - { - return static_cast<mantle_api::PedestrianProperties*>(properties_.get()); - } - -private: - std::string name_{}; - std::unique_ptr<mantle_api::EntityProperties> properties_{nullptr}; -}; - -class MockStaticObject : public mantle_api::IStaticObject -{ -public: - MOCK_METHOD(mantle_api::UniqueId, GetUniqueId, (), (const, override)); - - void SetName(const std::string& name) override { name_ = name; } - const std::string& GetName() const override { return name_; } - - MOCK_METHOD(void, SetPosition, (const mantle_api::Vec3<units::length::meter_t>& inert_pos), (override)); - MOCK_METHOD(mantle_api::Vec3<units::length::meter_t>, GetPosition, (), (const, override)); - - MOCK_METHOD(void, SetVelocity, (const mantle_api::Vec3<units::velocity::meters_per_second_t>& velocity), (override)); - MOCK_METHOD(mantle_api::Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); - - MOCK_METHOD(void, SetAcceleration, (const mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); - MOCK_METHOD(mantle_api::Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetOrientation, (const mantle_api::Orientation3<units::angle::radian_t>& orientation), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); - - MOCK_METHOD(void, SetOrientationRate, (const mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); - - MOCK_METHOD(void, - SetOrientationAcceleration, - (const mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), - (override)); - MOCK_METHOD(mantle_api::Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); - - MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<std::uint64_t>& ids), (override)); - MOCK_METHOD(std::vector<std::uint64_t>, GetAssignedLaneIds, (), (const, override)); - - MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); - MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); - - void SetProperties(std::unique_ptr<mantle_api::EntityProperties> properties) override { properties_ = std::move(properties); } - MOCK_METHOD(mantle_api::StaticObjectProperties*, GetPropertiesImpl, (), (const)); - - mantle_api::StaticObjectProperties* GetProperties() const override - { - if (auto* properties = GetPropertiesImpl()) - { - return properties; - } - return static_cast<mantle_api::StaticObjectProperties*>(properties_.get()); - } - -private: - std::string name_{}; - std::unique_ptr<mantle_api::EntityProperties> properties_{nullptr}; -}; - -class MockEntityRepository : public mantle_api::IEntityRepository -{ -public: - template <typename T> - T& RegisterEntity() - { - auto entity = std::make_unique<T>(); - auto& entity_ref = entities_.emplace_back(std::move(entity)); - return *(dynamic_cast<T*>(entity_ref.get())); - } - - MockEntityRepository() - : test_vehicle_{RegisterEntity<MockVehicle>()}, - test_pedestrian_{RegisterEntity<MockPedestrian>()}, - test_static_object_{RegisterEntity<MockStaticObject>()} - { - } - - MOCK_METHOD(mantle_api::IVehicle&, - Create, - (const std::string& name, const mantle_api::VehicleProperties& properties), - (override)); - - mantle_api::IVehicle& Create(mantle_api::UniqueId id, - const std::string& name, - const mantle_api::VehicleProperties& properties) override - { - std::ignore = id; - std::ignore = name; - std::ignore = properties; - return test_vehicle_; - } - - MOCK_METHOD(mantle_api::IPedestrian&, - Create, - (const std::string& name, const mantle_api::PedestrianProperties& properties), - (override)); - - mantle_api::IPedestrian& Create(mantle_api::UniqueId id, - const std::string& name, - const mantle_api::PedestrianProperties& properties) override - { - std::ignore = id; - std::ignore = name; - std::ignore = properties; - return test_pedestrian_; - } - - mantle_api::IStaticObject& Create(mantle_api::UniqueId id, - const std::string& name, - const mantle_api::StaticObjectProperties& properties) override - { - std::ignore = id; - std::ignore = name; - std::ignore = properties; - return test_static_object_; - } - - MOCK_METHOD(mantle_api::IStaticObject&, - Create, - (const std::string& name, const mantle_api::StaticObjectProperties& properties), - ()); - - MOCK_METHOD(mantle_api::IEntity*, - GetImpl, - (const std::string& name), - ()); - - MOCK_METHOD(mantle_api::IEntity*, - GetImpl, - (const std::string& name), - (const)); - - std::optional<std::reference_wrapper<IEntity>> Get(const std::string& name) override - { - if (auto* entity = GetImpl(name)) - { - return *entity; - } - return test_vehicle_; - } - - std::optional<std::reference_wrapper<const IEntity>> Get(const std::string& name) const override - { - if (auto* entity = GetImpl(name)) - { - return *entity; - } - return test_vehicle_; - } - - std::optional<std::reference_wrapper<IEntity>> Get(mantle_api::UniqueId id) override - { - std::ignore = id; - return test_vehicle_; - } - - std::optional<std::reference_wrapper<const IEntity>> Get(mantle_api::UniqueId id) const override - { - std::ignore = id; - return test_vehicle_; - } - - mantle_api::IVehicle& GetHost() override { return test_vehicle_; } - - MOCK_METHOD(std::vector<std::unique_ptr<mantle_api::IEntity>>&, - GetEntities, - (), - (const, override)); - - bool Contains(UniqueId id) const override - { - std::ignore = id; - return false; - } - - MOCK_METHOD(void, Delete, (UniqueId), (override)); - MOCK_METHOD(void, Delete, (const std::string&), (override)); - - MOCK_METHOD(void, - Reset, - (), - (override)); - - void RegisterEntityCreatedCallback(const std::function<void(IEntity&)>& callback) override { std::ignore = callback; } - void RegisterEntityDeletedCallback(const std::function<void(const std::string&)>& callback) override { std::ignore = callback; } - void RegisterEntityDeletedCallback(const std::function<void(UniqueId)>& callback) override { std::ignore = callback; } - -private: - std::vector<std::unique_ptr<mantle_api::IEntity>> entities_{}; - MockVehicle& test_vehicle_; - MockPedestrian& test_pedestrian_; - MockStaticObject& test_static_object_; -}; - -class MockController : public mantle_api::IController -{ -public: - MOCK_METHOD(UniqueId, - GetUniqueId, - (), - (const, override)); - - MOCK_METHOD(void, - SetName, - (const std::string& name), - (override)); - - MOCK_METHOD(const std::string&, - GetName, - (), - (const, override)); - - MOCK_METHOD(void, - ChangeState, - (mantle_api::IController::LateralState, mantle_api::IController::LongitudinalState), - (override)); -}; - -class MockControllerRepository : public mantle_api::IControllerRepository -{ -public: - MOCK_METHOD(mantle_api::IController&, - Create, - (std::unique_ptr<IControllerConfig> config), - (override)); - - MOCK_METHOD(mantle_api::IController&, - Create, - (UniqueId id, std::unique_ptr<IControllerConfig> config), - (override)); - - MOCK_METHOD(std::optional<std::reference_wrapper<IController>>, - Get, - (UniqueId id), - (override)); - - MOCK_METHOD(bool, - Contains, - (UniqueId id), - (const, override)); - - MOCK_METHOD(void, - Delete, - (UniqueId id), - (override)); - - MOCK_METHOD(void, - Reset, - (), - (override)); -}; - -class MockTrafficSwarmService : public mantle_api::ITrafficSwarmService -{ -public: - MOCK_METHOD(std::vector<ITrafficSwarmService::SpawningPosition>, - GetAvailableSpawningPoses, - (), - (const, override)); - - MOCK_METHOD(mantle_api::VehicleProperties, - GetVehicleProperties, - (mantle_api::VehicleClass), - (const, override)); - - MOCK_METHOD(void, - UpdateControllerConfig, - (std::unique_ptr<mantle_api::ExternalControllerConfig>&, units::velocity::meters_per_second_t), - (override)); - - MOCK_METHOD(void, - SetSwarmEntitiesCount, - (size_t), - (override)); -}; - -class MockTrafficAreaService : public mantle_api::ITrafficAreaService -{ -public: - MOCK_METHOD(std::vector<std::shared_ptr<mantle_api::ITrafficAreaStream>>, - CreateTrafficArea, - (const mantle_api::RoadRange&), - (const, override)); -}; - -class MockTrafficAreaStream : public mantle_api::ITrafficAreaStream -{ -public: - MOCK_METHOD(units::length::meter_t, - GetLength, - (), - (const, override)); - - MOCK_METHOD(bool, - Contains, - (const mantle_api::ITrafficAreaStream::StreamPosition&), - (const, override)); - - MOCK_METHOD(const mantle_api::IEntity*, - GetEntity, - (mantle_api::ITrafficAreaStream::SearchDirection, units::length::meter_t, units::length::meter_t), - (const, override)); - - MOCK_METHOD(std::optional<mantle_api::Pose>, - Convert, - (const mantle_api::ITrafficAreaStream::StreamPose&), - (const, override)); - - MOCK_METHOD(std::optional<mantle_api::ITrafficAreaStream::StreamPose>, - Convert, - (const mantle_api::Pose&), - (const, override)); -}; - -class MockEnvironment : public mantle_api::IEnvironment -{ -public: - MOCK_METHOD(void, - CreateMap, - (const std::string& file_path, const mantle_api::MapDetails& map_details, const std::string& map_model_reference), - (override) - - ); - - MOCK_METHOD(void, AddEntityToController, (mantle_api::IEntity & entity, std::uint64_t controller_id), (override) - - ); - - MOCK_METHOD(void, RemoveEntityFromController, (std::uint64_t entity_id, std::uint64_t controller_id), (override)); - - MOCK_METHOD(void, - UpdateControlStrategies, - (std::uint64_t entity_id, - std::vector<std::shared_ptr<mantle_api::ControlStrategy>> control_strategies), - (override)); - - MOCK_METHOD(bool, - HasControlStrategyGoalBeenReached, - (std::uint64_t entity_id, mantle_api::ControlStrategyType type), - (const, override)); - - MOCK_METHOD(void, - SetWeather, - (mantle_api::Weather weather), - (override)); - - const mantle_api::ILaneLocationQueryService& GetQueryService() const override { return query_service_; } - - mantle_api::ICoordConverter* GetConverter() override { return &converter_; } - - const mantle_api::IGeometryHelper* GetGeometryHelper() const override { return &geometry_helper_; } - - mantle_api::IEntityRepository& GetEntityRepository() override { return entity_repository_; } - - const mantle_api::IEntityRepository& GetEntityRepository() const override { return entity_repository_; } - - MockControllerRepository& GetControllerRepository() override { return controller_repository_; } - - const MockControllerRepository& GetControllerRepository() const override { return controller_repository_; } - - void SetRoadCondition(std::vector<mantle_api::FrictionPatch> friction_patches) override - { - std::ignore = friction_patches; - } - - MOCK_METHOD(void, - SetTrafficSignalState, - (const std::string& traffic_signal_name, const std::string& traffic_signal_state), - (override)); - - MOCK_METHOD(void, - ExecuteCustomCommand, - (const std::vector<std::string>& actors, const std::string& type, const std::string& command), - (override)); - - MOCK_METHOD(void, - SetUserDefinedValue, - (const std::string& name, const std::string& value), - (override)); - - MOCK_METHOD(std::optional<std::string>, - GetUserDefinedValue, - (const std::string& name), - (override)); - - MOCK_METHOD(void, - SetDateTime, - (mantle_api::Time date_time), - (override)); - - MOCK_METHOD(void, - SetVariable, - (const std::string& name, const ParameterType& value), - (override)); - - MOCK_METHOD(std::optional<ParameterType>, - GetVariable, - (const std::string& name), - (const, override)); - - mantle_api::Time GetDateTime() override { return {}; } - - MOCK_METHOD(mantle_api::Time, GetSimulationTime, (), (override)); - - MOCK_METHOD(void, - SetDefaultRoutingBehavior, - (mantle_api::DefaultRoutingBehavior default_routing_behavior), - (override)); - - MOCK_METHOD(void, - AssignRoute, - (mantle_api::UniqueId entity_id, mantle_api::RouteDefinition route_definition), - (override)); - - MOCK_METHOD(void, - InitTrafficSwarmService, - (const mantle_api::TrafficSwarmParameters& parameters), - (override)); - - MockTrafficSwarmService& GetTrafficSwarmService() override { return traffic_swarm_service_; } - - MockTrafficAreaService& GetTrafficAreaService() override { return traffic_area_service_; } - -private: - MockQueryService query_service_{}; - MockEntityRepository entity_repository_{}; - MockControllerRepository controller_repository_{}; - MockConverter converter_{}; - MockGeometryHelper geometry_helper_{}; - MockTrafficSwarmService traffic_swarm_service_{}; - MockTrafficAreaService traffic_area_service_{}; -}; - -} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/CMakeLists.txt b/test/MantleAPI/Traffic/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2cb5908731f0208bf4a53047cf842e7da751b70d --- /dev/null +++ b/test/MantleAPI/Traffic/CMakeLists.txt @@ -0,0 +1,20 @@ +################################################################################ +# Copyright (c) 2023-2024 Mercedes-Benz Tech Innovation GmbH +# +# This program and the accompanying materials are made available under the terms +# of the Eclipse Public License 2.0 which is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +################################################################################ + +add_executable(TrafficTest) +target_sources( + TrafficTest PUBLIC controller_repository_test.cc controller_test.cc entity_properties_test.cc + entity_repository_test.cc entity_test.cc traffic_swarm_service_test.cc +) +target_include_directories(TrafficTest PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/test>) +target_link_libraries(TrafficTest PUBLIC MantleAPI::MantleAPI GTest::gmock_main) + +include(GoogleTest) +gtest_discover_tests(TrafficTest) diff --git a/test/MantleAPI/Traffic/controller_repository_test.cc b/test/MantleAPI/Traffic/controller_repository_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..238ebf696d72ef030fb0d82781e5dd1f6c1546bf --- /dev/null +++ b/test/MantleAPI/Traffic/controller_repository_test.cc @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <memory> +#include <utility> + +#include "MantleAPI/Common/i_identifiable.h" +#include "MantleAPI/Traffic/mock_controller.h" +#include "MantleAPI/Traffic/mock_controller_repository.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +class ControllerRepositoryTest : public testing::Test +{ +protected: + MockControllerRepository mock_controller_repository_; + IControllerRepository& controller_repository_{mock_controller_repository_}; +}; + +TEST_F(ControllerRepositoryTest, Create) +{ + auto mock_controller = std::make_shared<MockController>(); + + EXPECT_CALL(mock_controller_repository_, Create(_)) + .Times(1) + .WillOnce(Return(mock_controller)); + + std::ignore = controller_repository_.Create(std::make_unique<IControllerConfig>()); +} + +TEST_F(ControllerRepositoryTest, Get) +{ + auto mock_controller = std::make_shared<MockController>(); + + EXPECT_CALL(mock_controller_repository_, Get(_)) + .Times(1) + .WillOnce(Return(mock_controller)); + + std::ignore = controller_repository_.Get(UniqueId{0U}); +} + +TEST_F(ControllerRepositoryTest, Contains) +{ + EXPECT_CALL(std::as_const(mock_controller_repository_), Contains(_)) + .Times(1) + .WillOnce(Return(true)); + + EXPECT_TRUE(std::as_const(controller_repository_).Contains(UniqueId{0U})); +} + +TEST_F(ControllerRepositoryTest, Delete) +{ + EXPECT_CALL(mock_controller_repository_, Delete(_)) + .Times(1); + + controller_repository_.Delete(UniqueId{0U}); +} + +TEST_F(ControllerRepositoryTest, Reset) +{ + EXPECT_CALL(mock_controller_repository_, Reset()) + .Times(1); + + controller_repository_.Reset(); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/controller_test.cc b/test/MantleAPI/Traffic/controller_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..8cb5244055a575aed11b35b0c6a0bcadc8572a5c --- /dev/null +++ b/test/MantleAPI/Traffic/controller_test.cc @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "MantleAPI/Traffic/i_controller.h" +#include "MantleAPI/Traffic/mock_controller.h" + +namespace mantle_api +{ + +using testing::_; +using LateralState = IController::LateralState; +using LongitudinalState = IController::LongitudinalState; + +class ControllerTest : public testing::Test +{ +protected: + MockController mock_controller_; + IController& controller_{mock_controller_}; +}; + +TEST_F(ControllerTest, ChangeState) +{ + EXPECT_CALL(mock_controller_, ChangeState(_, _)) + .Times(1); + + controller_.ChangeState(LateralState::kActivate, LongitudinalState::kActivate); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/entity_properties_test.cc b/test/MantleAPI/Traffic/entity_properties_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..a57af2dac40aef1d7092345ea9326962137af810 --- /dev/null +++ b/test/MantleAPI/Traffic/entity_properties_test.cc @@ -0,0 +1,322 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include "MantleAPI/Traffic/entity_properties.h" + +#include <gtest/gtest.h> +#include <units.h> + +#include <type_traits> + +#include "MantleAPI/Common/bounding_box.h" + +namespace mantle_api +{ + +using namespace units::literals; + +TEST(EntityPropertiesTest, DefaultConstructed) +{ + static_assert(!std::is_default_constructible_v<EntityProperties>); + static_assert(std::is_nothrow_destructible_v<EntityProperties>); + static_assert(!std::is_copy_constructible_v<EntityProperties>); + static_assert(!std::is_copy_assignable_v<EntityProperties>); + static_assert(!std::is_move_constructible_v<EntityProperties>); + static_assert(!std::is_move_assignable_v<EntityProperties>); +} + +TEST(VehiclePropertiesTest, DefaultConstructed) +{ + static_assert(std::is_nothrow_default_constructible_v<VehicleProperties>); + static_assert(std::is_nothrow_destructible_v<VehicleProperties>); + + const auto props = VehicleProperties{}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kVehicle); + EXPECT_EQ(props.model, ""); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 0_kg); + + EXPECT_EQ(props.classification, VehicleClass::kUnknown); + EXPECT_EQ(props.performance, Performance{}); + EXPECT_EQ(props.front_axle, Axle{}); + EXPECT_EQ(props.rear_axle, Axle{}); + EXPECT_FALSE(props.is_host); + EXPECT_FALSE(props.is_controlled_externally); +} + +TEST(VehiclePropertiesTest, CopyConstructed) +{ + static_assert(std::is_copy_constructible_v<VehicleProperties>); + + const auto props = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + const auto copy = VehicleProperties{props}; + + EXPECT_EQ(copy, props); +} + +TEST(VehiclePropertiesTest, MoveConstructed) +{ + static_assert(std::is_nothrow_move_constructible_v<VehicleProperties>); + + auto props = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + const auto copy = VehicleProperties{props}; + const auto move = VehicleProperties{std::move(props)}; + + EXPECT_EQ(move, copy); +} + +TEST(VehiclePropertiesTest, ConstructedWithArgs) +{ + static_assert(std::is_nothrow_constructible_v<VehicleProperties, BoundingBox, std::string, std::map<std::string, std::string>, units::mass::kilogram_t, VehicleClass, Performance, Axle, Axle, bool, bool>); + + const auto props = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kVehicle); + EXPECT_EQ(props.model, "name"); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 1_kg); + + EXPECT_EQ(props.classification, VehicleClass::kUnknown); + EXPECT_EQ(props.performance, Performance{}); + EXPECT_EQ(props.front_axle, Axle{}); + EXPECT_EQ(props.rear_axle, Axle{}); + EXPECT_FALSE(props.is_host); + EXPECT_FALSE(props.is_controlled_externally); +} + +TEST(VehiclePropertiesTest, CopyAssigned) +{ + static_assert(std::is_nothrow_copy_assignable_v<VehicleProperties>); + + const auto props = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + auto copy = VehicleProperties{}; + copy = props; + + EXPECT_EQ(copy, props); +} + +TEST(VehiclePropertiesTest, MoveAssigned) +{ + static_assert(std::is_nothrow_move_assignable_v<VehicleProperties>); + + auto props = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + const auto copy = VehicleProperties{props}; + auto move = VehicleProperties{}; + move = std::move(props); + + EXPECT_EQ(move, copy); +} + +TEST(VehiclePropertiesTest, OperatorEqual) +{ + const auto lhs = VehicleProperties{}; + const auto rhs = VehicleProperties{}; + + EXPECT_EQ(lhs, rhs); +} + +TEST(VehiclePropertiesTest, OperatorNotEqual) +{ + const auto lhs = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, false}; + const auto rhs = VehicleProperties{BoundingBox{}, "name", {}, 1_kg, VehicleClass::kUnknown, Performance{}, Axle{}, Axle{}, false, true}; + + EXPECT_NE(lhs, rhs); +} + +TEST(PedestrianProperties, DefaultConstructed) +{ + static_assert(std::is_nothrow_default_constructible_v<PedestrianProperties>); + static_assert(std::is_nothrow_destructible_v<PedestrianProperties>); + + const auto props = PedestrianProperties{}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kPedestrian); + EXPECT_EQ(props.model, ""); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 0_kg); +} + +TEST(PedestrianProperties, CopyConstructed) +{ + static_assert(std::is_copy_constructible_v<PedestrianProperties>); + + const auto props = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + const auto copy = PedestrianProperties{props}; + + EXPECT_EQ(copy, props); +} + +TEST(PedestrianProperties, MoveConstructed) +{ + static_assert(std::is_nothrow_move_constructible_v<PedestrianProperties>); + + auto props = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + const auto copy = PedestrianProperties{props}; + const auto move = PedestrianProperties{std::move(props)}; + + EXPECT_EQ(move, copy); +} + +TEST(PedestrianProperties, ConstructedWithArgs) +{ + static_assert(std::is_nothrow_constructible_v<PedestrianProperties, BoundingBox, std::string, std::map<std::string, std::string>, units::mass::kilogram_t>); + + const auto props = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kPedestrian); + EXPECT_EQ(props.model, "name"); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 1_kg); +} + +TEST(PedestrianProperties, CopyAssigned) +{ + static_assert(std::is_nothrow_copy_assignable_v<PedestrianProperties>); + + const auto props = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + auto copy = PedestrianProperties{}; + copy = props; + + EXPECT_EQ(copy, props); +} + +TEST(PedestrianProperties, MoveAssigned) +{ + static_assert(std::is_nothrow_move_assignable_v<PedestrianProperties>); + + auto props = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + const auto copy = PedestrianProperties{props}; + auto move = PedestrianProperties{}; + move = std::move(props); + + EXPECT_EQ(move, copy); +} + +TEST(PedestrianProperties, OperatorEqual) +{ + const auto lhs = PedestrianProperties{}; + const auto rhs = PedestrianProperties{}; + + EXPECT_EQ(lhs, rhs); +} + +TEST(PedestrianProperties, OperatorNotEqual) +{ + const auto lhs = PedestrianProperties{BoundingBox{}, "name", {}, 1_kg}; + const auto rhs = PedestrianProperties{BoundingBox{}, "name", {}, 2_kg}; + + EXPECT_NE(lhs, rhs); +} + +TEST(StaticObjectProperties, DefaultConstructed) +{ + static_assert(std::is_nothrow_default_constructible_v<StaticObjectProperties>); + static_assert(std::is_nothrow_destructible_v<StaticObjectProperties>); + + const auto props = StaticObjectProperties{}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kStatic); + EXPECT_EQ(props.model, ""); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 0_kg); + + EXPECT_EQ(props.static_object_type, StaticObjectType::kUnknown); + EXPECT_EQ(props.vertical_offset, 0_m); +} + +TEST(StaticObjectProperties, CopyConstructed) +{ + static_assert(std::is_copy_constructible_v<StaticObjectProperties>); + + const auto props = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + const auto copy = StaticObjectProperties{props}; + + EXPECT_EQ(copy, props); +} + +TEST(StaticObjectProperties, MoveConstructed) +{ + static_assert(std::is_nothrow_move_constructible_v<StaticObjectProperties>); + + auto props = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + const auto copy = StaticObjectProperties{props}; + const auto move = StaticObjectProperties{std::move(props)}; + + EXPECT_EQ(move, copy); +} + +TEST(StaticObjectProperties, ConstructedWithArgs) +{ + static_assert(std::is_nothrow_constructible_v<StaticObjectProperties, BoundingBox, std::string, std::map<std::string, std::string>, units::mass::kilogram_t, StaticObjectType, units::length::meter_t>); + + const auto props = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + + EXPECT_EQ(props.bounding_box, BoundingBox{}); + EXPECT_EQ(props.type, EntityType::kStatic); + EXPECT_EQ(props.model, "name"); + const auto empty_map = std::map<std::string, std::string>{}; + EXPECT_EQ(props.properties, empty_map); + EXPECT_EQ(props.mass, 1_kg); + + EXPECT_EQ(props.static_object_type, StaticObjectType::kUnknown); + EXPECT_EQ(props.vertical_offset, 1_m); +} + +TEST(StaticObjectProperties, CopyAssigned) +{ + static_assert(std::is_nothrow_copy_assignable_v<StaticObjectProperties>); + + const auto props = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + auto copy = StaticObjectProperties{}; + copy = props; + + EXPECT_EQ(copy, props); +} + +TEST(StaticObjectProperties, MoveAssigned) +{ + static_assert(std::is_nothrow_move_assignable_v<StaticObjectProperties>); + + auto props = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + const auto copy = StaticObjectProperties{props}; + auto move = StaticObjectProperties{}; + move = std::move(props); + + EXPECT_EQ(move, copy); +} + +TEST(StaticObjectProperties, OperatorEqual) +{ + const auto lhs = StaticObjectProperties{}; + const auto rhs = StaticObjectProperties{}; + + EXPECT_EQ(lhs, rhs); +} + +TEST(StaticObjectProperties, OperatorNotEqual) +{ + const auto lhs = StaticObjectProperties{BoundingBox{}, "name", {}, 1_kg, StaticObjectType::kUnknown, 1_m}; + const auto rhs = StaticObjectProperties{BoundingBox{}, "name", {}, 2_kg, StaticObjectType::kUnknown, 1_m}; + + EXPECT_NE(lhs, rhs); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/entity_repository_test.cc b/test/MantleAPI/Traffic/entity_repository_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..44272449081a3abff2ea30e9a7827ae84e9edfea --- /dev/null +++ b/test/MantleAPI/Traffic/entity_repository_test.cc @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <functional> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "MantleAPI/Common/i_identifiable.h" +#include "MantleAPI/Traffic/entity_properties.h" +#include "MantleAPI/Traffic/i_entity.h" +#include "MantleAPI/Traffic/mock_entity.h" +#include "MantleAPI/Traffic/mock_entity_repository.h" + +namespace mantle_api +{ +using testing::_; +using testing::An; +using testing::Return; + +class EntityRepositoryTest : public testing::Test +{ +protected: + MockEntityRepository mock_entity_repository_; + IEntityRepository& entity_repository_{mock_entity_repository_}; +}; + +TEST_F(EntityRepositoryTest, CreateVehicle) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(mock_entity_repository_, Create(_, An<const VehicleProperties&>())) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = entity_repository_.Create({}, VehicleProperties{}); +} + +TEST_F(EntityRepositoryTest, CreatePedestrian) +{ + auto mock_pedestrian = std::make_shared<MockPedestrian>(); + + EXPECT_CALL(mock_entity_repository_, Create(_, An<const PedestrianProperties&>())) + .Times(1) + .WillOnce(Return(mock_pedestrian)); + + std::ignore = entity_repository_.Create({}, PedestrianProperties{}); +} + +TEST_F(EntityRepositoryTest, CreateStaticObject) +{ + auto mock_static_object = std::make_shared<MockStaticObject>(); + + EXPECT_CALL(mock_entity_repository_, Create(_, An<const StaticObjectProperties&>())) + .Times(1) + .WillOnce(Return(mock_static_object)); + + std::ignore = entity_repository_.Create({}, StaticObjectProperties{}); +} + +TEST_F(EntityRepositoryTest, GetHost) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(mock_entity_repository_, GetHost()) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = entity_repository_.GetHost(); +} + +TEST_F(EntityRepositoryTest, GetByName) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(mock_entity_repository_, Get(An<const std::string&>())) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = entity_repository_.Get(""); +} + +TEST_F(EntityRepositoryTest, GetByNameConst) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(std::as_const(mock_entity_repository_), Get(An<const std::string&>())) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = std::as_const(entity_repository_).Get(""); +} + +TEST_F(EntityRepositoryTest, GetById) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(mock_entity_repository_, Get(An<UniqueId>())) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = entity_repository_.Get(UniqueId{0U}); +} + +TEST_F(EntityRepositoryTest, GetByIdConst) +{ + auto mock_vehicle = std::make_shared<MockVehicle>(); + + EXPECT_CALL(std::as_const(mock_entity_repository_), Get(An<UniqueId>())) + .Times(1) + .WillOnce(Return(mock_vehicle)); + + std::ignore = std::as_const(entity_repository_).Get(UniqueId{0U}); +} + +TEST_F(EntityRepositoryTest, Contains) +{ + EXPECT_CALL(std::as_const(mock_entity_repository_), Contains(_)) + .Times(1) + .WillOnce(Return(true)); + + EXPECT_TRUE(std::as_const(entity_repository_).Contains(UniqueId{0U})); +} + +TEST_F(EntityRepositoryTest, DeleteByName) +{ + EXPECT_CALL(mock_entity_repository_, Delete(An<const std::string&>())) + .Times(1); + + entity_repository_.Delete(""); +} + +TEST_F(EntityRepositoryTest, Reset) +{ + EXPECT_CALL(mock_entity_repository_, Reset()) + .Times(1); + + entity_repository_.Reset(); +} + +TEST_F(EntityRepositoryTest, DeleteById) +{ + EXPECT_CALL(mock_entity_repository_, Delete(An<UniqueId>())) + .Times(1); + + entity_repository_.Delete(UniqueId{0U}); +} + +TEST_F(EntityRepositoryTest, GetEntities) +{ + auto entities = std::vector<std::weak_ptr<IEntity>>{}; + + EXPECT_CALL(mock_entity_repository_, GetEntities()) + .Times(1) + .WillOnce(Return(entities)); + + std::ignore = entity_repository_.GetEntities(); +} + +TEST_F(EntityRepositoryTest, RegisterEntityCreatedCallback) +{ + auto callback = std::function<void(std::weak_ptr<IEntity>)>{}; + + EXPECT_CALL(mock_entity_repository_, RegisterEntityCreatedCallback(_)) + .Times(1); + + entity_repository_.RegisterEntityCreatedCallback(callback); +} + +TEST_F(EntityRepositoryTest, RegisterEntityDeletedCallbackByName) +{ + auto callback = std::function<void(const std::string&)>{}; + + EXPECT_CALL(mock_entity_repository_, RegisterEntityDeletedCallback(An<const std::function<void(const std::string&)>&>())) + .Times(1); + + entity_repository_.RegisterEntityDeletedCallback(callback); +} + +TEST_F(EntityRepositoryTest, RegisterEntityDeletedCallbackById) +{ + auto callback = std::function<void(UniqueId)>{}; + + EXPECT_CALL(mock_entity_repository_, RegisterEntityDeletedCallback(An<const std::function<void(UniqueId)>&>())) + .Times(1); + + entity_repository_.RegisterEntityDeletedCallback(callback); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/entity_test.cc b/test/MantleAPI/Traffic/entity_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..79c84f96b6b9126110c4a8566429c16851f95898 --- /dev/null +++ b/test/MantleAPI/Traffic/entity_test.cc @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <tuple> +#include <utility> + +#include "MantleAPI/Traffic/entity_properties.h" +#include "MantleAPI/Traffic/i_entity.h" +#include "MantleAPI/Traffic/mock_entity.h" + +namespace mantle_api +{ + +using testing::_; +using testing::Return; + +/******************************************************************************* + * EntityTest + *******************************************************************************/ +class EntityTest : public testing::Test +{ +protected: + MockEntity mock_entity_; + IEntity& entity_{mock_entity_}; +}; + +TEST_F(EntityTest, SetPosition) +{ + EXPECT_CALL(mock_entity_, SetPosition(_)) + .Times(1); + + entity_.SetPosition({}); +} + +TEST_F(EntityTest, GetPosition) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetPosition()) + .Times(1) + .WillOnce(Return(Vec3<units::length::meter_t>{})); + + std::ignore = std::as_const(entity_).GetPosition(); +} + +TEST_F(EntityTest, SetVelocity) +{ + EXPECT_CALL(mock_entity_, SetVelocity(_)) + .Times(1); + + entity_.SetVelocity({}); +} + +TEST_F(EntityTest, GetVelocity) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetVelocity()) + .Times(1) + .WillOnce(Return(Vec3<units::velocity::meters_per_second_t>{})); + + std::ignore = std::as_const(entity_).GetVelocity(); +} + +TEST_F(EntityTest, SetAcceleration) +{ + EXPECT_CALL(mock_entity_, SetAcceleration(_)) + .Times(1); + + entity_.SetAcceleration({}); +} + +TEST_F(EntityTest, GetAcceleration) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetAcceleration()) + .Times(1) + .WillOnce(Return(Vec3<units::acceleration::meters_per_second_squared_t>{})); + + std::ignore = std::as_const(entity_).GetAcceleration(); +} + +TEST_F(EntityTest, SetOrientation) +{ + EXPECT_CALL(mock_entity_, SetOrientation(_)) + .Times(1); + + entity_.SetOrientation({}); +} + +TEST_F(EntityTest, GetOrientation) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetOrientation()) + .Times(1) + .WillOnce(Return(Orientation3<units::angle::radian_t>{})); + + std::ignore = std::as_const(entity_).GetOrientation(); +} + +TEST_F(EntityTest, SetOrientationRate) +{ + EXPECT_CALL(mock_entity_, SetOrientationRate(_)) + .Times(1); + + entity_.SetOrientationRate({}); +} + +TEST_F(EntityTest, GetOrientationRate) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetOrientationRate()) + .Times(1) + .WillOnce(Return(Orientation3<units::angular_velocity::radians_per_second_t>{})); + + std::ignore = std::as_const(entity_).GetOrientationRate(); +} + +TEST_F(EntityTest, SetOrientationAcceleration) +{ + EXPECT_CALL(mock_entity_, SetOrientationAcceleration(_)) + .Times(1); + + entity_.SetOrientationAcceleration({}); +} + +TEST_F(EntityTest, GetOrientationAcceleration) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetOrientationAcceleration()) + .Times(1) + .WillOnce(Return(Orientation3<units::angular_acceleration::radians_per_second_squared_t>{})); + + std::ignore = std::as_const(entity_).GetOrientationAcceleration(); +} + +TEST_F(EntityTest, SetProperties) +{ + EXPECT_CALL(mock_entity_, SetProperties(_)) + .Times(1); + + entity_.SetProperties({}); +} + +TEST_F(EntityTest, GetProperties) +{ + auto properties = VehicleProperties{}; + + EXPECT_CALL(std::as_const(mock_entity_), GetProperties()) + .Times(1) + .WillOnce(Return(&properties)); + + const auto* result = std::as_const(entity_).GetProperties(); + + ASSERT_TRUE(result); +} + +TEST_F(EntityTest, SetAssignedLaneIds) +{ + EXPECT_CALL(mock_entity_, SetAssignedLaneIds(_)) + .Times(1); + + entity_.SetAssignedLaneIds({}); +} + +TEST_F(EntityTest, GetAssignedLaneIds) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetAssignedLaneIds()) + .Times(1) + .WillOnce(Return(std::vector<mantle_api::UniqueId>{})); + + std::ignore = std::as_const(entity_).GetAssignedLaneIds(); +} + +TEST_F(EntityTest, SetVisibility) +{ + EXPECT_CALL(mock_entity_, SetVisibility(_)) + .Times(1); + + entity_.SetVisibility({}); +} + +TEST_F(EntityTest, GetVisibility) +{ + EXPECT_CALL(std::as_const(mock_entity_), GetVisibility()) + .Times(1) + .WillOnce(Return(EntityVisibilityConfig{})); + + std::ignore = std::as_const(entity_).GetVisibility(); +} + +/******************************************************************************* + * VehicleTest + *******************************************************************************/ +class VehicleTest : public testing::Test +{ +protected: + MockVehicle mock_vehicle_; + IVehicle& vehicle_{mock_vehicle_}; +}; + +TEST_F(VehicleTest, GetProperties) +{ + auto properties = VehicleProperties{}; + + EXPECT_CALL(std::as_const(mock_vehicle_), GetProperties()) + .Times(1) + .WillOnce(Return(&properties)); + + const auto* result = std::as_const(vehicle_).GetProperties(); + + ASSERT_TRUE(result); +} + +/******************************************************************************* + * PedestrianTest + *******************************************************************************/ +class PedestrianTest : public testing::Test +{ +protected: + MockPedestrian mock_pedestrian_; + IPedestrian& pedestrian_{mock_pedestrian_}; +}; + +TEST_F(PedestrianTest, GetProperties) +{ + auto properties = PedestrianProperties{}; + + EXPECT_CALL(std::as_const(mock_pedestrian_), GetProperties()) + .Times(1) + .WillOnce(Return(&properties)); + + const auto* result = std::as_const(pedestrian_).GetProperties(); + + ASSERT_TRUE(result); +} + +/******************************************************************************* + * StaticObjectTest + *******************************************************************************/ +class StaticObjectTest : public testing::Test +{ +protected: + MockStaticObject mock_static_object_; + IStaticObject& static_object_{mock_static_object_}; +}; + +TEST_F(StaticObjectTest, GetProperties) +{ + auto properties = StaticObjectProperties{}; + + EXPECT_CALL(std::as_const(mock_static_object_), GetProperties()) + .Times(1) + .WillOnce(Return(&properties)); + + std::ignore = std::as_const(static_object_).GetProperties(); +} + +} // namespace mantle_api diff --git a/test/MantleAPI/Traffic/mock_controller.h b/test/MantleAPI/Traffic/mock_controller.h new file mode 100644 index 0000000000000000000000000000000000000000..e246eeeb0d2fdea2ed6d1ed8aa2c7525da9a7e62 --- /dev/null +++ b/test/MantleAPI/Traffic/mock_controller.h @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_H +#define MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_H + +#include <gmock/gmock.h> + +#include "MantleAPI/Traffic/i_controller.h" + +namespace mantle_api +{ + +class MockController : public IController +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IController + MOCK_METHOD(void, ChangeState, (LateralState lateral_state, LongitudinalState longitudinal_state), (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_H diff --git a/test/MantleAPI/Traffic/mock_controller_repository.h b/test/MantleAPI/Traffic/mock_controller_repository.h new file mode 100644 index 0000000000000000000000000000000000000000..7d5b9fbd0b26e6b1c3bf59964bf2b74e3d233589 --- /dev/null +++ b/test/MantleAPI/Traffic/mock_controller_repository.h @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_REPOSITORY_H +#define MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_REPOSITORY_H + +#include <gmock/gmock.h> + +#include "MantleAPI/Traffic/i_controller_repository.h" + +namespace mantle_api +{ + +class MockControllerRepository : public IControllerRepository +{ +public: + MOCK_METHOD(std::weak_ptr<IController>, Create, (std::unique_ptr<IControllerConfig> properties), (override)); + MOCK_METHOD(std::weak_ptr<IController>, Create, (UniqueId id, std::unique_ptr<IControllerConfig> properties), (override)); + MOCK_METHOD(std::weak_ptr<IController>, Get, (UniqueId id), (override)); + MOCK_METHOD(bool, Contains, (UniqueId id), (const, override)); + MOCK_METHOD(void, Delete, (UniqueId id), (override)); + MOCK_METHOD(void, Reset, (), (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_CONTROLLER_REPOSITORY_H diff --git a/test/MantleAPI/Traffic/mock_entity.h b/test/MantleAPI/Traffic/mock_entity.h new file mode 100644 index 0000000000000000000000000000000000000000..da0be33ba07b84ae26fb8d5664c479da4704af4a --- /dev/null +++ b/test/MantleAPI/Traffic/mock_entity.h @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_ENTITY_H +#define MANTLEAPI_TRAFFIC_MOCK_ENTITY_H + +#include <gmock/gmock.h> + +#include <memory> + +#include "MantleAPI/Map/i_route.h" +#include "MantleAPI/Traffic/i_entity.h" + +namespace mantle_api +{ + +class MockEntity : public IEntity +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IEntity + MOCK_METHOD(void, SetPosition, (const Vec3<units::length::meter_t>& inert_pos), (override)); + MOCK_METHOD(Vec3<units::length::meter_t>, GetPosition, (), (const, override)); + + MOCK_METHOD(void, SetVelocity, (const Vec3<units::velocity::meters_per_second_t>& velocity), (override)); + MOCK_METHOD(Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); + + MOCK_METHOD(void, SetAcceleration, (const Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); + MOCK_METHOD(Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetOrientation, (const Orientation3<units::angle::radian_t>& orientation), (override)); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); + + MOCK_METHOD(void, SetOrientationRate, (const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); + MOCK_METHOD(Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); + + MOCK_METHOD(void, SetOrientationAcceleration, (const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), (override)); + MOCK_METHOD(Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetProperties, (std::unique_ptr<EntityProperties> properties), (override)); + MOCK_METHOD(EntityProperties*, GetProperties, (), (const, override)); + + MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<mantle_api::UniqueId>& assigned_lane_ids), (override)); + MOCK_METHOD(std::vector<mantle_api::UniqueId>, GetAssignedLaneIds, (), (const, override)); + + MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); + MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); + + MOCK_METHOD(void, SetRoute, (const std::weak_ptr<const IRoute>& route), (override)); + MOCK_METHOD(std::weak_ptr<const IRoute>, GetRoute, (), (const, override)); +}; + +class MockVehicle : public IVehicle +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IEntity + MOCK_METHOD(void, SetPosition, (const Vec3<units::length::meter_t>& inert_pos), (override)); + MOCK_METHOD(Vec3<units::length::meter_t>, GetPosition, (), (const, override)); + + MOCK_METHOD(void, SetVelocity, (const Vec3<units::velocity::meters_per_second_t>& velocity), (override)); + MOCK_METHOD(Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); + + MOCK_METHOD(void, SetAcceleration, (const Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); + MOCK_METHOD(Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetOrientation, (const Orientation3<units::angle::radian_t>& orientation), (override)); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); + + MOCK_METHOD(void, SetOrientationRate, (const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); + MOCK_METHOD(Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); + + MOCK_METHOD(void, SetOrientationAcceleration, (const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), (override)); + MOCK_METHOD(Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetProperties, (std::unique_ptr<EntityProperties> properties), (override)); + // MOCK_METHOD(EntityProperties*, GetProperties, (), (const, override)); + + MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<mantle_api::UniqueId>& assigned_lane_ids), (override)); + MOCK_METHOD(std::vector<mantle_api::UniqueId>, GetAssignedLaneIds, (), (const, override)); + + MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); + MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); + + MOCK_METHOD(void, SetRoute, (const std::weak_ptr<const IRoute>& route), (override)); + MOCK_METHOD(std::weak_ptr<const IRoute>, GetRoute, (), (const, override)); + + // IVehicle + MOCK_METHOD(VehicleProperties*, GetProperties, (), (const, override)); + + MOCK_METHOD(void, SetSteeringWheelAngle, (units::angle::radian_t steering_wheel_angle), (override)); + MOCK_METHOD(units::angle::radian_t, GetSteeringWheelAngle, (), (const, override)); +}; + +class MockPedestrian : public IPedestrian +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IEntity + MOCK_METHOD(void, SetPosition, (const Vec3<units::length::meter_t>& inert_pos), (override)); + MOCK_METHOD(Vec3<units::length::meter_t>, GetPosition, (), (const, override)); + + MOCK_METHOD(void, SetVelocity, (const Vec3<units::velocity::meters_per_second_t>& velocity), (override)); + MOCK_METHOD(Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); + + MOCK_METHOD(void, SetAcceleration, (const Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); + MOCK_METHOD(Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetOrientation, (const Orientation3<units::angle::radian_t>& orientation), (override)); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); + + MOCK_METHOD(void, SetOrientationRate, (const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); + MOCK_METHOD(Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); + + MOCK_METHOD(void, SetOrientationAcceleration, (const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), (override)); + MOCK_METHOD(Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetProperties, (std::unique_ptr<EntityProperties> properties), (override)); + // MOCK_METHOD(EntityProperties*, GetProperties, (), (const, override)); + + MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<mantle_api::UniqueId>& assigned_lane_ids), (override)); + MOCK_METHOD(std::vector<mantle_api::UniqueId>, GetAssignedLaneIds, (), (const, override)); + + MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); + MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); + + MOCK_METHOD(void, SetRoute, (const std::weak_ptr<const IRoute>& route), (override)); + MOCK_METHOD(std::weak_ptr<const IRoute>, GetRoute, (), (const, override)); + + // IPedestrian + MOCK_METHOD(PedestrianProperties*, GetProperties, (), (const, override)); +}; + +class MockStaticObject : public IStaticObject +{ +public: + // IIdentifiable + MOCK_METHOD(UniqueId, GetUniqueId, (), (const, override)); + + MOCK_METHOD(void, SetName, (const std::string& name), (override)); + + MOCK_METHOD(const std::string&, GetName, (), (const, override)); + + // IEntity + MOCK_METHOD(void, SetPosition, (const Vec3<units::length::meter_t>& inert_pos), (override)); + MOCK_METHOD(Vec3<units::length::meter_t>, GetPosition, (), (const, override)); + + MOCK_METHOD(void, SetVelocity, (const Vec3<units::velocity::meters_per_second_t>& velocity), (override)); + MOCK_METHOD(Vec3<units::velocity::meters_per_second_t>, GetVelocity, (), (const, override)); + + MOCK_METHOD(void, SetAcceleration, (const Vec3<units::acceleration::meters_per_second_squared_t>& acceleration), (override)); + MOCK_METHOD(Vec3<units::acceleration::meters_per_second_squared_t>, GetAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetOrientation, (const Orientation3<units::angle::radian_t>& orientation), (override)); + MOCK_METHOD(Orientation3<units::angle::radian_t>, GetOrientation, (), (const, override)); + + MOCK_METHOD(void, SetOrientationRate, (const Orientation3<units::angular_velocity::radians_per_second_t>& orientation_rate), (override)); + MOCK_METHOD(Orientation3<units::angular_velocity::radians_per_second_t>, GetOrientationRate, (), (const, override)); + + MOCK_METHOD(void, SetOrientationAcceleration, (const Orientation3<units::angular_acceleration::radians_per_second_squared_t>& orientation_acceleration), (override)); + MOCK_METHOD(Orientation3<units::angular_acceleration::radians_per_second_squared_t>, GetOrientationAcceleration, (), (const, override)); + + MOCK_METHOD(void, SetProperties, (std::unique_ptr<EntityProperties> properties), (override)); + // MOCK_METHOD(EntityProperties*, GetProperties, (), (const, override)); + + MOCK_METHOD(void, SetAssignedLaneIds, (const std::vector<mantle_api::UniqueId>& assigned_lane_ids), (override)); + MOCK_METHOD(std::vector<mantle_api::UniqueId>, GetAssignedLaneIds, (), (const, override)); + + MOCK_METHOD(void, SetVisibility, (const EntityVisibilityConfig& visibility), (override)); + MOCK_METHOD(EntityVisibilityConfig, GetVisibility, (), (const, override)); + + MOCK_METHOD(void, SetRoute, (const std::weak_ptr<const IRoute>& route), (override)); + MOCK_METHOD(std::weak_ptr<const IRoute>, GetRoute, (), (const, override)); + + // IStaticObject + MOCK_METHOD(StaticObjectProperties*, GetProperties, (), (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_ENTITY_H diff --git a/test/MantleAPI/Traffic/mock_entity_repository.h b/test/MantleAPI/Traffic/mock_entity_repository.h new file mode 100644 index 0000000000000000000000000000000000000000..d4683a1ed6bbb4303764ebd4a600cbc1f185f3fe --- /dev/null +++ b/test/MantleAPI/Traffic/mock_entity_repository.h @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2023, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_ENTITY_REPOSITORY_H +#define MANTLEAPI_TRAFFIC_MOCK_ENTITY_REPOSITORY_H + +#include <gmock/gmock.h> + +#include "MantleAPI/Traffic/i_entity_repository.h" + +namespace mantle_api +{ + +class MockEntityRepository : public IEntityRepository +{ +public: + MOCK_METHOD(std::weak_ptr<IVehicle>, Create, (const std::string& name, const VehicleProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IVehicle>, Create, (UniqueId id, const std::string& name, const VehicleProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IPedestrian>, Create, (const std::string& name, const PedestrianProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IPedestrian>, Create, (UniqueId id, const std::string& name, const PedestrianProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IStaticObject>, Create, (const std::string& name, const StaticObjectProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IStaticObject>, Create, (UniqueId id, const std::string& name, const StaticObjectProperties& properties), (override)); + MOCK_METHOD(std::weak_ptr<IVehicle>, GetHost, (), (override)); + MOCK_METHOD(std::weak_ptr<IEntity>, Get, (const std::string& name), (override)); + MOCK_METHOD(std::weak_ptr<const IEntity>, Get, (const std::string& name), (const, override)); + MOCK_METHOD(std::weak_ptr<IEntity>, Get, (UniqueId id), (override)); + MOCK_METHOD(std::weak_ptr<const IEntity>, Get, (UniqueId id), (const, override)); + MOCK_METHOD(bool, Contains, (UniqueId id), (const, override)); + MOCK_METHOD(void, Delete, (const std::string& name), (override)); + MOCK_METHOD(void, Delete, (UniqueId id), (override)); + MOCK_METHOD(void, Reset, (), (override)); + MOCK_METHOD(std::vector<std::weak_ptr<IEntity>>, GetEntities, (), (const, override)); + MOCK_METHOD(void, RegisterEntityCreatedCallback, (const std::function<void(std::weak_ptr<IEntity>)>& callback), (override)); + MOCK_METHOD(void, RegisterEntityDeletedCallback, (const std::function<void(const std::string&)>& callback), (override)); + MOCK_METHOD(void, RegisterEntityDeletedCallback, (const std::function<void(UniqueId)>& callback), (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_ENTITY_REPOSITORY_H diff --git a/test/MantleAPI/Traffic/mock_traffic_area_service.h b/test/MantleAPI/Traffic/mock_traffic_area_service.h new file mode 100644 index 0000000000000000000000000000000000000000..a97cbaf48e91d4522d0800eb7a7500bf78c79ffb --- /dev/null +++ b/test/MantleAPI/Traffic/mock_traffic_area_service.h @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2025, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_AREA_SERVICE_H +#define MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_AREA_SERVICE_H + +#include <gmock/gmock.h> + +#include "MantleAPI/Traffic/i_traffic_area_service.h" + +namespace mantle_api +{ +class MockTrafficAreaService : public ITrafficAreaService +{ +public: + MOCK_METHOD(TrafficArea, CreateTrafficArea, (const RoadRange& road_range), (const, override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_AREA_SERVICE_H diff --git a/test/MantleAPI/Traffic/mock_traffic_swarm_service.h b/test/MantleAPI/Traffic/mock_traffic_swarm_service.h new file mode 100644 index 0000000000000000000000000000000000000000..56b7adfaf81d13d860b124ed2d99ad1f5bc2633e --- /dev/null +++ b/test/MantleAPI/Traffic/mock_traffic_swarm_service.h @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#ifndef MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_SWARM_SERVICE_H +#define MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_SWARM_SERVICE_H + +#include <gmock/gmock.h> +#include <units.h> + +#include <cstddef> +#include <memory> +#include <vector> + +#include "MantleAPI/Traffic/entity_properties.h" +#include "MantleAPI/Traffic/i_controller_config.h" +#include "MantleAPI/Traffic/i_traffic_swarm_service.h" + +namespace mantle_api +{ +class MockTrafficSwarmService : public ITrafficSwarmService +{ +public: + MOCK_METHOD(std::vector<SpawningPosition>, GetAvailableSpawningPoses, (), (const, override)); + MOCK_METHOD(mantle_api::VehicleProperties, GetVehicleProperties, (mantle_api::VehicleClass vehicle_class), (const, override)); + MOCK_METHOD(void, UpdateControllerConfig, (std::unique_ptr<mantle_api::ExternalControllerConfig> & config, units::velocity::meters_per_second_t speed), (override)); + MOCK_METHOD(void, SetSwarmEntitiesCount, (std::size_t count), (override)); +}; + +} // namespace mantle_api + +#endif // MANTLEAPI_TRAFFIC_MOCK_TRAFFIC_SWARM_SERVICE_H diff --git a/test/MantleAPI/Traffic/traffic_swarm_service_test.cc b/test/MantleAPI/Traffic/traffic_swarm_service_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..9ddb2f535cdb345942eb6763107652c09662a7f5 --- /dev/null +++ b/test/MantleAPI/Traffic/traffic_swarm_service_test.cc @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2024, Mercedes-Benz Tech Innovation GmbH + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <units.h> + +#include "MantleAPI/Traffic/i_traffic_swarm_service.h" +#include "MantleAPI/Traffic/mock_traffic_swarm_service.h" + +namespace mantle_api +{ + +using testing::_; +using units::literals::operator""_mps; + +class TrafficSwarmServiceTest : public testing::Test +{ +protected: + MockTrafficSwarmService mock_traffic_swarm_service_; + ITrafficSwarmService& traffic_swarm_service_{mock_traffic_swarm_service_}; +}; + +TEST_F(TrafficSwarmServiceTest, GetAvailableSpawningPoses) +{ + EXPECT_CALL(mock_traffic_swarm_service_, GetAvailableSpawningPoses()) + .Times(1); + + std::ignore = traffic_swarm_service_.GetAvailableSpawningPoses(); +} + +TEST_F(TrafficSwarmServiceTest, GetVehicleProperties) +{ + EXPECT_CALL(mock_traffic_swarm_service_, GetVehicleProperties(_)) + .Times(1); + + std::ignore = traffic_swarm_service_.GetVehicleProperties(VehicleClass::kSmallCar); +} + +TEST_F(TrafficSwarmServiceTest, UpdateControllerConfig) +{ + EXPECT_CALL(mock_traffic_swarm_service_, UpdateControllerConfig(_, _)) + .Times(1); + + auto config = std::make_unique<ExternalControllerConfig>(); + static constexpr auto kSpeed = 10.0_mps; + + traffic_swarm_service_.UpdateControllerConfig(config, kSpeed); +} + +TEST_F(TrafficSwarmServiceTest, SetSwarmEntitiesCount) +{ + EXPECT_CALL(mock_traffic_swarm_service_, SetSwarmEntitiesCount(_)) + .Times(1); + + static constexpr auto kCount = 10U; + + traffic_swarm_service_.SetSwarmEntitiesCount(kCount); +} + +} // namespace mantle_api diff --git a/test/interface_test.cpp b/test/interface_test.cpp deleted file mode 100644 index f22d8eddbe30ab667cc67b0ea92ec545582eca94..0000000000000000000000000000000000000000 --- a/test/interface_test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ - -//----------------------------------------------------------------------------- -/** @file interface_test.cpp */ -//----------------------------------------------------------------------------- - -#include <units.h> - -#include "MantleAPI/Common/position.h" -#include "MantleAPI/Map/i_coord_converter.h" -#include "MantleAPI/Test/test_utils.h" -#include "MantleAPI/Traffic/entity_properties.h" -#include "MantleAPI/Traffic/i_entity.h" -#include "MantleAPI/Traffic/i_entity_repository.h" - -TEST(InterfaceTest, GivenTeleportAction_When_ThenHostVehicleIsPlaced) -{ - using namespace units::literals; - - mantle_api::Position inert_pos{}; - inert_pos = mantle_api::OpenDriveRoadPosition{"0", 0_m, 0_m}; - mantle_api::MockEnvironment env{}; - env.CreateMap("dummy_map_path", {}, ""); - - mantle_api::VehicleProperties vehicle_properties; - vehicle_properties.is_host = true; - vehicle_properties.model = "G12"; - - auto& repo = env.GetEntityRepository(); - - mantle_api::MockVehicle mock_vehicle{}; - ON_CALL(dynamic_cast<mantle_api::MockEntityRepository&>(repo), Create(testing::_, vehicle_properties)) - .WillByDefault(testing::ReturnRef(mock_vehicle)); - - auto& host_vehicle = repo.Create("host", vehicle_properties); - auto* converter = env.GetConverter(); - auto world_pos = converter->Convert(inert_pos); - host_vehicle.SetPosition(world_pos); - host_vehicle.SetVisibility(mantle_api::EntityVisibilityConfig{true, false, true, {"radar"}}); -}