Added Traffic Lights from OpenDRIVE.

This commit is contained in:
Axel 2020-02-26 11:24:14 +01:00 committed by Axel1092
parent 0b9084495b
commit d533e359b6
16 changed files with 772 additions and 189 deletions

View File

@ -11,64 +11,64 @@
namespace carla { namespace carla {
namespace client { namespace client {
void TrafficLight::SetState(rpc::TrafficLightState state) { void TrafficLight::SetState(rpc::TrafficLightState state) {
GetEpisode().Lock()->SetTrafficLightState(*this, state); GetEpisode().Lock()->SetTrafficLightState(*this, state);
} }
rpc::TrafficLightState TrafficLight::GetState() const { rpc::TrafficLightState TrafficLight::GetState() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.state; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.state;
} }
void TrafficLight::SetGreenTime(float green_time) { void TrafficLight::SetGreenTime(float green_time) {
GetEpisode().Lock()->SetTrafficLightGreenTime(*this, green_time); GetEpisode().Lock()->SetTrafficLightGreenTime(*this, green_time);
} }
float TrafficLight::GetGreenTime() const { float TrafficLight::GetGreenTime() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.green_time; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.green_time;
} }
void TrafficLight::SetYellowTime(float yellow_time) { void TrafficLight::SetYellowTime(float yellow_time) {
GetEpisode().Lock()->SetTrafficLightYellowTime(*this, yellow_time); GetEpisode().Lock()->SetTrafficLightYellowTime(*this, yellow_time);
} }
float TrafficLight::GetYellowTime() const { float TrafficLight::GetYellowTime() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.yellow_time; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.yellow_time;
} }
void TrafficLight::SetRedTime(float red_time) { void TrafficLight::SetRedTime(float red_time) {
GetEpisode().Lock()->SetTrafficLightRedTime(*this, red_time); GetEpisode().Lock()->SetTrafficLightRedTime(*this, red_time);
} }
float TrafficLight::GetRedTime() const { float TrafficLight::GetRedTime() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.red_time; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.red_time;
} }
float TrafficLight::GetElapsedTime() const { float TrafficLight::GetElapsedTime() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.elapsed_time; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.elapsed_time;
} }
void TrafficLight::Freeze(bool freeze) { void TrafficLight::Freeze(bool freeze) {
GetEpisode().Lock()->FreezeTrafficLight(*this, freeze); GetEpisode().Lock()->FreezeTrafficLight(*this, freeze);
} }
bool TrafficLight::IsFrozen() const { bool TrafficLight::IsFrozen() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.time_is_frozen; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.time_is_frozen;
} }
uint32_t TrafficLight::GetPoleIndex() uint32_t TrafficLight::GetPoleIndex()
{ {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.pole_index; return GetEpisode().Lock()->GetActorSnapshot(*this).state.traffic_light_data.pole_index;
} }
std::vector<SharedPtr<TrafficLight>> TrafficLight::GetGroupTrafficLights() { std::vector<SharedPtr<TrafficLight>> TrafficLight::GetGroupTrafficLights() {
std::vector<SharedPtr<TrafficLight>> result; std::vector<SharedPtr<TrafficLight>> result;
auto ids = GetEpisode().Lock()->GetGroupTrafficLights(*this); auto ids = GetEpisode().Lock()->GetGroupTrafficLights(*this);
for (auto id : ids) { for (auto id : ids) {
SharedPtr<Actor> actor = GetWorld().GetActors()->Find(id); SharedPtr<Actor> actor = GetWorld().GetActors()->Find(id);
result.push_back(boost::static_pointer_cast<TrafficLight>(actor)); result.push_back(boost::static_pointer_cast<TrafficLight>(actor));
}
return result;
} }
return result;
}
} // namespace client } // namespace client
} // namespace carla } // namespace carla

View File

