1import random
2from typing import TYPE_CHECKING, Optional
3
4from agents.tools.logs import logger
5
6if TYPE_CHECKING:
7 import carla
8
9 from agents.lunatic_agent import LunaticAgent
10 from classes.constants import Hazard
11
12
[docs]
13def emergency_manager(
14 self: "LunaticAgent", *, reasons: "set[Hazard]", control: Optional["carla.VehicleControl"] = None, force=False
15) -> "carla.VehicleControl":
16 """
17 Modifies the control values to perform an emergency stop.
18 The steering remains unchanged to avoid going out of the lane during turns.
19
20 Parameters:
21 reasons: set of :py:class:`.Hazard` that triggered the emergency stop.
22 If empty this function will do nothing. Normally :py:attr:`detected_hazards <.LunaticAgent.detected_hazards>`.
23 control: control to be modified in place.
24 If :code:`None` the control for the current step will be calculated.
25 force: if True, the emergency stop will be performed even if the **reasons** are empty.
26 """
27 control = control or self.get_control()
28 if control is None:
29 control = self._calculate_control(debug=self.debug)
30 if not reasons and not force:
31 return control
32 logger.debug("Emergency Manager: Hazards not cleared or forced stopping. Reason: %s", reasons)
33
34 # TODO, future: Can be turned into a rule. Problem here and with rule it will trigger each step -> new random value
35 # rule should return consistent result for a period of time
36 if (
37 self.config.emergency.ignore_percentage > 0.0
38 and self.config.emergency.ignore_percentage / 100 > random.random()
39 ):
40 return control
41
42 control.throttle = 0.0
43 # negate the chosen default setting
44 if (
45 self.config.emergency.hand_brake_modify_chance > 0.0
46 and self.config.emergency.hand_brake_modify_chance / 100 > random.random()
47 ):
48 control.hand_brake = not self.config.emergency.hand_brake
49 else:
50 control.hand_brake = self.config.emergency.hand_brake
51
52 # Enable random steering if flagged
53 if self.config.emergency.do_random_steering:
54 control.steer = random.uniform(*self.config.emergency.random_steering_range) # Randomly adjust steering
55
56 control.brake = self.config.controls.max_brake
57
58 # TODO: more sophisticated emergency behavior
59
60 return control