LCOV - code coverage report
Current view: top level - src/drivers/vehicle_interface/include/vehicle_interface - safety_state_machine.hpp (source / functions) Hit Total Coverage
Test: lcov.total.filtered Lines: 9 10 90.0 %
Date: 2023-03-03 05:44:19 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 13 16 81.2 %

           Branch data     Line data    Source code
       1                 :            : // Copyright 2020 the Autoware Foundation
       2                 :            : //
       3                 :            : // Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            : // you may not use this file except in compliance with the License.
       5                 :            : // You may obtain a copy of the License at
       6                 :            : //
       7                 :            : //     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            : //
       9                 :            : // Unless required by applicable law or agreed to in writing, software
      10                 :            : // distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            : // See the License for the specific language governing permissions and
      13                 :            : // limitations under the License.
      14                 :            : //
      15                 :            : // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
      16                 :            : /// \file
      17                 :            : /// \brief Input validation state machine
      18                 :            : #ifndef VEHICLE_INTERFACE__SAFETY_STATE_MACHINE_HPP_
      19                 :            : #define VEHICLE_INTERFACE__SAFETY_STATE_MACHINE_HPP_
      20                 :            : 
      21                 :            : #include <common/types.hpp>
      22                 :            : #include <autoware_auto_vehicle_msgs/msg/wipers_command.hpp>
      23                 :            : #include <autoware_auto_vehicle_msgs/msg/headlights_command.hpp>
      24                 :            : #include <autoware_auto_vehicle_msgs/msg/horn_command.hpp>
      25                 :            : #include <autoware_auto_vehicle_msgs/msg/vehicle_control_command.hpp>
      26                 :            : #include <autoware_auto_vehicle_msgs/msg/vehicle_odometry.hpp>
      27                 :            : #include <autoware_auto_vehicle_msgs/msg/vehicle_state_command.hpp>
      28                 :            : #include <autoware_auto_vehicle_msgs/msg/vehicle_state_report.hpp>
      29                 :            : #include <vehicle_interface/visibility_control.hpp>
      30                 :            : 
      31                 :            : #include <experimental/optional>
      32                 :            : #include <algorithm>
      33                 :            : #include <chrono>
      34                 :            : #include <vector>
      35                 :            : 
      36                 :            : using autoware::common::types::bool8_t;
      37                 :            : 
      38                 :            : namespace autoware
      39                 :            : {
      40                 :            : namespace drivers
      41                 :            : {
      42                 :            : namespace vehicle_interface
      43                 :            : {
      44                 :            : using autoware_auto_vehicle_msgs::msg::HeadlightsCommand;
      45                 :            : using autoware_auto_vehicle_msgs::msg::HornCommand;
      46                 :            : using autoware_auto_vehicle_msgs::msg::WipersCommand;
      47                 :            : using MaybeStateCommand =
      48                 :            :   std::experimental::optional<autoware_auto_vehicle_msgs::msg::VehicleStateCommand>;
      49                 :            : using BasicControlCommand = autoware_auto_vehicle_msgs::msg::VehicleControlCommand;
      50                 :            : using Odometry = autoware_auto_vehicle_msgs::msg::VehicleOdometry;
      51                 :            : using StateReport = autoware_auto_vehicle_msgs::msg::VehicleStateReport;
      52                 :            : /// Simple wrapper for control command and state command together
      53                 :            : class VEHICLE_INTERFACE_PUBLIC Command
      54                 :            : {
      55                 :            : public:
      56                 :            :   /// Constructor
      57                 :            :   Command(
      58                 :            :     const BasicControlCommand & control = BasicControlCommand{},
      59                 :            :     const MaybeStateCommand & state = MaybeStateCommand{})
      60         [ +  + ]:        260 :   : m_control{control}, m_state{state} {}
      61                 :            : 
      62                 :            :   /// Getter
      63                 :        136 :   const BasicControlCommand & control() const noexcept {return m_control;}
      64                 :            :   /// Getter
      65                 :            :   const MaybeStateCommand & state() const noexcept {return m_state;}
      66                 :            : 
      67                 :            : private:
      68                 :            :   BasicControlCommand m_control;
      69                 :            :   MaybeStateCommand m_state;
      70                 :            : };  // class Command
      71                 :            : 
      72                 :            : /// Denotes one of the behaviors that the state machine has done; either a notification that it has
      73                 :            : /// done something (Info), or a warning that something bad has been detected
      74                 :            : enum class StateMachineReport : uint8_t
      75                 :            : {
      76                 :            :   CLAMP_PAST_THRESHOLD,  ///< Clamped a command that was way out of bounds
      77                 :            :   BAD_STATE,  ///< A state command was not one of the specified constants
      78                 :            :   WIPERS_ON_HEADLIGHTS_ON,  ///< Turn on headlights because you turned on wipers
      79                 :            :   REMOVE_GEAR_COMMAND,  ///< Converted gear command to GEAR_NO_COMMAND because you're going too fast
      80                 :            :   HIGH_FREQUENCY_ACCELERATION_COMMAND,  ///< Acceleration has high frequency components
      81                 :            :   HIGH_FREQUENCY_STEER_COMMAND,  ///< Steering has high frequency components
      82                 :            :   HIGH_FREQUENCY_VELOCITY_REPORT,  ///< Reported velocity has high frequency components
      83                 :            :   HIGH_FREQUENCY_STEER_REPORT,  ///< Reported steering has high frequency components
      84                 :            :   STATE_TRANSITION_TIMEOUT  ///< Commanded state transition didn't happen
      85                 :            : };  // enum class StateMachineWarning
      86                 :            : 
      87                 :            : // TODO(c.ho) concept comparable
      88                 :            : /// A simple class representing 1D limits and a threshold value for when something is considered
      89                 :            : /// warning worthy.
      90                 :            : template<typename T>
      91                 :            : class VEHICLE_INTERFACE_PUBLIC Limits
      92                 :            : {
      93                 :            : public:
      94                 :            :   /// Constructor
      95                 :            :   /// \throw std::domain_error if min >= max
      96                 :        282 :   Limits(T min, T max, T threshold)
      97                 :        282 :   : m_min{min}, m_max{max}, m_threshold{threshold}
      98                 :            :   {
      99         [ -  + ]:        282 :     if (min >= max) {
     100         [ #  # ]:          0 :       throw std::domain_error{"min >= max"};
     101                 :            :     }
     102                 :        282 :   }
     103                 :            : 
     104                 :            :   T min() const noexcept {return m_min;}
     105                 :            :   T max() const noexcept {return m_max;}
     106                 :            :   T threshold() const noexcept {return m_threshold;}
     107                 :            :   ///  Clamps value to max/min range; return true if value is threshold past limits
     108                 :            :   bool8_t clamp_warn(T & value) const noexcept
     109                 :            :   {
     110                 :        277 :     const auto value_raw = value;
     111   [ +  +  +  +  :        277 :     value = std::min(std::max(m_min, value_raw), m_max);
                   +  + ]
     112   [ +  +  +  + ]:        272 :     return std::abs(value - value_raw) >= m_threshold;
     113                 :            :   }
     114                 :            : 
     115                 :            : private:
     116                 :            :   T m_min;
     117                 :            :   T m_max;
     118                 :            :   T m_threshold;
     119                 :            : };
     120                 :            : 
     121                 :            : /// Configuration class for SafetyStateMachine
     122                 :            : class VEHICLE_INTERFACE_PUBLIC StateMachineConfig
     123                 :            : {
     124                 :            : public:
     125                 :            :   using VelocityT = decltype(Odometry::velocity_mps);
     126                 :            :   using AccelT = decltype(BasicControlCommand::long_accel_mps2);
     127                 :            :   using AccelLimits = Limits<AccelT>;
     128                 :            :   using FrontWheelLimits = Limits<decltype(BasicControlCommand::front_wheel_angle_rad)>;
     129                 :            : 
     130                 :            :   /// Constructor
     131                 :            :   /// \param[in] gear_shift_velocity_threshold Gear shifts between directions (i.e. park->drive,
     132                 :            :   /// low->reverse are allowed only if the magnitude of velocity is below this threshold. Must be
     133                 :            :   /// positive
     134                 :            :   /// \param[in] accel_limits Max/min value for command acceleration
     135                 :            :   /// \param[in] front_wheel_limits Max/min value for commanded wheel angles
     136                 :            :   /// \param[in] time_step Characteristic time step of the system: used for computing timeout
     137                 :            :   /// acceleration commands and when to do autonomous gear shifting. Must be postiive
     138                 :            :   /// \param[in] timeout_accel_mps2 Magnitude of acceleration to use to bring the vehicle to a stop
     139                 :            :   /// when the vehicle interface has timed out. Must be positive
     140                 :            :   /// \param[in] state_transition_timeout If a state component has not changed within this
     141                 :            :   /// period, then a warning is raised. Must be positive and bigger than time_step.
     142                 :            :   /// \param[in] auto_gear_shift_accel_deadzone_mps2 Acceleration must be bigger than this magnitude
     143                 :            :   /// to induce an automatic gear shift. Must be positive.
     144                 :            :   /// \throw std::domain_error If gear_shift_velocity_threshold is negative
     145                 :            :   /// \throw std::domain_error If time_step is non-positive
     146                 :            :   /// \throw std::domain_error If timeout_accel_mps2 is non-positive, or outside of accel_limits
     147                 :            :   /// \throw std::domain_error If state_transition_timeout is smaller than time_step
     148                 :            :   /// \throw std::domain_error If auto_gear_shift_accel_deadzone_mps2 is non-positive
     149                 :            :   StateMachineConfig(
     150                 :            :     const VelocityT gear_shift_velocity_threshold,
     151                 :            :     const AccelLimits & accel_limits,
     152                 :            :     const FrontWheelLimits & front_wheel_limits,
     153                 :            :     const std::chrono::nanoseconds time_step,
     154                 :            :     const AccelT timeout_accel_mps2,
     155                 :            :     const std::chrono::nanoseconds state_transition_timeout,
     156                 :            :     const AccelT auto_gear_shift_accel_deadzone_mps2
     157                 :            :   );
     158                 :            : 
     159                 :            :   VelocityT gear_shift_velocity_threshold() const noexcept;
     160                 :            :   const AccelLimits & accel_limits() const noexcept;
     161                 :            :   const FrontWheelLimits & front_wheel_limits() const noexcept;
     162                 :            :   std::chrono::nanoseconds time_step() const noexcept;
     163                 :            :   AccelT timeout_acceleration() const noexcept;
     164                 :            :   std::chrono::nanoseconds state_transition_timeout() const noexcept;
     165                 :            :   AccelT auto_gear_shift_accel_deadzone() const noexcept;
     166                 :            : 
     167                 :            : private:
     168                 :            :   VelocityT m_gear_shift_velocity_threshold;
     169                 :            :   AccelLimits m_accel_limits;
     170                 :            :   FrontWheelLimits m_front_wheel_limits;
     171                 :            :   std::chrono::nanoseconds m_time_step;
     172                 :            :   AccelT m_timeout_acceleration;
     173                 :            :   std::chrono::nanoseconds m_state_transition_timeout;
     174                 :            :   AccelT m_auto_gear_shift_accel_deadzone;
     175                 :            : };  // class StateMachineConfig
     176                 :            : 
     177                 :            : /// Implements stateful behavior for VehicleInterfaceNode
     178                 :            : /// Primary function is to ensure vehicle platform does not get
     179                 :            : /// conflicting commands
     180                 :            : class VEHICLE_INTERFACE_PUBLIC SafetyStateMachine
     181                 :            : {
     182                 :            : public:
     183                 :            :   using Reports = std::vector<StateMachineReport>;  // TODO(c.ho) maybe a set instead
     184                 :            :   /// Constructor
     185                 :            :   explicit SafetyStateMachine(const StateMachineConfig & config);
     186                 :            :   /// Ensure given commands are consistent and not dangerous. See design document for
     187                 :            :   /// full list of behaviors.
     188                 :            :   /// \param[in] command The raw input commands
     189                 :            :   /// \return Commands which are consistent and safe (within the scope of the vehicle interface)
     190                 :            :   Command compute_safe_commands(const Command & command);
     191                 :            :   /// Update the state of the state machine
     192                 :            :   /// \param[in] odom The odometry of the vehicle
     193                 :            :   /// \param[in] state The state of the vehicle
     194                 :            :   void update(const Odometry & odom, const StateReport & state);
     195                 :            :   /// Compute safety fallback commands that should be executed on a timeout
     196                 :            :   /// \return The safety fallback command for the current state
     197                 :            :   Command timeout_commands() const noexcept;
     198                 :            :   /// Get list of warnings state machine saw and adjusted
     199                 :            :   const Reports & reports() const noexcept;
     200                 :            :   /// Get config object
     201                 :            :   const StateMachineConfig & get_config() const noexcept;
     202                 :            : 
     203                 :            : private:
     204                 :            :   using VSC = autoware_auto_vehicle_msgs::msg::VehicleStateCommand;
     205                 :            :   using MaybeEnum = std::experimental::optional<decltype(VSC::blinker)>;
     206                 :            :   //lint -save -e9150 NOLINT Pure aggregate and only used internally; no constraints on state
     207                 :            :   template<typename T>
     208                 :            :   struct ValueStamp
     209                 :            :   {
     210                 :            :     T value;
     211                 :            :     std::chrono::system_clock::time_point stamp{std::chrono::system_clock::time_point::min()};
     212                 :            :   };
     213                 :            :   struct StateChangeRequests
     214                 :            :   {
     215                 :            :     ValueStamp<decltype(VSC::gear)> gear;
     216                 :            :     ValueStamp<decltype(VSC::blinker)> blinker;
     217                 :            :     ValueStamp<decltype(WipersCommand::command)> wiper;
     218                 :            :     ValueStamp<decltype(HeadlightsCommand::command)> headlight;
     219                 :            :     ValueStamp<decltype(VSC::mode)> mode;
     220                 :            :     ValueStamp<decltype(VSC::hand_brake)> hand_brake;
     221                 :            :     ValueStamp<decltype(HornCommand::active)> horn;
     222                 :            :   };  // struct StateChangeRequest
     223                 :            :   //lint -restore NOLINT
     224                 :            :   // Make sure uint members are within range--otherwise set to NO_COMMAND
     225                 :            :   VEHICLE_INTERFACE_LOCAL VSC sanitize(const VSC & msg) const;
     226                 :            :   // Turn on headlights if the wipers are being turned on
     227                 :            :   VEHICLE_INTERFACE_LOCAL static MaybeEnum headlights_on_if_wipers_on(const VSC & in);
     228                 :            :   // Apply gear shift if velocity is small and commanded acceleration is big enough
     229                 :            :   VEHICLE_INTERFACE_LOCAL uint8_t automatic_gear_shift(
     230                 :            :     const BasicControlCommand control,
     231                 :            :     const VSC & state) const;
     232                 :            :   // Remove "big" gear shifts if velocity is too large in magnitude
     233                 :            :   VEHICLE_INTERFACE_LOCAL bool8_t bad_gear_shift(const VSC & in) const;
     234                 :            :   // Clamp control values; warn if wildly out of range
     235                 :            :   VEHICLE_INTERFACE_LOCAL BasicControlCommand clamp(BasicControlCommand in) const;
     236                 :            :   // Add/overwrite any new state change requests
     237                 :            :   VEHICLE_INTERFACE_LOCAL void cache_state_change_request(const VSC & in);
     238                 :            :   // Clear any state changes that have happened, or warn on timeout
     239                 :            :   VEHICLE_INTERFACE_LOCAL void check_state_change(const StateReport & in);
     240                 :            : 
     241                 :            :   StateMachineConfig m_config;
     242                 :            :   Odometry m_odometry{};
     243                 :            :   StateReport m_state{};
     244                 :            :   StateChangeRequests m_requests{};
     245                 :            :   mutable Reports m_reports{};
     246                 :            : };  // class SafetyStateMachine
     247                 :            : }  // namespace vehicle_interface
     248                 :            : }  // namespace drivers
     249                 :            : }  // namespace autoware
     250                 :            : 
     251                 :            : #endif  // VEHICLE_INTERFACE__SAFETY_STATE_MACHINE_HPP_

Generated by: LCOV version 1.14