#15808·apollo

Ego stops inside the intersection during emergency pull over

Author: RomainLettuceCreated Jul 20, 2026Updated Jul 20, 2026

System Info

Apollo side

  • OS: Ubuntu 20.04.1 LTS
  • GPU: NVIDIA GeForce RTX 2080 Ti
  • Apollo version: 7.0, with a self-patched modification to the Pull Over feature (fixes an issue where the vehicle fails to merge into the rightmost lane and instead stops in the current lane)
  • Modules enabled: Localization, Perception, Transform, Routing, Prediction, Planning, Traffic Light, Control, Recorder
  • Prediction module modification: Perception input replaced with 3D ground truth (gt_perception)
  • Map: SanFrancisco_correct, with a correction applied to several lanes whose width was incorrectly set to 3.5m instead of the standard 3.7m

Simulator side

Bug Description

When the Ego vehicle triggers an EMERGENCY_PULL_OVER scenario near an intersection, it stops inside the intersection itself. In the attached video, the blue rectangle (pull_over_destination) can be seen being generated inside the intersection.

We want to note that this is unrelated to our self-patched modification to the Pull Over lane-selection logic mentioned in System Info above.

To Reproduce

Our Scenario

  • Ego initial pose: (-389.9, 10.2, 372.53)
  • Ego goal pose: (-442.9, 10.2, 423.3)
  • NPC initial pose: (519.80475126, 10.2, 565.26462672)
  • NPC maneuver: Stops

The NPC's position does not appear to matter; this occurs whenever EMERGENCY_PULL_OVER is triggered while the Ego vehicle is near an intersection.

Video and rosbag are attached below.

Expected Behavior

The pull-over destination should be generated past the intersection, and the Ego vehicle should stop there instead of inside the intersection.

Suspected Root Cause

(Note: given the complexity of ADS planning logic, this may not be the sole factor. We are sharing our analysis in case it is useful, but a full fix likely requires closer review from maintainers familiar with this code path.)

https://github.com/ApolloAuto/apollo/blob/463fb82f9e979d02dcb25044e60931293ab2dba0/modules/planning/tasks/deciders/path_bounds_decider/path_bounds_decider.cc#L728-L734

In modules/planning/tasks/deciders/path_bounds_decider/path_bounds_decider.cc (SearchPullOverPosition, lines 728-734), when checking whether a candidate pull-over point falls inside a PNC junction, GetJunctions is called with a hardcoded search radius of 1.0 (meter):

std::vector<std::shared_ptr<const JunctionInfo>> junctions;
HDMapUtil::BaseMap().GetJunctions(hdmap_point, 1.0, &junctions);
if (!junctions.empty()) {
  AWARN << "Point is in PNC-junction.";
  idx = search_backward ? idx - 1 : idx + 1;
  continue;
}

We experimented with this radius and found that 1m is far too small to reliably detect that a candidate point is within a junction; in our tests, a radius on the order of ten-plus meters was needed before the check would consistently recognize the point as being inside the junction. With the current 1m radius, a candidate point that is clearly inside the intersection can still fail to match any nearby JunctionInfo, so the check passes and the point gets accepted as a valid pull-over location.

Suggested Fix Direction

The straightforward fix is to increase this search radius to a more appropriate value. That said, we have not tested what radius would be both sufficiently reliable and general across different junction sizes/shapes, so this may need to be tuned rather than treated as a fixed constant.