Merge branch 'master' into NoRenderingMode
This commit is contained in:
commit
2f49b7ab6e
|
@ -1,5 +1,7 @@
|
|||
## Latest changes
|
||||
|
||||
* Updated the Python API to enable the retrieval of a vehicle's speed limit and impacting traffic light
|
||||
* Added functionality to the Python API to the allow control over traffic lights
|
||||
* Upgraded to Unreal Engine 4.21
|
||||
* Upgraded Boost to 1.69.0
|
||||
* Added point transformation functionality for LibCarla and PythonAPI
|
||||
|
@ -10,12 +12,14 @@
|
|||
* Added support for spawning and controlling walkers (pedestrians)
|
||||
* Renamed vehicle.get_vehicle_control() to vehicle.get_control() to be consistent with walkers
|
||||
* Remove crash reporter from packaged build
|
||||
* Added sensor for detecting obstacles
|
||||
* Added a few methods to manage an actor:
|
||||
- set_velocity: for setting the linear velocity
|
||||
- set_angular_velocity: for setting the angular velocity
|
||||
- get_angular_velocity: for getting the angular velocity
|
||||
- add_impulse: for applying an impulse (in world axis)
|
||||
* Added support for gnss_sensor
|
||||
* Fixed autopilot direction not properly initialized that interfered with the initial raycast direction
|
||||
* Fixed TCP accept error, too many open files while creating and destroying a lot of sensors
|
||||
* Fixed lost error messages in client-side, now when a request fails it reports the reason
|
||||
* Improved simulator fatal error handling, now uses UE4 fatal error system
|
||||
|
|
|
@ -46,6 +46,7 @@ This is the list of sensors currently available
|
|||
* [sensor.lidar.ray_cast](#sensorlidarray_cast)
|
||||
* [sensor.other.collision](#sensorothercollision)
|
||||
* [sensor.other.lane_detector](#sensorotherlane_detector)
|
||||
* [sensor.other.obstacle](#sensorotherobstacle)
|
||||
|
||||
sensor.camera.rgb
|
||||
-----------------
|
||||
|
@ -305,3 +306,26 @@ objects.
|
|||
| `longitude` | double | Longitude position of the actor |
|
||||
| `altitude` | double | Altitude of the actor |
|
||||
|
||||
sensor.other.obstacle
|
||||
---------------------
|
||||
|
||||
This sensor, when attached to an actor, reports if there is obstacles ahead.
|
||||
|
||||
| Blueprint attribute | Type | Default | Description |
|
||||
| -------------------- | ---- | ------- | ----------- |
|
||||
| `distance` | float | 5 | Distance to throw the trace to |
|
||||
| `hit_radius` | float | 0.5 | Radius of the trace |
|
||||
| `only_dynamics` | bool | false | If true, the trace will only look for dynamic objects |
|
||||
| `debug_linetrace` | bool | false | If true, the trace will be visible |
|
||||
| `sensor_tick` | float | 0.0 | Seconds between sensor captures (ticks) |
|
||||
|
||||
|
||||
This sensor produces
|
||||
[`carla.ObstacleDetectionSensorEvent`](python_api.md#carlaobstacledetectionsensoreventdata)
|
||||
objects.
|
||||
|
||||
| Sensor data attribute | Type | Description |
|
||||
| ---------------------- | ----------- | ----------- |
|
||||
| `actor` | carla.Actor | Actor that detected the obstacle ("self" actor) |
|
||||
| `other_actor` | carla.Actor | Actor detected as obstacle |
|
||||
| `distance ` | float | Distance from actor to other_actor |
|
|
@ -108,10 +108,25 @@
|
|||
- `apply_control(vehicle_control)`
|
||||
- `get_control()`
|
||||
- `set_autopilot(enabled=True)`
|
||||
- `get_speed_limit()`
|
||||
- `get_traffic_light_state()`
|
||||
- `is_at_traffic_light()`
|
||||
- `get_traffic_light()`
|
||||
|
||||
## `carla.TrafficLight(carla.Actor)`
|
||||
|
||||
- `state`
|
||||
- `set_state(traffic_light_state)`
|
||||
- `get_state()`
|
||||
- `set_green_time(green_time)`
|
||||
- `get_green_time()`
|
||||
- `set_yellow_time(yellow_time)`
|
||||
- `get_yellow_time()`
|
||||
- `set_red_time(red_time)`
|
||||
- `get_red_time()`
|
||||
- `get_elapsed_time()`
|
||||
- `freeze(True)`
|
||||
- `is_frozen()`
|
||||
|
||||
## `carla.Sensor(carla.Actor)`
|
||||
|
||||
|
@ -166,6 +181,12 @@
|
|||
- `longitude`
|
||||
- `altitude`
|
||||
|
||||
## `carla.ObstacleDetectionSensorEvent(carla.SensorData)`
|
||||
|
||||
- `actor`
|
||||
- `other_actor`
|
||||
- `distance`
|
||||
|
||||
## `carla.VehicleControl`
|
||||
|
||||
- `throttle`
|
||||
|
@ -303,10 +324,10 @@ Static presets
|
|||
|
||||
## `carla.TrafficLightState`
|
||||
|
||||
- `Off`
|
||||
- `Red`
|
||||
- `Yellow`
|
||||
- `Green`
|
||||
- `Off`
|
||||
- `Unknown`
|
||||
|
||||
## `carla.LaneMarking`
|
||||
|
|
|
@ -11,8 +11,48 @@
|
|||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
rpc::TrafficLightState TrafficLight::GetState() {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_state;
|
||||
void TrafficLight::SetState(rpc::TrafficLightState state) {
|
||||
GetEpisode().Lock()->SetTrafficLightState(*this, state);
|
||||
}
|
||||
|
||||
rpc::TrafficLightState TrafficLight::GetState() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.state;
|
||||
}
|
||||
|
||||
void TrafficLight::SetGreenTime(float green_time) {
|
||||
GetEpisode().Lock()->SetTrafficLightGreenTime(*this, green_time);
|
||||
}
|
||||
|
||||
float TrafficLight::GetGreenTime() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.green_time;
|
||||
}
|
||||
|
||||
void TrafficLight::SetYellowTime(float yellow_time) {
|
||||
GetEpisode().Lock()->SetTrafficLightYellowTime(*this, yellow_time);
|
||||
}
|
||||
|
||||
float TrafficLight::GetYellowTime() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.yellow_time;
|
||||
}
|
||||
|
||||
void TrafficLight::SetRedTime(float red_time) {
|
||||
GetEpisode().Lock()->SetTrafficLightRedTime(*this, red_time);
|
||||
}
|
||||
|
||||
float TrafficLight::GetRedTime() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.red_time;
|
||||
}
|
||||
|
||||
float TrafficLight::GetElapsedTime() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.elapsed_time;
|
||||
}
|
||||
|
||||
void TrafficLight::Freeze(bool freeze) {
|
||||
GetEpisode().Lock()->FreezeTrafficLight(*this, freeze);
|
||||
}
|
||||
|
||||
bool TrafficLight::IsFrozen() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.traffic_light_data.time_is_frozen;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -19,9 +19,30 @@ namespace client {
|
|||
|
||||
/// Return the current state of the traffic light.
|
||||
///
|
||||
/// @note This function does not call the simulator, it returns the
|
||||
/// traffic light state received in the last tick.
|
||||
rpc::TrafficLightState GetState();
|
||||
/// @note These functions do not call the simulator, they return the
|
||||
/// data received in the last tick.
|
||||
void SetState(rpc::TrafficLightState state);
|
||||
|
||||
rpc::TrafficLightState GetState() const;
|
||||
|
||||
void SetGreenTime(float green_time);
|
||||
|
||||
float GetGreenTime() const;
|
||||
|
||||
void SetYellowTime(float yellow_time);
|
||||
|
||||
float GetYellowTime() const;
|
||||
|
||||
void SetRedTime(float red_time);
|
||||
|
||||
float GetRedTime() const;
|
||||
|
||||
float GetElapsedTime() const;
|
||||
|
||||
void Freeze(bool freeze);
|
||||
|
||||
bool IsFrozen() const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "carla/client/Vehicle.h"
|
||||
|
||||
#include "carla/client/detail/Simulator.h"
|
||||
#include "carla/client/ActorList.h"
|
||||
#include "carla/client/TrafficLight.h"
|
||||
#include "carla/rpc/TrafficLightState.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
@ -23,7 +26,25 @@ namespace client {
|
|||
}
|
||||
|
||||
Vehicle::Control Vehicle::GetControl() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_control;
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_data.control;
|
||||
}
|
||||
|
||||
float Vehicle::GetSpeedLimit() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_data.speed_limit;
|
||||
}
|
||||
|
||||
rpc::TrafficLightState Vehicle::GetTrafficLightState() const {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_data.traffic_light_state;
|
||||
}
|
||||
|
||||
bool Vehicle::IsAtTrafficLight() {
|
||||
return GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_data.has_traffic_light;
|
||||
}
|
||||
|
||||
SharedPtr<TrafficLight> Vehicle::GetTrafficLight() const {
|
||||
auto id = GetEpisode().Lock()->GetActorDynamicState(*this).state.vehicle_data.traffic_light_id;
|
||||
SharedPtr<Actor> actor = GetWorld().GetActors()->Find(id);
|
||||
return boost::static_pointer_cast<TrafficLight>(actor);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/rpc/VehicleControl.h"
|
||||
#include "carla/rpc/TrafficLightState.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
class TrafficLight;
|
||||
|
||||
class Vehicle : public Actor {
|
||||
public:
|
||||
|
@ -27,10 +29,20 @@ namespace client {
|
|||
|
||||
/// Return the control last applied to this vehicle.
|
||||
///
|
||||
/// @note This function does not call the simulator, it returns the Control
|
||||
/// @note The following functions do not call the simulator, they return the
|
||||
/// data
|
||||
/// received in the last tick.
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
Control GetControl() const;
|
||||
|
||||
float GetSpeedLimit() const;
|
||||
|
||||
rpc::TrafficLightState GetTrafficLightState() const;
|
||||
|
||||
bool IsAtTrafficLight();
|
||||
|
||||
SharedPtr<TrafficLight> GetTrafficLight() const;
|
||||
|
||||
private:
|
||||
|
||||
Control _control;
|
||||
|
|
|
@ -170,6 +170,28 @@ namespace detail {
|
|||
_pimpl->AsyncCall("apply_control_to_walker", walker, control);
|
||||
}
|
||||
|
||||
void Client::SetTrafficLightState(
|
||||
const rpc::Actor &trafficLight,
|
||||
const rpc::TrafficLightState trafficLightState) {
|
||||
_pimpl->AsyncCall("set_traffic_light_state", trafficLight, trafficLightState);
|
||||
}
|
||||
|
||||
void Client::SetTrafficLightGreenTime(const rpc::Actor &trafficLight, float greenTime) {
|
||||
_pimpl->AsyncCall("set_traffic_light_green_time", trafficLight, greenTime);
|
||||
}
|
||||
|
||||
void Client::SetTrafficLightYellowTime(const rpc::Actor &trafficLight, float yellowTime) {
|
||||
_pimpl->AsyncCall("set_traffic_light_yellow_time", trafficLight, yellowTime);
|
||||
}
|
||||
|
||||
void Client::SetTrafficLightRedTime(const rpc::Actor &trafficLight, float redTime) {
|
||||
_pimpl->AsyncCall("set_traffic_light_red_time", trafficLight, redTime);
|
||||
}
|
||||
|
||||
void Client::FreezeTrafficLight(const rpc::Actor &trafficLight, bool freeze) {
|
||||
_pimpl->AsyncCall("freeze_traffic_light", trafficLight, freeze);
|
||||
}
|
||||
|
||||
void Client::SetActorVelocity(const rpc::Actor &actor, const geom::Vector3D &vector) {
|
||||
_pimpl->AsyncCall("set_actor_velocity", actor, vector);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "carla/rpc/EpisodeInfo.h"
|
||||
#include "carla/rpc/MapInfo.h"
|
||||
#include "carla/rpc/WeatherParameters.h"
|
||||
#include "carla/rpc/TrafficLightState.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
@ -30,8 +31,12 @@ namespace rpc {
|
|||
class VehicleControl;
|
||||
class WalkerControl;
|
||||
}
|
||||
namespace sensor { class SensorData; }
|
||||
namespace streaming { class Token; }
|
||||
namespace sensor {
|
||||
class SensorData;
|
||||
}
|
||||
namespace streaming {
|
||||
class Token;
|
||||
}
|
||||
}
|
||||
|
||||
namespace carla {
|
||||
|
@ -107,6 +112,26 @@ namespace detail {
|
|||
const rpc::Actor &walker,
|
||||
const rpc::WalkerControl &control);
|
||||
|
||||
void SetTrafficLightState(
|
||||
const rpc::Actor &trafficLight,
|
||||
const rpc::TrafficLightState trafficLightState);
|
||||
|
||||
void SetTrafficLightGreenTime(
|
||||
const rpc::Actor &trafficLight,
|
||||
float greenTime);
|
||||
|
||||
void SetTrafficLightYellowTime(
|
||||
const rpc::Actor &trafficLight,
|
||||
float yellowTime);
|
||||
|
||||
void SetTrafficLightRedTime(
|
||||
const rpc::Actor &trafficLight,
|
||||
float redTime);
|
||||
|
||||
void FreezeTrafficLight(
|
||||
const rpc::Actor &trafficLight,
|
||||
bool freeze);
|
||||
|
||||
void SetActorVelocity(
|
||||
const rpc::Actor &actor,
|
||||
const geom::Vector3D &vector);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "carla/client/detail/Episode.h"
|
||||
#include "carla/client/detail/EpisodeProxy.h"
|
||||
#include "carla/profiler/LifetimeProfiled.h"
|
||||
#include "carla/client/TrafficLight.h"
|
||||
#include "carla/rpc/TrafficLightState.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -235,6 +237,31 @@ namespace detail {
|
|||
|
||||
void UnSubscribeFromSensor(const Sensor &sensor);
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Operations with traffic lights
|
||||
// =========================================================================
|
||||
/// @{
|
||||
void SetTrafficLightState(TrafficLight &trafficLight, const rpc::TrafficLightState trafficLightState) {
|
||||
_client.SetTrafficLightState(trafficLight.Serialize(), trafficLightState);
|
||||
}
|
||||
|
||||
void SetTrafficLightGreenTime(TrafficLight &trafficLight, float greenTime) {
|
||||
_client.SetTrafficLightGreenTime(trafficLight.Serialize(), greenTime);
|
||||
}
|
||||
|
||||
void SetTrafficLightYellowTime(TrafficLight &trafficLight, float yellowTime) {
|
||||
_client.SetTrafficLightYellowTime(trafficLight.Serialize(), yellowTime);
|
||||
}
|
||||
|
||||
void SetTrafficLightRedTime(TrafficLight &trafficLight, float redTime) {
|
||||
_client.SetTrafficLightRedTime(trafficLight.Serialize(), redTime);
|
||||
}
|
||||
|
||||
void FreezeTrafficLight(TrafficLight &trafficLight, bool freeze) {
|
||||
_client.FreezeTrafficLight(trafficLight.Serialize(), freeze);
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Debug
|
||||
|
|
|
@ -14,11 +14,10 @@ namespace carla {
|
|||
namespace rpc {
|
||||
|
||||
enum class TrafficLightState : uint8_t {
|
||||
Off,
|
||||
Red,
|
||||
Yellow,
|
||||
Green,
|
||||
|
||||
Off,
|
||||
Unknown,
|
||||
SIZE
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "carla/sensor/s11n/EpisodeStateSerializer.h"
|
||||
#include "carla/sensor/s11n/ImageSerializer.h"
|
||||
#include "carla/sensor/s11n/LidarSerializer.h"
|
||||
#include "carla/sensor/s11n/ObstacleDetectionEventSerializer.h"
|
||||
|
||||
// 2. Add a forward-declaration of the sensor here.
|
||||
class ACollisionSensor;
|
||||
|
@ -27,6 +28,7 @@ class ASceneCaptureCamera;
|
|||
class ASemanticSegmentationCamera;
|
||||
class AWorldObserver;
|
||||
class AGnssSensor;
|
||||
class AObstacleDetectionSensor;
|
||||
|
||||
namespace carla {
|
||||
namespace sensor {
|
||||
|
@ -42,7 +44,8 @@ namespace sensor {
|
|||
std::pair<ASemanticSegmentationCamera *, s11n::ImageSerializer>,
|
||||
std::pair<ARayCastLidar *, s11n::LidarSerializer>,
|
||||
std::pair<ACollisionSensor *, s11n::CollisionEventSerializer>,
|
||||
std::pair<AGnssSensor *, s11n::ImageSerializer>
|
||||
std::pair<AGnssSensor *, s11n::ImageSerializer>,
|
||||
std::pair<AObstacleDetectionSensor *, s11n::ObstacleDetectionEventSerializer>
|
||||
>;
|
||||
|
||||
} // namespace sensor
|
||||
|
@ -60,5 +63,6 @@ namespace sensor {
|
|||
#include "Carla/Sensor/SemanticSegmentationCamera.h"
|
||||
#include "Carla/Sensor/WorldObserver.h"
|
||||
#include "Carla/Sensor/GnssSensor.h"
|
||||
#include "Carla/Sensor/ObstacleDetectionSensor.h"
|
||||
|
||||
#endif // LIBCARLA_SENSOR_REGISTRY_WITH_SENSOR_INCLUDES
|
||||
|
|
|
@ -50,6 +50,19 @@ namespace detail {
|
|||
bool manual_gear_shift;
|
||||
int32_t gear;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct VehicleData {
|
||||
VehicleData() = default;
|
||||
|
||||
PackedVehicleControl control;
|
||||
float speed_limit;
|
||||
rpc::TrafficLightState traffic_light_state;
|
||||
bool has_traffic_light;
|
||||
rpc::actor_id_type traffic_light_id;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
@ -73,8 +86,21 @@ namespace detail {
|
|||
float speed;
|
||||
bool jump;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TrafficLightData {
|
||||
TrafficLightData() = default;
|
||||
|
||||
rpc::TrafficLightState state;
|
||||
float green_time;
|
||||
float yellow_time;
|
||||
float red_time;
|
||||
float elapsed_time;
|
||||
bool time_is_frozen;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
} // namespace detail
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
@ -91,8 +117,8 @@ namespace detail {
|
|||
geom::Vector3D angular_velocity;
|
||||
|
||||
union TypeDependentState {
|
||||
rpc::TrafficLightState traffic_light_state;
|
||||
detail::PackedVehicleControl vehicle_control;
|
||||
detail::TrafficLightData traffic_light_data;
|
||||
detail::VehicleData vehicle_data;
|
||||
detail::PackedWalkerControl walker_control;
|
||||
} state;
|
||||
};
|
||||
|
@ -100,7 +126,7 @@ namespace detail {
|
|||
#pragma pack(pop)
|
||||
|
||||
static_assert(
|
||||
sizeof(ActorDynamicState) == 13u * sizeof(uint32_t) + sizeof(detail::PackedVehicleControl),
|
||||
sizeof(ActorDynamicState) == 13u * sizeof(uint32_t) + sizeof(detail::VehicleData),
|
||||
"Invalid ActorDynamicState size!");
|
||||
|
||||
} // namespace data
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
// 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/client/detail/ActorVariant.h"
|
||||
#include "carla/sensor/SensorData.h"
|
||||
#include "carla/sensor/s11n/ObstacleDetectionEventSerializer.h"
|
||||
|
||||
|
||||
namespace carla {
|
||||
namespace sensor {
|
||||
namespace data {
|
||||
|
||||
/// A registered detection.
|
||||
class ObstacleDetectionEvent : public SensorData {
|
||||
using Super = SensorData;
|
||||
protected:
|
||||
|
||||
using Serializer = s11n::ObstacleDetectionEventSerializer;
|
||||
|
||||
friend Serializer;
|
||||
|
||||
explicit ObstacleDetectionEvent(const RawData &data)
|
||||
: Super(data),
|
||||
//_deserialized_data(),
|
||||
_self_actor(nullptr),
|
||||
_other_actor(nullptr) {
|
||||
auto ddata = Serializer::DeserializeRawData(data);
|
||||
_self_actor = std::move(ddata.self_actor);
|
||||
_other_actor = std::move(ddata.other_actor);
|
||||
_distance = ddata.distance;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Get "self" actor. Actor that measured the collision.
|
||||
SharedPtr<client::Actor> GetActor() const {
|
||||
return _self_actor.Get(GetEpisode());
|
||||
}
|
||||
|
||||
/// Get the actor to which we collided.
|
||||
SharedPtr<client::Actor> GetOtherActor() const {
|
||||
return _other_actor.Get(GetEpisode());
|
||||
}
|
||||
|
||||
/// Normal impulse result of the collision.
|
||||
float GetDistance() const {
|
||||
return _distance;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
client::detail::ActorVariant _self_actor;
|
||||
|
||||
client::detail::ActorVariant _other_actor;
|
||||
|
||||
float _distance;
|
||||
|
||||
};
|
||||
|
||||
} // namespace data
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -0,0 +1,20 @@
|
|||
// 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/sensor/data/ObstacleDetectionEvent.h"
|
||||
#include "carla/sensor/s11n/ObstacleDetectionEventSerializer.h"
|
||||
|
||||
namespace carla {
|
||||
namespace sensor {
|
||||
namespace s11n {
|
||||
|
||||
SharedPtr<SensorData> ObstacleDetectionEventSerializer::Deserialize(RawData data) {
|
||||
return SharedPtr<SensorData>(new data::ObstacleDetectionEvent(std::move(data)));
|
||||
}
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -0,0 +1,57 @@
|
|||
// 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/Buffer.h"
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/Memory.h"
|
||||
#include "carla/rpc/Actor.h"
|
||||
#include "carla/sensor/RawData.h"
|
||||
|
||||
namespace carla {
|
||||
namespace sensor {
|
||||
|
||||
class SensorData;
|
||||
|
||||
namespace s11n {
|
||||
|
||||
/// Serializes the current state of the whole episode.
|
||||
class ObstacleDetectionEventSerializer {
|
||||
public:
|
||||
|
||||
struct Data {
|
||||
|
||||
rpc::Actor self_actor;
|
||||
|
||||
rpc::Actor other_actor;
|
||||
|
||||
float distance;
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(self_actor, other_actor, distance)
|
||||
};
|
||||
|
||||
constexpr static auto header_offset = 0u;
|
||||
|
||||
static Data DeserializeRawData(const RawData &message) {
|
||||
return MsgPack::UnPack<Data>(message.begin(), message.size());
|
||||
}
|
||||
|
||||
template <typename SensorT>
|
||||
static Buffer Serialize(
|
||||
const SensorT &,
|
||||
rpc::Actor self_actor,
|
||||
rpc::Actor other_actor,
|
||||
float distance) {
|
||||
return MsgPack::Pack(Data{self_actor, other_actor, distance});
|
||||
}
|
||||
|
||||
static SharedPtr<SensorData> Deserialize(RawData data);
|
||||
};
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -71,11 +71,16 @@ void export_actor() {
|
|||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle", no_init)
|
||||
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("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))
|
||||
;
|
||||
|
||||
|
@ -87,15 +92,28 @@ void export_actor() {
|
|||
;
|
||||
|
||||
enum_<cr::TrafficLightState>("TrafficLightState")
|
||||
.value("Off", cr::TrafficLightState::Off)
|
||||
.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::Actor>, boost::noncopyable, boost::shared_ptr<cc::TrafficLight>>("TrafficLight", no_init)
|
||||
class_<cc::TrafficLight, bases<cc::Actor>, 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(self_ns::str(self_ns::self))
|
||||
;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <carla/pointcloud/PointCloudIO.h>
|
||||
#include <carla/sensor/SensorData.h>
|
||||
#include <carla/sensor/data/CollisionEvent.h>
|
||||
#include <carla/sensor/data/ObstacleDetectionEvent.h>
|
||||
#include <carla/sensor/data/Image.h>
|
||||
#include <carla/sensor/data/LaneInvasionEvent.h>
|
||||
#include <carla/sensor/data/LidarMeasurement.h>
|
||||
|
@ -46,6 +47,13 @@ namespace data {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const ObstacleDetectionEvent &meas) {
|
||||
out << "ObstacleDetectionEvent(frame=" << meas.GetFrameNumber()
|
||||
<< ", other_actor=" << meas.GetOtherActor()
|
||||
<< ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const LaneInvasionEvent &meas) {
|
||||
out << "LaneInvasionEvent(frame=" << meas.GetFrameNumber() << ')';
|
||||
return out;
|
||||
|
@ -200,6 +208,13 @@ void export_sensor_data() {
|
|||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<csd::ObstacleDetectionEvent, bases<cs::SensorData>, boost::noncopyable, boost::shared_ptr<csd::ObstacleDetectionEvent>>("ObstacleDetectionEvent", no_init)
|
||||
.add_property("actor", &csd::ObstacleDetectionEvent::GetActor)
|
||||
.add_property("other_actor", &csd::ObstacleDetectionEvent::GetOtherActor)
|
||||
.add_property("distance", CALL_RETURNING_COPY(csd::ObstacleDetectionEvent, GetDistance))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
enum_<cre::LaneMarking>("LaneMarking")
|
||||
.value("Other", cre::LaneMarking::Other)
|
||||
.value("Broken", cre::LaneMarking::Broken)
|
||||
|
|
|
@ -441,6 +441,82 @@ void UActorBlueprintFunctionLibrary::MakePedestrianDefinitions(
|
|||
FillActorDefinitionArray(ParameterArray, Definitions, &MakePedestrianDefinition);
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::MakePropDefinition(
|
||||
const FPropParameters &Parameters,
|
||||
bool &Success,
|
||||
FActorDefinition &Definition)
|
||||
{
|
||||
/// @todo We need to validate here the params.
|
||||
FillIdAndTags(Definition, TEXT("static"), TEXT("prop"), Parameters.Name);
|
||||
AddRecommendedValuesForActorRoleName(Definition, {TEXT("prop")});
|
||||
|
||||
auto GetSize = [](EPropSize Value) {
|
||||
switch (Value)
|
||||
{
|
||||
case EPropSize::Tiny: return TEXT("tiny");
|
||||
case EPropSize::Small: return TEXT("small");
|
||||
case EPropSize::Medium: return TEXT("medium");
|
||||
case EPropSize::Big: return TEXT("big");
|
||||
case EPropSize::Huge: return TEXT("huge");
|
||||
default: return TEXT("unknown");
|
||||
}
|
||||
};
|
||||
|
||||
Definition.Attributes.Emplace(FActorAttribute{
|
||||
TEXT("size"),
|
||||
EActorAttributeType::String,
|
||||
GetSize(Parameters.Size)});
|
||||
|
||||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::MakePropDefinitions(
|
||||
const TArray<FPropParameters> &ParameterArray,
|
||||
TArray<FActorDefinition> &Definitions)
|
||||
{
|
||||
FillActorDefinitionArray(ParameterArray, Definitions, &MakePropDefinition);
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::MakeObstacleDetectorDefinitions(
|
||||
const FString &Type,
|
||||
const FString &Id,
|
||||
FActorDefinition &Definition)
|
||||
{
|
||||
Definition = MakeGenericSensorDefinition(TEXT("other"), TEXT("obstacle"));
|
||||
AddVariationsForSensor(Definition);
|
||||
// Distance.
|
||||
FActorVariation distance;
|
||||
distance.Id = TEXT("distance");
|
||||
distance.Type = EActorAttributeType::Float;
|
||||
distance.RecommendedValues = { TEXT("5.0") };
|
||||
distance.bRestrictToRecommended = false;
|
||||
// HitRadius.
|
||||
FActorVariation hitradius;
|
||||
hitradius.Id = TEXT("hit_radius");
|
||||
hitradius.Type = EActorAttributeType::Float;
|
||||
hitradius.RecommendedValues = { TEXT("0.5") };
|
||||
hitradius.bRestrictToRecommended = false;
|
||||
// Only Dynamics
|
||||
FActorVariation onlydynamics;
|
||||
onlydynamics.Id = TEXT("only_dynamics");
|
||||
onlydynamics.Type = EActorAttributeType::Bool;
|
||||
onlydynamics.RecommendedValues = { TEXT("false") };
|
||||
onlydynamics.bRestrictToRecommended = false;
|
||||
// Debug Line Trace
|
||||
FActorVariation debuglinetrace;
|
||||
debuglinetrace.Id = TEXT("debug_linetrace");
|
||||
debuglinetrace.Type = EActorAttributeType::Bool;
|
||||
debuglinetrace.RecommendedValues = { TEXT("false") };
|
||||
debuglinetrace.bRestrictToRecommended = false;
|
||||
|
||||
Definition.Variations.Append({
|
||||
distance,
|
||||
hitradius,
|
||||
onlydynamics,
|
||||
debuglinetrace
|
||||
});
|
||||
|
||||
}
|
||||
/// ============================================================================
|
||||
/// -- Helpers to retrieve attribute values ------------------------------------
|
||||
/// ============================================================================
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "Carla/Actor/PedestrianParameters.h"
|
||||
#include "Carla/Actor/PropParameters.h"
|
||||
#include "Carla/Actor/VehicleParameters.h"
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
|
@ -91,6 +92,23 @@ public:
|
|||
const TArray<FPedestrianParameters> &ParameterArray,
|
||||
TArray<FActorDefinition> &Definitions);
|
||||
|
||||
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
|
||||
static void MakePropDefinition(
|
||||
const FPropParameters &Parameters,
|
||||
bool &Success,
|
||||
FActorDefinition &Definition);
|
||||
|
||||
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
|
||||
static void MakePropDefinitions(
|
||||
const TArray<FPropParameters> &ParameterArray,
|
||||
TArray<FActorDefinition> &Definitions);
|
||||
|
||||
UFUNCTION()
|
||||
static void MakeObstacleDetectorDefinitions(
|
||||
const FString &Type,
|
||||
const FString &Id,
|
||||
FActorDefinition &Definition);
|
||||
|
||||
/// @}
|
||||
/// ==========================================================================
|
||||
/// @name Helpers to retrieve attribute values
|
||||
|
|
|
@ -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 "Engine/StaticMesh.h"
|
||||
|
||||
#include "PropParameters.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EPropSize : uint8
|
||||
{
|
||||
|
||||
Tiny UMETA(DisplayName = "Tiny", ToolTip = "Smaller than a mailbox"),
|
||||
Small UMETA(DisplayName = "Small", ToolTip = "Size of a mailbox"),
|
||||
Medium UMETA(DisplayName = "Medium", ToolTip = "Size of a human"),
|
||||
Big UMETA(DisplayName = "Big", ToolTip = "Size of a bus stop"),
|
||||
Huge UMETA(DisplayName = "Huge", ToolTip = "Size of a house or bigger"),
|
||||
|
||||
SIZE UMETA(Hidden),
|
||||
INVALID UMETA(DisplayName = "INVALID")
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct CARLA_API FPropParameters
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
UStaticMesh *Mesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EPropSize Size = EPropSize::INVALID;
|
||||
};
|
|
@ -169,28 +169,39 @@ void AOpenDriveActor::BuildRoutes()
|
|||
const std::vector<Waypoint> MapLaneBeginWaypoint =
|
||||
WaypointGen::GenerateLaneEnd(*map_ptr);
|
||||
|
||||
// Since we are going to iterate all the successors of all the lanes, we need
|
||||
// a vector to store the already visited lanes. Lanes can be successors of
|
||||
// multiple other lanes
|
||||
std::vector<std::pair<IdType, int>> AlreadyVisited;
|
||||
|
||||
for (auto &&EndLaneWaypoint : MapLaneBeginWaypoint)
|
||||
{
|
||||
std::vector<Waypoint> Successors = WaypointGen::GetSuccessors(EndLaneWaypoint);
|
||||
|
||||
// generate the RoutePlanner
|
||||
ARoutePlanner *RoutePlanner = GetWorld()->SpawnActor<ARoutePlanner>();
|
||||
RoutePlanner->bIsIntersection = std::any_of(Successors.begin(), Successors.end(), [](auto w) {
|
||||
return w.IsIntersection();
|
||||
});
|
||||
RoutePlanner->SetBoxExtent(FVector(70.f, 70.f, 50.f));
|
||||
RoutePlanner->SetActorRotation(EndLaneWaypoint.ComputeTransform().rotation);
|
||||
RoutePlanner->SetActorLocation(EndLaneWaypoint.ComputeTransform().location +
|
||||
FVector(0.f, 0.f, TriggersHeight));
|
||||
// The RoutePlanner will be created only if some route must be added to it
|
||||
// so no one will be created unnecessarily
|
||||
ARoutePlanner *RoutePlanner = nullptr;
|
||||
|
||||
// fill the RoutePlanner with all the needed roads
|
||||
// Fill the RoutePlanner with all the needed roads
|
||||
for (auto &&Successor : Successors)
|
||||
{
|
||||
const IdType RoadId = Successor.GetRoadId();
|
||||
const int LaneId = Successor.GetLaneId();
|
||||
|
||||
// Create an identifier of the current lane
|
||||
const auto Identifier = std::make_pair(RoadId, LaneId);
|
||||
|
||||
// If Identifier does not exist in AlreadyVisited we haven't visited the lane
|
||||
if (!std::any_of(AlreadyVisited.begin(), AlreadyVisited.end(), [&Identifier](auto i) {
|
||||
return (i.first == Identifier.first && i.second == Identifier.second);
|
||||
}))
|
||||
{
|
||||
// Add the identifier as visited
|
||||
AlreadyVisited.emplace_back(Identifier);
|
||||
|
||||
const float MaxDist = map.GetRoad(RoadId)->GetLength();
|
||||
|
||||
std::vector<Waypoint> Waypoints;
|
||||
|
||||
Waypoints.emplace_back(Successor);
|
||||
|
||||
for (float Dist = RoadAccuracy; Dist < MaxDist; Dist += RoadAccuracy)
|
||||
|
@ -203,7 +214,7 @@ void AOpenDriveActor::BuildRoutes()
|
|||
Waypoints.emplace_back(NewWaypoint[0]);
|
||||
}
|
||||
|
||||
// merge with the first waypoint of the next lane if needed
|
||||
// Merge with the first waypoint of the next lane if needed
|
||||
Waypoints.emplace_back(WaypointGen::GetNext(
|
||||
Successor, CarlaMath::clamp(MaxDist - 0.1f, 0.f, MaxDist))[0]);
|
||||
|
||||
|
@ -211,11 +222,25 @@ void AOpenDriveActor::BuildRoutes()
|
|||
|
||||
TArray<FVector> Positions = WaypointVector2FVectorArray(Waypoints, TriggersHeight);
|
||||
|
||||
// If the route planner does not exist, create it
|
||||
if (RoutePlanner == nullptr)
|
||||
{
|
||||
RoutePlanner = GetWorld()->SpawnActor<ARoutePlanner>();
|
||||
RoutePlanner->bIsIntersection = std::any_of(Successors.begin(), Successors.end(), [](auto w) {
|
||||
return w.IsIntersection();
|
||||
});
|
||||
RoutePlanner->SetBoxExtent(FVector(70.f, 70.f, 50.f));
|
||||
RoutePlanner->SetActorRotation(EndLaneWaypoint.ComputeTransform().rotation);
|
||||
RoutePlanner->SetActorLocation(EndLaneWaypoint.ComputeTransform().location +
|
||||
FVector(0.f, 0.f, TriggersHeight));
|
||||
}
|
||||
|
||||
RoutePlanner->AddRoute(1.f, Positions);
|
||||
RoutePlanners.Add(RoutePlanner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AOpenDriveActor::RemoveRoutes()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
// 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.h"
|
||||
#include "Carla/Sensor/ObstacleDetectionSensor.h"
|
||||
|
||||
#include "Carla/Actor/ActorBlueprintFunctionLibrary.h"
|
||||
#include "Carla/Actor/ActorRegistry.h"
|
||||
#include "Carla/Game/CarlaEpisode.h"
|
||||
#include "Carla/Game/CarlaGameInstance.h"
|
||||
#include "Carla/Game/TheNewCarlaGameModeBase.h"
|
||||
|
||||
AObstacleDetectionSensor::AObstacleDetectionSensor(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
FActorDefinition AObstacleDetectionSensor::GetSensorDefinition()
|
||||
{
|
||||
FActorDefinition SensorDefinition = FActorDefinition();
|
||||
UActorBlueprintFunctionLibrary::MakeObstacleDetectorDefinitions(TEXT("other"), TEXT("obstacle"), SensorDefinition);
|
||||
return SensorDefinition;
|
||||
}
|
||||
|
||||
void AObstacleDetectionSensor::Set(const FActorDescription &Description)
|
||||
{
|
||||
//Multiplying numbers for 100 in order to convert from meters to centimeters
|
||||
Super::Set(Description);
|
||||
Distance = UActorBlueprintFunctionLibrary::RetrieveActorAttributeToFloat(
|
||||
"distance",
|
||||
Description.Variations,
|
||||
Distance) * 100.0f;
|
||||
HitRadius = UActorBlueprintFunctionLibrary::RetrieveActorAttributeToFloat(
|
||||
"hit_radius",
|
||||
Description.Variations,
|
||||
HitRadius) * 100.0f;
|
||||
bOnlyDynamics = UActorBlueprintFunctionLibrary::RetrieveActorAttributeToBool(
|
||||
"only_dynamics",
|
||||
Description.Variations,
|
||||
bOnlyDynamics);
|
||||
bDebugLineTrace = UActorBlueprintFunctionLibrary::RetrieveActorAttributeToBool(
|
||||
"debug_linetrace",
|
||||
Description.Variations,
|
||||
bDebugLineTrace);
|
||||
|
||||
}
|
||||
|
||||
void AObstacleDetectionSensor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
auto *GameMode = Cast<ATheNewCarlaGameModeBase>(GetWorld()->GetAuthGameMode());
|
||||
|
||||
if (GameMode == nullptr)
|
||||
{
|
||||
UE_LOG(LogCarla, Error, TEXT("AObstacleDetectionSensor: Game mode not compatible with this sensor"));
|
||||
return;
|
||||
}
|
||||
Episode = &GameMode->GetCarlaEpisode();
|
||||
}
|
||||
|
||||
void AObstacleDetectionSensor::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
const FVector &Start = GetActorLocation();
|
||||
const FVector &End = Start + (GetActorForwardVector() * Distance);
|
||||
UWorld* currentWorld = GetWorld();
|
||||
|
||||
// Struct in which the result of the scan will be saved
|
||||
FHitResult HitOut = FHitResult();
|
||||
|
||||
// Initialization of Query Parameters
|
||||
FCollisionQueryParams TraceParams(FName(TEXT("ObstacleDetection Trace")), true, this);
|
||||
|
||||
// If debug mode enabled, we create a tag that will make the sweep be
|
||||
// displayed.
|
||||
if (bDebugLineTrace)
|
||||
{
|
||||
const FName TraceTag("ObstacleDebugTrace");
|
||||
currentWorld->DebugDrawTraceTag = TraceTag;
|
||||
TraceParams.TraceTag = TraceTag;
|
||||
}
|
||||
|
||||
// Hit against complex meshes
|
||||
TraceParams.bTraceComplex = true;
|
||||
|
||||
// Ignore trigger boxes
|
||||
TraceParams.bIgnoreTouches = true;
|
||||
|
||||
// Limit the returned information
|
||||
TraceParams.bReturnPhysicalMaterial = false;
|
||||
|
||||
// Ignore ourselves
|
||||
TraceParams.AddIgnoredActor(this);
|
||||
if(Super::GetOwner()!=nullptr)
|
||||
TraceParams.AddIgnoredActor(Super::GetOwner());
|
||||
|
||||
bool isHitReturned;
|
||||
// Choosing a type of sweep is a workaround until everything get properly
|
||||
// organized under correct collision channels and object types.
|
||||
if (bOnlyDynamics)
|
||||
{
|
||||
// If we go only for dynamics, we check the object type AllDynamicObjects
|
||||
FCollisionObjectQueryParams TraceChannel = FCollisionObjectQueryParams(
|
||||
FCollisionObjectQueryParams::AllDynamicObjects);
|
||||
isHitReturned = currentWorld->SweepSingleByObjectType(
|
||||
HitOut,
|
||||
Start,
|
||||
End,
|
||||
FQuat(),
|
||||
TraceChannel,
|
||||
FCollisionShape::MakeSphere(HitRadius),
|
||||
TraceParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else, if we go for everything, we get everything that interacts with a
|
||||
// Pawn
|
||||
ECollisionChannel TraceChannel = ECC_WorldStatic;
|
||||
isHitReturned = currentWorld->SweepSingleByChannel(
|
||||
HitOut,
|
||||
Start,
|
||||
End,
|
||||
FQuat(),
|
||||
TraceChannel,
|
||||
FCollisionShape::MakeSphere(HitRadius),
|
||||
TraceParams);
|
||||
}
|
||||
|
||||
if (isHitReturned)
|
||||
{
|
||||
OnObstacleDetectionEvent(this, HitOut.Actor.Get(), HitOut.Distance, HitOut);
|
||||
}
|
||||
}
|
||||
|
||||
void AObstacleDetectionSensor::OnObstacleDetectionEvent(
|
||||
AActor *Actor,
|
||||
AActor *OtherActor,
|
||||
float HitDistance,
|
||||
const FHitResult &Hit)
|
||||
{
|
||||
if ((Episode != nullptr) && (Actor != nullptr) && (OtherActor != nullptr))
|
||||
{
|
||||
GetDataStream(*this).Send(*this,
|
||||
Episode->SerializeActor(Episode->FindOrFakeActor(Actor)),
|
||||
Episode->SerializeActor(Episode->FindOrFakeActor(OtherActor)),
|
||||
HitRadius);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// 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/Sensor/Sensor.h"
|
||||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "ObstacleDetectionSensor.generated.h"
|
||||
|
||||
class UCarlaEpisode;
|
||||
|
||||
/// A sensor to register collisions.
|
||||
UCLASS()
|
||||
class CARLA_API AObstacleDetectionSensor : public ASensor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
static FActorDefinition GetSensorDefinition();
|
||||
|
||||
AObstacleDetectionSensor(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
void Set(const FActorDescription &Description) override;
|
||||
|
||||
void BeginPlay() override;
|
||||
|
||||
void Tick(float DeltaSeconds) override;
|
||||
|
||||
private:
|
||||
|
||||
UFUNCTION()
|
||||
void OnObstacleDetectionEvent(
|
||||
AActor *Actor,
|
||||
AActor *OtherActor,
|
||||
float Distance,
|
||||
const FHitResult &Hit);
|
||||
|
||||
UPROPERTY()
|
||||
const UCarlaEpisode *Episode = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
float Distance;
|
||||
|
||||
float HitRadius;
|
||||
|
||||
bool bOnlyDynamics = false;
|
||||
|
||||
bool bDebugLineTrace = false;
|
||||
|
||||
};
|
|
@ -17,7 +17,7 @@
|
|||
#include <carla/sensor/data/ActorDynamicState.h>
|
||||
#include <compiler/enable-ue4-macros.h>
|
||||
|
||||
static auto AWorldObserver_GetActorState(const FActorView &View)
|
||||
static auto AWorldObserver_GetActorState(const FActorView &View, const FActorRegistry &Registry)
|
||||
{
|
||||
using AType = FActorView::ActorType;
|
||||
|
||||
|
@ -28,9 +28,28 @@ static auto AWorldObserver_GetActorState(const FActorView &View)
|
|||
auto Vehicle = Cast<ACarlaWheeledVehicle>(View.GetActor());
|
||||
if (Vehicle != nullptr)
|
||||
{
|
||||
state.vehicle_control = carla::rpc::VehicleControl{Vehicle->GetVehicleControl()};
|
||||
state.vehicle_data.control = carla::rpc::VehicleControl{Vehicle->GetVehicleControl()};
|
||||
auto Controller = Cast<AWheeledVehicleAIController>(Vehicle->GetController());
|
||||
if (Controller != nullptr)
|
||||
{
|
||||
using TLS = carla::rpc::TrafficLightState;
|
||||
state.vehicle_data.traffic_light_state = static_cast<TLS>(Controller->GetTrafficLightState());
|
||||
state.vehicle_data.speed_limit = Controller->GetSpeedLimit();
|
||||
auto TrafficLight = Controller->GetTrafficLight();
|
||||
if (TrafficLight != nullptr)
|
||||
{
|
||||
state.vehicle_data.has_traffic_light = true;
|
||||
auto TrafficLightView = Registry.Find(TrafficLight);
|
||||
state.vehicle_data.traffic_light_id = TrafficLightView.GetActorId();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.vehicle_data.has_traffic_light = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (AType::Walker == View.GetActorType())
|
||||
{
|
||||
auto Walker = Cast<APawn>(View.GetActor());
|
||||
|
@ -46,7 +65,12 @@ static auto AWorldObserver_GetActorState(const FActorView &View)
|
|||
if (TrafficLight != nullptr)
|
||||
{
|
||||
using TLS = carla::rpc::TrafficLightState;
|
||||
state.traffic_light_state = static_cast<TLS>(TrafficLight->GetTrafficSignState());
|
||||
state.traffic_light_data.state = static_cast<TLS>(TrafficLight->GetTrafficLightState());
|
||||
state.traffic_light_data.green_time = TrafficLight->GetGreenTime();
|
||||
state.traffic_light_data.yellow_time = TrafficLight->GetYellowTime();
|
||||
state.traffic_light_data.red_time = TrafficLight->GetRedTime();
|
||||
state.traffic_light_data.elapsed_time = TrafficLight->GetElapsedTime();
|
||||
state.traffic_light_data.time_is_frozen = TrafficLight->GetTimeIsFrozen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +99,8 @@ static carla::Buffer AWorldObserver_Serialize(
|
|||
write_data(header);
|
||||
|
||||
// Write every actor.
|
||||
for (auto &&View : Registry) {
|
||||
for (auto &&View : Registry)
|
||||
{
|
||||
check(View.IsValid());
|
||||
constexpr float TO_METERS = 1e-2;
|
||||
const auto velocity = TO_METERS * View.GetActor()->GetVelocity();
|
||||
|
@ -83,13 +108,15 @@ static carla::Buffer AWorldObserver_Serialize(
|
|||
const auto RootComponent = Cast<UPrimitiveComponent>(View.GetActor()->GetRootComponent());
|
||||
FVector angularVelocity { 0.0f, 0.0f, 0.0f };
|
||||
if (RootComponent != nullptr)
|
||||
{
|
||||
angularVelocity = RootComponent->GetPhysicsAngularVelocityInDegrees();
|
||||
}
|
||||
ActorDynamicState info = {
|
||||
View.GetActorId(),
|
||||
View.GetActor()->GetActorTransform(),
|
||||
carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z},
|
||||
carla::geom::Vector3D{angularVelocity.X, angularVelocity.Y, angularVelocity.Z},
|
||||
AWorldObserver_GetActorState(View)
|
||||
AWorldObserver_GetActorState(View, Registry)
|
||||
};
|
||||
write_data(info);
|
||||
}
|
||||
|
@ -119,6 +146,5 @@ void AWorldObserver::Tick(float DeltaSeconds)
|
|||
GameTimeStamp,
|
||||
FPlatformTime::Seconds(),
|
||||
Episode->GetActorRegistry());
|
||||
|
||||
AsyncStream.Send(*this, std::move(buffer));
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ public:
|
|||
|
||||
FPimpl(uint16_t port)
|
||||
: Server(port),
|
||||
StreamingServer(port + 1u) {
|
||||
StreamingServer(port + 1u)
|
||||
{
|
||||
BindActions();
|
||||
}
|
||||
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
private:
|
||||
|
||||
void BindActions();
|
||||
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
@ -110,7 +112,8 @@ void FTheNewCarlaServer::FPimpl::BindActions()
|
|||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto WorldObserver = Episode->GetWorldObserver();
|
||||
if (WorldObserver == nullptr) {
|
||||
if (WorldObserver == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("internal error: missing world observer");
|
||||
}
|
||||
return cr::EpisodeInfo{
|
||||
|
@ -450,6 +453,101 @@ void FTheNewCarlaServer::FPimpl::BindActions()
|
|||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("set_traffic_light_state", [this](
|
||||
cr::Actor Actor,
|
||||
cr::TrafficLightState trafficLightState) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
|
||||
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill())
|
||||
{
|
||||
RESPOND_ERROR("unable to set state: actor not found");
|
||||
}
|
||||
auto TrafficLight = Cast<ATrafficLightBase>(ActorView.GetActor());
|
||||
if (TrafficLight == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to set state: actor is not a traffic light");
|
||||
}
|
||||
TrafficLight->SetTrafficLightState(static_cast<ETrafficLightState>(trafficLightState));
|
||||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("set_traffic_light_green_time", [this](
|
||||
cr::Actor Actor,
|
||||
float GreenTime) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
|
||||
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill())
|
||||
{
|
||||
RESPOND_ERROR("unable to set green time: actor not found");
|
||||
}
|
||||
auto TrafficLight = Cast<ATrafficLightBase>(ActorView.GetActor());
|
||||
if (TrafficLight == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to set green time: actor is not a traffic light");
|
||||
}
|
||||
TrafficLight->SetGreenTime(GreenTime);
|
||||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("set_traffic_light_yellow_time", [this](
|
||||
cr::Actor Actor,
|
||||
float YellowTime) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
|
||||
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill())
|
||||
{
|
||||
RESPOND_ERROR("unable to set yellow time: actor not found");
|
||||
}
|
||||
auto TrafficLight = Cast<ATrafficLightBase>(ActorView.GetActor());
|
||||
if (TrafficLight == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to set yellow time: actor is not a traffic light");
|
||||
}
|
||||
TrafficLight->SetYellowTime(YellowTime);
|
||||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("set_traffic_light_red_time", [this](
|
||||
cr::Actor Actor,
|
||||
float RedTime) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
|
||||
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill())
|
||||
{
|
||||
RESPOND_ERROR("unable to set red time: actor not found");
|
||||
}
|
||||
auto TrafficLight = Cast<ATrafficLightBase>(ActorView.GetActor());
|
||||
if (TrafficLight == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to set red time: actor is not a traffic light");
|
||||
}
|
||||
TrafficLight->SetRedTime(RedTime);
|
||||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("freeze_traffic_light", [this](
|
||||
cr::Actor Actor,
|
||||
bool Freeze) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
|
||||
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill())
|
||||
{
|
||||
RESPOND_ERROR("unable to alter frozen state: actor not found");
|
||||
}
|
||||
auto TrafficLight = Cast<ATrafficLightBase>(ActorView.GetActor());
|
||||
if (TrafficLight == nullptr)
|
||||
{
|
||||
RESPOND_ERROR("unable to alter frozen state: actor is not a traffic light");
|
||||
}
|
||||
TrafficLight->SetTimeIsFrozen(Freeze);
|
||||
return R<void>::Success();
|
||||
});
|
||||
|
||||
Server.BindSync("draw_debug_shape", [this](const cr::DebugShape &shape) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
|
|
|
@ -19,8 +19,10 @@ static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
|
|||
return ((Vehicle != nullptr) && !Vehicle->IsPendingKill());
|
||||
}
|
||||
|
||||
static ETrafficSignState ToTrafficSignState(ETrafficLightState State) {
|
||||
switch (State) {
|
||||
static ETrafficSignState ToTrafficSignState(ETrafficLightState State)
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case ETrafficLightState::Green:
|
||||
return ETrafficSignState::TrafficLightGreen;
|
||||
case ETrafficLightState::Yellow:
|
||||
|
@ -38,7 +40,7 @@ static ETrafficSignState ToTrafficSignState(ETrafficLightState State) {
|
|||
ATrafficLightBase::ATrafficLightBase(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void ATrafficLightBase::OnConstruction(const FTransform &Transform)
|
||||
|
@ -47,13 +49,48 @@ void ATrafficLightBase::OnConstruction(const FTransform &Transform)
|
|||
SetTrafficLightState(State);
|
||||
}
|
||||
|
||||
void ATrafficLightBase::Tick(float DeltaSeconds)
|
||||
{
|
||||
if (TimeIsFrozen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ElapsedTime += DeltaSeconds;
|
||||
|
||||
float ChangeTime;
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case ETrafficLightState::Red:
|
||||
ChangeTime = RedTime;
|
||||
break;
|
||||
case ETrafficLightState::Yellow:
|
||||
ChangeTime = YellowTime;
|
||||
break;
|
||||
case ETrafficLightState::Green:
|
||||
ChangeTime = GreenTime;
|
||||
break;
|
||||
default:
|
||||
UE_LOG(LogCarla, Error, TEXT("Invalid traffic light state!"));
|
||||
SetTrafficLightState(ETrafficLightState::Red);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ElapsedTime > ChangeTime)
|
||||
{
|
||||
SwitchTrafficLightState();
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void ATrafficLightBase::PostEditChangeProperty(FPropertyChangedEvent &Event)
|
||||
{
|
||||
Super::PostEditChangeProperty(Event);
|
||||
|
||||
const FName PropertyName = (Event.Property != nullptr ? Event.Property->GetFName() : NAME_None);
|
||||
if (PropertyName == GET_MEMBER_NAME_CHECKED(ATrafficLightBase, State)) {
|
||||
if (PropertyName == GET_MEMBER_NAME_CHECKED(ATrafficLightBase, State))
|
||||
{
|
||||
SetTrafficLightState(State);
|
||||
}
|
||||
}
|
||||
|
@ -61,14 +98,23 @@ void ATrafficLightBase::PostEditChangeProperty(FPropertyChangedEvent &Event)
|
|||
|
||||
void ATrafficLightBase::SetTrafficLightState(const ETrafficLightState InState)
|
||||
{
|
||||
NumChanges++;
|
||||
ElapsedTime = 0.0f;
|
||||
State = InState;
|
||||
SetTrafficSignState(ToTrafficSignState(State));
|
||||
for (auto Controller : Vehicles) {
|
||||
if (Controller != nullptr) {
|
||||
for (auto Controller : Vehicles)
|
||||
{
|
||||
if (Controller != nullptr)
|
||||
{
|
||||
Controller->SetTrafficLightState(State);
|
||||
if (State == ETrafficLightState::Green)
|
||||
{
|
||||
Controller->SetTrafficLight(nullptr);
|
||||
}
|
||||
}
|
||||
if (State == ETrafficLightState::Green) {
|
||||
}
|
||||
if (State == ETrafficLightState::Green)
|
||||
{
|
||||
Vehicles.Empty();
|
||||
}
|
||||
OnTrafficLightStateChanged(State);
|
||||
|
@ -76,7 +122,8 @@ void ATrafficLightBase::SetTrafficLightState(const ETrafficLightState InState)
|
|||
|
||||
void ATrafficLightBase::SwitchTrafficLightState()
|
||||
{
|
||||
switch (State) {
|
||||
switch (State)
|
||||
{
|
||||
case ETrafficLightState::Red:
|
||||
SetTrafficLightState(ETrafficLightState::Green);
|
||||
break;
|
||||
|
@ -95,13 +142,72 @@ void ATrafficLightBase::SwitchTrafficLightState()
|
|||
|
||||
void ATrafficLightBase::NotifyWheeledVehicle(ACarlaWheeledVehicle *Vehicle)
|
||||
{
|
||||
if (IsValid(Vehicle)) {
|
||||
if (IsValid(Vehicle))
|
||||
{
|
||||
auto Controller = Cast<AWheeledVehicleAIController>(Vehicle->GetController());
|
||||
if (Controller != nullptr) {
|
||||
if (Controller != nullptr)
|
||||
{
|
||||
Controller->SetTrafficLightState(State);
|
||||
if (State != ETrafficLightState::Green) {
|
||||
if (State != ETrafficLightState::Green)
|
||||
{
|
||||
Vehicles.Add(Controller);
|
||||
Controller->SetTrafficLight(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ATrafficLightBase::SetGreenTime(float InGreenTime)
|
||||
{
|
||||
GreenTime = InGreenTime;
|
||||
}
|
||||
|
||||
float ATrafficLightBase::GetGreenTime() const
|
||||
{
|
||||
return GreenTime;
|
||||
}
|
||||
|
||||
void ATrafficLightBase::SetYellowTime(float InYellowTime)
|
||||
{
|
||||
YellowTime = InYellowTime;
|
||||
}
|
||||
|
||||
float ATrafficLightBase::GetYellowTime() const
|
||||
{
|
||||
return YellowTime;
|
||||
}
|
||||
|
||||
void ATrafficLightBase::SetRedTime(float InRedTime)
|
||||
{
|
||||
RedTime = InRedTime;
|
||||
}
|
||||
|
||||
float ATrafficLightBase::GetRedTime() const
|
||||
{
|
||||
return RedTime;
|
||||
}
|
||||
|
||||
float ATrafficLightBase::GetElapsedTime() const
|
||||
{
|
||||
return ElapsedTime;
|
||||
}
|
||||
|
||||
void ATrafficLightBase::SetTimeIsFrozen(bool InTimeIsFrozen)
|
||||
{
|
||||
TimeIsFrozen = InTimeIsFrozen;
|
||||
if (!TimeIsFrozen)
|
||||
{
|
||||
NumChanges = 0;
|
||||
ElapsedTime = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool ATrafficLightBase::GetTimeIsFrozen() const
|
||||
{
|
||||
return TimeIsFrozen;
|
||||
}
|
||||
|
||||
int ATrafficLightBase::GetNumChanges() const
|
||||
{
|
||||
return NumChanges;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ class ACarlaWheeledVehicle;
|
|||
class AWheeledVehicleAIController;
|
||||
|
||||
UCLASS()
|
||||
class CARLA_API ATrafficLightBase : public ATrafficSignBase {
|
||||
class CARLA_API ATrafficLightBase : public ATrafficSignBase
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
|
@ -24,12 +25,15 @@ public:
|
|||
|
||||
ATrafficLightBase(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnConstruction(const FTransform &Transform) override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) override;
|
||||
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
public:
|
||||
|
@ -50,6 +54,36 @@ public:
|
|||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
void NotifyWheeledVehicle(ACarlaWheeledVehicle *Vehicle);
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
void SetGreenTime(float InGreenTime);
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
float GetGreenTime() const;
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
void SetYellowTime(float InYellowTime);
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
float GetYellowTime() const;
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
void SetRedTime(float InRedTime);
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
float GetRedTime() const;
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
float GetElapsedTime() const;
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
void SetTimeIsFrozen(bool InTimeIsFrozen);
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
bool GetTimeIsFrozen() const;
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintCallable)
|
||||
int GetNumChanges() const;
|
||||
|
||||
protected:
|
||||
|
||||
UFUNCTION(Category = "Traffic Light", BlueprintImplementableEvent)
|
||||
|
@ -62,4 +96,22 @@ private:
|
|||
|
||||
UPROPERTY(Category = "Traffic Light", VisibleAnywhere)
|
||||
TArray<AWheeledVehicleAIController *> Vehicles;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", EditAnywhere)
|
||||
float GreenTime = 10.0f;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", EditAnywhere)
|
||||
float YellowTime = 2.0f;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", EditAnywhere)
|
||||
float RedTime = 7.0f;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", VisibleAnywhere)
|
||||
float ElapsedTime = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", EditAnywhere)
|
||||
bool TimeIsFrozen = false;
|
||||
|
||||
UPROPERTY(Category = "Traffic Light", VisibleAnywhere)
|
||||
int NumChanges = 0;
|
||||
};
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
/// State of a ACarlaWheeledVehicle, to be displayed in editor for debugging
|
||||
/// purposes.
|
||||
UENUM(BlueprintType)
|
||||
enum class ECarlaWheeledVehicleState : uint8 {
|
||||
enum class ECarlaWheeledVehicleState : uint8
|
||||
{
|
||||
AutopilotOff UMETA(DisplayName = "Autopilot Off"),
|
||||
FreeDriving UMETA(DisplayName = "Free driving"),
|
||||
FollowingFixedRoute UMETA(DisplayName = "Following fixed route"),
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
// -- Static local methods -----------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
static bool RayTrace(const AActor &Actor, const FVector &Start, const FVector &End) {
|
||||
static bool RayCast(const AActor &Actor, const FVector &Start, const FVector &End)
|
||||
{
|
||||
FHitResult OutHit;
|
||||
static FName TraceTag = FName(TEXT("VehicleTrace"));
|
||||
FCollisionQueryParams CollisionParams(TraceTag, true);
|
||||
|
@ -31,6 +32,9 @@ static bool RayTrace(const AActor &Actor, const FVector &Start, const FVector &E
|
|||
FCollisionObjectQueryParams(FCollisionObjectQueryParams::AllDynamicObjects),
|
||||
CollisionParams);
|
||||
|
||||
// DrawDebugLine(Actor.GetWorld(), Start, End,
|
||||
// Success ? FColor(255, 0, 0) : FColor(0, 255, 0), false);
|
||||
|
||||
return Success && OutHit.bBlockingHit;
|
||||
}
|
||||
|
||||
|
@ -42,21 +46,26 @@ static bool IsThereAnObstacleAhead(
|
|||
const auto ForwardVector = Vehicle.GetVehicleOrientation();
|
||||
const auto VehicleBounds = Vehicle.GetVehicleBoundingBoxExtent();
|
||||
|
||||
FVector NormDirection = Direction.GetSafeNormal();
|
||||
|
||||
const float Distance = std::max(50.0f, Speed * Speed); // why?
|
||||
|
||||
const FVector StartCenter = Vehicle.GetActorLocation() + (ForwardVector * (250.0f + VehicleBounds.X / 2.0f)) + FVector(0.0f, 0.0f, 50.0f);
|
||||
const FVector EndCenter = StartCenter + Direction * (Distance + VehicleBounds.X / 2.0f);
|
||||
const FVector StartCenter = Vehicle.GetActorLocation() +
|
||||
(ForwardVector * (250.0f + VehicleBounds.X / 2.0f)) + FVector(0.0f, 0.0f, 50.0f);
|
||||
const FVector EndCenter = StartCenter + NormDirection * (Distance + VehicleBounds.X / 2.0f);
|
||||
|
||||
const FVector StartRight = StartCenter + (FVector(ForwardVector.Y, -ForwardVector.X, ForwardVector.Z) * 100.0f);
|
||||
const FVector EndRight = StartRight + Direction * (Distance + VehicleBounds.X / 2.0f);
|
||||
const FVector StartRight = StartCenter +
|
||||
(FVector(ForwardVector.Y, -ForwardVector.X, ForwardVector.Z) * 100.0f);
|
||||
const FVector EndRight = StartRight + NormDirection * (Distance + VehicleBounds.X / 2.0f);
|
||||
|
||||
const FVector StartLeft = StartCenter + (FVector(-ForwardVector.Y, ForwardVector.X, ForwardVector.Z) * 100.0f);
|
||||
const FVector EndLeft = StartLeft + Direction * (Distance + VehicleBounds.X / 2.0f);
|
||||
const FVector StartLeft = StartCenter +
|
||||
(FVector(-ForwardVector.Y, ForwardVector.X, ForwardVector.Z) * 100.0f);
|
||||
const FVector EndLeft = StartLeft + NormDirection * (Distance + VehicleBounds.X / 2.0f);
|
||||
|
||||
return
|
||||
RayTrace(Vehicle, StartCenter, EndCenter) ||
|
||||
RayTrace(Vehicle, StartRight, EndRight) ||
|
||||
RayTrace(Vehicle, StartLeft, EndLeft);
|
||||
RayCast(Vehicle, StartCenter, EndCenter) ||
|
||||
RayCast(Vehicle, StartRight, EndRight) ||
|
||||
RayCast(Vehicle, StartLeft, EndLeft);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -70,8 +79,8 @@ static void ClearQueue(std::queue<T> &Queue)
|
|||
// -- Constructor and destructor -----------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
AWheeledVehicleAIController::AWheeledVehicleAIController(const FObjectInitializer& ObjectInitializer) :
|
||||
Super(ObjectInitializer)
|
||||
AWheeledVehicleAIController::AWheeledVehicleAIController(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
|
||||
|
||||
|
@ -162,10 +171,12 @@ void AWheeledVehicleAIController::SetFixedRoute(
|
|||
const TArray<FVector> &Locations,
|
||||
const bool bOverwriteCurrent)
|
||||
{
|
||||
if (bOverwriteCurrent) {
|
||||
if (bOverwriteCurrent)
|
||||
{
|
||||
ClearQueue(TargetLocations);
|
||||
}
|
||||
for (auto &Location : Locations) {
|
||||
for (auto &Location : Locations)
|
||||
{
|
||||
TargetLocations.emplace(Location);
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +187,9 @@ void AWheeledVehicleAIController::SetFixedRoute(
|
|||
|
||||
void AWheeledVehicleAIController::TickAutopilotController()
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Vehicle == nullptr) { // This happens in simulation mode in editor.
|
||||
#if WITH_EDITOR // This happens in simulation mode in editor.
|
||||
if (Vehicle == nullptr)
|
||||
{
|
||||
bAutopilotEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
@ -185,37 +197,45 @@ void AWheeledVehicleAIController::TickAutopilotController()
|
|||
|
||||
check(Vehicle != nullptr);
|
||||
|
||||
if (RoadMap == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
FVector Direction;
|
||||
|
||||
float Steering;
|
||||
if (!TargetLocations.empty()) {
|
||||
if (!TargetLocations.empty())
|
||||
{
|
||||
Steering = GoToNextTargetLocation(Direction);
|
||||
} else {
|
||||
Steering = CalcStreeringValue(Direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
Steering = RoadMap != nullptr ? CalcStreeringValue(Direction) : 0.0f;
|
||||
Direction = Vehicle->GetVehicleTransform().GetRotation().Rotator().Vector();
|
||||
}
|
||||
|
||||
// Speed in km/h.
|
||||
const auto Speed = Vehicle->GetVehicleForwardSpeed() * 0.036f;
|
||||
|
||||
float Throttle;
|
||||
if (TrafficLightState != ETrafficLightState::Green) {
|
||||
if (TrafficLightState != ETrafficLightState::Green)
|
||||
{
|
||||
Vehicle->SetAIVehicleState(ECarlaWheeledVehicleState::WaitingForRedLight);
|
||||
Throttle = Stop(Speed);
|
||||
} else if (IsThereAnObstacleAhead(*Vehicle, Speed, Direction)) {
|
||||
}
|
||||
else if (IsThereAnObstacleAhead(*Vehicle, Speed, Direction))
|
||||
{
|
||||
Vehicle->SetAIVehicleState(ECarlaWheeledVehicleState::ObstacleAhead);
|
||||
Throttle = Stop(Speed);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Throttle = Move(Speed);
|
||||
}
|
||||
|
||||
if (Throttle < 0.001f) {
|
||||
if (Throttle < 0.001f)
|
||||
{
|
||||
AutopilotControl.Brake = 1.0f;
|
||||
AutopilotControl.Throttle = 0.0f;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
AutopilotControl.Brake = 0.0f;
|
||||
AutopilotControl.Throttle = Throttle;
|
||||
}
|
||||
|
@ -236,12 +256,16 @@ float AWheeledVehicleAIController::GoToNextTargetLocation(FVector &Direction)
|
|||
return FVector{Result.X, Result.Y, CurrentLocation.Z};
|
||||
} ();
|
||||
|
||||
if (Target.Equals(CurrentLocation, 200.0f)) {
|
||||
if (Target.Equals(CurrentLocation, 200.0f))
|
||||
{
|
||||
TargetLocations.pop();
|
||||
if (!TargetLocations.empty()) {
|
||||
if (!TargetLocations.empty())
|
||||
{
|
||||
return GoToNextTargetLocation(Direction);
|
||||
} else {
|
||||
return CalcStreeringValue(Direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RoadMap != nullptr ? CalcStreeringValue(Direction) : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,16 +281,26 @@ float AWheeledVehicleAIController::GoToNextTargetLocation(FVector &Direction)
|
|||
|
||||
float angle = dirAngle - actorAngle;
|
||||
|
||||
if (angle > 180.0f) { angle -= 360.0f;} else if (angle < -180.0f) {
|
||||
if (angle > 180.0f)
|
||||
{
|
||||
angle -= 360.0f;
|
||||
}
|
||||
else if (angle < -180.0f)
|
||||
{
|
||||
angle += 360.0f;
|
||||
}
|
||||
|
||||
float Steering = 0.0f;
|
||||
if (angle < -MaximumSteerAngle) {
|
||||
if (angle < -MaximumSteerAngle)
|
||||
{
|
||||
Steering = -1.0f;
|
||||
} else if (angle > MaximumSteerAngle) {
|
||||
}
|
||||
else if (angle > MaximumSteerAngle)
|
||||
{
|
||||
Steering = 1.0f;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Steering += angle / MaximumSteerAngle;
|
||||
}
|
||||
|
||||
|
@ -285,7 +319,8 @@ float AWheeledVehicleAIController::CalcStreeringValue(FVector &direction)
|
|||
|
||||
float forwardMagnitude = BoxExtent.X / 2.0f;
|
||||
|
||||
float Magnitude = (float) sqrt(pow((double) leftSensorPosition.X, 2.0) + pow((double) leftSensorPosition.Y, 2.0));
|
||||
float Magnitude =
|
||||
(float) sqrt(pow((double) leftSensorPosition.X, 2.0) + pow((double) leftSensorPosition.Y, 2.0));
|
||||
|
||||
// same for the right and left
|
||||
float offset = FGenericPlatformMath::Acos(forwardMagnitude / Magnitude);
|
||||
|
@ -304,19 +339,32 @@ float AWheeledVehicleAIController::CalcStreeringValue(FVector &direction)
|
|||
leftSensorPosition.Y = sinL * Magnitude;
|
||||
leftSensorPosition.X = cosL * Magnitude;
|
||||
|
||||
FVector rightPositon = GetPawn()->GetActorLocation() + FVector(rightSensorPosition.X, rightSensorPosition.Y, 0.0f);
|
||||
FVector leftPosition = GetPawn()->GetActorLocation() + FVector(leftSensorPosition.X, leftSensorPosition.Y, 0.0f);
|
||||
FVector rightPositon = GetPawn()->GetActorLocation() + FVector(rightSensorPosition.X,
|
||||
rightSensorPosition.Y,
|
||||
0.0f);
|
||||
FVector leftPosition = GetPawn()->GetActorLocation() + FVector(leftSensorPosition.X,
|
||||
leftSensorPosition.Y,
|
||||
0.0f);
|
||||
|
||||
FRoadMapPixelData rightRoadData = RoadMap->GetDataAt(rightPositon);
|
||||
if (!rightRoadData.IsRoad()) { steering -= 0.2f;}
|
||||
if (!rightRoadData.IsRoad())
|
||||
{
|
||||
steering -= 0.2f;
|
||||
}
|
||||
|
||||
FRoadMapPixelData leftRoadData = RoadMap->GetDataAt(leftPosition);
|
||||
if (!leftRoadData.IsRoad()) { steering += 0.2f;}
|
||||
if (!leftRoadData.IsRoad())
|
||||
{
|
||||
steering += 0.2f;
|
||||
}
|
||||
|
||||
FRoadMapPixelData roadData = RoadMap->GetDataAt(GetPawn()->GetActorLocation());
|
||||
if (!roadData.IsRoad()) {
|
||||
if (!roadData.IsRoad())
|
||||
{
|
||||
steering = 0.0f;
|
||||
} else if (roadData.HasDirection()) {
|
||||
}
|
||||
else if (roadData.HasDirection())
|
||||
{
|
||||
|
||||
direction = roadData.GetDirection();
|
||||
FVector right = rightRoadData.GetDirection();
|
||||
|
@ -334,30 +382,61 @@ float AWheeledVehicleAIController::CalcStreeringValue(FVector &direction)
|
|||
actorAngle *= (180.0 / PI);
|
||||
|
||||
float min = dirAngle - 90.0f;
|
||||
if (min < -180.0f) { min = 180.0f + (min + 180.0f);}
|
||||
if (min < -180.0f)
|
||||
{
|
||||
min = 180.0f + (min + 180.0f);
|
||||
}
|
||||
|
||||
float max = dirAngle + 90.0f;
|
||||
if (max > 180.0f) { max = -180.0f + (max - 180.0f);}
|
||||
if (max > 180.0f)
|
||||
{
|
||||
max = -180.0f + (max - 180.0f);
|
||||
}
|
||||
|
||||
if (dirAngle < -90.0 || dirAngle > 90.0) {
|
||||
if (rightAngle < min && rightAngle > max) { steering -= 0.2f;}
|
||||
if (leftAngle < min && leftAngle > max) { steering += 0.2f;}
|
||||
} else {
|
||||
if (rightAngle < min || rightAngle > max) { steering -= 0.2f;}
|
||||
if (leftAngle < min || leftAngle > max) { steering += 0.2f;}
|
||||
if (dirAngle < -90.0 || dirAngle > 90.0)
|
||||
{
|
||||
if (rightAngle < min && rightAngle > max)
|
||||
{
|
||||
steering -= 0.2f;
|
||||
}
|
||||
if (leftAngle < min && leftAngle > max)
|
||||
{
|
||||
steering += 0.2f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rightAngle < min || rightAngle > max)
|
||||
{
|
||||
steering -= 0.2f;
|
||||
}
|
||||
if (leftAngle < min || leftAngle > max)
|
||||
{
|
||||
steering += 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
float angle = dirAngle - actorAngle;
|
||||
|
||||
if (angle > 180.0f) { angle -= 360.0f;} else if (angle < -180.0f) {
|
||||
if (angle > 180.0f)
|
||||
{
|
||||
angle -= 360.0f;
|
||||
}
|
||||
else if (angle < -180.0f)
|
||||
{
|
||||
angle += 360.0f;
|
||||
}
|
||||
|
||||
if (angle < -MaximumSteerAngle) {
|
||||
if (angle < -MaximumSteerAngle)
|
||||
{
|
||||
steering = -1.0f;
|
||||
} else if (angle > MaximumSteerAngle) {
|
||||
}
|
||||
else if (angle > MaximumSteerAngle)
|
||||
{
|
||||
steering = 1.0f;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
steering += angle / MaximumSteerAngle;
|
||||
}
|
||||
}
|
||||
|
@ -366,16 +445,23 @@ float AWheeledVehicleAIController::CalcStreeringValue(FVector &direction)
|
|||
return steering;
|
||||
}
|
||||
|
||||
float AWheeledVehicleAIController::Stop(const float Speed) {
|
||||
float AWheeledVehicleAIController::Stop(const float Speed)
|
||||
{
|
||||
return (Speed >= 1.0f ? -Speed / SpeedLimit : 0.0f);
|
||||
}
|
||||
|
||||
float AWheeledVehicleAIController::Move(const float Speed) {
|
||||
if (Speed >= SpeedLimit) {
|
||||
float AWheeledVehicleAIController::Move(const float Speed)
|
||||
{
|
||||
if (Speed >= SpeedLimit)
|
||||
{
|
||||
return Stop(Speed);
|
||||
} else if (Speed >= SpeedLimit - 10.0f) {
|
||||
}
|
||||
else if (Speed >= SpeedLimit - 10.0f)
|
||||
{
|
||||
return 0.5f;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class CARLA_API AWheeledVehicleAIController : public APlayerController
|
|||
/// @name Constructor and destructor
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
AWheeledVehicleAIController(const FObjectInitializer &ObjectInitializer);
|
||||
|
@ -40,6 +41,7 @@ public:
|
|||
/// @name APlayerController overrides
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
void Possess(APawn *aPawn) override;
|
||||
|
@ -53,6 +55,7 @@ public:
|
|||
/// @name Possessed vehicle
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
|
@ -83,6 +86,7 @@ public:
|
|||
/// @name Road map
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
void SetRoadMap(URoadMap *InRoadMap)
|
||||
|
@ -101,6 +105,7 @@ public:
|
|||
/// @name Random engine
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(Category = "Random Engine", BlueprintCallable)
|
||||
|
@ -115,6 +120,7 @@ public:
|
|||
/// @name Autopilot
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
|
@ -126,7 +132,8 @@ public:
|
|||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
void SetAutopilot(bool Enable)
|
||||
{
|
||||
if (IsAutopilotEnabled() != Enable) {
|
||||
if (IsAutopilotEnabled() != Enable)
|
||||
{
|
||||
ConfigureAutopilot(Enable);
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +153,7 @@ private:
|
|||
/// @name Traffic
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
/// Get current speed limit in km/h.
|
||||
|
@ -176,6 +184,20 @@ public:
|
|||
TrafficLightState = InTrafficLightState;
|
||||
}
|
||||
|
||||
/// Get traffic light currently affecting this vehicle.
|
||||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
ATrafficLightBase *GetTrafficLight() const
|
||||
{
|
||||
return TrafficLight;
|
||||
}
|
||||
|
||||
/// Set traffic light currently affecting this vehicle.
|
||||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
void SetTrafficLight(ATrafficLightBase *InTrafficLight)
|
||||
{
|
||||
TrafficLight = InTrafficLight;
|
||||
}
|
||||
|
||||
/// Set a fixed route to follow if autopilot is enabled.
|
||||
UFUNCTION(Category = "Wheeled Vehicle Controller", BlueprintCallable)
|
||||
void SetFixedRoute(const TArray<FVector> &Locations, bool bOverwriteCurrent = true);
|
||||
|
@ -212,6 +234,8 @@ private:
|
|||
// ===========================================================================
|
||||
// -- Member variables -------------------------------------------------------
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
|
@ -235,6 +259,9 @@ private:
|
|||
UPROPERTY(VisibleAnywhere)
|
||||
float MaximumSteerAngle = -1.0f;
|
||||
|
||||
UPROPERTY()
|
||||
ATrafficLightBase *TrafficLight;
|
||||
|
||||
FVehicleControl AutopilotControl;
|
||||
|
||||
std::queue<FVector> TargetLocations;
|
||||
|
|
|
@ -153,7 +153,8 @@ unset BOOST_BASENAME
|
|||
# -- Get rpclib and compile it with libc++ and libstdc++ -----------------------
|
||||
# ==============================================================================
|
||||
|
||||
RPCLIB_BASENAME=rpclib-d1146b7-ex
|
||||
RPCLIB_PATCH=v2.2.1_c1
|
||||
RPCLIB_BASENAME=rpclib-${RPCLIB_PATCH}
|
||||
|
||||
RPCLIB_LIBCXX_INCLUDE=${PWD}/${RPCLIB_BASENAME}-libcxx-install/include
|
||||
RPCLIB_LIBCXX_LIBPATH=${PWD}/${RPCLIB_BASENAME}-libcxx-install/lib
|
||||
|
@ -170,10 +171,7 @@ else
|
|||
|
||||
log "Retrieving rpclib."
|
||||
|
||||
git clone https://github.com/rpclib/rpclib.git ${RPCLIB_BASENAME}-source
|
||||
pushd ${RPCLIB_BASENAME}-source >/dev/null
|
||||
git reset --hard d1146b7
|
||||
popd >/dev/null
|
||||
git clone -b ${RPCLIB_PATCH} https://github.com/carla-simulator/rpclib.git ${RPCLIB_BASENAME}-source
|
||||
|
||||
log "Building rpclib with libc++."
|
||||
|
||||
|
|
Loading…
Reference in New Issue