weather_sim.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python
  2. # Copyright (c) 2020 Intel Corporation
  3. #
  4. # This work is licensed under the terms of the MIT license.
  5. # For a copy, see <https://opensource.org/licenses/MIT>.
  6. """
  7. This module provides a weather class and py_trees behavior
  8. to simulate weather in CARLA according to the astronomic
  9. behavior of the sun.
  10. """
  11. import datetime
  12. import math
  13. import operator
  14. import ephem
  15. import py_trees
  16. import carla
  17. from srunner.scenariomanager.carla_data_provider import CarlaDataProvider
  18. from srunner.scenariomanager.timer import GameTime
  19. class Weather(object):
  20. """
  21. Class to simulate weather in CARLA according to the astronomic behavior of the sun
  22. The sun position (azimuth and altitude angles) is obtained by calculating its
  23. astronomic position for the CARLA reference position (x=0, y=0, z=0) using the ephem
  24. library.
  25. Args:
  26. carla_weather (carla.WeatherParameters): Initial weather settings.
  27. dtime (datetime): Initial date and time in UTC (required for animation only).
  28. Defaults to None.
  29. animation (bool): Flag to allow animating the sun position over time.
  30. Defaults to False.
  31. Attributes:
  32. carla_weather (carla.WeatherParameters): Weather parameters for CARLA.
  33. animation (bool): Flag to allow animating the sun position over time.
  34. _sun (ephem.Sun): The sun as astronomic entity.
  35. _observer_location (ephem.Observer): Holds the geographical position (lat/lon/altitude)
  36. for which the sun position is obtained.
  37. datetime (datetime): Date and time in UTC (required for animation only).
  38. """
  39. def __init__(self, carla_weather, dtime=None, animation=False):
  40. """
  41. Class constructor
  42. """
  43. self.carla_weather = carla_weather
  44. self.animation = animation
  45. self._sun = ephem.Sun() # pylint: disable=no-member
  46. self._observer_location = ephem.Observer()
  47. geo_location = CarlaDataProvider.get_map().transform_to_geolocation(carla.Location(0, 0, 0))
  48. self._observer_location.lon = str(geo_location.longitude)
  49. self._observer_location.lat = str(geo_location.latitude)
  50. # @TODO This requires the time to be in UTC to be accurate
  51. self.datetime = dtime
  52. if self.datetime:
  53. self._observer_location.date = self.datetime
  54. self.update()
  55. def update(self, delta_time=0):
  56. """
  57. If the weather animation is true, the new sun position is calculated w.r.t delta_time
  58. Nothing happens if animation or datetime are None.
  59. Args:
  60. delta_time (float): Time passed since self.datetime [seconds].
  61. """
  62. if not self.animation or not self.datetime:
  63. return
  64. self.datetime = self.datetime + datetime.timedelta(seconds=delta_time)
  65. self._observer_location.date = self.datetime
  66. self._sun.compute(self._observer_location)
  67. self.carla_weather.sun_altitude_angle = math.degrees(self._sun.alt)
  68. self.carla_weather.sun_azimuth_angle = math.degrees(self._sun.az)
  69. class WeatherBehavior(py_trees.behaviour.Behaviour):
  70. """
  71. Atomic to read weather settings from the blackboard and apply these in CARLA.
  72. Used in combination with UpdateWeather() to have a continuous weather simulation.
  73. This behavior is always in a running state and must never terminate.
  74. The user must not add this behavior. It is automatically added by the ScenarioManager.
  75. This atomic also sets the datetime to blackboard variable, used by TimeOfDayComparison atomic
  76. Args:
  77. name (string): Name of the behavior.
  78. Defaults to 'WeatherBehavior'.
  79. Attributes:
  80. _weather (srunner.scenariomanager.weather_sim.Weather): Weather settings.
  81. _current_time (float): Current CARLA time [seconds].
  82. """
  83. def __init__(self, name="WeatherBehavior"):
  84. """
  85. Setup parameters
  86. """
  87. super(WeatherBehavior, self).__init__(name)
  88. self._weather = None
  89. self._current_time = None
  90. def initialise(self):
  91. """
  92. Set current time to current CARLA time
  93. """
  94. self._current_time = GameTime.get_time()
  95. def update(self):
  96. """
  97. Check if new weather settings are available on the blackboard, and if yes fetch these
  98. into the _weather attribute.
  99. Apply the weather settings from _weather to CARLA.
  100. Note:
  101. To minimize CARLA server interactions, the weather is only updated, when the blackboard
  102. is updated, or if the weather animation flag is true. In the latter case, the update
  103. frequency is 1 Hz.
  104. returns:
  105. py_trees.common.Status.RUNNING
  106. """
  107. weather = None
  108. try:
  109. check_weather = operator.attrgetter("CarlaWeather")
  110. weather = check_weather(py_trees.blackboard.Blackboard())
  111. except AttributeError:
  112. pass
  113. if weather:
  114. self._weather = weather
  115. delattr(py_trees.blackboard.Blackboard(), "CarlaWeather")
  116. CarlaDataProvider.get_world().set_weather(self._weather.carla_weather)
  117. py_trees.blackboard.Blackboard().set("Datetime", self._weather.datetime, overwrite=True)
  118. if self._weather and self._weather.animation:
  119. new_time = GameTime.get_time()
  120. delta_time = new_time - self._current_time
  121. if delta_time > 1:
  122. self._weather.update(delta_time)
  123. self._current_time = new_time
  124. CarlaDataProvider.get_world().set_weather(self._weather.carla_weather)
  125. py_trees.blackboard.Blackboard().set("Datetime", self._weather.datetime, overwrite=True)
  126. return py_trees.common.Status.RUNNING