@ -12,57 +12,57 @@
namespace carla { namespace carla {
namespace client { namespace client {
class TrafficLight : public Actor { class TrafficLight : public Actor {
public: public:
explicit TrafficLight(ActorInitializer init) : Actor(std::move(init)) {} explicit TrafficLight(ActorInitializer init) : Actor(std::move(init)) {}
void SetState(rpc::TrafficLightState state); void SetState(rpc::TrafficLightState state);
/// Return the current state of the traffic light. /// Return the current state of the traffic light.
/// ///
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
rpc::TrafficLightState GetState() const; rpc::TrafficLightState GetState() const;
void SetGreenTime(float green_time); void SetGreenTime(float green_time);
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
float GetGreenTime() const; float GetGreenTime() const;
void SetYellowTime(float yellow_time); void SetYellowTime(float yellow_time);
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
float GetYellowTime() const; float GetYellowTime() const;
void SetRedTime(float red_time); void SetRedTime(float red_time);
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
float GetRedTime() const; float GetRedTime() const;
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
float GetElapsedTime() const; float GetElapsedTime() const;
void Freeze(bool freeze); void Freeze(bool freeze);
/// @note This function does not call the simulator, it returns the data /// @note This function does not call the simulator, it returns the data
/// received in the last tick. /// received in the last tick.
bool IsFrozen() const; bool IsFrozen() const;
/// Returns the index of the pole in the traffic light group /// Returns the index of the pole in the traffic light group
uint32_t GetPoleIndex(); uint32_t GetPoleIndex();
/// Return all traffic lights in the group this one belongs to. /// Return all traffic lights in the group this one belongs to.
/// ///
/// @note This function calls the simulator /// @note This function calls the simulator
std::vector<SharedPtr<TrafficLight>> GetGroupTrafficLights(); std::vector<SharedPtr<TrafficLight>> GetGroupTrafficLights();
}; };
} // namespace client } // namespace client
} // namespace carla } // namespace carla

View File

@ -14,44 +14,44 @@ namespace carla {
namespace opendrive { namespace opendrive {
namespace parser { namespace parser {
void ControllerParser::Parse( void ControllerParser::Parse(
const pugi::xml_document &xml, const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder) { carla::road::MapBuilder &map_builder) {
// Extracting the OpenDRIVE // Extracting the OpenDRIVE
const pugi::xml_node opendrive_node = xml.child("OpenDRIVE"); const pugi::xml_node opendrive_node = xml.child("OpenDRIVE");
for (pugi::xml_node controller_node = opendrive_node.child("controller"); for (pugi::xml_node controller_node = opendrive_node.child("controller");
controller_node; controller_node;
controller_node = controller_node.next_sibling("controller")) { controller_node = controller_node.next_sibling("controller")) {
const road::ContId controller_id = controller_node.attribute("id").value(); const road::ContId controller_id = controller_node.attribute("id").value();
const std::string controller_name = controller_node.attribute("name").value(); const std::string controller_name = controller_node.attribute("name").value();
const uint32_t controller_sequence = controller_node.attribute("sequence").as_uint(); const uint32_t controller_sequence = controller_node.attribute("sequence").as_uint();
log_debug("Controller: ", log_debug("Controller: ",
controller_id, controller_id,
controller_name, controller_name,
controller_sequence); controller_sequence);
std::set<road::SignId> signals; std::set<road::SignId> signals;
for (pugi::xml_node control_node : controller_node.children("control")) { for (pugi::xml_node control_node : controller_node.children("control")) {
const road::SignId signal_id = control_node.attribute("signalId").value(); const road::SignId signal_id = control_node.attribute("signalId").value();
// The controller_type is included in the OpenDrive format but not used yet // The controller_type is included in the OpenDrive format but not used yet
// const std::string controller_type = control_node.attribute("type").value(); // const std::string controller_type = control_node.attribute("type").value();
signals.insert(signal_id); signals.insert(signal_id);
}
map_builder.CreateController(
controller_id,
controller_name,
controller_sequence,
std::move(signals)
);
} }
map_builder.CreateController(
controller_id,
controller_name,
controller_sequence,
std::move(signals)
);
} }
}
} // namespace parser } // namespace parser
} // namespace opendrive } // namespace opendrive
} // namespace carla } // namespace carla

View File

@ -14,51 +14,51 @@
namespace carla { namespace carla {
namespace road { namespace road {
class MapBuilder; class MapBuilder;
class Controller : private MovableNonCopyable { class Controller : private MovableNonCopyable {
public: public:
Controller( Controller(
ContId id, ContId id,
std::string name, std::string name,
uint32_t sequence) uint32_t sequence)
: _id(id), : _id(id),
_name(name), _name(name),
_sequence(sequence){} _sequence(sequence){}
const ContId& GetControllerId() const{ const ContId& GetControllerId() const{
return _id; return _id;
} }
const std::string& GetName() const { const std::string& GetName() const {
return _name; return _name;
} }
const uint32_t &GetSequence() const { const uint32_t &GetSequence() const {
return _sequence; return _sequence;
} }
const std::set<SignId>& GetSignals() const { const std::set<SignId>& GetSignals() const {
return _signals; return _signals;
} }
const std::set<JuncId>& GetJunctions() const { const std::set<JuncId>& GetJunctions() const {
return _junctions; return _junctions;
} }
private: private:
friend MapBuilder; friend MapBuilder;
ContId _id; ContId _id;
std::string _name; std::string _name;
uint32_t _sequence; uint32_t _sequence;
std::set<JuncId> _junctions; std::set<JuncId> _junctions;
std::set<SignId> _signals; std::set<SignId> _signals;
}; };
} // namespace road } // namespace road
} // namespace carla } // namespace carla

View File

@ -769,6 +769,10 @@ namespace road {
auto it = _map_data._controllers.find(controller); auto it = _map_data._controllers.find(controller);
DEBUG_ASSERT(it != _map_data._controllers.end()); DEBUG_ASSERT(it != _map_data._controllers.end());
it->second->_junctions.insert(junction.first); it->second->_junctions.insert(junction.first);
for(const auto & signal : it->second->_signals) {
auto signal_it = _map_data._signals.find(signal);
signal_it->second->_controllers.insert(controller);
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019 Computer Vision Center (CVC) at the Universitat Autonoma // Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB). // de Barcelona (UAB).
// //
// This work is licensed under the terms of the MIT license. // This work is licensed under the terms of the MIT license.
@ -173,6 +173,10 @@ namespace road {
return _transform; return _transform;
} }
const std::set<ContId>& GetControllers() const {
return _controllers;
}
private: private:
friend MapBuilder; friend MapBuilder;

View File

@ -1,16 +1,15 @@
// 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>. // Copyright (c) 2020 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 "SignComponent.h" #include "SignComponent.h"
// Sets default values for this component's properties
USignComponent::USignComponent() USignComponent::USignComponent()
{ {
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = false; PrimaryComponentTick.bCanEverTick = false;
} }
// Called when the game starts // Called when the game starts
@ -27,3 +26,12 @@ void USignComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorC
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
} }
const FString& USignComponent::GetSignId() const
{
return SignId;
}
void USignComponent::SetSignId(const FString &Id) {
SignId = Id;
}

View File

@ -1,40 +1,41 @@
// 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>. // Copyright (c) 2020 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 #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Components/ActorComponent.h" #include "Components/SceneComponent.h"
#include "Carla/OpenDrive/OpenDrive.h" #include "Carla/OpenDrive/OpenDrive.h"
#include "SignComponent.generated.h" #include "SignComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CARLA_API USignComponent : public UActorComponent class CARLA_API USignComponent : public USceneComponent
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
// Sets default values for this component's properties
USignComponent(); USignComponent();
void SetSignId(carla::road::SignId SignId) UFUNCTION(BlueprintPure)
{ const FString &GetSignId() const;
Id = SignId;
} UFUNCTION(BlueprintCallable)
void SetSignId(const FString &Id);
protected: protected:
// Called when the game starts // Called when the game starts
virtual void BeginPlay() override; virtual void BeginPlay() override;
public:
// Called every frame // Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
private: private:
carla::road::SignId Id;
FTransform Transform;
UPROPERTY(Category = "Traffic Sign", EditAnywhere)
FString SignId;
}; };

View File

@ -1,34 +1,71 @@
// 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>. // Copyright (c) 2020 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 "TrafficLightComponent.h" #include "TrafficLightComponent.h"
#include "Kismet/GameplayStatics.h"
#include "TrafficLightGroup.h"
#include "TrafficLightManager.h"
// Sets default values for this component's properties
UTrafficLightComponent::UTrafficLightComponent() UTrafficLightComponent::UTrafficLightComponent()
: Super()
{ {
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
} }
// Called when the game starts // Called when the game starts
void UTrafficLightComponent::BeginPlay() void UTrafficLightComponent::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
// ... // Search the Traffic Light Manager
TArray<AActor*> TrafficLightManagerArray;
UGameplayStatics::GetAllActorsOfClass(
GetWorld(),
ATrafficLightManager::StaticClass(),
TrafficLightManagerArray);
// Create it if missing
if (!TrafficLightManagerArray.Num())
{
TrafficLightManagerArray.Add(
GetWorld()->SpawnActor<ATrafficLightManager>());
}
// Register this component
ATrafficLightManager *TrafficLightManager = Cast<ATrafficLightManager>(TrafficLightManagerArray.Top());
TrafficLightManager->RegisterLightComponent(this);
} }
// Called every frame // Called every frame
void UTrafficLightComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) void UTrafficLightComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{ {
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// ... // ...
} }
void UTrafficLightComponent::SetLightState(ETrafficLightState NewState)
{
LightState = NewState;
LightChangeDispatcher.Broadcast();
}
ETrafficLightState UTrafficLightComponent::GetLightState() const
{
return LightState;
}
void UTrafficLightComponent::SetFrozenGroup(bool InFreeze)
{
if (TrafficLightGroup)
{
TrafficLightGroup->SetFrozenGroup(InFreeze);
}
}
ATrafficLightGroup* UTrafficLightComponent::GetGroup()
{
return TrafficLightGroup;
}

