MCPcopy Create free account
hub / github.com/botbotrobotics/BotBrain / projectPathPoint

Function projectPathPoint

frontend/src/utils/waypointProjection.ts:192–263  ·  view source on GitHub ↗
(
  point: { x: number; y: number },
  robotPose: { x: number; y: number; theta: number },
  canvasWidth: number,
  canvasHeight: number,
  config: CameraConfig
)

Source from the content-addressed store, hash-verified

190 * the ground/road perspective - closer points at bottom, farther at middle.
191 */
192export function projectPathPoint(
193 point: { x: number; y: number },
194 robotPose: { x: number; y: number; theta: number },
195 canvasWidth: number,
196 canvasHeight: number,
197 config: CameraConfig
198): ProjectedPathPoint {
199 // Calculate vector from robot to point
200 const dx = point.x - robotPose.x;
201 const dy = point.y - robotPose.y;
202 const distance = Math.sqrt(dx * dx + dy * dy);
203
204 // Get bearing angle from robot to point in map frame
205 const pointBearing = Math.atan2(dy, dx);
206
207 // Calculate relative bearing based on camera facing direction
208 let robotHeading = robotPose.theta;
209 if (!config.isFrontFacing) {
210 // For back camera, flip the robot heading by 180 degrees
211 robotHeading = normalizeAngle(robotHeading + Math.PI);
212 }
213
214 const relativeBearing = normalizeAngle(pointBearing - robotHeading);
215
216 // Determine if point is in front (within +/- 90 degrees of camera direction)
217 const isInFront = Math.abs(relativeBearing) < Math.PI / 2;
218
219 // Determine if point is within camera FOV
220 const halfFov = config.horizontalFov / 2;
221 const isInView = Math.abs(relativeBearing) <= halfFov;
222
223 // Calculate screen X position
224 const centerX = canvasWidth / 2;
225 let screenX: number;
226
227 if (isInView) {
228 // Linear mapping within FOV (negate bearing for correct screen mapping)
229 screenX = centerX - (relativeBearing / halfFov) * (canvasWidth / 2);
230 } else {
231 // Clamp to edge for off-screen points
232 screenX = relativeBearing > 0 ? 0 : canvasWidth;
233 }
234
235 // Calculate screen Y position based on distance
236 // Path should appear on the ground level - closer points near bottom, farther toward horizon
237 // Using a more limited range focused on the lower-middle portion of the screen
238 const minDistance = 0.5;
239 const maxDistance = 8; // Reduced from 20m - only show nearby path
240 const clampedDistance = Math.max(minDistance, Math.min(maxDistance, distance));
241
242 // Use exponential mapping for more natural perspective (closer points spread out more)
243 const normalizedDistance = (clampedDistance - minDistance) / (maxDistance - minDistance);
244 const perspectiveDistance = Math.pow(normalizedDistance, 0.7); // Exponential for better depth
245
246 // Position path in lower-center area: close = 90% height, far = 55% height (horizon line)
247 const minY = canvasHeight * 0.55; // Horizon line (farther points)
248 const maxY = canvasHeight * 0.92; // Near bottom (closer points)
249 const screenY = maxY - perspectiveDistance * (maxY - minY);

Callers

nothing calls this directly

Calls 2

calculatePathWidthFunction · 0.85
normalizeAngleFunction · 0.70

Tested by

no test coverage detected