Skip to content

Commit a599e2a

Browse files
committed
Implement Part2.3: Keep slow until ped crossed
1 parent 790b033 commit a599e2a

2 files changed

Lines changed: 85 additions & 293 deletions

File tree

GEMstack/onboard/planning/longitudinal_planning.py

Lines changed: 70 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import matplotlib.patches as patches
1111
import math
1212

13-
class CollosionDetector:
13+
class CollisionDetector:
1414
"""
1515
Simulation class to update positions of two rectangles (vehicle and pedestrian)
1616
with velocities v1 and v2, performing collision detection at each time step.
1717
All functions remain within the class, and variables defined in __init__ remain unchanged;
1818
local copies are used during simulation.
1919
"""
20-
def __init__(self, x1, y1, t1, x2, y2, t2, v1, v2, total_time=10.0, basic_deceleration=2.0, max_deceleration=8.0):
20+
def __init__(self, x1, y1, t1, x2, y2, t2, v1, v2, total_time=10.0, desired_speed=2.0, acceleration=0.5):
2121

2222
self.vehicle_x = x1
2323
self.vehicle_y = y1
@@ -50,8 +50,13 @@ def __init__(self, x1, y1, t1, x2, y2, t2, v1, v2, total_time=10.0, basic_decele
5050

5151
self.dt = 0.1 # seconds
5252
self.total_time = total_time # seconds
53-
self.basic_deceleration = basic_deceleration
54-
self.max_deceleration = max_deceleration
53+
54+
self.desired_speed = desired_speed
55+
self.acceleration = acceleration
56+
57+
def set_params(self, speed, acceleration):
58+
self.desired_speed = speed
59+
self.acceleration = acceleration
5560

5661
def get_corners(self, x, y, w, h, theta):
5762
"""
@@ -121,13 +126,7 @@ def plot_rectangles(self, rect1, rect2, collision, ax):
121126
ax.set_title(f"Collision: {'Yes' if collision else 'No'}")
122127

123128
def run(self, is_displayed=False):
124-
output_deceleration = 0.0
125129
collision_distance = -1
126-
relation = "None"
127-
# None: No relation
128-
# Yielding: Vehicle is yielding to pedestrian
129-
# Stopping: Vehicle is stopping for pedestrian
130-
131130
steps = int(self.total_time / self.dt) + 1
132131

133132
# Create local variables for positions; these will be updated
@@ -136,6 +135,7 @@ def run(self, is_displayed=False):
136135
current_y1 = self.y1
137136
current_x2 = self.x2
138137
current_y2 = self.y2
138+
current_v1 = self.v1[0]
139139

140140
if is_displayed:
141141
plt.ion() # Turn on interactive mode
@@ -180,35 +180,26 @@ def run(self, is_displayed=False):
180180

181181
# Stop simulation if collision is detected.
182182
if collision:
183-
# Check if the vehicle will hit the pedestrian or can stop before hitting.
184-
# Dmin = v^2 / (2 * a) => a = -v^2 / (2 * D)
185-
# Minimum distance required to stop before hitting with basic_deceleration
186-
minimum_distance = self.v1[0]**2 / (2 * self.basic_deceleration)
187-
current_vehicle_x = current_x1 - (self.vehicle_size_x + self.vehicle_buffer_x) * 0.5
188-
current_vehicle_y = current_y1
189-
190-
print("Collision detected. Stopping simulation.")
191-
print(f"Collision coordinates: ({current_vehicle_x:.1f}, {current_vehicle_y:.1f})")
192-
print(f"Vehicle speed: {self.v1[0]:.1f}")
193-
print(f"Minimum distance required to avoid collision: {minimum_distance:.1f}")
194-
183+
current_vehicle_x = current_x1 - (self.vehicle_size_x + self.vehicle_buffer_x) * 0.5
184+
current_vehicle_y = current_y1
195185
collision_distance = current_vehicle_x - self.vehicle_x
196-
197-
if minimum_distance > collision_distance:
198-
print("Vehicle will hit the pedestrian!!!")
199-
relation = "Stopping"
200-
# Deceleration to stop at the current position > basic_deceleration
201-
output_deceleration = min(self.max_deceleration, self.v1[0]**2 / (2 * (collision_distance)))
202-
else:
203-
print("Vehicle can yield. Speed down with:")
204-
# Deceleration to stop at the current position < basic_deceleration
205-
output_deceleration = self.v1[0]**2 / (2 * (current_vehicle_x - self.vehicle_x))
206-
print(f"Appropriate deceleration: {output_deceleration:.2f}")
207-
relation = "Yielding"
208186
break
209187

188+
# Update the vehicle's speed if it is not at the desired speed.
189+
next_v = current_v1 + self.acceleration * self.dt
190+
# Accelerating: Check if the vehicle is about to exceed the desired speed.
191+
if next_v > self.desired_speed and current_v1 <= self.desired_speed:
192+
current_v1 = self.desired_speed
193+
# Decelerating: Check if the vehicle is about to fall below the desired speed.
194+
elif next_v < self.desired_speed and current_v1 >= self.desired_speed:
195+
current_v1 = self.desired_speed
196+
else:
197+
current_v1 = next_v
198+
199+
current_v1 = 0.0 if current_v1 < 0.0 else current_v1
200+
210201
# Update local positions based on velocities.
211-
current_x1 += self.v1[0] * self.dt
202+
current_x1 += current_v1 * self.dt
212203
current_y1 += self.v1[1] * self.dt
213204
current_x2 += self.v2[0] * self.dt
214205
current_y2 += self.v2[1] * self.dt
@@ -217,7 +208,9 @@ def run(self, is_displayed=False):
217208
plt.ioff()
218209
plt.show(block=True)
219210

220-
return relation, output_deceleration, collision_distance
211+
print("Collision distance:", collision_distance)
212+
213+
return collision_distance
221214

222215

223216
def longitudinal_plan(path : Path, acceleration : float, deceleration : float, max_speed : float, current_speed : float) -> Trajectory:
@@ -457,7 +450,6 @@ def longitudinal_brake(path : Path, deceleration : float, current_speed : float)
457450

458451
print("=====LONGITUDINAL BRAKE=====")
459452
print("path length: ", path.length())
460-
print("deceleration: ", deceleration)
461453
length = path.length()
462454

463455
x0 = points[0][0]
@@ -494,9 +486,11 @@ def __init__(self):
494486
self.t_last = None
495487
self.acceleration = 0.5
496488
self.desired_speed = 2.0 # default 1.0
497-
self.deceleration = 2.0
498489

499-
self.max_deceleration = 8.0
490+
self.yield_speed = 0.5
491+
self.yield_deceleration = 0.5
492+
self.deceleration = 2.0
493+
self.max_deceleration = 8.0
500494
self.relation = "None"
501495

502496
def state_inputs(self):
@@ -530,18 +524,15 @@ def update(self, state : AllState):
530524
closest_dist,closest_parameter = state.route.closest_point_local((curr_x,curr_y),[self.route_progress-5.0,self.route_progress+5.0])
531525
self.route_progress = closest_parameter
532526

533-
lookahead_distance = max(10, curr_v**2 / (2 * self.deceleration))
527+
lookahead_distance = max(10, curr_v**2 / (2 * self.yield_deceleration))
534528
route_with_lookahead = route.trim(closest_parameter,closest_parameter + lookahead_distance)
535529
print("Lookahead distance:", lookahead_distance)
536530
#extract out a 10m segment of the route
537531
# route_with_lookahead = route.trim(closest_parameter,closest_parameter+10.0)
538532

539-
decel = self.deceleration
540-
prev_relation = self.relation
541-
should_yield = False
542-
543533
#parse the relations indicated
544534
should_brake = False
535+
should_yield = False
545536

546537
for r in state.relations:
547538
if r.type == EntityRelationEnum.YIELDING and r.obj1 == '':
@@ -583,30 +574,50 @@ def update(self, state : AllState):
583574
# Create and run the simulation.
584575
print(f"Vehicle: ({x1:.1f}, {y1:.1f}, ({v1[0]:.1f}, {v1[1]:.1f}))")
585576
print(f"Pedestrian: ({x2:.1f}, {y2:.1f}, ({v2[0]:.1f}, {v2[1]:.1f}))")
586-
sim = CollosionDetector(x1, y1, 0, x2, y2, 0, v1, v2, total_time, self.deceleration, self.max_deceleration)
587577

588-
self.relation, decel, collision_distance = sim.run()
589-
print(f"Relation: {self.relation}")
590-
print(f"Deceleration: {decel:.2f} m/s^2")
578+
# Simulate if a collision will occur when the vehicle accelerate to desired speed.
579+
sim = CollisionDetector(x1, y1, 0, x2, y2, 0, v1, v2, total_time, self.desired_speed, self.acceleration)
580+
collision_distance = sim.run()
581+
582+
# No collision detected
583+
if collision_distance < 0:
584+
print("No collision detected.")
585+
self.relation = "None"
591586

592-
# Update the lookahead distance based on the deceleration
593-
if collision_distance >= 0:
594-
route_with_lookahead = route.trim(closest_parameter,closest_parameter + collision_distance)
587+
# Collision detected
588+
else:
589+
# Update lookahead distance to pedestrian.
590+
route_with_lookahead = route.trim(closest_parameter, closest_parameter + collision_distance)
591+
592+
# Simulate if a collision will occur when the vehicle decelerate to yield speed.
593+
sim.set_params(self.yield_speed, self.yield_deceleration * -1)
594+
collision_distance_after_yield = sim.run()
595+
596+
# Can yield to the pedestrian => Yielding
597+
if collision_distance_after_yield < 0:
598+
print("The vehicle can yield to the pedestrian.")
599+
self.relation = "Yielding"
600+
decel = self.yield_deceleration
601+
602+
# Cannot yield to the pedestrian => Stopping
603+
else:
604+
print("The vehicle is Stopping.")
605+
self.relation = "Stopping"
606+
decel = max(self.deceleration, v1[0]**2 / (2 * (collision_distance)))
607+
if decel > self.max_deceleration:
608+
decel = self.max_deceleration
609+
610+
print(f"Relation: {self.relation}")
611+
print(f"Deceleration: {decel:.2f} m/s^2")
595612

596613
# relation: None, Yielding, Stopping
597614
# None: No need to speed down
598615
# Yielding: Speed down but not to 0 m/s
599616
# Stopping: Speed down to 0 m/s
600-
# State transition:
601-
# None => Yielding or Stopping
602-
# Yielding => Stopping
603-
# Stopping => nan
604-
605-
if prev_relation == "Stopping" and self.relation == "Yielding":
606-
self.relation = "Stopping"
607617

608618
break
609619

620+
610621
if self.relation == "Yielding":
611622
should_brake = True
612623
should_yield = True
@@ -628,11 +639,9 @@ def update(self, state : AllState):
628639
if should_accelerate:
629640
traj = longitudinal_plan(route_with_lookahead, self.acceleration, self.deceleration, self.desired_speed, curr_v)
630641
elif should_brake and not should_yield:
631-
# Stopping: 2.0 < Decel < 8.0
632642
traj = longitudinal_brake(route_with_lookahead, decel, curr_v)
633643
elif should_brake and should_yield:
634-
# Yielding: 0.0 < Decel < 2.0
635-
traj = longitudinal_brake(route_with_lookahead, decel, curr_v)
644+
traj = longitudinal_plan(route_with_lookahead, self.acceleration, self.yield_deceleration, self.yield_speed, curr_v)
636645
else:
637646
traj = longitudinal_plan(route_with_lookahead, 0.0, self.deceleration, self.desired_speed, curr_v)
638647

0 commit comments

Comments
 (0)