From db325a85da6805ed2ea0802fecd60e519fd36961 Mon Sep 17 00:00:00 2001 From: Arun Das <arun.das@bmw.de> Date: Wed, 26 May 2021 07:47:23 +0200 Subject: [PATCH] - rename 'SimulationTime' typedef to 'Time' and rename simulation_time.h to time_utils.h - add new SimulationTime struct containing the current_sim_time and the last_delta_time - Add 'SimulationTime GetSimulationTime()' to IEnvironment for fixing SimulationTimeCondition - Add 'HasControlStrategyGoalBeenReached' to IEnvironment to check with the controller, if an action can be set to 'completed' state - Add ControlStrategyType to avoid dynamic_cast - followed C++ guideline for enum values with leading k... - cleaned up deprecated controller configs Signed-off-by: Arun Das <arun.das@bmw.de> --- .../MantleAPI/Common/simulation_time.h | 24 +-- MantleAPI/include/MantleAPI/Common/spline.h | 8 +- .../include/MantleAPI/Common/time_utils.h | 44 ++++++ MantleAPI/include/MantleAPI/Common/vector.h | 3 + .../EnvironmentalConditions/date_time.h | 7 +- .../MantleAPI/Execution/i_environment.h | 14 +- .../MantleAPI/Execution/scenario_info.h | 4 +- .../MantleAPI/Traffic/control_strategy.h | 140 +++++++++++++----- .../MantleAPI/Traffic/entity_properties.h | 2 + .../MantleAPI/Traffic/i_controller_config.h | 30 +--- .../include/MantleAPI/Traffic/i_entity.h | 1 - MantleAPI/test/MantleAPI/Test/test_utils.h | 11 +- 12 files changed, 189 insertions(+), 99 deletions(-) create mode 100644 MantleAPI/include/MantleAPI/Common/time_utils.h diff --git a/MantleAPI/include/MantleAPI/Common/simulation_time.h b/MantleAPI/include/MantleAPI/Common/simulation_time.h index 77200149..bd06dbaf 100644 --- a/MantleAPI/include/MantleAPI/Common/simulation_time.h +++ b/MantleAPI/include/MantleAPI/Common/simulation_time.h @@ -15,30 +15,16 @@ #ifndef MANTLEAPI_COMMON_SIMULATION_TIME_H #define MANTLEAPI_COMMON_SIMULATION_TIME_H -#include <chrono> +#include "time_utils.h" namespace mantle_api { -using SimulationTime = std::chrono::duration<std::int64_t, std::milli>; -/// @brief Converts input in [s] to @ref SimulationTime. -/// @tparam T Input type, eg. `double`. -/// @param duration Input value -/// @return Duration representing the given input in units of @ref SimulationTime. -template <typename T> -inline SimulationTime SecondsToSimulationTime(T duration) +struct SimulationTime { - return std::chrono::duration_cast<SimulationTime>(std::chrono::duration<T>{duration}); -} + mantle_api::Time current_sim_time_ms{0}; + mantle_api::Time last_delta_time_ms{0}; +}; -/// @brief Converts input @ref SimulationTime to [s]. -/// @param time Simulation time -/// @return Duration ins seconds representing the passed in @ref SimulationTime. -inline double SimulationTimeToSeconds(const SimulationTime& time) -{ - return static_cast<double>(time.count()) / 1000.0; -} - } // namespace mantle_api - #endif // MANTLEAPI_COMMON_SIMULATION_TIME_H diff --git a/MantleAPI/include/MantleAPI/Common/spline.h b/MantleAPI/include/MantleAPI/Common/spline.h index 1fd7c9be..d12d4ddc 100644 --- a/MantleAPI/include/MantleAPI/Common/spline.h +++ b/MantleAPI/include/MantleAPI/Common/spline.h @@ -16,7 +16,7 @@ #define MANTLEAPI_COMMON_SPLINE_H #include <MantleAPI/Common/floating_point_helper.h> -#include <MantleAPI/Common/simulation_time.h> +#include <MantleAPI/Common/time_utils.h> #include <array> @@ -24,15 +24,15 @@ namespace mantle_api { struct SplineSection { - mantle_api::SimulationTime start_time{0}; - mantle_api::SimulationTime end_time{0}; + mantle_api::Time start_time{0}; + mantle_api::Time end_time{0}; /// @brief Represents the polynomial. /// /// The array 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::array<double, 4> polynomial; + std::array<double, 4> polynomial{0, 0, 0, 0}; }; /// @brief Equality comparison for SplineSection. diff --git a/MantleAPI/include/MantleAPI/Common/time_utils.h b/MantleAPI/include/MantleAPI/Common/time_utils.h new file mode 100644 index 00000000..78b9b51a --- /dev/null +++ b/MantleAPI/include/MantleAPI/Common/time_utils.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2021, 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 time_utils.h */ +//----------------------------------------------------------------------------- + +#ifndef MANTLEAPI_COMMON_TIME_UTILS_H +#define MANTLEAPI_COMMON_TIME_UTILS_H + +#include <chrono> + +namespace mantle_api +{ +using Time = std::chrono::duration<std::int64_t, std::milli>; + +/// @brief Converts input in [s] to @ref Time. +/// @tparam T Input type, eg. `double`. +/// @param duration Input value +/// @return Duration representing the given input in units of @ref Time. +template <typename T> +inline Time SecondsToTime(T duration) +{ + return std::chrono::duration_cast<Time>(std::chrono::duration<T>{duration}); +} + +/// @brief Converts input @ref Time to [s]. +/// @param time Time +/// @return Duration in seconds representing the passed in @ref Time. +inline double TimeToSeconds(const Time& time) +{ + return static_cast<double>(time.count()) / 1000.0; +} + +} // namespace mantle_api + +#endif // MANTLEAPI_COMMON_TIME_UTILS_H diff --git a/MantleAPI/include/MantleAPI/Common/vector.h b/MantleAPI/include/MantleAPI/Common/vector.h index d495f9dd..5127e5e0 100644 --- a/MantleAPI/include/MantleAPI/Common/vector.h +++ b/MantleAPI/include/MantleAPI/Common/vector.h @@ -31,7 +31,10 @@ struct Vec3 T x{}; T y{}; T z{}; + + inline T Length() const { return sqrt((x * x) + (y * y) + (z * z)); } }; + using Vec3d = Vec3<double>; inline bool operator==(const Vec3d& lhs, const Vec3d& rhs) noexcept diff --git a/MantleAPI/include/MantleAPI/EnvironmentalConditions/date_time.h b/MantleAPI/include/MantleAPI/EnvironmentalConditions/date_time.h index f1005118..b879da03 100644 --- a/MantleAPI/include/MantleAPI/EnvironmentalConditions/date_time.h +++ b/MantleAPI/include/MantleAPI/EnvironmentalConditions/date_time.h @@ -15,16 +15,17 @@ #ifndef MANTLEAPI_ENVIRONMENTALCONDITIONS_DATETIME_H #define MANTLEAPI_ENVIRONMENTALCONDITIONS_DATETIME_H -#include <MantleAPI/Common/simulation_time.h> +#include <MantleAPI/Common/time_utils.h> #include <chrono> namespace mantle_api { -struct DateTime +// TODO: Delete this struct and use Time directly in Get/SetDateTime once the move to the MantleAPI is complete +struct [[deprecated]] DateTime { - SimulationTime date_time_ms{0}; + Time date_time_ms{0}; }; } // namespace mantle_api diff --git a/MantleAPI/include/MantleAPI/Execution/i_environment.h b/MantleAPI/include/MantleAPI/Execution/i_environment.h index 337b8207..5fbbcbf9 100644 --- a/MantleAPI/include/MantleAPI/Execution/i_environment.h +++ b/MantleAPI/include/MantleAPI/Execution/i_environment.h @@ -15,6 +15,7 @@ #ifndef MANTLEAPI_EXECUTION_IENVIRONMENT_H #define MANTLEAPI_EXECUTION_IENVIRONMENT_H +#include <MantleAPI/Common/simulation_time.h> #include <MantleAPI/EnvironmentalConditions/date_time.h> #include <MantleAPI/EnvironmentalConditions/road_condition.h> #include <MantleAPI/EnvironmentalConditions/weather.h> @@ -32,9 +33,6 @@ class IEnvironment public: virtual ~IEnvironment() = default; - virtual void Init() = 0; - virtual void Step() = 0; - /// Load a map file and parse it into the memory. /// /// @param file_path raw map file path from the scenario file. Resolving to a valid file path is done in the @@ -64,6 +62,13 @@ class IEnvironment std::uint64_t controller_id, std::vector<std::unique_ptr<mantle_api::ControlStrategy>>& control_strategies) = 0; + /// Checks, if a control strategy of a certain type in a specific controller is fulfilled + /// + /// @param controller_id The controller to check + /// @param type The control strategy type + virtual bool HasControlStrategyGoalBeenReached(std::uint64_t controller_id, + mantle_api::ControlStrategyType type) const = 0; + virtual const ILaneLocationQueryService& GetQueryService() const = 0; virtual const ICoordConverter* GetConverter() const = 0; @@ -74,6 +79,9 @@ class IEnvironment virtual void SetDateTime(DateTime date_time) = 0; virtual DateTime GetDateTime() = 0; + /// @brief Time since start of simulation and delta time to previous step + virtual SimulationTime GetSimulationTime() = 0; + virtual void SetWeather(Weather weather) = 0; virtual void SetRoadCondition(std::vector<FrictionPatch> friction_patches) = 0; }; diff --git a/MantleAPI/include/MantleAPI/Execution/scenario_info.h b/MantleAPI/include/MantleAPI/Execution/scenario_info.h index 6e0dd3b4..72f0cede 100644 --- a/MantleAPI/include/MantleAPI/Execution/scenario_info.h +++ b/MantleAPI/include/MantleAPI/Execution/scenario_info.h @@ -15,7 +15,7 @@ #ifndef MANTLEAPI_EXECUTION_SCENARIOINFO_H #define MANTLEAPI_EXECUTION_SCENARIOINFO_H -#include <MantleAPI/Common/simulation_time.h> +#include <MantleAPI/Common/time_utils.h> #include <map> #include <string> @@ -25,7 +25,7 @@ namespace mantle_api struct ScenarioInfo { - SimulationTime scenario_timeout_duration; + Time scenario_timeout_duration; std::string description; std::map<std::string, std::string> additional_information; }; diff --git a/MantleAPI/include/MantleAPI/Traffic/control_strategy.h b/MantleAPI/include/MantleAPI/Traffic/control_strategy.h index 68252a16..42a736d4 100644 --- a/MantleAPI/include/MantleAPI/Traffic/control_strategy.h +++ b/MantleAPI/include/MantleAPI/Traffic/control_strategy.h @@ -25,10 +25,22 @@ namespace mantle_api enum class MovementDomain { - undefined = 0, - lateral, - longitudinal, - both + kUndefined = 0, + kLateral, + kLongitudinal, + kBoth +}; + +enum class ControlStrategyType +{ + kUndefined = 0, + kKeepVelocity, + kKeepLaneOffset, + kFollowHeadingSpline, + kFollowLateralOffsetSpline, + kFollowVelocitySpline, + kFollowRoute, + kAcquireLaneOffset }; struct ControlStrategy @@ -37,12 +49,13 @@ struct ControlStrategy // TODO: extend by bool use_dynamic_constraints when needed (false assumed at the moment) - MovementDomain movement_domain{MovementDomain::undefined}; + MovementDomain movement_domain{MovementDomain::kUndefined}; + ControlStrategyType type{ControlStrategyType::kUndefined}; }; inline bool operator==(const ControlStrategy& lhs, const ControlStrategy& rhs) noexcept { - return lhs.movement_domain == rhs.movement_domain; + return lhs.movement_domain == rhs.movement_domain && lhs.type == rhs.type; } inline bool operator!=(const ControlStrategy& lhs, const ControlStrategy& rhs) noexcept @@ -52,74 +65,119 @@ inline bool operator!=(const ControlStrategy& lhs, const ControlStrategy& rhs) n struct KeepVelocityControlStrategy : public ControlStrategy { - KeepVelocityControlStrategy() { movement_domain = MovementDomain::longitudinal; } - // Doesn`t need configuration attributes. Controller keeps current velocity on adding entity or update + KeepVelocityControlStrategy() + { + movement_domain = MovementDomain::kLongitudinal; + type = ControlStrategyType::kKeepVelocity; + } + // Doesn't need configuration attributes. Controller keeps current velocity on adding entity or update }; struct KeepLaneOffsetControlStrategy : public ControlStrategy { - KeepLaneOffsetControlStrategy() { movement_domain = MovementDomain::lateral; } - // Doesn`t need configuration attributes. Controller keeps current lane offset on adding entity or update + KeepLaneOffsetControlStrategy() + { + movement_domain = MovementDomain::kLateral; + type = ControlStrategyType::kKeepLaneOffset; + } + // Doesn't need configuration attributes. Controller keeps current lane offset on adding entity or update +}; + +struct FollowHeadingSplineControlStrategy : public ControlStrategy +{ + FollowHeadingSplineControlStrategy() + { + movement_domain = MovementDomain::kLateral; + type = ControlStrategyType::kFollowHeadingSpline; + } + + std::vector<mantle_api::SplineSection> heading_splines; + double default_value{0}; }; -// Control strategy which sets the respective value y (heading/velocity) as a polynomial function y = P(x) of simulation -// time x -struct FollowSplineControlStrategy : public ControlStrategy +struct FollowVelocitySplineControlStrategy : public ControlStrategy +{ + FollowVelocitySplineControlStrategy() + { + movement_domain = MovementDomain::kLongitudinal; + type = ControlStrategyType::kFollowVelocitySpline; + } + + std::vector<mantle_api::SplineSection> velocity_splines; + double default_value{0}; +}; + +inline bool operator==(const FollowVelocitySplineControlStrategy& lhs, + const FollowVelocitySplineControlStrategy& rhs) noexcept +{ + return lhs.default_value == rhs.default_value && lhs.velocity_splines == rhs.velocity_splines; +} + +inline bool operator!=(const FollowVelocitySplineControlStrategy& lhs, + const FollowVelocitySplineControlStrategy& rhs) noexcept +{ + return !(lhs == rhs); +} + +struct FollowLateralOffsetSplineControlStrategy : public ControlStrategy { - // movement_domain has to be set when used! Lat=heading, Lon=velocity - FollowSplineControlStrategy() {} + FollowLateralOffsetSplineControlStrategy() + { + movement_domain = MovementDomain::kLateral; + type = ControlStrategyType::kFollowLateralOffsetSpline; + } - std::vector<mantle_api::SplineSection> splines; - double default_value{0}; // when no spline section is defined for a certain simulation time + std::vector<mantle_api::SplineSection> lateral_offset_splines; }; // TODO: Create new control strategy for following 3D trajectories with shapes NURBS, polyline, clothoid struct FollowRouteControlStrategy : public ControlStrategy { - FollowRouteControlStrategy() { movement_domain = MovementDomain::lateral; } + FollowRouteControlStrategy() + { + movement_domain = MovementDomain::kLateral; + type = ControlStrategyType::kFollowRoute; + } std::vector<mantle_api::Vec3d> waypoints; }; enum class Dimension { - undefined = 0, - distance, - rate, - time + kUndefined = 0, + kDistance, + kRate, + kTime }; enum class Shape { - undefined = 0, - cubic, - linear, - sinusoidal + kUndefined = 0, + kStep, + kCubic, + kLinear, + kSinusoidal }; struct TransitionDynamics { - Dimension dimension{Dimension::undefined}; - Shape shape{Shape::undefined}; + Dimension dimension{Dimension::kUndefined}; + Shape shape{Shape::kUndefined}; double value{0}; }; -struct AcquireVelocityControlStrategy : public ControlStrategy -{ - AcquireVelocityControlStrategy() { movement_domain = MovementDomain::longitudinal; } - - double velocity_target; - TransitionDynamics transition_dynamics; -}; - struct AcquireLaneOffsetControlStrategy : public ControlStrategy { - AcquireLaneOffsetControlStrategy() { movement_domain = MovementDomain::lateral; } - - int road_id; - int lane_id; - double offset; + AcquireLaneOffsetControlStrategy() + { + movement_domain = MovementDomain::kLateral; + type = ControlStrategyType::kAcquireLaneOffset; + } + + int road_id{}; + int lane_id{}; + double offset{}; TransitionDynamics transition_dynamics; }; diff --git a/MantleAPI/include/MantleAPI/Traffic/entity_properties.h b/MantleAPI/include/MantleAPI/Traffic/entity_properties.h index 7e37ccb5..8d9002ab 100644 --- a/MantleAPI/include/MantleAPI/Traffic/entity_properties.h +++ b/MantleAPI/include/MantleAPI/Traffic/entity_properties.h @@ -122,6 +122,8 @@ struct VehicleProperties : public EntityProperties double front_wheel_diameter{0.0}; double rear_wheel_diameter{0.0}; bool is_host{false}; + // TODO: remove, once external control for traffic is implemented through controllers + bool is_controlled_externally{false}; }; inline bool operator==(const VehicleProperties& lhs, const VehicleProperties& rhs) noexcept diff --git a/MantleAPI/include/MantleAPI/Traffic/i_controller_config.h b/MantleAPI/include/MantleAPI/Traffic/i_controller_config.h index 81d0ef00..3d2355bd 100644 --- a/MantleAPI/include/MantleAPI/Traffic/i_controller_config.h +++ b/MantleAPI/include/MantleAPI/Traffic/i_controller_config.h @@ -21,6 +21,7 @@ #include <MantleAPI/Common/vector.h> #include <MantleAPI/Map/i_lane_location_query_service.h> +#include <algorithm> #include <memory> #include <vector> @@ -29,19 +30,19 @@ namespace mantle_api struct IControllerConfig { - virtual ~IControllerConfig() = default; - - // TODO: Remove copy constructor and then remove config as member of NoOpController and RouteController IControllerConfig() {} IControllerConfig(const IControllerConfig& controller_config) : map_query_service(controller_config.map_query_service), id(controller_config.id) { - for (const auto& control_strategy : controller_config.control_strategies) - { - control_strategies.push_back(std::make_unique<mantle_api::ControlStrategy>(*control_strategy)); - } + std::transform( + controller_config.control_strategies.begin(), + controller_config.control_strategies.end(), + std::back_inserter(control_strategies), + [](auto& control_strategy) { return std::make_unique<mantle_api::ControlStrategy>(*control_strategy); }); } + virtual ~IControllerConfig() = default; + // TODO: Check why map_query_service is part of the interface because it is not set from engine side but only in the // environment on calling AddController() ILaneLocationQueryService* map_query_service{nullptr}; @@ -70,21 +71,6 @@ inline bool operator==(const IControllerConfig& lhs, const IControllerConfig& rh return lhs.id == rhs.id && control_strategies_equal; } -// TODO: Remove and use FollowRoute (lat) and FollowSpline (lon) control strategy instead -struct PathControllerConfig : public IControllerConfig -{ - std::vector<mantle_api::Vec3d> waypoints; - std::vector<mantle_api::SplineSection> velocity_splines; - double default_velocity; -}; - -// TODO: Remove and use FollowSpline (lat) and FollowSpline (lon) control strategy instead -struct TrajectoryControllerConfig : public IControllerConfig -{ - std::vector<mantle_api::SplineSection> heading_splines; - std::vector<mantle_api::SplineSection> velocity_splines; -}; - struct NoOpControllerConfig : public IControllerConfig { }; diff --git a/MantleAPI/include/MantleAPI/Traffic/i_entity.h b/MantleAPI/include/MantleAPI/Traffic/i_entity.h index 1d25f1bd..89b1e48a 100644 --- a/MantleAPI/include/MantleAPI/Traffic/i_entity.h +++ b/MantleAPI/include/MantleAPI/Traffic/i_entity.h @@ -51,7 +51,6 @@ class IEntity : public IIdentifiable virtual void SetProperties(std::unique_ptr<mantle_api::EntityProperties> properties) = 0; virtual EntityProperties* GetProperties() const = 0; - // TODO: evaluate if this will be part of the final interface virtual void SetAssignedLaneIds(const std::vector<std::uint64_t>& assigned_lane_ids) = 0; virtual std::vector<std::uint64_t> GetAssignedLaneIds() const = 0; }; diff --git a/MantleAPI/test/MantleAPI/Test/test_utils.h b/MantleAPI/test/MantleAPI/Test/test_utils.h index a72d175a..dc03ff8e 100644 --- a/MantleAPI/test/MantleAPI/Test/test_utils.h +++ b/MantleAPI/test/MantleAPI/Test/test_utils.h @@ -285,10 +285,6 @@ class MockEntityRepository : public mantle_api::IEntityRepository class MockEnvironment : public mantle_api::IEnvironment { public: - virtual void Init() override {} - - virtual void Step() override {} - MOCK_METHOD(void, CreateMap, (const std::string& file_path, const std::vector<mantle_api::Position>& map_region), @@ -312,6 +308,11 @@ class MockEnvironment : public mantle_api::IEnvironment std::vector<std::unique_ptr<mantle_api::ControlStrategy>>& control_strategies), (override)); + MOCK_METHOD(bool, + HasControlStrategyGoalBeenReached, + (std::uint64_t controller_id, mantle_api::ControlStrategyType type), + (const, override)); + const mantle_api::ILaneLocationQueryService& GetQueryService() const override { return query_service_; } const mantle_api::ICoordConverter* GetConverter() const override { return &converter_; } @@ -331,6 +332,8 @@ class MockEnvironment : public mantle_api::IEnvironment mantle_api::DateTime GetDateTime() override { return mantle_api::DateTime(); } + mantle_api::SimulationTime GetSimulationTime() override { return mantle_api::SimulationTime(); } + private: MockQueryService query_service_{}; MockEntityRepository entity_repository_{}; -- GitLab