Skip to content

Commit 8055e27

Browse files
committed
add changes from control group
1 parent e6d0497 commit 8055e27

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

GEMstack/onboard/planning/stanley.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,111 @@ def _find_front_axle_position(self, x, y, yaw):
151151
fy = y + self.wheelbase * sin(yaw)
152152
return fx, fy
153153

154+
def _find_rear_axle_position(self, x, y, yaw):
155+
"""Compute rear-axle world position from the vehicle's reference point and yaw."""
156+
rx = x - self.wheelbase * cos(yaw)
157+
ry = y - self.wheelbase * sin(yaw)
158+
return rx, ry
159+
160+
def initialize_state_and_direction(self, state: VehicleState):
161+
# Initializes the controller's state and determines initial driving direction (forward/reverse).
162+
if self.path is None:
163+
raise ValueError("Stanley: Path must be set before initializing state and direction.")
164+
curr_x = state.pose.x
165+
curr_y = state.pose.y
166+
curr_yaw = state.pose.yaw if state.pose.yaw is not None else 0.0
167+
fx, fy = self._find_front_axle_position(curr_x, curr_y, curr_yaw)
168+
path_domain_start, path_domain_end = self.path.domain()
169+
search_end = min(path_domain_end, path_domain_start + 5.0)
170+
search_domain_start = [path_domain_start, search_end]
171+
_, closest_param_at_start = self.path.closest_point_local((fx, fy), search_domain_start)
172+
tangent_at_start = self.path.eval_tangent(closest_param_at_start)
173+
initial_reverse = False
174+
if np.linalg.norm(tangent_at_start) > 1e-6:
175+
path_yaw_at_start = atan2(tangent_at_start[1], tangent_at_start[0])
176+
heading_diff = normalise_angle(path_yaw_at_start - curr_yaw)
177+
initial_reverse = abs(heading_diff) > (np.pi / 2.0)
178+
self.pid_speed.reset()
179+
self.current_path_parameter = closest_param_at_start
180+
if self.trajectory:
181+
self.current_traj_parameter = self.trajectory.domain()[0]
182+
return initial_reverse
183+
184+
def is_target_behind_vehicle(self, vehicle_pose, target_point_coords):
185+
"""Checks if a target point is behind the vehicle."""
186+
curr_x = vehicle_pose.x
187+
curr_y = vehicle_pose.y
188+
curr_yaw = vehicle_pose.yaw
189+
if curr_yaw is None:
190+
return False
191+
target_x = target_point_coords[0]
192+
target_y = target_point_coords[1]
193+
vec_x = target_x - curr_x
194+
vec_y = target_y - curr_y
195+
if abs(vec_x) < 1e-6 and abs(vec_y) < 1e-6:
196+
return False
197+
heading_x = cos(curr_yaw)
198+
heading_y = sin(curr_yaw)
199+
dot_product = vec_x * heading_x + vec_y * heading_y
200+
return (dot_product < 0)
201+
202+
def _check_sharp_turn_ahead(self, lookahead_s=3.0, threshold_angle=np.pi/2.0, num_steps=4):
203+
"""Checks for sharp turns within a lookahead distance on the path."""
204+
if not self.path:
205+
return False
206+
207+
path = self.path
208+
current_s = self.current_path_parameter
209+
domain_start, domain_end = path.domain()
210+
211+
if current_s >= domain_end - 1e-3:
212+
return False
213+
214+
step_s = lookahead_s / num_steps
215+
s_prev = current_s
216+
217+
try:
218+
tangent_prev = path.eval_tangent(s_prev)
219+
if np.linalg.norm(tangent_prev) < 1e-6:
220+
s_prev_adjusted = min(s_prev + step_s / 2, domain_end)
221+
if s_prev_adjusted <= s_prev:
222+
return False
223+
tangent_prev = path.eval_tangent(s_prev_adjusted)
224+
if np.linalg.norm(tangent_prev) < 1e-6:
225+
return False
226+
s_prev = s_prev_adjusted
227+
228+
angle_prev = atan2(tangent_prev[1], tangent_prev[0])
229+
230+
except Exception as e:
231+
return False
232+
233+
for i in range(num_steps):
234+
s_next = s_prev + step_s
235+
s_next = min(s_next, domain_end)
236+
237+
if s_next <= s_prev + 1e-6:
238+
break
239+
240+
try:
241+
tangent_next = path.eval_tangent(s_next)
242+
if np.linalg.norm(tangent_next) < 1e-6:
243+
s_prev = s_next
244+
continue
245+
246+
angle_next = atan2(tangent_next[1], tangent_next[0])
247+
except Exception as e:
248+
break
249+
250+
angle_change = abs(normalise_angle(angle_next - angle_prev))
251+
252+
if angle_change > threshold_angle:
253+
return True
254+
255+
angle_prev = angle_next
256+
s_prev = s_next
257+
return False
258+
154259
def compute(self, state: VehicleState, component: Component = None):
155260
"""Compute the control outputs: (longitudinal acceleration, front wheel angle)."""
156261
t = state.pose.t

0 commit comments

Comments
 (0)