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

@ -769,6 +769,10 @@ namespace road {
auto it = _map_data._controllers.find(controller);
DEBUG_ASSERT(it != _map_data._controllers.end());
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).
//
// This work is licensed under the terms of the MIT license.
@ -173,6 +173,10 @@ namespace road {
return _transform;
}
const std::set<ContId>& GetControllers() const {
return _controllers;
}
private:
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"
// Sets default values for this component's properties
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;
}
// Called when the game starts
@ -27,3 +26,12 @@ void USignComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorC
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
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/SceneComponent.h"
#include "Carla/OpenDrive/OpenDrive.h"
#include "SignComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CARLA_API USignComponent : public UActorComponent
class CARLA_API USignComponent : public USceneComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
USignComponent();
void SetSignId(carla::road::SignId SignId)
{
Id = SignId;
}
UFUNCTION(BlueprintPure)
const FString &GetSignId() const;
UFUNCTION(BlueprintCallable)
void SetSignId(const FString &Id);
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
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 "Kismet/GameplayStatics.h"
#include "TrafficLightGroup.h"
#include "TrafficLightManager.h"
// Sets default values for this component's properties
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
void UTrafficLightComponent::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
void UTrafficLightComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* 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
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "SignComponent.h"
#include "TrafficLightState.h"
#include "TrafficLightComponent.generated.h"
class ATrafficLightManager;
class ATrafficLightGroup;
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class CARLA_API UTrafficLightComponent : public UActorComponent
// Delegate to define dispatcher
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()
@ -16,12 +27,34 @@ public:
// Sets default values for this component's properties
UTrafficLightComponent();
UFUNCTION(BlueprintCallable)
void SetLightState(ETrafficLightState NewState);
UFUNCTION(BlueprintCallable)
ETrafficLightState GetLightState() const;
UFUNCTION(BlueprintCallable)
void SetFrozenGroup(bool InFreeze);
UFUNCTION(BlueprintPure)
ATrafficLightGroup* GetGroup();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
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;
};