"""Debug Pure Pursuit logic"""
|
import json
|
from math import pi, hypot, atan2, cos, sin
|
from path_planner import plan_approach_path, compute_path_heading, combine_paths
|
from mower_controller import MowerController
|
|
# Load work path
|
work_path = json.load(open('example_path.json'))
|
mower_start_pos = (work_path[0][0] - 1.5, work_path[0][1] - 1.0)
|
mower_start_heading = pi / 4
|
|
# Generate approach path
|
work_path_heading = compute_path_heading(work_path, 0)
|
approach_path = plan_approach_path(mower_start_pos, mower_start_heading,
|
work_path[0], work_path_heading,
|
method='smooth')
|
|
# Combine paths
|
combined_path, approach_end_idx = combine_paths(approach_path, work_path)
|
|
print(f"Combined path: {len(combined_path)} points")
|
print(f"First 10 points:")
|
for i in range(min(10, len(combined_path))):
|
print(f" {i}: {combined_path[i]}")
|
|
# Initialize controller
|
ctrl = MowerController(combined_path)
|
print(f"\nDensified path: {len(ctrl.path)} points")
|
print(f"First 20 densified points:")
|
for i in range(min(20, len(ctrl.path))):
|
print(f" {i}: {ctrl.path[i]}")
|
|
# Simulate a few steps
|
ctrl.update_gps(pos_xy=mower_start_pos, heading=mower_start_heading)
|
ctrl.stage = ctrl.STAGE_FOLLOW_PATH # Skip goto_start
|
|
print("\n=== Testing Pure Pursuit Logic ===")
|
for step in range(5):
|
result = ctrl.compute_control(timestamp=step * 0.014)
|
x, y = ctrl.pos
|
target_idx = ctrl.current_target_idx if hasattr(ctrl, 'current_target_idx') else -1
|
if target_idx >= 0 and target_idx < len(ctrl.path):
|
tx, ty = ctrl.path[target_idx]
|
target_heading = atan2(ty - y, tx - x)
|
print(f"\nStep {step}:")
|
print(f" Pos: ({x:.3f}, {y:.3f}), heading: {ctrl.heading:.3f}")
|
print(f" Target idx: {target_idx}, target: ({tx:.3f}, {ty:.3f})")
|
print(f" Target heading: {target_heading:.3f}")
|
print(f" Command: forward={result['forward']}, turn={result['turn']}")
|
|
# Simulate motion (simplified kinematic model)
|
dt = 0.014
|
forward_mps = result['forward'] / 100.0 * ctrl.max_forward_mps
|
yawrate = result['turn'] / 100.0 * ctrl.max_yawrate
|
|
# Update heading
|
new_heading = ctrl.heading + yawrate * dt
|
|
# Update position
|
vx = forward_mps * cos(new_heading)
|
vy = forward_mps * sin(new_heading)
|
new_x = x + vx * dt
|
new_y = y + vy * dt
|
|
ctrl.update_gps(pos_xy=(new_x, new_y), heading=new_heading)
|