View File

@ -1,14 +1,25 @@
// 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>. // Copyright (c) 2020 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 #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Components/ActorComponent.h" #include "SignComponent.h"
#include "TrafficLightState.h"
#include "TrafficLightComponent.generated.h" #include "TrafficLightComponent.generated.h"
class ATrafficLightManager;
class ATrafficLightGroup;
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) // Delegate to define dispatcher
class CARLA_API UTrafficLightComponent : public UActorComponent DECLARE_DYNAMIC_MULTICAST_DELEGATE(FLightChangeDispatcher);
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_RetVal(ETrafficLightState, FLightChangeDispatcher);
UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CARLA_API UTrafficLightComponent : public USignComponent
{ {
GENERATED_BODY() GENERATED_BODY()
@ -16,12 +27,34 @@ public:
// Sets default values for this component's properties // Sets default values for this component's properties
UTrafficLightComponent(); UTrafficLightComponent();
UFUNCTION(BlueprintCallable)
void SetLightState(ETrafficLightState NewState);
UFUNCTION(BlueprintCallable)
ETrafficLightState GetLightState() const;
UFUNCTION(BlueprintCallable)
void SetFrozenGroup(bool InFreeze);
UFUNCTION(BlueprintPure)
ATrafficLightGroup* GetGroup();
protected: protected:
// Called when the game starts // Called when the game starts
virtual void BeginPlay() override; virtual void BeginPlay() override;
public:
// Called every frame // Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
private:
friend ATrafficLightManager;
UPROPERTY(Category = "Traffic Light", EditAnywhere)
ETrafficLightState LightState;
UPROPERTY(BlueprintAssignable, Category = "Traffic Light")
FLightChangeDispatcher LightChangeDispatcher;
UPROPERTY()
ATrafficLightGroup *TrafficLightGroup = nullptr;
}; };

