CARLA
Episode.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
8 
9 #include "carla/Logging.h"
14 
15 #include <exception>
16 
17 namespace carla {
18 namespace client {
19 namespace detail {
20 
21 using namespace std::chrono_literals;
22 
23  static auto &CastData(const sensor::SensorData &data) {
24  using target_t = const sensor::data::RawEpisodeState;
25  return static_cast<target_t &>(data);
26  }
27 
28  template <typename RangeT>
29  static auto GetActorsById_Impl(Client &client, CachedActorList &actors, const RangeT &actor_ids) {
30  auto missing_ids = actors.GetMissingIds(actor_ids);
31  if (!missing_ids.empty()) {
32  actors.InsertRange(client.GetActorsById(missing_ids));
33  }
34  return actors.GetActorsById(actor_ids);
35  }
36 
38  : Episode(client, client.GetEpisodeInfo()) {}
39 
41  : _client(client),
42  _state(std::make_shared<EpisodeState>(info.id)),
43  _token(info.token) {}
44 
46  try {
48  } catch (const std::exception &e) {
49  log_error("exception trying to disconnect from episode:", e.what());
50  }
51  }
52 
53  void Episode::Listen() {
54  std::weak_ptr<Episode> weak = shared_from_this();
55  _client.SubscribeToStream(_token, [weak](auto buffer) {
56  auto self = weak.lock();
57  if (self != nullptr) {
58 
59  auto data = sensor::Deserializer::Deserialize(std::move(buffer));
60  auto next = std::make_shared<const EpisodeState>(CastData(*data));
61  auto prev = self->GetState();
62 
63  // TODO: Update how the map change is detected
64  bool HasMapChanged = next->HasMapChanged();
65  bool UpdateLights = next->IsLightUpdatePending();
66 
67  /// Check for pending exceptions (Mainly TM server closed)
68  if(self->_pending_exceptions) {
69 
70  /// Mark pending exception false
71  self->_pending_exceptions = false;
72 
73  /// Create exception for the error message
74  auto exception(self->_pending_exceptions_msg);
75  // Notify waiting threads that exception occurred
76  self->_snapshot.SetException(std::runtime_error(exception));
77  }
78  /// Sensor case: inconsistent data
79  else {
80  bool episode_changed = (next->GetEpisodeId() != prev->GetEpisodeId());
81 
82  do {
83  if (prev->GetFrame() >= next->GetFrame() && !episode_changed) {
84  self->_on_tick_callbacks.Call(next);
85  return;
86  }
87  } while (!self->_state.compare_exchange(&prev, next));
88 
89  if(UpdateLights || HasMapChanged) {
90  self->_on_light_update_callbacks.Call(next);
91  }
92 
93  if(HasMapChanged) {
94  self->_should_update_map = true;
95  }
96 
97  /// Episode change
98  if(episode_changed) {
99  self->OnEpisodeChanged();
100  }
101 
102  // Notify waiting threads and do the callbacks.
103  self->_snapshot.SetValue(next);
104 
105  // Tick navigation.
106  auto navigation = self->_navigation.load();
107  if (navigation != nullptr) {
108  navigation->Tick(self);
109  }
110 
111  // Call user callbacks.
112  self->_on_tick_callbacks.Call(next);
113  }
114  }
115  });
116  }
117 
118  boost::optional<rpc::Actor> Episode::GetActorById(ActorId id) {
119  auto actor = _actors.GetActorById(id);
120  if (!actor.has_value()) {
121  auto actor_list = _client.GetActorsById({id});
122  if (!actor_list.empty()) {
123  actor = std::move(actor_list.front());
124  _actors.Insert(*actor);
125  }
126  }
127  return actor;
128  }
129 
130  std::shared_ptr<WalkerNavigation> Episode::CreateNavigationIfMissing() {
131  std::shared_ptr<WalkerNavigation> navigation;
132  do {
133  navigation = _navigation.load();
134  if (navigation == nullptr) {
135  auto new_navigation = std::make_shared<WalkerNavigation>(_client);
136  _navigation.compare_exchange(&navigation, new_navigation);
137  }
138  } while (navigation == nullptr);
139  return navigation;
140  }
141 
142  std::vector<rpc::Actor> Episode::GetActorsById(const std::vector<ActorId> &actor_ids) {
143  return GetActorsById_Impl(_client, _actors, actor_ids);
144  }
145 
146  std::vector<rpc::Actor> Episode::GetActors() {
147  return GetActorsById_Impl(_client, _actors, GetState()->GetActorIds());
148  }
149 
151  _actors.Clear();
152  _on_tick_callbacks.Clear();
153  _navigation.reset();
155  }
156 
159  }
160 
162  if(_should_update_map) {
163  _should_update_map = false;
164  return true;
165  }
166  return false;
167  }
168 
169 } // namespace detail
170 } // namespace client
171 } // namespace carla
AtomicSharedPtr< const EpisodeState > _state
Definition: Episode.h:127
static SharedPtr< SensorData > Deserialize(Buffer &&buffer)
Holds the current episode, and the current episode state.
Definition: Episode.h:33
CachedActorList _actors
Definition: Episode.h:133
std::vector< rpc::Actor > GetActors()
Definition: Episode.cpp:146
AtomicSharedPtr< WalkerNavigation > _navigation
Definition: Episode.h:129
static void log_error(Args &&... args)
Definition: Logging.h:110
This file contains definitions of common data structures used in traffic manager. ...
Definition: Carla.cpp:133
std::shared_ptr< WalkerNavigation > CreateNavigationIfMissing()
Definition: Episode.cpp:130
Represents the state of all the actors of an episode at a given frame.
Definition: EpisodeState.h:27
void SubscribeToStream(const streaming::Token &token, std::function< void(Buffer)> callback)
Keeps a list of actor descriptions to avoid requesting each time the descriptions to the server...
std::vector< rpc::Actor > GetActorsById(const RangeT &range) const
Retrieve the actors matching the ids in range.
boost::optional< rpc::Actor > GetActorById(ActorId id) const
Retrieve the actor matching id, or empty optional if actor is not cached.
static auto & CastData(const sensor::SensorData &data)
Definition: Episode.cpp:23
void Insert(rpc::Actor actor)
Inserts an actor into the list.
Base class for all the objects containing data generated by a sensor.
Definition: SensorData.h:20
void InsertRange(RangeT range)
Inserts a range containing actors.
const streaming::Token _token
Definition: Episode.h:143
boost::optional< rpc::Actor > GetActorById(ActorId id)
Definition: Episode.cpp:118
carla::ActorId ActorId
std::vector< rpc::Actor > GetActorsById(const std::vector< ActorId > &ids)
std::vector< rpc::Actor > GetActorsById(const std::vector< ActorId > &actor_ids)
Definition: Episode.cpp:142
std::shared_ptr< const EpisodeState > GetState() const
Definition: Episode.h:48
Provides communication with the rpc and streaming servers of a CARLA simulator.
std::vector< ActorId > GetMissingIds(const RangeT &range) const
Return the actor ids present in range that haven&#39;t been added to this list.
State of the episode at a given frame.
void UnSubscribeFromStream(const streaming::Token &token)
CallbackList< WorldSnapshot > _on_tick_callbacks
Definition: Episode.h:135
static auto GetActorsById_Impl(Client &client, CachedActorList &actors, const RangeT &actor_ids)
Definition: Episode.cpp:29