liaofang
2026-08-14 222185cb9f03ea8c8ab8992aaa264c7683eaf39c
refactor(camera): 优化地图相机控制逻辑及移除调试组件引用

- 注释掉调试面板 DebugOrderSimulatorPanel 的导入与使用,防止线上干扰
- 新增 userLocation 支持,优先使用最新用户定位,降低定位误差
- 完善 map-camera 中的性能日志,增加关键流程的调用记录
- 调整车辆到达上车点意图逻辑,改为准确聚焦上车点并居中可视区域
- 移除不再使用的 userLocation 旧值及 fit(includePoints)方案,改用 focus 聚焦
- 细化相机位置计算时的回退策略与日志,提升调试效率与稳定性
4个文件已修改
49 ■■■■■ 已修改文件
src/robotaxi/pages/begin-route/hooks/camera/map-camera.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/camera/policies/pickup.policy.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/camera/use-map-camera-controller.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/camera/map-camera.ts
@@ -179,7 +179,7 @@
    const isAuto = options?.isAuto ?? true;
    const signature = options?.signature ?? '';
    const paddingInput = options?.padding;
    // mapPerfLog('focus:request', { point, isAuto, signature });
    mapPerfLog('focus:request', { point, isAuto, signature });
    this.enqueue({
      kind: 'focus',
      isAuto,
@@ -187,15 +187,16 @@
      points: [point],
      // 执行时才解析 padding 并换算纵向偏移,保证用的是执行那一刻的卡片高度/缩放
      run: () =>
        this.resolveFocusCenter(point, paddingInput).then((center) =>
          this.runNative((done) => {
        this.resolveFocusCenter(point, paddingInput).then((center) => {
          mapPerfLog('focus:exec', { point, center });
          return this.runNative((done) => {
            this.getCtx().moveToLocation({
              latitude: center.latitude,
              longitude: center.longitude,
              complete: done,
            } as any);
          })
        ),
          });
        }),
    });
  }
@@ -214,6 +215,7 @@
        const [top, , bottom] = padding;
        const offsetPx = (Number(bottom) - Number(top)) / 2;
        if (!Number.isFinite(offsetPx) || offsetPx === 0) {
          mapPerfLog('focus:fallback', { reason: 'zero-offset', offsetPx, padding });
          return point;
        }
        return Promise.all([this.getRegionSafe(), this.getMapHeightPx()]).then(
@@ -221,6 +223,7 @@
            const latSpan =
              (region?.northeast?.latitude ?? NaN) - (region?.southwest?.latitude ?? NaN);
            if (!Number.isFinite(latSpan) || latSpan <= 0 || !heightPx) {
              mapPerfLog('focus:fallback', { reason: 'region-or-height-invalid', latSpan, heightPx });
              return point;
            }
            const degPerPx = latSpan / heightPx;
@@ -228,7 +231,7 @@
              latitude: point.latitude - offsetPx * degPerPx,
              longitude: point.longitude,
            };
            // mapPerfLog('focus:visible-center', { point, center, offsetPx });
            mapPerfLog('focus:visible-center', { point, center, offsetPx, latSpan, heightPx, degPerPx });
            return center;
          }
        );
@@ -342,7 +345,7 @@
  private enqueue(cmd: InternalCommand): void {
    // 避让窗口内忽略自动意图
    if (cmd.isAuto && this.isHolding()) {
      // mapPerfLog('skip:hold', { kind: cmd.kind, signature: cmd.signature, points: cmd.points });
      mapPerfLog('skip:hold', { kind: cmd.kind, signature: cmd.signature, points: cmd.points });
      return;
    }
    // 自动意图去重(fit/focus):相同签名且已应用/在途/排队则跳过(用户显式意图不去重)
@@ -352,7 +355,7 @@
        cmd.signature === this.lastAppliedSignature ||
        this.queue.some((q) => q.signature === cmd.signature);
      if (duplicate) {
        // mapPerfLog('skip:dedup', { signature: cmd.signature, points: cmd.points });
        mapPerfLog('skip:dedup', { signature: cmd.signature, points: cmd.points });
        return;
      }
    }