View File

@ -0,0 +1,79 @@
// Copyright (c) 2020 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 "TrafficLightController.h"
UTrafficLightController::UTrafficLightController()
{
}
void UTrafficLightController::SetState(TArray<FTrafficLightStage> States)
{
LightStates = States;
CurrentState = 0;
}
const FTrafficLightStage &UTrafficLightController::GetCurrentState() const
{
return LightStates[CurrentState];
}
float UTrafficLightController::NextState()
{
CurrentState = (CurrentState + 1) % LightStates.Num();
SetTrafficLightsState(GetCurrentState().State);
return GetCurrentState().Time;
}
const TArray<UTrafficLightComponent *> &UTrafficLightController::GetTrafficLights()
{
return TrafficLights;
}
void UTrafficLightController::AddTrafficLight(UTrafficLightComponent * TrafficLight)
{
TrafficLights.Add(TrafficLight);
}
const FString &UTrafficLightController::GetControllerId() const
{
return ControllerId;
}
void UTrafficLightController::SetControllerId(const FString &Id)
{
ControllerId = Id;
}
bool UTrafficLightController::IsCycleFinished() const
{
return CurrentState == (LightStates.Num() - 1);
}
void UTrafficLightController::SetTrafficLightsState(ETrafficLightState NewState)
{
for(auto *Light : TrafficLights)
{
Light->SetLightState(NewState);
}
}
int UTrafficLightController::GetSequence() const
{
return Sequence;
}
void UTrafficLightController::SetSequence(int InSequence)
{
Sequence = InSequence;
}
void UTrafficLightController::ResetState()
{
CurrentState = (LightStates.Num() - 1);
SetTrafficLightsState(GetCurrentState().State);
}

View File

@ -0,0 +1,96 @@
// Copyright (c) 2020 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 "CoreMinimal.h"
#include "Object.h"
#include "TrafficLightState.h"
#include "TrafficLightComponent.h"
#include "Containers/Map.h"
#include "TrafficLightController.generated.h"
// Defines a stage of a semaphor with a State and
// the time this state lasts
USTRUCT(BlueprintType)
struct FTrafficLightStage
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Time;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
ETrafficLightState State;
};
// Maps a controller from OpenDrive.
// Controls the asociated traffic lights and its cycles
UCLASS(BlueprintType)
class CARLA_API UTrafficLightController : public UObject
{
GENERATED_BODY()
public:
UTrafficLightController();
UFUNCTION(BlueprintCallable)
void SetState(TArray<FTrafficLightStage> States);
UFUNCTION(BlueprintPure)
const FTrafficLightStage &GetCurrentState() const;
// Updates traffic light components to the next state
UFUNCTION(BlueprintCallable)
float NextState();
UFUNCTION(BlueprintPure)
const TArray<UTrafficLightComponent *> &GetTrafficLights();
UFUNCTION(BlueprintPure)
const FString &GetControllerId() const;
UFUNCTION(BlueprintCallable)
void SetControllerId(const FString &Id);
UFUNCTION(BlueprintCallable)
void AddTrafficLight(UTrafficLightComponent * TrafficLight);
UFUNCTION(BlueprintCallable)
bool IsCycleFinished() const;
UFUNCTION(BlueprintCallable)
void SetTrafficLightsState(ETrafficLightState NewState);
UFUNCTION(BlueprintCallable)
int GetSequence() const;
UFUNCTION(BlueprintCallable)
void SetSequence(int InSequence);
UFUNCTION(BlueprintCallable)
void ResetState();
private:
UPROPERTY(EditAnywhere)
FString ControllerId;
UPROPERTY(EditAnywhere)
int CurrentState = 0;
// Pairs with the state of the semaphors (time - state) e.g. 10s in green
UPROPERTY(EditAnywhere)
TArray<FTrafficLightStage> LightStates = {
{10, ETrafficLightState::Green}, {3, ETrafficLightState::Yellow}, {2, ETrafficLightState::Red}};
UPROPERTY(EditAnywhere)
TArray<UTrafficLightComponent *> TrafficLights;
// Sequence within junction (unused for now)
UPROPERTY(EditAnywhere)
int Sequence = 0;
};

View File

@ -0,0 +1,73 @@
// Copyright (c) 2020 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 "TrafficLightGroup.h"
// Sets default values
ATrafficLightGroup::ATrafficLightGroup()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
RootComponent = SceneComponent;
}
// Called when the game starts or when spawned
void ATrafficLightGroup::BeginPlay()
{
Super::BeginPlay();
}
void ATrafficLightGroup::SetFrozenGroup(bool InFreeze)
{
bIsFrozen = InFreeze;
}
// Called every frame
void ATrafficLightGroup::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bIsFrozen)
{
return;
}
Timer -= DeltaTime;
if(Timer <= 0 && Controllers.Num())
{
NextCycleStep();
}
}
void ATrafficLightGroup::NextCycleStep()
{
UTrafficLightController* controller = Controllers[CurrentController];
if (controller->IsCycleFinished())
{
NextController();
}
else
{
Timer = controller->NextState();
}
}
void ATrafficLightGroup::NextController()
{
CurrentController = (CurrentController + 1) % Controllers.Num();
UTrafficLightController* controller = Controllers[CurrentController];
Timer = controller->NextState();
}
int ATrafficLightGroup::GetJunctionId() const
{
return JunctionId;
}

View File

@ -0,0 +1,72 @@
// Copyright (c) 2020 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 "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SceneComponent.h"
#include "TrafficLightComponent.h"
#include "TrafficLightController.h"
#include "TrafficLightGroup.generated.h"
class ATrafficLightManager;
// Class with the logic of semaphors
UCLASS()
class CARLA_API ATrafficLightGroup : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATrafficLightGroup();
UFUNCTION(BlueprintPure)
TArray<UTrafficLightController*>& GetControllers() {
return Controllers;
}
UFUNCTION(BlueprintCallable)
void SetFrozenGroup(bool InFreeze);
UFUNCTION(BlueprintPure)
int GetJunctionId() const;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
friend ATrafficLightManager;
UPROPERTY(Category = "Traffic Group", VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
USceneComponent *SceneComponent;
UPROPERTY(Category = "Traffic Group", EditAnywhere)
TArray<UTrafficLightController*> Controllers;
UPROPERTY()
float Timer = 0;
UPROPERTY()
int CurrentController = 0;
UFUNCTION()
void NextCycleStep();
UFUNCTION()
void NextController();
UPROPERTY(Category = "Traffic Group", EditAnywhere)
bool bIsFrozen = false;
UPROPERTY(Category = "Traffic Group", EditAnywhere)
int JunctionId = -1;
};

View File

