Add on_tick event
This commit is contained in:
parent
aa83b8abf8
commit
b80f70b8b9
|
@ -25,6 +25,7 @@
|
|||
- `spawn_actor(blueprint, transform, attach_to=None)`
|
||||
- `try_spawn_actor(blueprint, transform, attach_to=None)`
|
||||
- `wait_for_tick(seconds=1.0)`
|
||||
- `on_tick(callback)`
|
||||
|
||||
## `carla.BlueprintLibrary`
|
||||
|
||||
|
|
|
@ -74,5 +74,9 @@ namespace client {
|
|||
return _episode.Lock()->WaitForTick(timeout);
|
||||
}
|
||||
|
||||
void World::OnTick(std::function<void(Timestamp)> callback) {
|
||||
return _episode.Lock()->RegisterOnTickEvent(std::move(callback));
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
||||
|
|
|
@ -58,6 +58,8 @@ namespace client {
|
|||
|
||||
Timestamp WaitForTick(time_duration timeout) const;
|
||||
|
||||
void OnTick(std::function<void(Timestamp)> callback);
|
||||
|
||||
private:
|
||||
|
||||
detail::EpisodeProxy _episode;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/AtomicSharedPtr.h"
|
||||
#include "carla/NonCopyable.h"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
namespace detail {
|
||||
|
||||
template <typename... InputsT>
|
||||
class CallbackList : private NonCopyable {
|
||||
public:
|
||||
|
||||
using CallbackType = std::function<void(InputsT...)>;
|
||||
|
||||
CallbackList() : _list(std::make_shared<ListType>()) {}
|
||||
|
||||
void Call(InputsT... args) const {
|
||||
auto list = _list.load();
|
||||
for (auto &callback : *list) {
|
||||
callback(args...);
|
||||
}
|
||||
}
|
||||
|
||||
/// @todo This function cannot be called concurrently.
|
||||
void RegisterCallback(CallbackType callback) {
|
||||
auto new_list = std::make_shared<ListType>(*_list.load());
|
||||
new_list->emplace_back(std::move(callback));
|
||||
_list = new_list;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using ListType = std::vector<CallbackType>;
|
||||
|
||||
AtomicSharedPtr<const ListType> _list;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -39,6 +39,7 @@ namespace detail {
|
|||
/// @todo Check that this state occurred after.
|
||||
self->_state = next;
|
||||
self->_timestamp.SetValue(next->GetTimestamp());
|
||||
self->_on_tick_callbacks.Call(next->GetTimestamp());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "carla/RecurrentSharedFuture.h"
|
||||
#include "carla/client/Timestamp.h"
|
||||
#include "carla/client/detail/CachedActorList.h"
|
||||
#include "carla/client/detail/CallbackList.h"
|
||||
#include "carla/client/detail/EpisodeState.h"
|
||||
#include "carla/rpc/EpisodeInfo.h"
|
||||
|
||||
|
@ -32,10 +33,6 @@ namespace detail {
|
|||
|
||||
void Listen();
|
||||
|
||||
Timestamp WaitForState(time_duration timeout) {
|
||||
return _timestamp.WaitFor(timeout);
|
||||
}
|
||||
|
||||
auto GetId() const {
|
||||
return _description.id;
|
||||
}
|
||||
|
@ -56,6 +53,14 @@ namespace detail {
|
|||
|
||||
std::vector<rpc::Actor> GetActors();
|
||||
|
||||
Timestamp WaitForState(time_duration timeout) {
|
||||
return _timestamp.WaitFor(timeout);
|
||||
}
|
||||
|
||||
void RegisterOnTickEvent(std::function<void(Timestamp)> callback) {
|
||||
_on_tick_callbacks.RegisterCallback(std::move(callback));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Client &_client;
|
||||
|
@ -67,6 +72,8 @@ namespace detail {
|
|||
AtomicSharedPtr<const EpisodeState> _state;
|
||||
|
||||
CachedActorList _actors;
|
||||
|
||||
CallbackList<Timestamp> _on_tick_callbacks;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -106,6 +106,11 @@ namespace detail {
|
|||
return _episode->WaitForState(timeout);
|
||||
}
|
||||
|
||||
void RegisterOnTickEvent(std::function<void(Timestamp)> callback) {
|
||||
DEBUG_ASSERT(_episode != nullptr);
|
||||
_episode->RegisterOnTickEvent(std::move(callback));
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Access to global objects in the episode
|
||||
|
|
|
@ -8,27 +8,7 @@
|
|||
#include <carla/client/Sensor.h>
|
||||
|
||||
static void SubscribeToStream(carla::client::Sensor &self, boost::python::object callback) {
|
||||
namespace py = boost::python;
|
||||
// Make sure the callback is actually callable.
|
||||
if (!PyCallable_Check(callback.ptr())) {
|
||||
PyErr_SetString(PyExc_TypeError, "callback argument must be callable!");
|
||||
py::throw_error_already_set();
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to delete the callback while holding the GIL.
|
||||
using Deleter = carla::PythonUtil::AcquireGILDeleter;
|
||||
auto callback_ptr = carla::SharedPtr<py::object>{new py::object(callback), Deleter()};
|
||||
|
||||
// Subscribe to the sensor.
|
||||
self.Listen([callback=std::move(callback_ptr)](auto message) {
|
||||
carla::PythonUtil::AcquireGIL lock;
|
||||
try {
|
||||
py::call<void>(callback->ptr(), py::object(message));
|
||||
} catch (const py::error_already_set &e) {
|
||||
PyErr_Print();
|
||||
}
|
||||
});
|
||||
self.Listen(MakeCallback(std::move(callback)));
|
||||
}
|
||||
|
||||
void export_sensor() {
|
||||
|
|
|
@ -39,6 +39,10 @@ static auto WaitForTick(const carla::client::World &world, double seconds) {
|
|||
return world.WaitForTick(TimeDurationFromSeconds(seconds));
|
||||
}
|
||||
|
||||
static void OnTick(carla::client::World &self, boost::python::object callback) {
|
||||
self.OnTick(MakeCallback(std::move(callback)));
|
||||
}
|
||||
|
||||
void export_world() {
|
||||
using namespace boost::python;
|
||||
namespace cc = carla::client;
|
||||
|
@ -88,6 +92,7 @@ void export_world() {
|
|||
.def("try_spawn_actor", SPAWN_ACTOR_WITHOUT_GIL(TrySpawnActor))
|
||||
.def("spawn_actor", SPAWN_ACTOR_WITHOUT_GIL(SpawnActor))
|
||||
.def("wait_for_tick", &WaitForTick, (arg("seconds")=1.0))
|
||||
.def("on_tick", &OnTick, (arg("callback")))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
|
|
|
@ -66,6 +66,29 @@ static carla::time_duration TimeDurationFromSeconds(double seconds) {
|
|||
return carla::time_duration::milliseconds(ms);
|
||||
}
|
||||
|
||||
static auto MakeCallback(boost::python::object callback) {
|
||||
namespace py = boost::python;
|
||||
// Make sure the callback is actually callable.
|
||||
if (!PyCallable_Check(callback.ptr())) {
|
||||
PyErr_SetString(PyExc_TypeError, "callback argument must be callable!");
|
||||
py::throw_error_already_set();
|
||||
}
|
||||
|
||||
// We need to delete the callback while holding the GIL.
|
||||
using Deleter = carla::PythonUtil::AcquireGILDeleter;
|
||||
auto callback_ptr = carla::SharedPtr<py::object>{new py::object(callback), Deleter()};
|
||||
|
||||
// Make a lambda callback.
|
||||
return [callback=std::move(callback_ptr)](auto message) {
|
||||
carla::PythonUtil::AcquireGIL lock;
|
||||
try {
|
||||
py::call<void>(callback->ptr(), py::object(message));
|
||||
} catch (const py::error_already_set &e) {
|
||||
PyErr_Print();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include "Actor.cpp"
|
||||
#include "Blueprint.cpp"
|
||||
#include "Client.cpp"
|
||||
|
|
Loading…
Reference in New Issue