CARLA
YieldSignComponent.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
7 #include "YieldSignComponent.h"
8 #include "TrafficLightState.h"
9 #include <queue>
10 
18 
19 void UYieldSignComponent::InitializeSign(const carla::road::Map &Map)
20 {
21 
22  const double epsilon = 0.00001;
23 
24  auto References = GetAllReferencesToThisSignal(Map);
25 
26  for (auto& Reference : References)
27  {
28  auto RoadId = Reference.first;
29  const auto* SignalReference = Reference.second;
30  TSet<carla::road::RoadId> SignalPredecessors;
31  // Yield box
32  for(auto &validity : SignalReference->GetValidities())
33  {
34  for(auto lane : carla::geom::Math::GenerateRange(validity._from_lane, validity._to_lane))
35  {
36  if(lane == 0)
37  continue;
38 
39  auto signal_waypoint = Map.GetWaypoint(
40  RoadId, lane, SignalReference->GetS()).get();
41 
42  if(Map.GetLane(signal_waypoint).GetType() != cr::Lane::LaneType::Driving)
43  continue;
44 
45  auto box_waypoint = signal_waypoint;
46  // Prevent adding the bounding box inside the intersection
47  if (Map.IsJunction(RoadId)) {
48  auto predecessors = Map.GetPredecessors(box_waypoint);
49  if (predecessors.size() == 1) {
50  auto predecessor = predecessors.front();
51  if (!Map.IsJunction(predecessor.road_id)) {
52  box_waypoint = predecessor;
53  }
54  }
55  }
56 
57  // Get 50% of the half size of the width of the lane
58  float BoxWidth = static_cast<float>(
59  0.5f*Map.GetLaneWidth(box_waypoint)*0.5);
60  float BoxLength = 1.5f;
61  float BoxHeight = 1.0f;
62  // Prevent a situation where the road width is 0,
63  // this could happen in a lane that is just appearing
64  BoxWidth = std::max(0.01f, BoxWidth);
65  // Get min and max
66  double LaneLength = Map.GetLane(box_waypoint).GetLength();
67  double LaneDistance = Map.GetLane(box_waypoint).GetDistance();
68  // Safe distance to avoid overlapping the bounding box with the intersection
69  float AdditionalDistance = 1.5f;
70  if(lane < 0)
71  {
72  box_waypoint.s = FMath::Clamp(box_waypoint.s - (BoxLength + AdditionalDistance),
73  LaneDistance + epsilon, LaneDistance + LaneLength - epsilon);
74  }
75  else
76  {
77  box_waypoint.s = FMath::Clamp(box_waypoint.s + (BoxLength + AdditionalDistance),
78  LaneDistance + epsilon, LaneDistance + LaneLength - epsilon);
79  }
80  FTransform BoxTransform = Map.ComputeTransform(box_waypoint);
81  ALargeMapManager* LargeMapManager = UCarlaStatics::GetLargeMapManager(GetWorld());
82  if (LargeMapManager)
83  {
84  BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
85  }
86  GenerateYieldBox(BoxTransform, FVector(100*BoxLength, 100*BoxWidth, 100*BoxHeight));
87 
88  auto Predecessors = Map.GetPredecessors(signal_waypoint);
89  for(auto &Prev : Predecessors)
90  {
91  if(!SignalPredecessors.Contains(Prev.road_id))
92  {
93  SignalPredecessors.Add(Prev.road_id);
94  }
95  }
96  }
97  }
98 
99  //Check boxes
100  if(Map.IsJunction(RoadId))
101  {
102  auto JuncId = Map.GetJunctionId(RoadId);
103  const auto * Junction = Map.GetJunction(JuncId);
104  if(Junction->RoadHasConflicts(RoadId))
105  {
106  const auto &ConflictingRoads = Junction->GetConflictsOfRoad(RoadId);
107  for(const auto &Conflict : ConflictingRoads)
108  {
109  auto Waypoints = Map.GenerateWaypointsInRoad(Conflict);
110  for(auto& Waypoint : Waypoints)
111  {
112  // Skip roads that share the same previous road
113  bool bHasSamePredecessor = false;
114  auto Predecessors = Map.GetPredecessors(Waypoint);
115  for(auto &Prev : Predecessors)
116  {
117  if(SignalPredecessors.Contains(Prev.road_id))
118  {
119  bHasSamePredecessor = true;
120  }
121  }
122  if(bHasSamePredecessor)
123  {
124  continue;
125  }
126 
127  if(Map.GetLane(Waypoint).GetType() != cr::Lane::LaneType::Driving)
128  continue;
129 
130  // Cover the road within the junction
131  auto CurrentWaypoint = Waypoint;
132  auto NextWaypoint = CurrentWaypoint;
133  float BoxSize = static_cast<float>(
134  0.9*Map.GetLaneWidth(NextWaypoint)/2.0);
135  // Prevent a situation where the road width is 0,
136  // this could happen in a lane that is just appearing
137  BoxSize = std::max(0.01f, BoxSize);
138  float UEBoxSize = 100*BoxSize;
139 
140  FTransform BoxTransform = Map.ComputeTransform(NextWaypoint);
141  ALargeMapManager* LargeMapManager = UCarlaStatics::GetLargeMapManager(GetWorld());
142  if (LargeMapManager)
143  {
144  BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
145  }
146  GenerateCheckBox(BoxTransform, UEBoxSize);
147 
148  while (true)
149  {
150  auto Next = Map.GetNext(NextWaypoint, 2*BoxSize);
151  if (Next.size() != 1)
152  {
153  break;
154  }
155  NextWaypoint = Next.front();
156  if(NextWaypoint.road_id != Waypoint.road_id)
157  {
158  break;
159  }
160  BoxTransform = Map.ComputeTransform(NextWaypoint);
161  if (LargeMapManager)
162  {
163  BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
164  }
165  GenerateCheckBox(BoxTransform, UEBoxSize);
166 
167  }
168  // Cover the road before the junction
169  // Hard coded anticipation time (boxes placed prior to the junction)
170  double AnticipationTime = 0.1;
171  auto Previous = Map.GetPrevious(Waypoint, 2*BoxSize);
172  std::queue<std::pair<float, carla::road::element::Waypoint>>
173  WaypointQueue;
174  for (auto & Prev : Previous)
175  {
176  WaypointQueue.push({AnticipationTime, Prev});
177  }
178  while (!WaypointQueue.empty())
179  {
180  auto CurrentElement = WaypointQueue.front();
181  WaypointQueue.pop();
182  GenerateCheckBox(Map.ComputeTransform(CurrentElement.second), UEBoxSize);
183 
184  float Speed = 40;
185  auto* InfoSpeed = Map.GetLane(CurrentElement.second).GetRoad()->GetInfo<carla::road::element::RoadInfoSpeed>(CurrentElement.second.s);
186  if(InfoSpeed)
187  {
188  Speed = InfoSpeed->GetSpeed();
189  }
190  float RemainingTime = CurrentElement.first - BoxSize/Speed;
191  if(RemainingTime > 0)
192  {
193  Previous = Map.GetPrevious(CurrentElement.second, 2*BoxSize);
194  for (auto & Prev : Previous)
195  {
196  WaypointQueue.push({RemainingTime, Prev});
197  }
198  }
199  }
200  }
201  }
202  }
203  }
204  }
205 }
206 
207 void UYieldSignComponent::GenerateYieldBox(const FTransform BoxTransform,
208  const FVector BoxSize)
209 {
210  UBoxComponent* BoxComponent = GenerateTriggerBox(BoxTransform, BoxSize);
211  BoxComponent->OnComponentBeginOverlap.AddDynamic(this, &UYieldSignComponent::OnOverlapBeginYieldEffectBox);
212  BoxComponent->OnComponentEndOverlap.AddDynamic(this, &UYieldSignComponent::OnOverlapEndYieldEffectBox);
213  AddEffectTriggerVolume(BoxComponent);
214 }
215 
216 void UYieldSignComponent::GenerateCheckBox(const FTransform BoxTransform,
217  float BoxSize)
218 {
219  UBoxComponent* BoxComponent = GenerateTriggerBox(BoxTransform, BoxSize);
220  BoxComponent->OnComponentBeginOverlap.AddDynamic(this, &UYieldSignComponent::OnOverlapBeginYieldCheckBox);
221  BoxComponent->OnComponentEndOverlap.AddDynamic(this, &UYieldSignComponent::OnOverlapEndYieldCheckBox);
222 }
223 
224 void UYieldSignComponent::GiveWayIfPossible()
225 {
226  if (VehiclesToCheck.Num() == 0)
227  {
228  for (auto Vehicle : VehiclesInYield)
229  {
230  AWheeledVehicleAIController* VehicleController =
231  Cast<AWheeledVehicleAIController>(Vehicle->GetController());
232  VehicleController->SetTrafficLightState(ETrafficLightState::Green);
233  }
234  }
235  else
236  {
237  if(VehiclesInYield.Num())
238  {
239  for (auto Vehicle : VehiclesInYield)
240  {
241  AWheeledVehicleAIController* VehicleController =
242  Cast<AWheeledVehicleAIController>(Vehicle->GetController());
243  VehicleController->SetTrafficLightState(ETrafficLightState::Red);
244  }
245  // 0.5 second delay
246  DelayedGiveWay(0.5f);
247  }
248  }
249 }
250 
251 void UYieldSignComponent::DelayedGiveWay(float Delay)
252 {
253  FTimerHandle TimerHandler;
254  GetWorld()->GetTimerManager().
255  SetTimer(TimerHandler, this, &UYieldSignComponent::GiveWayIfPossible, Delay);
256 }
257 
258 void UYieldSignComponent::OnOverlapBeginYieldEffectBox(UPrimitiveComponent *OverlappedComp,
259  AActor *OtherActor,
260  UPrimitiveComponent *OtherComp,
261  int32 OtherBodyIndex,
262  bool bFromSweep,
263  const FHitResult &SweepResult)
264 {
265  ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
266  if (Vehicle)
267  {
268  AWheeledVehicleAIController* VehicleController =
269  Cast<AWheeledVehicleAIController>(Vehicle->GetController());
270  if (VehicleController)
271  {
272  VehiclesInYield.Add(Vehicle);
273  RemoveSameVehicleInBothLists();
274  GiveWayIfPossible();
275  }
276  }
277 }
278 
279 void UYieldSignComponent::OnOverlapEndYieldEffectBox(UPrimitiveComponent *OverlappedComp,
280  AActor *OtherActor,
281  UPrimitiveComponent *OtherComp,
282  int32 OtherBodyIndex)
283 {
284  ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
285  if (Vehicle)
286  {
287  VehiclesInYield.Remove(Vehicle);
288  }
289 }
290 
291 void UYieldSignComponent::OnOverlapBeginYieldCheckBox(UPrimitiveComponent *OverlappedComp,
292  AActor *OtherActor,
293  UPrimitiveComponent *OtherComp,
294  int32 OtherBodyIndex,
295  bool bFromSweep,
296  const FHitResult &SweepResult)
297 {
298  ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
299  if (Vehicle)
300  {
301  if(!VehiclesInYield.Contains(Vehicle))
302  {
303  if (!VehiclesToCheck.Contains(Vehicle))
304  {
305  VehiclesToCheck.Add(Vehicle, 0);
306  }
307  VehiclesToCheck[Vehicle]++;
308  }
309  GiveWayIfPossible();
310  }
311 }
312 
313 void UYieldSignComponent::OnOverlapEndYieldCheckBox(UPrimitiveComponent *OverlappedComp,
314  AActor *OtherActor,
315  UPrimitiveComponent *OtherComp,
316  int32 OtherBodyIndex)
317 {
318  ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
319  if (Vehicle)
320  {
321  if(VehiclesToCheck.Contains(Vehicle))
322  {
323  VehiclesToCheck[Vehicle]--;
324  if(VehiclesToCheck[Vehicle] <= 0)
325  {
326  VehiclesToCheck.Remove(Vehicle);
327  }
328  }
329  // 0.5 second delay
330  DelayedGiveWay(0.5);
331  }
332 }
333 void UYieldSignComponent::RemoveSameVehicleInBothLists()
334 {
335  for(auto* Vehicle : VehiclesInYield)
336  {
337  if(VehiclesToCheck.Contains(Vehicle))
338  {
339  VehiclesToCheck.Remove(Vehicle);
340  }
341  }
342 }
LaneType GetType() const
Definition: Lane.cpp:38
std::vector< Waypoint > GetPrevious(Waypoint waypoint, double distance) const
Return the list of waypoints at distance in the reversed direction that a vehicle at waypoint could d...
Definition: road/Map.cpp:590
boost::optional< element::Waypoint > GetWaypoint(const geom::Location &location, int32_t lane_type=static_cast< int32_t >(Lane::LaneType::Driving)) const
Definition: road/Map.cpp:212
Road * GetRoad() const
Definition: Lane.cpp:29
const Lane & GetLane(Waypoint waypoint) const
======================================================================== – Road information --------...
Definition: road/Map.cpp:834
double GetDistance() const
Definition: Lane.cpp:46
Junction * GetJunction(JuncId id)
Definition: road/Map.cpp:997
double GetLength() const
Definition: Lane.cpp:51
const T * GetInfo(const double s) const
Definition: Road.h:113
void SetTrafficLightState(ETrafficLightState InTrafficLightState)
Set traffic light state currently affecting this vehicle.
std::vector< Waypoint > GetNext(Waypoint waypoint, double distance) const
Return the list of waypoints at distance such that a vehicle at waypoint could drive to...
Definition: road/Map.cpp:554
Wheeled vehicle controller with optional AI.
geom::Transform ComputeTransform(Waypoint waypoint) const
Definition: road/Map.cpp:273
bool IsJunction(RoadId road_id) const
Definition: road/Map.cpp:302
std::vector< Waypoint > GetPredecessors(Waypoint waypoint) const
Definition: road/Map.cpp:536
static std::vector< int > GenerateRange(int a, int b)
Definition: Math.cpp:151
std::vector< Waypoint > GenerateWaypointsInRoad(RoadId road_id, Lane::LaneType lane_type=Lane::LaneType::Driving) const
Generate waypoints at the entry of each lane of the specified road.
Definition: road/Map.cpp:692
FTransform GlobalToLocalTransform(const FTransform &InTransform) const
static ALargeMapManager * GetLargeMapManager(const UObject *WorldContextObject)
Definition: CarlaStatics.h:100
JuncId GetJunctionId(RoadId road_id) const
Definition: road/Map.cpp:298
Base class for CARLA wheeled vehicles.
double GetLaneWidth(Waypoint waypoint) const
Definition: road/Map.cpp:285
carla::SharedPtr< carla::client::Junction > Junction