@ -0,0 +1,116 @@
// Copyright (c) 2020 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 "TrafficLightManager.h"
#include "Game/CarlaStatics.h"
#include <string>
ATrafficLightManager::ATrafficLightManager() {
PrimaryActorTick.bCanEverTick = false;
}
void ATrafficLightManager::RegisterLightComponent(UTrafficLightComponent * TrafficLight) {
// Cast to std::string
carla::road::SignId SignId(TCHAR_TO_UTF8(*(TrafficLight->GetSignId())));
// Get OpenDRIVE signal
if (GetMap()->GetSignals().count(SignId) == 0)
{
carla::log_warning("Error: missing signal with id:", SignId);
return;
}
const auto &Signal = GetMap()->GetSignals().at(SignId);
if(Signal->GetControllers().empty())
{
carla::log_warning("Error: no controllers in signal", SignId);
return;
}
// Only one controller per signal
auto ControllerId = *(Signal->GetControllers().begin());
// Get controller
const auto &Controller = GetMap()->GetControllers().at(ControllerId);
if(Controller->GetJunctions().empty())
{
carla::log_warning("Error: no junctions in controller", ControllerId);
return;
}
// Get junction of the controller
auto JunctionId = *(Controller->GetJunctions().begin());
// Search/create TrafficGroup (junction traffic light manager)
if(!TrafficGroups.Contains(JunctionId))
{
auto * TrafficLightGroup =
GetWorld()->SpawnActor<ATrafficLightGroup>();
TrafficLightGroup->JunctionId = JunctionId;
TrafficGroups.Add(JunctionId, TrafficLightGroup);
carla::log_warning("Spawn TrafficLight Group");
}
auto * TrafficLightGroup = TrafficGroups[JunctionId];
// Search/create controller in the junction
if(!TrafficControllers.Contains(ControllerId.c_str()))
{
auto *TrafficLightController = NewObject<UTrafficLightController>();
TrafficLightController->SetControllerId(ControllerId.c_str());
TrafficLightGroup->GetControllers().Add(TrafficLightController);
TrafficControllers.Add(ControllerId.c_str(), TrafficLightController);
carla::log_warning("Created Controller");
}
auto *TrafficLightController = TrafficControllers[ControllerId.c_str()];
TrafficLight->TrafficLightGroup = TrafficLightGroup;
// Add signal to controller
TrafficLightController->AddTrafficLight(TrafficLight);
TrafficLightController->ResetState();
// Add signal to map
TrafficLights.Add(TrafficLight->GetSignId(), TrafficLight);
}
const boost::optional<carla::road::Map>& ATrafficLightManager::GetMap() {
if(!GameMode) {
GameMode = UCarlaStatics::GetGameMode(this);
}
return GameMode->GetMap();
}
// Called when the game starts
void ATrafficLightManager::BeginPlay()
{
Super::BeginPlay();
}
ATrafficLightGroup* ATrafficLightManager::GetTrafficGroup(carla::road::JuncId JunctionId)
{
if (TrafficGroups.Contains(JunctionId))
{
return TrafficGroups[JunctionId];
}
return nullptr;
}
UTrafficLightController* ATrafficLightManager::GetController(FString ControllerId)
{
if (TrafficControllers.Contains(ControllerId))
{
return TrafficControllers[ControllerId];
}
return nullptr;
}
UTrafficLightComponent* ATrafficLightManager::GetTrafficLight(FString SignId)
{
if (!TrafficLights.Contains(SignId))
{
return nullptr;
}
return TrafficLights[SignId];
}

View File

@ -0,0 +1,60 @@
// Copyright (c) 2020 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 "TrafficLightComponent.h"
#include "TrafficLightGroup.h"
#include "Game/CarlaGameModeBase.h"
#include "TrafficLightManager.generated.h"
// Class In charge of creating and assigning traffic
// light groups, controllers and components.
UCLASS()
class CARLA_API ATrafficLightManager : public AActor
{
GENERATED_BODY()
public:
ATrafficLightManager();
UFUNCTION(BlueprintCallable)
void RegisterLightComponent(UTrafficLightComponent * TrafficLight);
const boost::optional<carla::road::Map> &GetMap();
UFUNCTION(BlueprintCallable)
ATrafficLightGroup* GetTrafficGroup(int JunctionId);
UFUNCTION(BlueprintCallable)
UTrafficLightController* GetController(FString ControllerId);
UFUNCTION(BlueprintCallable)
UTrafficLightComponent* GetTrafficLight(FString SignId);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
private:
// Cached Carla Game Mode
UPROPERTY()
ACarlaGameModeBase *GameMode = 0;
// Mapped references to ATrafficLightGroup (junction)
UPROPERTY()
TMap<int, ATrafficLightGroup *> TrafficGroups;
// Mapped references to UTrafficLightController (controllers)
UPROPERTY()
TMap<FString, UTrafficLightController *> TrafficControllers;
// Mapped references to individual TrafficLightComponents
UPROPERTY()
TMap<FString, UTrafficLightComponent *> TrafficLights;
};