Control walker skeleton from Python API (#1719)
This commit is contained in:
parent
33dc5dde8d
commit
d8145c8dba
Binary file not shown.
After Width: | Height: | Size: 530 KiB |
|
@ -290,6 +290,19 @@
|
|||
- `__eq__(other)`
|
||||
- `__ne__(other)`
|
||||
|
||||
## `carla.WalkerControl`
|
||||
|
||||
- `direction`
|
||||
- `speed`
|
||||
- `jump`
|
||||
- `__eq__(other)`
|
||||
- `__ne__(other)`
|
||||
|
||||
## `carla.WalkerBoneControl`
|
||||
|
||||
- `bone_transforms`
|
||||
|
||||
|
||||
## `carla.Map`
|
||||
|
||||
- `__init__(name, xodr_content)`
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<h1>Walker Bone Control</h1>
|
||||
|
||||
In this tutorial we describe how to manually control and animate the
|
||||
skeletons of walkers from the CARLA Python API. The reference of
|
||||
all classes and methods available can be found at
|
||||
[Python API reference](python_api.md).
|
||||
|
||||
!!! note
|
||||
**This document assumes the user is familiar with the Python API**. <br>
|
||||
The user should read the Python API tutorial before reading this document.
|
||||
[Python API tutorial](python_api_tutorial.md).
|
||||
|
||||
|
||||
### Walker skeleton structure
|
||||
All walkers have the same skeleton hierarchy and bone names. Below is an image of the skeleton
|
||||
hierarchy.
|
||||
|
||||

|
||||
|
||||
|
||||
### How to manually control a walker's bones
|
||||
|
||||
Following is a detailed step-by-step example of how to change the bone transforms of a walker
|
||||
from the CARLA Python API
|
||||
|
||||
#### Connecting to the simulator
|
||||
|
||||
Import neccessary libraries used in this example
|
||||
|
||||
```py
|
||||
import carla
|
||||
import random
|
||||
```
|
||||
|
||||
Initialize the carla client
|
||||
|
||||
```py
|
||||
client = carla.Client('127.0.0.1', 2000)
|
||||
client.set_timeout(2.0)
|
||||
```
|
||||
|
||||
#### Spawning a walker
|
||||
Spawn a random walker at one of the map's spawn points
|
||||
|
||||
```py
|
||||
world = client.get_world()
|
||||
blueprint = random.choice(self.world.get_blueprint_library().filter('walker.*'))
|
||||
spawn_points = world.get_map().get_spawn_points()
|
||||
spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform()
|
||||
world.try_spawn_actor(blueprint, spawn_point)
|
||||
```
|
||||
|
||||
#### Controlling a walker's skeleton
|
||||
|
||||
A walker's skeleton can be modified by passing an instance of the WalkerBoneControl class
|
||||
to the walker's apply_control function. The WalkerBoneControl class contains the transforms
|
||||
of the bones to be modified. Its bone_transforms member is a list of tuples of value pairs
|
||||
where the first value is the bone name and the second value is the bone transform. The
|
||||
apply_control function can be called on every tick to animate a walker's skeleton. The
|
||||
location and rotation of each transform is relative to its parent. Therefore when a
|
||||
parent bone's transform is modified, the transforms of the child bones in model space
|
||||
will also be changed relatively.
|
||||
|
||||
In the example below, the rotations of the walker's hands are set to be 90 degrees around
|
||||
the forward axis and the locations are set to the origin.
|
||||
|
||||
```py
|
||||
control = carla.WalkerBoneControl()
|
||||
first_tuple = ('crl_hand__R', carla.Transform(rotation=carla.Rotation(roll=90)))
|
||||
second_tuple = ('crl_hand__L', carla.Transform(rotation=carla.Rotation(roll=90)))
|
||||
control.bone_transforms = [first_tuple, second_tuple]
|
||||
world.player.apply_control(control)
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -18,9 +18,12 @@ namespace client {
|
|||
}
|
||||
}
|
||||
|
||||
void Walker::ApplyControl(const BoneControl &bone_control) {
|
||||
GetEpisode().Lock()->ApplyBoneControlToWalker(*this, bone_control);
|
||||
}
|
||||
|
||||
Walker::Control Walker::GetWalkerControl() const {
|
||||
return GetEpisode().Lock()->GetActorSnapshot(*this).state.walker_control;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/rpc/WalkerControl.h"
|
||||
#include "carla/rpc/WalkerBoneControl.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
@ -16,6 +17,7 @@ namespace client {
|
|||
public:
|
||||
|
||||
using Control = rpc::WalkerControl;
|
||||
using BoneControl = rpc::WalkerBoneControl;
|
||||
|
||||
explicit Walker(ActorInitializer init) : Actor(std::move(init)) {}
|
||||
|
||||
|
@ -24,6 +26,8 @@ namespace client {
|
|||
/// Apply @a control to this Walker.
|
||||
void ApplyControl(const Control &control);
|
||||
|
||||
void ApplyControl(const BoneControl &bone_control);
|
||||
|
||||
/// Return the control last applied to this Walker.
|
||||
///
|
||||
/// @note This function does not call the simulator, it returns the Control
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
#include "carla/Version.h"
|
||||
#include "carla/client/TimeoutException.h"
|
||||
#include "carla/rpc/ActorDescription.h"
|
||||
#include "carla/rpc/BoneTransformData.h"
|
||||
#include "carla/rpc/Client.h"
|
||||
#include "carla/rpc/DebugShape.h"
|
||||
#include "carla/rpc/Response.h"
|
||||
#include "carla/rpc/VehicleControl.h"
|
||||
#include "carla/rpc/WalkerBoneControl.h"
|
||||
#include "carla/rpc/WalkerControl.h"
|
||||
#include "carla/streaming/Client.h"
|
||||
|
||||
|
@ -50,18 +52,18 @@ namespace detail {
|
|||
worker_threads > 0u ? worker_threads : std::thread::hardware_concurrency());
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto RawCall(const std::string &function, Args &&... args) {
|
||||
template <typename ... Args>
|
||||
auto RawCall(const std::string &function, Args && ... args) {
|
||||
try {
|
||||
return rpc_client.call(function, std::forward<Args>(args)...);
|
||||
return rpc_client.call(function, std::forward<Args>(args) ...);
|
||||
} catch (const ::rpc::timeout &) {
|
||||
throw_exception(TimeoutException(endpoint, GetTimeout()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
auto CallAndWait(const std::string &function, Args &&... args) {
|
||||
auto object = RawCall(function, std::forward<Args>(args)...);
|
||||
template <typename T, typename ... Args>
|
||||
auto CallAndWait(const std::string &function, Args && ... args) {
|
||||
auto object = RawCall(function, std::forward<Args>(args) ...);
|
||||
using R = typename carla::rpc::Response<T>;
|
||||
auto response = object.template as<R>();
|
||||
if (response.HasError()) {
|
||||
|
@ -70,10 +72,10 @@ namespace detail {
|
|||
return Get(response);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void AsyncCall(const std::string &function, Args &&... args) {
|
||||
template <typename ... Args>
|
||||
void AsyncCall(const std::string &function, Args && ... args) {
|
||||
// Discard returned future.
|
||||
rpc_client.async_call(function, std::forward<Args>(args)...);
|
||||
rpc_client.async_call(function, std::forward<Args>(args) ...);
|
||||
}
|
||||
|
||||
time_duration GetTimeout() const {
|
||||
|
@ -242,6 +244,10 @@ namespace detail {
|
|||
_pimpl->AsyncCall("apply_control_to_walker", walker, control);
|
||||
}
|
||||
|
||||
void Client::ApplyBoneControlToWalker(rpc::ActorId walker, const rpc::WalkerBoneControl &control) {
|
||||
_pimpl->AsyncCall("apply_bone_control_to_walker", walker, control);
|
||||
}
|
||||
|
||||
void Client::SetTrafficLightState(
|
||||
rpc::ActorId traffic_light,
|
||||
const rpc::TrafficLightState traffic_light_state) {
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace rpc {
|
|||
class DebugShape;
|
||||
class VehicleControl;
|
||||
class WalkerControl;
|
||||
class WalkerBoneControl;
|
||||
}
|
||||
namespace sensor {
|
||||
class SensorData;
|
||||
|
@ -147,6 +148,10 @@ namespace detail {
|
|||
rpc::ActorId walker,
|
||||
const rpc::WalkerControl &control);
|
||||
|
||||
void ApplyBoneControlToWalker(
|
||||
rpc::ActorId walker,
|
||||
const rpc::WalkerBoneControl &control);
|
||||
|
||||
void SetTrafficLightState(
|
||||
rpc::ActorId traffic_light,
|
||||
const rpc::TrafficLightState trafficLightState);
|
||||
|
|
|
@ -296,6 +296,10 @@ namespace detail {
|
|||
_client.ApplyControlToWalker(walker.GetId(), control);
|
||||
}
|
||||
|
||||
void ApplyBoneControlToWalker(Walker &walker, const rpc::WalkerBoneControl &control) {
|
||||
_client.ApplyBoneControlToWalker(walker.GetId(), control);
|
||||
}
|
||||
|
||||
void ApplyPhysicsControlToVehicle(Vehicle &vehicle, const rpc::VehiclePhysicsControl &physicsControl) {
|
||||
_client.ApplyPhysicsControlToVehicle(vehicle.GetId(), physicsControl);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2019 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/rpc/Transform.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
using BoneTransformData = std::pair<std::string, geom::Transform>;
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -48,14 +48,17 @@ namespace rpc {
|
|||
|
||||
struct DestroyActor : CommandBase<DestroyActor> {
|
||||
DestroyActor() = default;
|
||||
DestroyActor(ActorId id) : actor(id) {}
|
||||
DestroyActor(ActorId id)
|
||||
: actor(id) {}
|
||||
ActorId actor;
|
||||
MSGPACK_DEFINE_ARRAY(actor);
|
||||
};
|
||||
|
||||
struct ApplyVehicleControl : CommandBase<ApplyVehicleControl> {
|
||||
ApplyVehicleControl() = default;
|
||||
ApplyVehicleControl(ActorId id, const VehicleControl &value) : actor(id), control(value) {}
|
||||
ApplyVehicleControl(ActorId id, const VehicleControl &value)
|
||||
: actor(id),
|
||||
control(value) {}
|
||||
ActorId actor;
|
||||
VehicleControl control;
|
||||
MSGPACK_DEFINE_ARRAY(actor, control);
|
||||
|
@ -63,7 +66,9 @@ namespace rpc {
|
|||
|
||||
struct ApplyWalkerControl : CommandBase<ApplyWalkerControl> {
|
||||
ApplyWalkerControl() = default;
|
||||
ApplyWalkerControl(ActorId id, const WalkerControl &value) : actor(id), control(value) {}
|
||||
ApplyWalkerControl(ActorId id, const WalkerControl &value)
|
||||
: actor(id),
|
||||
control(value) {}
|
||||
ActorId actor;
|
||||
WalkerControl control;
|
||||
MSGPACK_DEFINE_ARRAY(actor, control);
|
||||
|
@ -71,7 +76,9 @@ namespace rpc {
|
|||
|
||||
struct ApplyTransform : CommandBase<ApplyTransform> {
|
||||
ApplyTransform() = default;
|
||||
ApplyTransform(ActorId id, const geom::Transform &value) : actor(id), transform(value) {}
|
||||
ApplyTransform(ActorId id, const geom::Transform &value)
|
||||
: actor(id),
|
||||
transform(value) {}
|
||||
ActorId actor;
|
||||
geom::Transform transform;
|
||||
MSGPACK_DEFINE_ARRAY(actor, transform);
|
||||
|
@ -79,7 +86,9 @@ namespace rpc {
|
|||
|
||||
struct ApplyVelocity : CommandBase<ApplyVelocity> {
|
||||
ApplyVelocity() = default;
|
||||
ApplyVelocity(ActorId id, const geom::Vector3D &value) : actor(id), velocity(value) {}
|
||||
ApplyVelocity(ActorId id, const geom::Vector3D &value)
|
||||
: actor(id),
|
||||
velocity(value) {}
|
||||
ActorId actor;
|
||||
geom::Vector3D velocity;
|
||||
MSGPACK_DEFINE_ARRAY(actor, velocity);
|
||||
|
@ -87,7 +96,9 @@ namespace rpc {
|
|||
|
||||
struct ApplyAngularVelocity : CommandBase<ApplyAngularVelocity> {
|
||||
ApplyAngularVelocity() = default;
|
||||
ApplyAngularVelocity(ActorId id, const geom::Vector3D &value) : actor(id), angular_velocity(value) {}
|
||||
ApplyAngularVelocity(ActorId id, const geom::Vector3D &value)
|
||||
: actor(id),
|
||||
angular_velocity(value) {}
|
||||
ActorId actor;
|
||||
geom::Vector3D angular_velocity;
|
||||
MSGPACK_DEFINE_ARRAY(actor, angular_velocity);
|
||||
|
@ -95,7 +106,9 @@ namespace rpc {
|
|||
|
||||
struct ApplyImpulse : CommandBase<ApplyImpulse> {
|
||||
ApplyImpulse() = default;
|
||||
ApplyImpulse(ActorId id, const geom::Vector3D &value) : actor(id), impulse(value) {}
|
||||
ApplyImpulse(ActorId id, const geom::Vector3D &value)
|
||||
: actor(id),
|
||||
impulse(value) {}
|
||||
ActorId actor;
|
||||
geom::Vector3D impulse;
|
||||
MSGPACK_DEFINE_ARRAY(actor, impulse);
|
||||
|
@ -103,7 +116,9 @@ namespace rpc {
|
|||
|
||||
struct SetSimulatePhysics : CommandBase<SetSimulatePhysics> {
|
||||
SetSimulatePhysics() = default;
|
||||
SetSimulatePhysics(ActorId id, bool value) : actor(id), enabled(value) {}
|
||||
SetSimulatePhysics(ActorId id, bool value)
|
||||
: actor(id),
|
||||
enabled(value) {}
|
||||
ActorId actor;
|
||||
bool enabled;
|
||||
MSGPACK_DEFINE_ARRAY(actor, enabled);
|
||||
|
@ -111,7 +126,9 @@ namespace rpc {
|
|||
|
||||
struct SetAutopilot : CommandBase<SetAutopilot> {
|
||||
SetAutopilot() = default;
|
||||
SetAutopilot(ActorId id, bool value) : actor(id), enabled(value) {}
|
||||
SetAutopilot(ActorId id, bool value)
|
||||
: actor(id),
|
||||
enabled(value) {}
|
||||
ActorId actor;
|
||||
bool enabled;
|
||||
MSGPACK_DEFINE_ARRAY(actor, enabled);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2019 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/rpc/BoneTransformData.h"
|
||||
#include "carla/rpc/String.h"
|
||||
#include "carla/rpc/Transform.h"
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
# include "Carla/Walker/WalkerBoneControl.h"
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class WalkerBoneControl {
|
||||
public:
|
||||
|
||||
WalkerBoneControl() = default;
|
||||
|
||||
explicit WalkerBoneControl(
|
||||
std::vector<rpc::BoneTransformData> bone_transforms)
|
||||
: bone_transforms(bone_transforms) {}
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
operator FWalkerBoneControl() const {
|
||||
FWalkerBoneControl Control;
|
||||
for (auto &bone_transform : bone_transforms) {
|
||||
Control.BoneTransforms.Add(ToFString(bone_transform.first), bone_transform.second);
|
||||
}
|
||||
return Control;
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
std::vector<rpc::BoneTransformData> bone_transforms;
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(bone_transforms);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -43,6 +43,11 @@ static auto GetGroupTrafficLights(carla::client::TrafficLight &self) {
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename ControlT>
|
||||
static void ApplyControl(carla::client::Walker &self, const ControlT &control) {
|
||||
self.ApplyControl(control);
|
||||
}
|
||||
|
||||
void export_actor() {
|
||||
using namespace boost::python;
|
||||
namespace cc = carla::client;
|
||||
|
@ -54,87 +59,89 @@ void export_actor() {
|
|||
;
|
||||
|
||||
class_<cc::Actor, boost::noncopyable, boost::shared_ptr<cc::Actor>>("Actor", no_init)
|
||||
// work-around, force return copy to resolve Actor instead of ActorState.
|
||||
.add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId))
|
||||
.add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId))
|
||||
.add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent))
|
||||
.add_property("semantic_tags", &GetSemanticTags)
|
||||
.add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive))
|
||||
.add_property("attributes", +[] (const cc::Actor &self) {
|
||||
boost::python::dict atttribute_dict;
|
||||
for (auto &&attribute_value : self.GetAttributes()) {
|
||||
atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue();
|
||||
}
|
||||
return atttribute_dict;
|
||||
})
|
||||
.def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld))
|
||||
.def("get_location", &cc::Actor::GetLocation)
|
||||
.def("get_transform", &cc::Actor::GetTransform)
|
||||
.def("get_velocity", &cc::Actor::GetVelocity)
|
||||
.def("get_angular_velocity", &cc::Actor::GetAngularVelocity)
|
||||
.def("get_acceleration", &cc::Actor::GetAcceleration)
|
||||
.def("set_location", &cc::Actor::SetLocation, (arg("location")))
|
||||
.def("set_transform", &cc::Actor::SetTransform, (arg("transform")))
|
||||
.def("set_velocity", &cc::Actor::SetVelocity, (arg("vector")))
|
||||
.def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector")))
|
||||
.def("add_impulse", &cc::Actor::AddImpulse, (arg("vector")))
|
||||
.def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true))
|
||||
.def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
// work-around, force return copy to resolve Actor instead of ActorState.
|
||||
.add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId))
|
||||
.add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId))
|
||||
.add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent))
|
||||
.add_property("semantic_tags", &GetSemanticTags)
|
||||
.add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive))
|
||||
.add_property("attributes", +[] (const cc::Actor &self) {
|
||||
boost::python::dict atttribute_dict;
|
||||
for (auto &&attribute_value : self.GetAttributes()) {
|
||||
atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue();
|
||||
}
|
||||
return atttribute_dict;
|
||||
})
|
||||
.def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld))
|
||||
.def("get_location", &cc::Actor::GetLocation)
|
||||
.def("get_transform", &cc::Actor::GetTransform)
|
||||
.def("get_velocity", &cc::Actor::GetVelocity)
|
||||
.def("get_angular_velocity", &cc::Actor::GetAngularVelocity)
|
||||
.def("get_acceleration", &cc::Actor::GetAcceleration)
|
||||
.def("set_location", &cc::Actor::SetLocation, (arg("location")))
|
||||
.def("set_transform", &cc::Actor::SetTransform, (arg("transform")))
|
||||
.def("set_velocity", &cc::Actor::SetVelocity, (arg("vector")))
|
||||
.def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector")))
|
||||
.def("add_impulse", &cc::Actor::AddImpulse, (arg("vector")))
|
||||
.def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true))
|
||||
.def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle", no_init)
|
||||
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox))
|
||||
.def("apply_control", &cc::Vehicle::ApplyControl, (arg("control")))
|
||||
.def("get_control", &cc::Vehicle::GetControl)
|
||||
.def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control")))
|
||||
.def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl))
|
||||
.def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true))
|
||||
.def("get_speed_limit", &cc::Vehicle::GetSpeedLimit)
|
||||
.def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState)
|
||||
.def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight)
|
||||
.def("get_traffic_light", &cc::Vehicle::GetTrafficLight)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle",
|
||||
no_init)
|
||||
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox))
|
||||
.def("apply_control", &cc::Vehicle::ApplyControl, (arg("control")))
|
||||
.def("get_control", &cc::Vehicle::GetControl)
|
||||
.def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control")))
|
||||
.def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl))
|
||||
.def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true))
|
||||
.def("get_speed_limit", &cc::Vehicle::GetSpeedLimit)
|
||||
.def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState)
|
||||
.def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight)
|
||||
.def("get_traffic_light", &cc::Vehicle::GetTrafficLight)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cc::Walker, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Walker>>("Walker", no_init)
|
||||
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox))
|
||||
.def("apply_control", &cc::Walker::ApplyControl, (arg("control")))
|
||||
.def("get_control", &cc::Walker::GetWalkerControl)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox))
|
||||
.def("apply_control", &ApplyControl<cr::WalkerControl>, (arg("control")))
|
||||
.def("apply_control", &ApplyControl<cr::WalkerBoneControl>, (arg("control")))
|
||||
.def("get_control", &cc::Walker::GetWalkerControl)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cc::TrafficSign, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::TrafficSign>>(
|
||||
"TrafficSign",
|
||||
no_init)
|
||||
.add_property("trigger_volume", CALL_RETURNING_COPY(cc::TrafficSign, GetTriggerVolume))
|
||||
.add_property("trigger_volume", CALL_RETURNING_COPY(cc::TrafficSign, GetTriggerVolume))
|
||||
;
|
||||
|
||||
enum_<cr::TrafficLightState>("TrafficLightState")
|
||||
.value("Red", cr::TrafficLightState::Red)
|
||||
.value("Yellow", cr::TrafficLightState::Yellow)
|
||||
.value("Green", cr::TrafficLightState::Green)
|
||||
.value("Off", cr::TrafficLightState::Off)
|
||||
.value("Unknown", cr::TrafficLightState::Unknown)
|
||||
.value("Red", cr::TrafficLightState::Red)
|
||||
.value("Yellow", cr::TrafficLightState::Yellow)
|
||||
.value("Green", cr::TrafficLightState::Green)
|
||||
.value("Off", cr::TrafficLightState::Off)
|
||||
.value("Unknown", cr::TrafficLightState::Unknown)
|
||||
;
|
||||
|
||||
class_<cc::TrafficLight, bases<cc::TrafficSign>, boost::noncopyable, boost::shared_ptr<cc::TrafficLight>>(
|
||||
"TrafficLight",
|
||||
no_init)
|
||||
.add_property("state", &cc::TrafficLight::GetState)
|
||||
.def("set_state", &cc::TrafficLight::SetState, (arg("state")))
|
||||
.def("get_state", &cc::TrafficLight::GetState)
|
||||
.def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time")))
|
||||
.def("get_green_time", &cc::TrafficLight::GetGreenTime)
|
||||
.def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time")))
|
||||
.def("get_yellow_time", &cc::TrafficLight::GetYellowTime)
|
||||
.def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time")))
|
||||
.def("get_red_time", &cc::TrafficLight::GetRedTime)
|
||||
.def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime)
|
||||
.def("freeze", &cc::TrafficLight::Freeze, (arg("freeze")))
|
||||
.def("is_frozen", &cc::TrafficLight::IsFrozen)
|
||||
.def("get_pole_index", &cc::TrafficLight::GetPoleIndex)
|
||||
.def("get_group_traffic_lights", &GetGroupTrafficLights)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
.add_property("state", &cc::TrafficLight::GetState)
|
||||
.def("set_state", &cc::TrafficLight::SetState, (arg("state")))
|
||||
.def("get_state", &cc::TrafficLight::GetState)
|
||||
.def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time")))
|
||||
.def("get_green_time", &cc::TrafficLight::GetGreenTime)
|
||||
.def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time")))
|
||||
.def("get_yellow_time", &cc::TrafficLight::GetYellowTime)
|
||||
.def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time")))
|
||||
.def("get_red_time", &cc::TrafficLight::GetRedTime)
|
||||
.def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime)
|
||||
.def("freeze", &cc::TrafficLight::Freeze, (arg("freeze")))
|
||||
.def("is_frozen", &cc::TrafficLight::IsFrozen)
|
||||
.def("get_pole_index", &cc::TrafficLight::GetPoleIndex)
|
||||
.def("get_group_traffic_lights", &GetGroupTrafficLights)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
}
|
||||
|
|
|
@ -98,33 +98,33 @@ void export_blueprint() {
|
|||
;
|
||||
|
||||
class_<cc::ActorAttribute>("ActorAttribute", no_init)
|
||||
.add_property("id", CALL_RETURNING_COPY(cc::ActorAttribute, GetId))
|
||||
.add_property("type", &cc::ActorAttribute::GetType)
|
||||
.add_property("recommended_values", CALL_RETURNING_LIST(cc::ActorAttribute, GetRecommendedValues))
|
||||
.add_property("is_modifiable", &cc::ActorAttribute::IsModifiable)
|
||||
.def("as_bool", &cc::ActorAttribute::As<bool>)
|
||||
.def("as_int", &cc::ActorAttribute::As<int>)
|
||||
.def("as_float", &cc::ActorAttribute::As<float>)
|
||||
.def("as_str", &cc::ActorAttribute::As<std::string>)
|
||||
.def("as_color", &cc::ActorAttribute::As<csd::Color>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<bool>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<int>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<float>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<std::string>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<csd::Color>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<cc::ActorAttribute>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<bool>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<int>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<float>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<std::string>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<csd::Color>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<cc::ActorAttribute>)
|
||||
.def("__nonzero__", &cc::ActorAttribute::As<bool>)
|
||||
.def("__bool__", &cc::ActorAttribute::As<bool>)
|
||||
.def("__int__", &cc::ActorAttribute::As<int>)
|
||||
.def("__float__", &cc::ActorAttribute::As<float>)
|
||||
.def("__str__", &cc::ActorAttribute::As<std::string>)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
.add_property("id", CALL_RETURNING_COPY(cc::ActorAttribute, GetId))
|
||||
.add_property("type", &cc::ActorAttribute::GetType)
|
||||
.add_property("recommended_values", CALL_RETURNING_LIST(cc::ActorAttribute, GetRecommendedValues))
|
||||
.add_property("is_modifiable", &cc::ActorAttribute::IsModifiable)
|
||||
.def("as_bool", &cc::ActorAttribute::As<bool>)
|
||||
.def("as_int", &cc::ActorAttribute::As<int>)
|
||||
.def("as_float", &cc::ActorAttribute::As<float>)
|
||||
.def("as_str", &cc::ActorAttribute::As<std::string>)
|
||||
.def("as_color", &cc::ActorAttribute::As<csd::Color>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<bool>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<int>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<float>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<std::string>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<csd::Color>)
|
||||
.def("__eq__", &cc::ActorAttributeValueAccess::operator==<cc::ActorAttribute>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<bool>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<int>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<float>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<std::string>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<csd::Color>)
|
||||
.def("__ne__", &cc::ActorAttributeValueAccess::operator!=<cc::ActorAttribute>)
|
||||
.def("__nonzero__", &cc::ActorAttribute::As<bool>)
|
||||
.def("__bool__", &cc::ActorAttribute::As<bool>)
|
||||
.def("__int__", &cc::ActorAttribute::As<int>)
|
||||
.def("__float__", &cc::ActorAttribute::As<float>)
|
||||
.def("__str__", &cc::ActorAttribute::As<std::string>)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cc::ActorBlueprint>("ActorBlueprint", no_init)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <carla/rpc/VehiclePhysicsControl.h>
|
||||
#include <carla/rpc/WheelPhysicsControl.h>
|
||||
#include <carla/rpc/WalkerControl.h>
|
||||
#include <carla/rpc/WalkerBoneControl.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
|
@ -16,7 +17,7 @@ namespace rpc {
|
|||
|
||||
static auto boolalpha(bool b) {
|
||||
return b ? "True" : "False";
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const VehicleControl &control) {
|
||||
out << "VehicleControl(throttle=" << std::to_string(control.throttle)
|
||||
|
@ -36,6 +37,16 @@ namespace rpc {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const WalkerBoneControl &control) {
|
||||
out << "WalkerBoneControl(bone_transforms(";
|
||||
for (auto bone_transform : control.bone_transforms) {
|
||||
out << "(name=" << bone_transform.first
|
||||
<< ", transform=" << bone_transform.second << ')';
|
||||
}
|
||||
out << "))";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const WheelPhysicsControl &control) {
|
||||
out << "WheelPhysicsControl(tire_friction=" << std::to_string(control.tire_friction)
|
||||
<< ", damping_rate=" << std::to_string(control.damping_rate)
|
||||
|
@ -65,6 +76,7 @@ namespace rpc {
|
|||
} // namespace rpc
|
||||
} // namespace carla
|
||||
|
||||
|
||||
static auto GetVectorOfVector2DFromList(const boost::python::list &list) {
|
||||
std::vector<carla::geom::Vector2D> v;
|
||||
|
||||
|
@ -83,6 +95,24 @@ static auto GetVectorOfVector2DFromList(const boost::python::list &list) {
|
|||
return v;
|
||||
}
|
||||
|
||||
static auto GetVectorOfBoneTransformFromList(const boost::python::list &list) {
|
||||
std::vector<carla::rpc::BoneTransformData> v;
|
||||
|
||||
auto length = boost::python::len(list);
|
||||
v.reserve(static_cast<size_t>(length));
|
||||
for (auto i = 0u; i < length; ++i) {
|
||||
boost::python::extract<carla::rpc::BoneTransformData> ext(list[i]);
|
||||
if (ext.check()) {
|
||||
v.push_back(ext);
|
||||
} else {
|
||||
v.push_back(carla::rpc::BoneTransformData{
|
||||
boost::python::extract<std::string>(list[i][0u]),
|
||||
boost::python::extract<carla::geom::Transform>(list[i][1u])});
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static auto GetWheels(const carla::rpc::VehiclePhysicsControl &self) {
|
||||
const auto &wheels = self.GetWheels();
|
||||
boost::python::object get_iter = boost::python::iterator<std::vector<carla::rpc::WheelPhysicsControl>>();
|
||||
|
@ -122,60 +152,99 @@ static void SetSteeringCurve(carla::rpc::VehiclePhysicsControl &self, const boos
|
|||
}
|
||||
|
||||
boost::python::object VehiclePhysicsControl_init(boost::python::tuple args, boost::python::dict kwargs) {
|
||||
// Args names
|
||||
const uint32_t NUM_ARGUMENTS = 16;
|
||||
const char* args_names[NUM_ARGUMENTS] = {
|
||||
"torque_curve",
|
||||
"max_rpm",
|
||||
"moi",
|
||||
"damping_rate_full_throttle",
|
||||
"damping_rate_zero_throttle_clutch_engaged",
|
||||
"damping_rate_zero_throttle_clutch_disengaged",
|
||||
// Args names
|
||||
const uint32_t NUM_ARGUMENTS = 16;
|
||||
const char *args_names[NUM_ARGUMENTS] = {
|
||||
"torque_curve",
|
||||
"max_rpm",
|
||||
"moi",
|
||||
"damping_rate_full_throttle",
|
||||
"damping_rate_zero_throttle_clutch_engaged",
|
||||
"damping_rate_zero_throttle_clutch_disengaged",
|
||||
|
||||
"use_gear_autobox",
|
||||
"gear_switch_time",
|
||||
"clutch_strength",
|
||||
"use_gear_autobox",
|
||||
"gear_switch_time",
|
||||
"clutch_strength",
|
||||
|
||||
"mass",
|
||||
"drag_coefficient",
|
||||
"mass",
|
||||
"drag_coefficient",
|
||||
|
||||
"center_of_mass",
|
||||
"steering_curve",
|
||||
"wheels"
|
||||
};
|
||||
"center_of_mass",
|
||||
"steering_curve",
|
||||
"wheels"
|
||||
};
|
||||
|
||||
boost::python::object self = args[0];
|
||||
args = boost::python::tuple(args.slice(1, boost::python::_));
|
||||
boost::python::object self = args[0];
|
||||
args = boost::python::tuple(args.slice(1, boost::python::_));
|
||||
|
||||
auto res = self.attr("__init__")();
|
||||
if (len(args) > 0) {
|
||||
for (unsigned int i=0; i < len(args); ++i)
|
||||
self.attr(args_names[i]) = args[i];
|
||||
auto res = self.attr("__init__")();
|
||||
if (len(args) > 0) {
|
||||
for (unsigned int i = 0; i < len(args); ++i) {
|
||||
self.attr(args_names[i]) = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ARGUMENTS; ++i) {
|
||||
if (kwargs.contains(args_names[i])) {
|
||||
self.attr(args_names[i]) = kwargs[args_names[i]];
|
||||
}
|
||||
for (unsigned int i = 0; i < NUM_ARGUMENTS; ++i) {
|
||||
if (kwargs.contains(args_names[i])) {
|
||||
self.attr(args_names[i]) = kwargs[args_names[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
static auto GetBonesTransform(const carla::rpc::WalkerBoneControl &self) {
|
||||
const std::vector<carla::rpc::BoneTransformData> &bone_transform_data = self.bone_transforms;
|
||||
boost::python::object get_iter =
|
||||
boost::python::iterator<const std::vector<carla::rpc::BoneTransformData>>();
|
||||
boost::python::object iter = get_iter(bone_transform_data);
|
||||
return boost::python::list(iter);
|
||||
}
|
||||
|
||||
static void SetBonesTransform(carla::rpc::WalkerBoneControl &self, const boost::python::list &list) {
|
||||
self.bone_transforms = GetVectorOfBoneTransformFromList(list);
|
||||
}
|
||||
|
||||
boost::python::object WalkerBoneControl_init(boost::python::tuple args, boost::python::dict kwargs) {
|
||||
// Args names
|
||||
const uint32_t NUM_ARGUMENTS = 1;
|
||||
const char *args_names[NUM_ARGUMENTS] = {
|
||||
"bone_transforms"
|
||||
};
|
||||
|
||||
boost::python::object self = args[0];
|
||||
args = boost::python::tuple(args.slice(1, boost::python::_));
|
||||
|
||||
auto res = self.attr("__init__")();
|
||||
if (len(args) > 0) {
|
||||
for (unsigned int i = 0; i < len(args); ++i) {
|
||||
self.attr(args_names[i]) = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ARGUMENTS; ++i) {
|
||||
if (kwargs.contains(args_names[i])) {
|
||||
self.attr(args_names[i]) = kwargs[args_names[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void export_control() {
|
||||
using namespace boost::python;
|
||||
namespace cr = carla::rpc;
|
||||
namespace cg = carla::geom;
|
||||
namespace cr = carla::rpc;
|
||||
|
||||
class_<cr::VehicleControl>("VehicleControl")
|
||||
.def(init<float, float, float, bool, bool, bool, int>(
|
||||
(arg("throttle")=0.0f,
|
||||
arg("steer")=0.0f,
|
||||
arg("brake")=0.0f,
|
||||
arg("hand_brake")=false,
|
||||
arg("reverse")=false,
|
||||
arg("manual_gear_shift")=false,
|
||||
arg("gear")=0)))
|
||||
(arg("throttle") = 0.0f,
|
||||
arg("steer") = 0.0f,
|
||||
arg("brake") = 0.0f,
|
||||
arg("hand_brake") = false,
|
||||
arg("reverse") = false,
|
||||
arg("manual_gear_shift") = false,
|
||||
arg("gear") = 0)))
|
||||
.def_readwrite("throttle", &cr::VehicleControl::throttle)
|
||||
.def_readwrite("steer", &cr::VehicleControl::steer)
|
||||
.def_readwrite("brake", &cr::VehicleControl::brake)
|
||||
|
@ -190,9 +259,9 @@ void export_control() {
|
|||
|
||||
class_<cr::WalkerControl>("WalkerControl")
|
||||
.def(init<cg::Vector3D, float, bool>(
|
||||
(arg("direction")=cg::Vector3D{1.0f, 0.0f, 0.0f},
|
||||
arg("speed")=0.0f,
|
||||
arg("jump")=false)))
|
||||
(arg("direction") = cg::Vector3D{1.0f, 0.0f, 0.0f},
|
||||
arg("speed") = 0.0f,
|
||||
arg("jump") = false)))
|
||||
.def_readwrite("direction", &cr::WalkerControl::direction)
|
||||
.def_readwrite("speed", &cr::WalkerControl::speed)
|
||||
.def_readwrite("jump", &cr::WalkerControl::jump)
|
||||
|
@ -201,9 +270,16 @@ void export_control() {
|
|||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cr::WalkerBoneControl>("WalkerBoneControl")
|
||||
.def("__init__", raw_function(WalkerBoneControl_init))
|
||||
.def(init<>())
|
||||
.add_property("bone_transforms", &GetBonesTransform, &SetBonesTransform)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<std::vector<cr::WheelPhysicsControl>>("vector_of_wheels")
|
||||
.def(boost::python::vector_indexing_suite<std::vector<cr::WheelPhysicsControl>>())
|
||||
.def(self_ns::str(self_ns::self))
|
||||
.def(boost::python::vector_indexing_suite<std::vector<cr::WheelPhysicsControl>>())
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cr::WheelPhysicsControl>("WheelPhysicsControl")
|
||||
|
@ -224,28 +300,25 @@ void export_control() {
|
|||
;
|
||||
|
||||
class_<cr::VehiclePhysicsControl>("VehiclePhysicsControl", no_init)
|
||||
.def("__init__", raw_function(VehiclePhysicsControl_init), "raw ctor")
|
||||
.def("__init__", raw_function(VehiclePhysicsControl_init))
|
||||
.def(init<>())
|
||||
|
||||
.add_property("torque_curve", &GetTorqueCurve, &SetTorqueCurve)
|
||||
.def_readwrite("max_rpm", &cr::VehiclePhysicsControl::max_rpm)
|
||||
.def_readwrite("moi", &cr::VehiclePhysicsControl::moi)
|
||||
.def_readwrite("damping_rate_full_throttle", &cr::VehiclePhysicsControl::damping_rate_full_throttle)
|
||||
.def_readwrite("damping_rate_zero_throttle_clutch_engaged", &cr::VehiclePhysicsControl::damping_rate_zero_throttle_clutch_engaged)
|
||||
.def_readwrite("damping_rate_zero_throttle_clutch_disengaged", &cr::VehiclePhysicsControl::damping_rate_zero_throttle_clutch_disengaged)
|
||||
|
||||
.def_readwrite("damping_rate_full_throttle",
|
||||
&cr::VehiclePhysicsControl::damping_rate_full_throttle)
|
||||
.def_readwrite("damping_rate_zero_throttle_clutch_engaged",
|
||||
&cr::VehiclePhysicsControl::damping_rate_zero_throttle_clutch_engaged)
|
||||
.def_readwrite("damping_rate_zero_throttle_clutch_disengaged",
|
||||
&cr::VehiclePhysicsControl::damping_rate_zero_throttle_clutch_disengaged)
|
||||
.def_readwrite("use_gear_autobox", &cr::VehiclePhysicsControl::use_gear_autobox)
|
||||
.def_readwrite("gear_switch_time", &cr::VehiclePhysicsControl::gear_switch_time)
|
||||
.def_readwrite("clutch_strength", &cr::VehiclePhysicsControl::clutch_strength)
|
||||
|
||||
.def_readwrite("mass", &cr::VehiclePhysicsControl::mass)
|
||||
.def_readwrite("drag_coefficient", &cr::VehiclePhysicsControl::drag_coefficient)
|
||||
|
||||
.def_readwrite("center_of_mass", &cr::VehiclePhysicsControl::center_of_mass)
|
||||
|
||||
.add_property("steering_curve", &GetSteeringCurve, &SetSteeringCurve)
|
||||
.add_property("wheels", &GetWheels, &SetWheels)
|
||||
|
||||
.def("__eq__", &cr::VehiclePhysicsControl::operator==)
|
||||
.def("__ne__", &cr::VehiclePhysicsControl::operator!=)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <carla/rpc/Vector3D.h>
|
||||
#include <carla/rpc/VehicleControl.h>
|
||||
#include <carla/rpc/VehiclePhysicsControl.h>
|
||||
#include <carla/rpc/WalkerBoneControl.h>
|
||||
#include <carla/rpc/WalkerControl.h>
|
||||
#include <carla/rpc/WeatherParameters.h>
|
||||
#include <carla/streaming/Server.h>
|
||||
|
@ -81,7 +82,6 @@ public:
|
|||
private:
|
||||
|
||||
void BindActions();
|
||||
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
@ -103,10 +103,11 @@ private:
|
|||
return carla::rpc::ResponseError(carla::rpc::FromFString(fstr)); }
|
||||
|
||||
#define REQUIRE_CARLA_EPISODE() \
|
||||
CARLA_ENSURE_GAME_THREAD(); \
|
||||
if (Episode == nullptr) { RESPOND_ERROR("episode not ready"); }
|
||||
CARLA_ENSURE_GAME_THREAD(); \
|
||||
if (Episode == nullptr) { RESPOND_ERROR("episode not ready"); }
|
||||
|
||||
class ServerBinder {
|
||||
class ServerBinder
|
||||
{
|
||||
public:
|
||||
|
||||
constexpr ServerBinder(const char *name, carla::rpc::Server &srv, bool sync)
|
||||
|
@ -115,10 +116,14 @@ public:
|
|||
_sync(sync) {}
|
||||
|
||||
template <typename FuncT>
|
||||
auto operator<<(FuncT func) {
|
||||
if (_sync) {
|
||||
auto operator<<(FuncT func)
|
||||
{
|
||||
if (_sync)
|
||||
{
|
||||
_server.BindSync(_name, func);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.BindAsync(_name, func);
|
||||
}
|
||||
return func;
|
||||
|
@ -133,8 +138,8 @@ private:
|
|||
bool _sync;
|
||||
};
|
||||
|
||||
#define BIND_SYNC(name) auto name = ServerBinder(#name, Server, true)
|
||||
#define BIND_ASYNC(name) auto name = ServerBinder(#name, Server, false)
|
||||
#define BIND_SYNC(name) auto name = ServerBinder(# name, Server, true)
|
||||
#define BIND_ASYNC(name) auto name = ServerBinder(# name, Server, false)
|
||||
|
||||
// =============================================================================
|
||||
// -- Bind Actions -------------------------------------------------------------
|
||||
|
@ -145,7 +150,7 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
namespace cr = carla::rpc;
|
||||
namespace cg = carla::geom;
|
||||
|
||||
BIND_ASYNC(version) << []() -> R<std::string>
|
||||
BIND_ASYNC(version) << [] () -> R<std::string>
|
||||
{
|
||||
return carla::version();
|
||||
};
|
||||
|
@ -188,8 +193,8 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
return cr::EpisodeInfo{
|
||||
Episode->GetId(),
|
||||
BroadcastStream.token()};
|
||||
Episode->GetId(),
|
||||
BroadcastStream.token()};
|
||||
};
|
||||
|
||||
BIND_SYNC(get_map_info) << [this]() -> R<cr::MapInfo>
|
||||
|
@ -351,10 +356,10 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
RESPOND_ERROR("unable to set actor location: actor not found");
|
||||
}
|
||||
ActorView.GetActor()->SetActorRelativeLocation(
|
||||
Location,
|
||||
false,
|
||||
nullptr,
|
||||
ETeleportType::TeleportPhysics);
|
||||
Location,
|
||||
false,
|
||||
nullptr,
|
||||
ETeleportType::TeleportPhysics);
|
||||
return R<void>::Success();
|
||||
};
|
||||
|
||||
|
@ -369,10 +374,10 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
RESPOND_ERROR("unable to set actor transform: actor not found");
|
||||
}
|
||||
ActorView.GetActor()->SetActorRelativeTransform(
|
||||
Transform,
|
||||
false,
|
||||
nullptr,
|
||||
ETeleportType::TeleportPhysics);
|
||||
Transform,
|
||||
false,
|
||||
nullptr,
|
||||
ETeleportType::TeleportPhysics);
|
||||
return R<void>::Success();
|
||||
};
|
||||
|
||||
|
@ -545,6 +550,30 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
return R<void>::Success();
|
||||
};
|
||||
|
||||
BIND_SYNC(apply_bone_control_to_walker) << [this](
|
||||
cr::ActorId ActorId,
|
||||
cr::WalkerBoneControl Control) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->FindActor(ActorId);
|
||||
if (!ActorView.IsValid())
|
||||
{
|
||||
RESPOND_ERROR("unable to apply control: actor not found");
|
||||
}
|
||||
auto Pawn = Cast<APawn>(ActorView.GetActor());
|
||||
if (Pawn == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to apply control: actor is not a walker");
|
||||
}
|
||||
auto Controller = Cast<AWalkerController>(Pawn->GetController());
|
||||
if (Controller == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to apply control: walker has an incompatible controller");
|
||||
}
|
||||
Controller->ApplyWalkerControl(Control);
|
||||
return R<void>::Success();
|
||||
};
|
||||
|
||||
BIND_SYNC(set_actor_autopilot) << [this](
|
||||
cr::ActorId ActorId,
|
||||
bool bEnabled) -> R<void>
|
||||
|
@ -707,7 +736,9 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
return R<void>::Success();
|
||||
};
|
||||
|
||||
BIND_SYNC(show_recorder_file_info) << [this](std::string name, bool show_all) -> R<std::string>
|
||||
BIND_SYNC(show_recorder_file_info) << [this](
|
||||
std::string name,
|
||||
bool show_all) -> R<std::string>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
return R<std::string>(Episode->GetRecorder()->ShowFileInfo(
|
||||
|
@ -715,7 +746,10 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
show_all));
|
||||
};
|
||||
|
||||
BIND_SYNC(show_recorder_collisions) << [this](std::string name, char type1, char type2) -> R<std::string>
|
||||
BIND_SYNC(show_recorder_collisions) << [this](
|
||||
std::string name,
|
||||
char type1,
|
||||
char type2) -> R<std::string>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
return R<std::string>(Episode->GetRecorder()->ShowFileCollisions(
|
||||
|
@ -724,7 +758,10 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
type2));
|
||||
};
|
||||
|
||||
BIND_SYNC(show_recorder_actors_blocked) << [this](std::string name, double min_time, double min_distance) -> R<std::string>
|
||||
BIND_SYNC(show_recorder_actors_blocked) << [this](
|
||||
std::string name,
|
||||
double min_time,
|
||||
double min_distance) -> R<std::string>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
return R<std::string>(Episode->GetRecorder()->ShowFileActorsBlocked(
|
||||
|
@ -733,7 +770,11 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
min_distance));
|
||||
};
|
||||
|
||||
BIND_SYNC(replay_file) << [this](std::string name, double start, double duration, uint32_t follow_id) -> R<std::string>
|
||||
BIND_SYNC(replay_file) << [this](
|
||||
std::string name,
|
||||
double start,
|
||||
double duration,
|
||||
uint32_t follow_id) -> R<std::string>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
return R<std::string>(Episode->GetRecorder()->ReplayFile(
|
||||
|
@ -777,18 +818,20 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
auto command_visitor = carla::Functional::MakeRecursiveOverload(
|
||||
[=](auto self, const C::SpawnActor &c) -> CR {
|
||||
auto result = c.parent.has_value() ?
|
||||
spawn_actor_with_parent(
|
||||
c.description,
|
||||
c.transform,
|
||||
*c.parent,
|
||||
cr::AttachmentType::Rigid) :
|
||||
spawn_actor(c.description, c.transform);
|
||||
if (!result.HasError()) {
|
||||
spawn_actor_with_parent(
|
||||
c.description,
|
||||
c.transform,
|
||||
*c.parent,
|
||||
cr::AttachmentType::Rigid) :
|
||||
spawn_actor(c.description, c.transform);
|
||||
if (!result.HasError())
|
||||
{
|
||||
ActorId id = result.Get().id;
|
||||
auto set_id = carla::Functional::MakeOverload(
|
||||
[](C::SpawnActor &) {},
|
||||
[id](auto &s) { s.actor = id; });
|
||||
for (auto command : c.do_after) {
|
||||
for (auto command : c.do_after)
|
||||
{
|
||||
boost::apply_visitor(set_id, command.command);
|
||||
boost::apply_visitor(self, command.command);
|
||||
}
|
||||
|
@ -808,7 +851,9 @@ void FCarlaServer::FPimpl::BindActions()
|
|||
|
||||
#undef MAKE_RESULT
|
||||
|
||||
BIND_SYNC(apply_batch) << [=](const std::vector<cr::Command> &commands, bool do_tick_cue)
|
||||
BIND_SYNC(apply_batch) << [=](
|
||||
const std::vector<cr::Command> &commands,
|
||||
bool do_tick_cue)
|
||||
{
|
||||
std::vector<CR> result;
|
||||
result.reserve(commands.size());
|
||||
|
@ -847,7 +892,12 @@ FDataMultiStream FCarlaServer::Start(uint16_t RPCPort, uint16_t StreamingPort)
|
|||
{
|
||||
Pimpl = MakeUnique<FPimpl>(RPCPort, StreamingPort);
|
||||
StreamingPort = Pimpl->StreamingServer.GetLocalEndpoint().port();
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Initialized CarlaServer: Ports(rpc=%d, streaming=%d)"), RPCPort, StreamingPort);
|
||||
UE_LOG(
|
||||
LogCarlaServer,
|
||||
Log,
|
||||
TEXT("Initialized CarlaServer: Ports(rpc=%d, streaming=%d)"),
|
||||
RPCPort,
|
||||
StreamingPort);
|
||||
return Pimpl->BroadcastStream;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// 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 "WalkerBoneControl.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct CARLA_API FWalkerBoneControl
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(Category = "Walker Bone Control", EditAnywhere, BlueprintReadWrite)
|
||||
TMap<FString, FTransform> BoneTransforms;
|
||||
|
||||
};
|
|
@ -7,10 +7,15 @@
|
|||
#include "Carla.h"
|
||||
#include "Carla/Walker/WalkerController.h"
|
||||
|
||||
#include "Components/PoseableMeshComponent.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
|
||||
AWalkerController::AWalkerController(const FObjectInitializer& ObjectInitializer)
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
AWalkerController::AWalkerController(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
@ -39,18 +44,107 @@ void AWalkerController::OnPossess(APawn *InPawn)
|
|||
Character->JumpMaxCount = 2;
|
||||
}
|
||||
|
||||
void AWalkerController::Tick(float DeltaSeconds)
|
||||
UPoseableMeshComponent *AddNewBoneComponent(AActor *InActor, FVector inLocation, FRotator inRotator)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
UPoseableMeshComponent *NewComp = NewObject<UPoseableMeshComponent>(InActor,
|
||||
UPoseableMeshComponent::StaticClass());
|
||||
if (NewComp)
|
||||
{
|
||||
NewComp->RegisterComponent();
|
||||
NewComp->SetWorldLocation(inLocation);
|
||||
NewComp->SetWorldRotation(inRotator);
|
||||
NewComp->AttachToComponent(InActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
|
||||
}
|
||||
return NewComp;
|
||||
}
|
||||
|
||||
void AWalkerController::ApplyWalkerControl(const FWalkerControl &InControl)
|
||||
{
|
||||
Control = InControl;
|
||||
if (bManualBones)
|
||||
{
|
||||
SetManualBones(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AWalkerController::ApplyWalkerControl(const FWalkerBoneControl &InBoneControl)
|
||||
{
|
||||
Control = InBoneControl;
|
||||
if (!bManualBones)
|
||||
{
|
||||
SetManualBones(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AWalkerController::SetManualBones(const bool bIsEnabled)
|
||||
{
|
||||
bManualBones = bIsEnabled;
|
||||
|
||||
auto *Character = GetCharacter();
|
||||
TArray<UPoseableMeshComponent *> PoseableMeshes;
|
||||
TArray<USkeletalMeshComponent *> SkeletalMeshes;
|
||||
Character->GetComponents<UPoseableMeshComponent>(PoseableMeshes, false);
|
||||
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
|
||||
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
|
||||
if (SkeletalMesh)
|
||||
{
|
||||
if (bManualBones)
|
||||
{
|
||||
UPoseableMeshComponent *PoseableMesh =
|
||||
PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : AddNewBoneComponent(Character,
|
||||
SkeletalMesh->GetRelativeTransform().GetLocation(),
|
||||
SkeletalMesh->GetRelativeTransform().GetRotation().Rotator());
|
||||
PoseableMesh->SetSkeletalMesh(SkeletalMesh->SkeletalMesh);
|
||||
PoseableMesh->SetVisibility(true);
|
||||
SkeletalMesh->SetVisibility(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPoseableMeshComponent *PoseableMesh = PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : nullptr;
|
||||
PoseableMesh->SetVisibility(false);
|
||||
SkeletalMesh->SetVisibility(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AWalkerController::ControlTickVisitor::operator()(const FWalkerControl &WalkerControl)
|
||||
{
|
||||
auto *Character = Controller->GetCharacter();
|
||||
if (Character != nullptr)
|
||||
{
|
||||
Character->AddMovementInput(Control.Direction, Control.Speed / GetMaximumWalkSpeed());
|
||||
if (Control.Jump)
|
||||
Character->AddMovementInput(WalkerControl.Direction,
|
||||
WalkerControl.Speed / Controller->GetMaximumWalkSpeed());
|
||||
if (WalkerControl.Jump)
|
||||
{
|
||||
Character->Jump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AWalkerController::ControlTickVisitor::operator()(FWalkerBoneControl &WalkerBoneControl)
|
||||
{
|
||||
auto *Character = Controller->GetCharacter();
|
||||
if (Character == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TArray<UPoseableMeshComponent *> PoseableMeshes;
|
||||
Character->GetComponents<UPoseableMeshComponent>(PoseableMeshes, false);
|
||||
UPoseableMeshComponent *PoseableMesh = PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : nullptr;
|
||||
if (PoseableMesh)
|
||||
{
|
||||
for (const TPair<FString, FTransform> &pair : WalkerBoneControl.BoneTransforms)
|
||||
{
|
||||
FName BoneName = FName(*pair.Key);
|
||||
PoseableMesh->SetBoneTransformByName(BoneName, pair.Value, EBoneSpaces::Type::ComponentSpace);
|
||||
}
|
||||
WalkerBoneControl.BoneTransforms.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
void AWalkerController::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
AWalkerController::ControlTickVisitor ControlTickVisitor(this);
|
||||
boost::apply_visitor(ControlTickVisitor, Control);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Carla/Walker/WalkerBoneControl.h"
|
||||
#include "Carla/Walker/WalkerControl.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Controller.h"
|
||||
|
||||
#include <compiler/disable-ue4-macros.h>
|
||||
#include <boost/variant.hpp>
|
||||
#include <compiler/enable-ue4-macros.h>
|
||||
|
||||
#include "WalkerController.generated.h"
|
||||
|
||||
UCLASS()
|
||||
|
@ -18,9 +23,27 @@ class CARLA_API AWalkerController : public AController
|
|||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
|
||||
class ControlTickVisitor : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
|
||||
ControlTickVisitor(AWalkerController *Controller)
|
||||
: Controller(Controller) {}
|
||||
|
||||
void operator()(const FWalkerControl &WalkerControl);
|
||||
|
||||
void operator()(FWalkerBoneControl &WalkerBoneControl);
|
||||
|
||||
private:
|
||||
|
||||
AWalkerController *Controller;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
AWalkerController(const FObjectInitializer& ObjectInitializer);
|
||||
AWalkerController(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
void OnPossess(APawn *InPawn) override;
|
||||
|
||||
|
@ -34,19 +57,28 @@ public:
|
|||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ApplyWalkerControl(const FWalkerControl &InControl)
|
||||
void ApplyWalkerControl(const FWalkerControl &InControl);
|
||||
|
||||
void ApplyWalkerControl(const FWalkerBoneControl &InBoneControl);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
const FWalkerControl GetWalkerControl() const
|
||||
{
|
||||
Control = InControl;
|
||||
return Control.which() == 0u ? boost::get<FWalkerControl>(Control) : FWalkerControl{};
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
const FWalkerControl &GetWalkerControl() const
|
||||
const FWalkerBoneControl GetBoneWalkerControl() const
|
||||
{
|
||||
return Control;
|
||||
return Control.which() == 1u ? boost::get<FWalkerBoneControl>(Control) : FWalkerBoneControl{};
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetManualBones(const bool bIsEnabled);
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
FWalkerControl Control;
|
||||
boost::variant<FWalkerControl, FWalkerBoneControl> Control;
|
||||
|
||||
bool bManualBones;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue