Fix GNSS sensor concurrency
This commit is contained in:
parent
39f5c4da49
commit
a2c60994f5
|
@ -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 ×tamp) {
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 ×tamp);
|
std::atomic_size_t _callback_id{0u};
|
||||||
|
|
||||||
geom::GeoLocation _geo_reference;
|
|
||||||
|
|
||||||
boost::optional<size_t> _callback_id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue