Make Simulator class, leave Client to pure networking methods only

This commit is contained in:
nsubiron 2018-10-16 18:00:13 +02:00
parent 38b9822860
commit c7de4c0be7
20 changed files with 566 additions and 276 deletions

View File

@ -7,7 +7,7 @@
#include "carla/client/Actor.h"
#include "carla/Logging.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {

View File

@ -8,7 +8,7 @@
#include "carla/PythonUtil.h"
#include "carla/client/World.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {
@ -28,36 +28,36 @@ namespace client {
size_t worker_threads = 0u);
void SetTimeout(time_duration timeout) {
_client_state->SetTimeout(timeout);
_simulator->SetNetworkingTimeout(timeout);
}
std::string GetClientVersion() const {
return _client_state->GetClientVersion();
return _simulator->GetClientVersion();
}
std::string GetServerVersion() const {
return _client_state->GetServerVersion();
return _simulator->GetServerVersion();
}
bool Ping() const {
return _client_state->Ping();
return _simulator->Ping();
}
World GetWorld() const {
return _client_state->GetCurrentEpisode();
return World{_simulator->GetCurrentEpisode()};
}
private:
SharedPtr<detail::Client> _client_state;
SharedPtr<detail::Simulator> _simulator;
};
inline Client::Client(
const std::string &host,
uint16_t port,
size_t worker_threads)
: _client_state(
new detail::Client(host, port, worker_threads),
: _simulator(
new detail::Simulator(host, port, worker_threads),
PythonUtil::ReleaseGILDeleter()) {}
} // namespace client

View File

@ -7,7 +7,7 @@
#include "carla/client/Sensor.h"
#include "carla/Logging.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {
@ -32,9 +32,7 @@ namespace client {
GetDisplayId());
return;
}
GetEpisode()->SubscribeToStream(
GetActorDescription().GetStreamToken(),
std::move(callback));
GetEpisode()->SubscribeToSensor(*this, std::move(callback));
_is_listening = true;
}
@ -45,8 +43,7 @@ namespace client {
GetDisplayId());
return;
}
GetEpisode()->UnSubscribeFromStream(
GetActorDescription().GetStreamToken());
GetEpisode()->UnSubscribeFromSensor(*this);
_is_listening = false;
}

View File

@ -5,7 +5,8 @@
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "carla/client/Vehicle.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {

View File

@ -9,7 +9,7 @@
#include "carla/Logging.h"
#include "carla/client/Actor.h"
#include "carla/client/ActorBlueprint.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
#include <exception>

View File

@ -7,7 +7,7 @@
#pragma once
#include "carla/Memory.h"
#include "carla/client/detail/Episode.h"
#include "carla/client/detail/EpisodeProxy.h"
#include "carla/geom/Transform.h"
#include "carla/rpc/WeatherParameters.h"
@ -21,7 +21,7 @@ namespace client {
class World {
public:
World(detail::Episode episode) : _episode(std::move(episode)) {}
explicit World(detail::EpisodeProxy episode) : _episode(std::move(episode)) {}
World(const World &) = default;
World(World &&) = default;
@ -49,7 +49,7 @@ namespace client {
private:
detail::Episode _episode;
detail::EpisodeProxy _episode;
};
} // namespace client

View File

@ -55,11 +55,6 @@ namespace detail {
template <typename ActorT>
static auto MakeActorImpl(ActorInitializer init, GarbageCollectionPolicy gc) {
log_debug(
init.GetDisplayId(),
"created",
gc == GarbageCollectionPolicy::Enabled ? "with" : "without",
"garbage collection");
if (gc == GarbageCollectionPolicy::Enabled) {
return SharedPtr<ActorT>{new ActorT(std::move(init)), GarbageCollector()};
}
@ -68,17 +63,15 @@ namespace detail {
}
SharedPtr<Actor> ActorFactory::MakeActor(
Episode episode,
EpisodeProxy episode,
rpc::Actor description,
GarbageCollectionPolicy gc) {
const auto gcw = episode->GetGarbageCollectionPolicy();
const auto gca = (gc == GarbageCollectionPolicy::Inherit ? gcw : gc);
if (description.HasAStream()) {
return MakeActorImpl<Sensor>(ActorInitializer{description, episode}, gca);
return MakeActorImpl<Sensor>(ActorInitializer{description, episode}, gc);
} else if (StringUtil::StartsWith(description.description.id, "vehicle.")) {
return MakeActorImpl<Vehicle>(ActorInitializer{description, episode}, gca);
return MakeActorImpl<Vehicle>(ActorInitializer{description, episode}, gc);
}
return MakeActorImpl<Actor>(ActorInitializer{description, episode}, gca);
return MakeActorImpl<Actor>(ActorInitializer{description, episode}, gc);
}
} // namespace detail

View File

@ -8,7 +8,7 @@
#include "carla/Memory.h"
#include "carla/client/GarbageCollectionPolicy.h"
#include "carla/client/detail/Episode.h"
#include "carla/client/detail/EpisodeProxy.h"
#include "carla/rpc/Actor.h"
namespace carla {
@ -22,9 +22,9 @@ namespace detail {
public:
static SharedPtr<Actor> MakeActor(
Episode episode,
EpisodeProxy episode,
rpc::Actor actor_description,
GarbageCollectionPolicy gc = GarbageCollectionPolicy::Inherit);
GarbageCollectionPolicy gc);
};
} // namespace detail

View File

@ -8,6 +8,7 @@
#include "carla/NonCopyable.h"
#include "carla/client/World.h"
#include "carla/client/detail/EpisodeProxy.h"
#include "carla/rpc/Actor.h"
namespace carla {
@ -16,6 +17,7 @@ namespace detail {
class ActorFactory;
/// Internal state of an Actor.
class ActorState : private MovableNonCopyable {
public:
@ -30,7 +32,7 @@ namespace detail {
std::string GetDisplayId() const;
World GetWorld() const {
return _episode;
return World{_episode};
}
protected:
@ -39,29 +41,31 @@ namespace detail {
return _description;
}
Episode &GetEpisode() {
EpisodeProxy &GetEpisode() {
return _episode;
}
const Episode &GetEpisode() const {
const EpisodeProxy &GetEpisode() const {
return _episode;
}
private:
friend class detail::Client;
friend class Simulator;
ActorState(rpc::Actor description, Episode episode)
ActorState(rpc::Actor description, EpisodeProxy episode)
: _description(std::move(description)),
_episode(std::move(episode)) {}
rpc::Actor _description;
Episode _episode;
EpisodeProxy _episode;
};
} // namespace detail
/// Used to initialize Actor classes. Only the ActorFactory can create this
/// object, thus only the ActorFactory can create actors.
class ActorInitializer : public detail::ActorState {
public:
ActorInitializer(ActorInitializer &&) = default;

View File

@ -7,13 +7,9 @@
#include "carla/client/detail/Client.h"
#include "carla/Version.h"
#include "carla/client/Actor.h"
#include "carla/client/BlueprintLibrary.h"
#include "carla/client/Vehicle.h"
#include "carla/client/World.h"
#include "carla/client/detail/ActorFactory.h"
#include "carla/client/detail/Episode.h"
#include "carla/rpc/ActorDescription.h"
#include "carla/rpc/Client.h"
#include "carla/rpc/VehicleControl.h"
#include "carla/sensor/Deserializer.h"
#include "carla/streaming/Client.h"
@ -60,12 +56,8 @@ namespace detail {
Client::Client(
const std::string &host,
const uint16_t port,
const size_t worker_threads,
const bool enable_garbage_collection)
: LIBCARLA_INITIALIZE_LIFETIME_PROFILER("carla::client::detail::Client"),
_pimpl(std::make_unique<Pimpl>(host, port, worker_threads)),
_gc_policy(enable_garbage_collection ?
GarbageCollectionPolicy::Enabled : GarbageCollectionPolicy::Disabled) {}
const size_t worker_threads)
: _pimpl(std::make_unique<Pimpl>(host, port, worker_threads)) {}
Client::~Client() = default;
@ -73,12 +65,6 @@ namespace detail {
_pimpl->rpc_client.set_timeout(timeout.milliseconds());
}
// Keep this function in the cpp, to avoid recompiling everything on each
// commit.
std::string Client::GetClientVersion() {
return ::carla::version();
}
std::string Client::GetServerVersion() {
return _pimpl->CallAndWait<std::string>("version");
}
@ -87,60 +73,63 @@ namespace detail {
return _pimpl->CallAndWait<bool>("ping");
}
SharedPtr<BlueprintLibrary> Client::GetBlueprintLibrary() {
using return_type = std::vector<carla::rpc::ActorDefinition>;
auto result = _pimpl->CallAndWait<return_type>("get_actor_definitions");
return MakeShared<BlueprintLibrary>(result);
std::vector<rpc::ActorDefinition> Client::GetActorDefinitions() {
return _pimpl->CallAndWait<std::vector<rpc::ActorDefinition>>("get_actor_definitions");
}
SharedPtr<Actor> Client::GetSpectator() {
auto spectator = _pimpl->CallAndWait<carla::rpc::Actor>("get_spectator");
return ActorFactory::MakeActor(
GetCurrentEpisode(),
spectator,
GarbageCollectionPolicy::Disabled);
rpc::Actor Client::GetSpectator() {
return _pimpl->CallAndWait<carla::rpc::Actor>("get_spectator");
}
rpc::WeatherParameters Client::GetWeatherParameters() {
return _pimpl->CallAndWait<rpc::WeatherParameters>("get_weather");
return _pimpl->CallAndWait<rpc::WeatherParameters>("get_weather_parameters");
}
void Client::SetWeatherParameters(const rpc::WeatherParameters &weather) {
_pimpl->AsyncCall("set_weather", weather);
_pimpl->AsyncCall("set_weather_parameters", weather);
}
SharedPtr<Actor> Client::SpawnActor(
const ActorBlueprint &blueprint,
rpc::Actor Client::SpawnActor(
const rpc::ActorDescription &description,
const geom::Transform &transform) {
return _pimpl->CallAndWait<rpc::Actor>("spawn_actor", description, transform);
}
rpc::Actor Client::SpawnActorWithParent(
const rpc::ActorDescription &description,
const geom::Transform &transform,
Actor *parent,
GarbageCollectionPolicy gc) {
rpc::Actor actor;
if (parent != nullptr) {
actor = _pimpl->CallAndWait<rpc::Actor>("spawn_actor_with_parent",
transform,
blueprint.MakeActorDescription(),
parent->Serialize());
} else {
actor = _pimpl->CallAndWait<rpc::Actor>("spawn_actor",
transform,
blueprint.MakeActorDescription());
}
return ActorFactory::MakeActor(GetCurrentEpisode(), actor, gc);
const rpc::Actor &parent) {
return _pimpl->CallAndWait<rpc::Actor>("spawn_actor_with_parent",
description,
transform,
parent);
}
bool Client::DestroyActor(Actor &actor) {
auto result = _pimpl->CallAndWait<bool>("destroy_actor", actor.Serialize());
// Remove it's persistent state so it cannot access the client anymore.
actor.GetEpisode().ClearState();
log_debug(actor.GetDisplayId(), "destroyed.");
return result;
bool Client::DestroyActor(const rpc::Actor &actor) {
return _pimpl->CallAndWait<bool>("destroy_actor", actor);
}
void Client::SetActorLocation(const rpc::Actor &actor, const geom::Location &location) {
_pimpl->AsyncCall("set_actor_location", actor, location);
}
void Client::SetActorTransform(const rpc::Actor &actor, const geom::Transform &transform) {
_pimpl->AsyncCall("set_actor_transform", actor, transform);
}
void Client::SetActorAutopilot(const rpc::Actor &vehicle, const bool enabled) {
_pimpl->AsyncCall("set_actor_autopilot", vehicle, enabled);
}
void Client::ApplyControlToActor(const rpc::Actor &vehicle, const rpc::VehicleControl &control) {
_pimpl->AsyncCall("apply_control_to_actor", vehicle, control);
}
void Client::SubscribeToStream(
const streaming::Token &token,
std::function<void(SharedPtr<sensor::SensorData>)> callback) {
_pimpl->streaming_client.Subscribe(token, [callback](auto buffer) {
callback(sensor::Deserializer::Deserialize(std::move(buffer)));
_pimpl->streaming_client.Subscribe(token, [cb=std::move(callback)](auto buffer) {
cb(sensor::Deserializer::Deserialize(std::move(buffer)));
});
}
@ -148,34 +137,6 @@ namespace detail {
_pimpl->streaming_client.UnSubscribe(token);
}
geom::Location Client::GetActorLocation(const Actor &actor) {
return _pimpl->CallAndWait<geom::Location>("get_actor_location", actor.Serialize());
}
geom::Transform Client::GetActorTransform(const Actor &actor) {
return _pimpl->CallAndWait<geom::Transform>("get_actor_transform", actor.Serialize());
}
void Client::SetActorLocation(Actor &actor, const geom::Location &location) {
_pimpl->AsyncCall("set_actor_location", actor.Serialize(), location);
}
void Client::SetActorTransform(Actor &actor, const geom::Transform &transform) {
_pimpl->AsyncCall("set_actor_transform", actor.Serialize(), transform);
}
void Client::SetVehicleAutopilot(
Vehicle &vehicle,
const bool enabled) {
_pimpl->AsyncCall("set_actor_autopilot", vehicle.Serialize(), enabled);
}
void Client::ApplyControlToVehicle(
Vehicle &vehicle,
const rpc::VehicleControl &control) {
_pimpl->AsyncCall("apply_control_to_actor", vehicle.Serialize(), control);
}
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -9,26 +9,22 @@
#include "carla/Memory.h"
#include "carla/NonCopyable.h"
#include "carla/Time.h"
#include "carla/client/GarbageCollectionPolicy.h"
#include "carla/client/detail/Episode.h"
#include "carla/geom/Transform.h"
#include "carla/profiler/LifetimeProfiled.h"
#include "carla/rpc/Actor.h"
#include "carla/rpc/ActorDefinition.h"
#include "carla/rpc/WeatherParameters.h"
#include <functional>
#include <memory>
#include <string>
#include <vector>
// Forward declarations.
namespace carla {
namespace client {
class Actor;
class ActorBlueprint;
class BlueprintLibrary;
class Vehicle;
class Episode;
namespace rpc {
class ActorDescription;
class VehicleControl;
}
namespace rpc { class VehicleControl; }
namespace sensor { class SensorData; }
namespace streaming { class Token; }
}
@ -37,44 +33,60 @@ namespace carla {
namespace client {
namespace detail {
/// Provides communication with the rpc and streaming servers of a CARLA
/// simulator.
///
/// @todo Make sure this class is really thread-safe.
class Client
: public EnableSharedFromThis<Client>,
private profiler::LifetimeProfiled,
private NonCopyable {
class Client : private NonCopyable {
public:
explicit Client(
const std::string &host,
uint16_t port,
size_t worker_threads = 0u,
bool enable_garbage_collection = false);
size_t worker_threads = 0u);
~Client();
void SetTimeout(time_duration timeout);
std::string GetClientVersion();
std::string GetServerVersion();
bool Ping();
SharedPtr<BlueprintLibrary> GetBlueprintLibrary();
std::vector<rpc::ActorDefinition> GetActorDefinitions();
SharedPtr<Actor> GetSpectator();
rpc::Actor GetSpectator();
rpc::WeatherParameters GetWeatherParameters();
void SetWeatherParameters(const rpc::WeatherParameters &weather);
SharedPtr<Actor> SpawnActor(
const ActorBlueprint &blueprint,
const geom::Transform &transform,
Actor *parent,
GarbageCollectionPolicy gc = GarbageCollectionPolicy::Inherit);
rpc::Actor SpawnActor(
const rpc::ActorDescription &description,
const geom::Transform &transform);
bool DestroyActor(Actor &actor);
rpc::Actor SpawnActorWithParent(
const rpc::ActorDescription &description,
const geom::Transform &transform,
const rpc::Actor &parent);
bool DestroyActor(const rpc::Actor &actor);
void SetActorLocation(
const rpc::Actor &actor,
const geom::Location &location);
void SetActorTransform(
const rpc::Actor &actor,
const geom::Transform &transform);
void SetActorAutopilot(
const rpc::Actor &vehicle,
bool enabled);
void ApplyControlToActor(
const rpc::Actor &vehicle,
const rpc::VehicleControl &control);
void SubscribeToStream(
const streaming::Token &token,
@ -82,40 +94,10 @@ namespace detail {
void UnSubscribeFromStream(const streaming::Token &token);
geom::Location GetActorLocation(const Actor &actor);
geom::Transform GetActorTransform(const Actor &actor);
void SetActorLocation(Actor &actor, const geom::Location &location);
void SetActorTransform(Actor &actor, const geom::Transform &transform);
void SetVehicleAutopilot(Vehicle &vehicle, bool enabled = true);
void ApplyControlToVehicle(Vehicle &vehicle, const rpc::VehicleControl &control);
GarbageCollectionPolicy GetGarbageCollectionPolicy() const {
return _gc_policy;
}
size_t GetCurrentEpisodeId() const {
return _episode_id;
}
Episode GetCurrentEpisode() {
return shared_from_this();
}
private:
class Pimpl;
const std::unique_ptr<Pimpl> _pimpl;
const GarbageCollectionPolicy _gc_policy;
// At this point the id won't change because we cannot yet restart the
// episode from the client.
const size_t _episode_id = 0u;
};
} // namespace detail

View File

@ -1,58 +0,0 @@
// 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/Debug.h"
#include "carla/Memory.h"
#include "carla/client/detail/PersistentState.h"
namespace carla {
namespace client {
namespace detail {
class EpisodeImpl {
public:
PersistentState &operator*() const {
return GetPersistentStateWithChecks();
}
PersistentState *operator->() const {
return &GetPersistentStateWithChecks();
}
protected:
EpisodeImpl(SharedPtr<PersistentState> state);
void ClearState();
private:
PersistentState &GetPersistentStateWithChecks() const;
SharedPtr<PersistentState> _state;
size_t _episode_id;
};
class Episode : private EpisodeImpl {
public:
using EpisodeImpl::operator*;
using EpisodeImpl::operator->;
private:
friend PersistentState;
using EpisodeImpl::EpisodeImpl;
};
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -4,9 +4,9 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "carla/client/detail/Episode.h"
#include "carla/client/detail/EpisodeProxy.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Simulator.h"
#include <boost/atomic.hpp>
@ -16,27 +16,27 @@ namespace carla {
namespace client {
namespace detail {
EpisodeImpl::EpisodeImpl(SharedPtr<PersistentState> state)
: _state(std::move(state)),
_episode_id(_state->GetCurrentEpisodeId()) {}
EpisodeProxyImpl::EpisodeProxyImpl(SharedPtr<Simulator> simulator)
: _simulator(std::move(simulator)),
_episode_id(_simulator->GetCurrentEpisodeId()) {}
void EpisodeImpl::ClearState() {
boost::atomic_store_explicit(&_state, {nullptr}, boost::memory_order_relaxed);
void EpisodeProxyImpl::ClearState() {
boost::atomic_store_explicit(&_simulator, {nullptr}, boost::memory_order_relaxed);
}
PersistentState &EpisodeImpl::GetPersistentStateWithChecks() const {
auto state = boost::atomic_load_explicit(&_state, boost::memory_order_relaxed);
Simulator &EpisodeProxyImpl::GetSimulatorWithChecks() const {
auto state = boost::atomic_load_explicit(&_simulator, boost::memory_order_relaxed);
if (state == nullptr) {
throw std::runtime_error(
"trying to operate on a destroyed actor; an actor's function "
"was called, but the actor is already destroyed.");
}
if (_episode_id != _state->GetCurrentEpisodeId()) {
if (_episode_id != _simulator->GetCurrentEpisodeId()) {
throw std::runtime_error(
"trying to access an expired episode; a new episode was started "
"in the simulation but an object tried accessing the old one.");
}
return *_state;
return *_simulator;
}
} // namespace detail

View File

@ -0,0 +1,61 @@
// 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/Memory.h"
namespace carla {
namespace client {
namespace detail {
class Simulator;
/// Private implementation of a EpisodeProxy.
class EpisodeProxyImpl {
public:
Simulator &operator*() const {
return GetSimulatorWithChecks();
}
Simulator *operator->() const {
return &GetSimulatorWithChecks();
}
protected:
EpisodeProxyImpl(SharedPtr<Simulator> simulator);
void ClearState();
private:
Simulator &GetSimulatorWithChecks() const;
SharedPtr<Simulator> _simulator;
size_t _episode_id;
};
/// Provides access to the Simulator during a given episode. After the episode
/// is ended any access to the simulator throws an std::runtime_error.
class EpisodeProxy : private EpisodeProxyImpl {
public:
using EpisodeProxyImpl::operator*;
using EpisodeProxyImpl::operator->;
private:
friend class Simulator;
using EpisodeProxyImpl::EpisodeProxyImpl;
};
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -0,0 +1,40 @@
// 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/NonCopyable.h"
#include "carla/rpc/EpisodeInfo.h"
namespace carla {
namespace client {
namespace detail {
/// Represents an episode running on the Simulator.
class EpisodeState : private MovableNonCopyable {
public:
EpisodeState() = default; /// @todo
EpisodeState(rpc::EpisodeInfo description)
: _description(std::move(description)) {}
auto GetId() const {
return _description.id;
}
const std::string &GetMapName() const {
return _description.map_name;
}
private:
rpc::EpisodeInfo _description;
};
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -1,23 +0,0 @@
// 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/client/detail/Client.h"
namespace carla {
namespace client {
namespace detail {
class Client;
/// At this point the client is the only persistent state we have, but
/// conceptually is nice to make the distinction.
using PersistentState = Client;
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -0,0 +1,120 @@
// 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>.
#include "carla/client/detail/Simulator.h"
#include "carla/Logging.h"
#include "carla/client/BlueprintLibrary.h"
#include "carla/client/Sensor.h"
#include "carla/client/detail/ActorFactory.h"
#include <exception>
using namespace std::string_literals;
namespace carla {
namespace client {
namespace detail {
// ===========================================================================
// -- Constructor ------------------------------------------------------------
// ===========================================================================
Simulator::Simulator(
const std::string &host,
const uint16_t port,
const size_t worker_threads,
const bool enable_garbage_collection)
: LIBCARLA_INITIALIZE_LIFETIME_PROFILER("SimulatorClient("s + host + ":" + std::to_string(port) + ")"),
_client(host, port, worker_threads),
_episode(), /// @todo
_gc_policy(enable_garbage_collection ?
GarbageCollectionPolicy::Enabled : GarbageCollectionPolicy::Disabled) {}
// ===========================================================================
// -- Access to global objects in the episode --------------------------------
// ===========================================================================
SharedPtr<BlueprintLibrary> Simulator::GetBlueprintLibrary() {
return MakeShared<BlueprintLibrary>(_client.GetActorDefinitions());
}
SharedPtr<Actor> Simulator::GetSpectator() {
return ActorFactory::MakeActor(
GetCurrentEpisode(),
_client.GetSpectator(),
GarbageCollectionPolicy::Disabled);
}
// ===========================================================================
// -- General operations with actors -----------------------------------------
// ===========================================================================
SharedPtr<Actor> Simulator::SpawnActor(
const ActorBlueprint &blueprint,
const geom::Transform &transform,
Actor *parent,
GarbageCollectionPolicy gc) {
rpc::Actor actor;
if (parent != nullptr) {
actor = _client.SpawnActorWithParent(
blueprint.MakeActorDescription(),
transform,
parent->Serialize());
} else {
actor = _client.SpawnActor(
blueprint.MakeActorDescription(),
transform);
}
const auto gca = (gc == GarbageCollectionPolicy::Inherit ? _gc_policy : gc);
auto result = ActorFactory::MakeActor(GetCurrentEpisode(), actor, gca);
log_debug(
result->GetDisplayId(),
"created",
gca == GarbageCollectionPolicy::Enabled ? "with" : "without",
"garbage collection");
return result;
}
bool Simulator::DestroyActor(Actor &actor) {
auto success = _client.DestroyActor(actor.Serialize());
if (success) {
// Remove it's persistent state so it cannot access the client anymore.
actor.GetEpisode().ClearState();
log_debug(actor.GetDisplayId(), "destroyed.");
} else {
log_debug("failed to destroy", actor.GetDisplayId());
}
return success;
}
geom::Location Simulator::GetActorLocation(const Actor &) {
throw std::runtime_error("GetActorLocation() not implemented!");
}
geom::Transform Simulator::GetActorTransform(const Actor &) {
throw std::runtime_error("GetActorTransform() not implemented!");
}
// ===========================================================================
// -- Operations with sensors ------------------------------------------------
// ===========================================================================
void Simulator::SubscribeToSensor(
const Sensor &sensor,
std::function<void(SharedPtr<sensor::SensorData>)> callback) {
_client.SubscribeToStream(
sensor.GetActorDescription().GetStreamToken(),
std::move(callback));
}
void Simulator::UnSubscribeFromSensor(const Sensor &sensor) {
_client.UnSubscribeFromStream(sensor.GetActorDescription().GetStreamToken());
}
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -0,0 +1,179 @@
// 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/Memory.h"
#include "carla/NonCopyable.h"
#include "carla/Version.h"
#include "carla/client/Actor.h"
#include "carla/client/GarbageCollectionPolicy.h"
#include "carla/client/Vehicle.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/EpisodeProxy.h"
#include "carla/client/detail/EpisodeState.h"
#include "carla/profiler/LifetimeProfiled.h"
namespace carla {
namespace client {
class ActorBlueprint;
class BlueprintLibrary;
class Episode;
class Sensor;
namespace detail {
/// Connects and controls a CARLA Simulator.
///
/// @todo Make sure this class is really thread-safe.
class Simulator
: public EnableSharedFromThis<Simulator>,
private profiler::LifetimeProfiled,
private NonCopyable {
public:
// =========================================================================
/// @name Constructor
// =========================================================================
/// @{
explicit Simulator(
const std::string &host,
uint16_t port,
size_t worker_threads = 0u,
bool enable_garbage_collection = false);
/// @}
// =========================================================================
/// @name Access to current episode
// =========================================================================
/// @{
auto GetCurrentEpisodeId() const {
return _episode.GetId();
}
EpisodeProxy GetCurrentEpisode() {
return EpisodeProxy{shared_from_this()};
}
/// @}
// =========================================================================
/// @name Garbage collection policy
// =========================================================================
/// @{
GarbageCollectionPolicy GetGarbageCollectionPolicy() const {
return _gc_policy;
}
/// @}
// =========================================================================
/// @name Pure networking operations
// =========================================================================
/// @{
void SetNetworkingTimeout(time_duration timeout) {
_client.SetTimeout(timeout);
}
std::string GetClientVersion() {
return ::carla::version();
}
std::string GetServerVersion() {
return _client.GetServerVersion();
}
bool Ping() {
return _client.Ping();
}
/// @}
// =========================================================================
/// @name Access to global objects in the episode
// =========================================================================
/// @{
SharedPtr<BlueprintLibrary> GetBlueprintLibrary();
SharedPtr<Actor> GetSpectator();
rpc::WeatherParameters GetWeatherParameters() {
return _client.GetWeatherParameters();
}
void SetWeatherParameters(const rpc::WeatherParameters &weather) {
_client.SetWeatherParameters(weather);
}
/// @}
// =========================================================================
/// @name General operations with actors
// =========================================================================
/// @{
SharedPtr<Actor> SpawnActor(
const ActorBlueprint &blueprint,
const geom::Transform &transform,
Actor *parent = nullptr,
GarbageCollectionPolicy gc = GarbageCollectionPolicy::Inherit);
bool DestroyActor(Actor &actor);
geom::Location GetActorLocation(const Actor &actor);
geom::Transform GetActorTransform(const Actor &actor);
void SetActorLocation(Actor &actor, const geom::Location &location) {
_client.SetActorLocation(actor.Serialize(), location);
}
void SetActorTransform(Actor &actor, const geom::Transform &transform) {
_client.SetActorTransform(actor.Serialize(), transform);
}
/// @}
// =========================================================================
/// @name Operations with vehicles
// =========================================================================
/// @{
void SetVehicleAutopilot(Vehicle &vehicle, bool enabled = true) {
_client.SetActorAutopilot(vehicle.Serialize(), enabled);
}
void ApplyControlToVehicle(Vehicle &vehicle, const rpc::VehicleControl &control) {
_client.ApplyControlToActor(vehicle.Serialize(), control);
}
/// @}
// =========================================================================
/// @name Operations with sensors
// =========================================================================
/// @{
void SubscribeToSensor(
const Sensor &sensor,
std::function<void(SharedPtr<sensor::SensorData>)> callback);
void UnSubscribeFromSensor(const Sensor &sensor);
/// @}
private:
Client _client;
EpisodeState _episode;
GarbageCollectionPolicy _gc_policy;
};
} // namespace detail
} // namespace client
} // namespace carla

View File

@ -0,0 +1,33 @@
// 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/MsgPack.h"
#include "carla/streaming/Token.h"
#include <cstdint>
#include <string>
namespace carla {
namespace rpc {
class EpisodeInfo {
public:
using id_type = uint32_t;
id_type id;
std::string map_name;
streaming::Token token;
MSGPACK_DEFINE_ARRAY(id, map_name, token);
};
} // namespace rpc
} // namespace carla

View File

@ -149,7 +149,7 @@ void FTheNewCarlaServer::FPimpl::BindActions()
return ActorView;
});
Server.BindSync("get_weather", [this]() -> cr::WeatherParameters {
Server.BindSync("get_weather_parameters", [this]() -> cr::WeatherParameters {
RequireEpisode();
auto *Weather = Episode->GetWeather();
if (Weather == nullptr) {
@ -158,7 +158,7 @@ void FTheNewCarlaServer::FPimpl::BindActions()
return Weather->GetCurrentWeather();
});
Server.BindSync("set_weather", [this](const cr::WeatherParameters &weather) {
Server.BindSync("set_weather_parameters", [this](const cr::WeatherParameters &weather) {
RequireEpisode();
auto *Weather = Episode->GetWeather();
if (Weather == nullptr) {
@ -168,15 +168,15 @@ void FTheNewCarlaServer::FPimpl::BindActions()
});
Server.BindSync("spawn_actor", [this](
const cr::Transform &Transform,
cr::ActorDescription Description) -> cr::Actor {
cr::ActorDescription Description,
const cr::Transform &Transform) -> cr::Actor {
RequireEpisode();
return SerializeActor(SpawnActor(Transform, Description));
});
Server.BindSync("spawn_actor_with_parent", [this](
const cr::Transform &Transform,
cr::ActorDescription Description,
const cr::Transform &Transform,
cr::Actor Parent) -> cr::Actor {
RequireEpisode();
auto ActorView = SpawnActor(Transform, Description);