src/robotaxi/pages/begin-route/hooks/camera/policies/pickup.policy.ts
@@ -47,31 +47,21 @@
};
/**
 * 车辆已到(VehicleArrivedPickup) 意图:focus 上车点(车已到,二者接近),
 * centerInVisibleArea 居中到扣除底部卡片后的可视区域。
 *
 * 不使用 fit(includePoints):
 * 1. 不使用 userLocation——到达上车点时用户定位仍是页面进入时的旧值,会把视口撑歪
 *    (与 arrivedDestinationPolicy 同理);
 * 2. 车+用户+上车点三点极近时 includePoints 不理会不对称 padding,会把点放到
 *    整张地图几何中心(视觉上贴近底部卡片),与 callingPolicy 注释同理。
 * 改用 focus + centerInVisibleArea:与 callingPolicy 一致,精确居中到可视区域。
 * 车辆已到(VehicleArrivedPickup) 意图:focus 上车点,centerInVisibleArea 居中到
 * 扣除底部卡片后的可视区域。车已到上车点,二者接近,直接居中上车点即可。
 */
const buildArrivedPickupIntent = (ctx: CameraContext, stable: boolean): CameraIntent => {
  const vehicleRaw = siteToPoint(ctx.vehicleLocation);
  const pickup = siteToPoint(ctx.startSite);
  const car = vehicleRaw || pickup; // 车辆坐标校验,缺失用上车点兜底
  mapPerfLog('policy:arrived-pickup-points', {
    stable,
    car: { got: !!vehicleRaw, usedPickupFallback: !vehicleRaw && !!pickup, point: car },
    pickup: { got: !!pickup, point: pickup },
  });
  if (!car) {
  if (!pickup) {
    return NO_CAMERA_INTENT;
  }
  return {
    type: 'focus',
    point: car,
    point: pickup,
    centerInVisibleArea: true,
    signature: stable ? 'arrived-pickup' : undefined,
  };
src/robotaxi/pages/begin-route/hooks/camera/use-map-camera-controller.ts
@@ -29,6 +29,8 @@
  walkingPoints: LatLng[];
  /** 车辆当前位置(接驾/行程态 fit 用)。 */
  vehicleLocation: LatLng | null;
  /** 最新用户定位(接驾态 fit 用,由外部刷新传入;为空时回退首帧定位值)。 */
  userLocation?: LatLng | null;
  /** includePoints 留白(按底部卡片/安全区算好;支持异步,即 fit 执行前即时测量)。 */
  getPadding?: () => CameraPadding | Promise<CameraPadding>;
  /**
@@ -95,7 +97,7 @@
      endSite: d.endSite,
      routePoints: d.routePoints || [],
      walkingPoints: d.walkingPoints || [],
      userLocation: userLocationRef.current,
      userLocation: d.userLocation ?? userLocationRef.current,
      vehicleLocation: d.vehicleLocation ?? null,
    };
  }, []);
@@ -180,6 +182,7 @@
    params.routePoints,
    params.walkingPoints,
    params.vehicleLocation,
    params.userLocation,
    getPolicy,
    executeIntent,
    buildContext,
src/robotaxi/pages/begin-route/index.tsx
@@ -10,7 +10,7 @@
import PickupExceptionPopup from './components/pickup-exception-popup';
import CreditPayPopup from './components/credit-pay-popup';
// 调试面板:模拟完整行程流转(仅 dev 构建可见)
import DebugOrderSimulatorPanel from './components/debug-order-simulator-panel';
// import DebugOrderSimulatorPanel from './components/debug-order-simulator-panel';
// 转场动效调试面板:呼叫中→派单成功、送驾中→行程结束(仅 dev 构建可见)
// import DebugTransitionPanel from './components/debug-transition-panel';
// 到达结束态全屏礼花动效
@@ -1051,6 +1051,7 @@
    routePoints,
    walkingPoints,
    vehicleLocation,
    userLocation: currentUserLocation,
    getPadding: cameraGetPadding,
    getFocusPadding: cameraGetFocusPadding,
    onLocated: () => setMapLoading(false),
@@ -2684,7 +2685,7 @@
        bindSocketListeners={bindSocketListeners}
      /> */}
      {/* 模拟器入口已关闭,如需本地调试可取消下方注释 */}
      <DebugOrderSimulatorPanel
      {/* <DebugOrderSimulatorPanel
        orderId={orderId}
        setOrderId={setOrderId}
        setTripStatus={setTripStatus}
@@ -2695,7 +2696,7 @@
        setShowCancelPopup={setShowCancelPopup}
        setShowModifyDestinationFailPopup={setShowModifyDestinationFailPopup}
        setModifyDestinationFailMessage={setModifyDestinationFailMessage}
      />
      /> */}
    </>
  )