Fix GNSS sensor concurrency

This commit is contained in:
nsubiron 2019-07-08 19:43:17 +02:00 committed by Néstor Subirón
parent 39f5c4da49
commit a2c60994f5
3 changed files with 63 additions and 47 deletions

View File

@ -8,6 +8,7 @@
#include "carla/Logging.h" #include "carla/Logging.h"
#include "carla/client/Map.h" #include "carla/client/Map.h"
#include "carla/client/detail/Simulator.h" #include "carla/client/detail/Simulator.h"
#include "carla/geom/GeoLocation.h"
#include "carla/sensor/data/GnssEvent.h" #include "carla/sensor/data/GnssEvent.h"
#include <exception> #include <exception>
@ -15,58 +16,77 @@
namespace carla { namespace carla {
namespace client { namespace client {
GnssSensor::~GnssSensor() = default; // ===========================================================================
// -- GnssCallback -----------------------------------------------------------
// ===========================================================================
void GnssSensor::Listen(CallbackFunctionType callback) { class GnssCallback {
if (IsListening()) { public:
log_error(GetDisplayId(), ": already listening");
return;
}
if (GetParent() == nullptr) { GnssCallback(
throw_exception(std::runtime_error(GetDisplayId() + ": not attached to vehicle")); ActorId sensor_id,
return; geom::GeoLocation geo_reference,
} Sensor::CallbackFunctionType &&user_callback)
: _sensor_id(sensor_id),
_geo_reference(geo_reference),
_callback(std::move(user_callback)) {}
SharedPtr<Map> map = GetWorld().GetMap(); void operator()(const WorldSnapshot &snapshot) const;
DEBUG_ASSERT(map != nullptr);
_geo_reference = map->GetGeoReference();
auto self = boost::static_pointer_cast<GnssSensor>(shared_from_this()); private:
log_debug(GetDisplayId(), ": subscribing to tick event"); ActorId _sensor_id;
_callback_id = GetEpisode().Lock()->RegisterOnTickEvent([
cb=std::move(callback),
weak_self=WeakPtr<GnssSensor>(self)](const auto &snapshot) {
auto self = weak_self.lock();
if (self != nullptr) {
auto data = self->TickGnssSensor(snapshot.GetTimestamp());
if (data != nullptr) {
cb(std::move(data));
}
}
});
}
SharedPtr<sensor::SensorData> GnssSensor::TickGnssSensor( geom::GeoLocation _geo_reference;
const Timestamp &timestamp) {
Sensor::CallbackFunctionType _callback;
};
void GnssCallback::operator()(const WorldSnapshot &snapshot) const {
try { try {
return MakeShared<sensor::data::GnssEvent>( auto actor_snapshot = snapshot.Find(_sensor_id);
timestamp.frame, if (actor_snapshot.has_value()) {
timestamp.elapsed_seconds, auto transform = actor_snapshot->transform;
GetTransform(), _callback(MakeShared<sensor::data::GnssEvent>(
_geo_reference.Transform(GetLocation())); snapshot.GetTimestamp().frame,
snapshot.GetTimestamp().elapsed_seconds,
transform,
_geo_reference.Transform(transform.location)));
}
} catch (const std::exception &e) { } catch (const std::exception &e) {
log_error("GnssSensor:", e.what()); log_error("GnssSensor:", e.what());
}
}
// ===========================================================================
// -- GnssSensor -------------------------------------------------------------
// ===========================================================================
GnssSensor::~GnssSensor() {
Stop(); Stop();
return nullptr; }
void GnssSensor::Listen(CallbackFunctionType callback) {
auto episode = GetEpisode().Lock();
SharedPtr<Map> map = episode->GetCurrentMap();
DEBUG_ASSERT(map != nullptr);
const size_t callback_id = episode->RegisterOnTickEvent(GnssCallback(
GetId(),
map->GetGeoReference(),
std::move(callback)));
const size_t previous = _callback_id.exchange(callback_id);
if (previous != 0u) {
episode->RemoveOnTickEvent(previous);
} }
} }
void GnssSensor::Stop() { void GnssSensor::Stop() {
if (_callback_id.has_value()) { const size_t previous = _callback_id.exchange(0u);
GetEpisode().Lock()->RemoveOnTickEvent(*_callback_id); auto episode = GetEpisode().TryLock();
_callback_id = boost::none; if ((previous != 0u) && (episode != nullptr)) {
episode->RemoveOnTickEvent(previous);
} }
} }

View File

@ -6,9 +6,8 @@
#pragma once #pragma once
#include "carla/client/ClientSideSensor.h" #include "carla/client/ClientSideSensor.h"
#include "carla/geom/GeoLocation.h"
#include <boost/optional.hpp> #include <atomic>
namespace carla { namespace carla {
namespace client { namespace client {
@ -35,16 +34,12 @@ namespace client {
/// Return whether this Sensor instance is currently listening to the /// Return whether this Sensor instance is currently listening to the
/// associated sensor in the simulator. /// associated sensor in the simulator.
bool IsListening() const override { bool IsListening() const override {
return _callback_id.has_value(); return _callback_id != 0u;
} }
private: private:
SharedPtr<sensor::SensorData> TickGnssSensor(const Timestamp &timestamp); std::atomic_size_t _callback_id{0u};
geom::GeoLocation _geo_reference;
boost::optional<size_t> _callback_id;
}; };
} // namespace client } // namespace client

View File

@ -31,6 +31,7 @@ namespace detail {
size_t Push(CallbackType &&callback) { size_t Push(CallbackType &&callback) {
auto id = ++_counter; auto id = ++_counter;
DEBUG_ASSERT(id != 0u);
_list.Push(Item{id, std::move(callback)}); _list.Push(Item{id, std::move(callback)});
return id; return id;
} }