PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question tests practical application of kinematics, feedback control, and object-oriented design in a real-time simulation context. It evaluates the ability to implement safety logic, model longitudinal vehicle dynamics, and manage multi-agent state across discrete time steps — skills central to embedded systems and autonomous vehicle software roles.

  • medium
  • Zoox
  • Coding & Algorithms
  • Software Engineer

Lane-Change Safety and Longitudinal Motion Simulation

Company: Zoox

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

Simulate a self-driving car ("Hero") deciding whether it is safe to change lanes, modulating its acceleration when it is not, and stepping the whole scene forward in time using basic longitudinal kinematics. ## Scenario - Hero (our car) drives in the **right lane** of a straight, two-lane, one-way road. There is no other car in the right lane. - Hero wants to execute a lane change into the **left lane**. - Some cars ("entities") are already driving in the left lane. They may block Hero's lane change. - **Only longitudinal (along-the-road) dynamics are modeled.** Lateral motion is abstracted away — a lane change is "allowed" when, looking only at along-the-road positions and speeds, there is a safe gap. Every car's motion state is: ```cpp struct State { double x = 0; // position along the road, in meters (absolute, NOT relative to Hero) double vx = 0; // speed along the road, in m/s double ax = 0; // acceleration along the road, in m/s^2 }; ``` You are given two controller helper functions and must use them (do not invent your own control law): ```cpp // Use this to drive at a target speed. Returns the desired ax to track vx_desired. double velocityController(double vx_current, double vx_desired) { static constexpr double kp = 0.5; vx_current = std::max(vx_current, 0.0); double vx_error = vx_desired - vx_current; return kp * vx_error; } // Use this to fall in behind a leading entity, settling at a target following // distance. current_distance and desired_distance are gaps (meters); vx_relative // is Hero's speed minus the entity's speed (m/s). Returns the desired ax. double fallBehindController(double current_distance, double desired_distance, double vx_relative) { static constexpr double kp_vx = 0.5; static constexpr double kp_ax = 0.2; double vx_relative_desired = kp_vx * (desired_distance - current_distance); double ax_desired = kp_ax * (vx_relative_desired - vx_relative); return -ax_desired; } ``` ## Part 1 — Lane-change feature Implement a class `LaneChangeFeature` exposing two methods plus an accessor. **(a) `void checkLaneChangeAllowedAndPopulateTargets(const State& hero, const std::vector<State>& entities)`** Decide whether changing lanes at the *current* timestep is safe. Hero's policy is: if a car ahead in the target lane is within Hero's safety buffer, Hero slows to fall in behind it and waits for the gap to open; once all entities are clear of the buffer the lane change is committed. Maintain a reasonable **longitudinal safety buffer** around Hero throughout the maneuver. - Treat an entity as **relevant** (i.e. blocking, must be tracked) when its along-the-road position falls within Hero's safety buffer — that is, the entity is currently beside Hero or close enough fore that merging now would violate the buffer. Only entities that are **ahead of or beside Hero** ($x_\text{entity} \geq x_\text{hero}$) need be considered as blocking targets; entities that have already passed Hero are not relevant. - Set the boolean member `lane_change_active_` to `true` when the lane change is safe to commit at this timestep (no relevant entity blocks the buffer), and `false` otherwise. - Populate the member `std::vector<State> relevant_targets_` with the blocking entities, so the acceleration logic can react to them. - Define and document any safety-buffer constant you introduce. A value in the range $[8, 25]$ meters is physically reasonable for highway speeds. **(b) `double calculateAx(const State& hero, double vx_speed_limit)`** Compute Hero's desired longitudinal acceleration for this timestep. - For each relevant target, use `fallBehindController` to get the acceleration that would let Hero settle behind that target at the safety buffer distance. The **gap** passed to the controller is $x_\text{entity} - x_\text{hero}$ (a positive number when the entity is ahead). - Also compute the acceleration from `velocityController` that keeps Hero at the speed limit. - Hero must stay between `vx_speed_limit` and **50% of the speed limit**: clamp the desired behavior so the commanded acceleration does not drive Hero above `vx_speed_limit` or below `0.5 * vx_speed_limit`. - Output the **most conservative** (smallest, i.e. most decelerating / least accelerating) acceleration among these candidates. - When there are no relevant targets, Hero simply tracks the speed limit (subject to the speed bounds). **(c) `bool LaneChangeActive() const`** — returns `lane_change_active_`. ## Part 2 — Simulation Implement the time-stepping loop that advances the whole scene. - Initial conditions: - Hero: `x = 30`, `vx = 15`, `ax = 0` - Entities (left lane): `{x = 35, vx = 18, ax = 0}` and `{x = 90, vx = 20, ax = 0}` - Speed limit: `vx_speed_limit = 20` (constant) - Time: start `t = 0`, end `t_end = 10`, step `dt = 0.1` - On each step: 1. Call `checkLaneChangeAllowedAndPopulateTargets` and `calculateAx` to get Hero's acceleration for this step; assign it to `hero.ax`. 2. Advance every car with the standard constant-acceleration kinematic equations over `dt`: update position from speed (and acceleration) and update speed from acceleration. The **other entities keep `ax == 0`** (constant speed); only Hero accelerates/decelerates. 3. Print the timestamp, all positions, all speeds, Hero's `ax`, and the lane-change flag. 4. If the lane change has become active, print that it was triggered and stop the simulation. ### Required output format Each timestep prints exactly one line in this form (Hero first, then each entity, in order): ``` t <t> x (<hero.x>, <entity0.x>, <entity1.x>) vx (<hero.vx>, <entity0.vx>, <entity1.vx>) ax <hero.ax> lc <0 or 1> ``` When the lane change activates, print on the following line: ``` Lane change triggered! ``` and terminate. ## Constraints & Assumptions - Use only the two provided controllers for acceleration; do not introduce a different control law. - Distances/gaps are computed from absolute `x` positions (positions are *not* stored relative to Hero). For `fallBehindController`, the gap to a leading entity is $x_\text{entity} - x_\text{hero}$ (always positive when the entity is ahead). - Only entities with $x_\text{entity} \geq x_\text{hero}$ are eligible blocking targets; use `fallBehindController` only for such entities. - Floating-point output may be printed with default formatting; exact decimal rendering is not graded, but the sequence of decisions must be correct and the lane change must trigger at an interior simulation step (not at $t = 0$). - The safety buffer is a design choice you must make explicit and document. A buffer in $[8, 25]$ m is acceptable. With the given initial conditions (entity e0 starts only 5 m ahead of Hero), e0 is inside any reasonable buffer at $t = 0$, so the lane change is blocked initially and triggers later as e0 pulls ahead — you should observe the trigger between $t \approx 1$ s and $t \approx 7$ s depending on your buffer choice.

Quick Answer: This question tests practical application of kinematics, feedback control, and object-oriented design in a real-time simulation context. It evaluates the ability to implement safety logic, model longitudinal vehicle dynamics, and manage multi-agent state across discrete time steps — skills central to embedded systems and autonomous vehicle software roles.

Simulate a self-driving car ("Hero") deciding whether it is safe to change lanes from the right into the left lane of a straight, one-way, two-lane road, modulating its longitudinal acceleration when a lane change is blocked and stepping the whole scene forward in time with constant-acceleration kinematics. Only longitudinal (along-the-road) dynamics are modeled. Each car has a state (x position in meters, vx speed in m/s, ax acceleration in m/s^2); positions are absolute, not relative to Hero. You must use the two provided P-controllers (do not invent your own control law): velocityController(vx_current, vx_desired): kp=0.5; clamps vx_current to >=0; returns kp*(vx_desired - vx_current). fallBehindController(current_distance, desired_distance, vx_relative): kp_vx=0.5, kp_ax=0.2; vx_relative_desired = kp_vx*(desired_distance - current_distance); ax_desired = kp_ax*(vx_relative_desired - vx_relative); returns -ax_desired. Here vx_relative is Hero's speed minus the entity's speed, and the gap to a leading entity is x_entity - x_hero (positive when the entity is ahead). Lane-change feature (per timestep): - An entity is RELEVANT (blocking) when it is ahead of or beside Hero (x_entity >= x_hero) AND inside Hero's longitudinal safety buffer (x_entity - x_hero <= safety_buffer). Entities that have passed Hero are ignored. - The lane change is safe to commit (lane_change_active = true) exactly when no relevant entity remains in the buffer. - Desired ax = the MOST CONSERVATIVE (smallest) of: the velocityController output tracking the speed limit, and one fallBehindController output per relevant target (desired_distance = the buffer). Then clamp so the commanded ax never drives Hero above the speed limit or below 50% of it. With no relevant targets, Hero just tracks the speed limit (subject to the bounds). Simulation (Part 2): fixed initial conditions are Hero {x=30, vx=15, ax=0}; entities {x=35, vx=18, ax=0} and {x=90, vx=20, ax=0}; speed limit = 20; t from 0 to t_end=10 in dt=0.1 steps. Each step: compute Hero's ax, advance every car by one dt (entities keep ax=0, so constant speed), and stop once the lane change becomes active. Because the first entity starts only 5 m ahead, it is inside any reasonable buffer at t=0, so the change is blocked initially and triggers later as that entity pulls ahead. The safety buffer is a documented design choice; any value in [8, 25] m is acceptable and the trigger should land at an interior step (roughly t in [1, 7] s depending on the buffer). Implement solution(safety_buffer): run the simulation with the fixed scenario above and the given safety_buffer (meters), returning the time (seconds, rounded to 4 dp) at the START of the step where the lane change first becomes active, or None if it never triggers within [0, t_end).

Constraints

  • Use ONLY the two provided controllers (velocityController, fallBehindController) for acceleration; do not introduce a different control law.
  • Positions are absolute, not relative to Hero; the gap to a leading entity is x_entity - x_hero (positive when ahead).
  • Only entities with x_entity >= x_hero are eligible blocking targets; use fallBehindController only for such entities.
  • An entity is relevant (blocking) iff x_entity >= x_hero and x_entity - x_hero <= safety_buffer.
  • Commanded ax is the smallest (most conservative) candidate, then clamped so Hero's speed stays within [0.5 * speed_limit, speed_limit].
  • safety_buffer is a documented design constant; a value in [8, 25] m is physically reasonable. Entities keep ax = 0 (constant speed); only Hero accelerates.
  • Fixed scenario: Hero {x=30, vx=15}, entities {x=35, vx=18} and {x=90, vx=20}, speed_limit=20, dt=0.1, t_end=10.
  • The lane change must trigger at an interior step (not at t=0); return the trigger time, or None if it never triggers within [0, t_end).

Examples

Input: (10.0,)

Expected Output: 1.4

Explanation: Documented default buffer of 10 m. e0 starts 5 m ahead (inside the buffer) so the change is blocked at t=0; Hero falls behind e0, the gap opens, and at the start of t=1.4 s no entity remains inside the buffer -> lane change triggers.

Input: (8.0,)

Expected Output: 0.9

Explanation: Smallest acceptable buffer (8 m): the 5 m gap to e0 clears sooner, triggering at t=0.9 s.

Input: (15.0,)

Expected Output: 2.2

Explanation: Mid-range buffer (15 m): wider safety margin means Hero waits longer for e0 to pull ahead; triggers at t=2.2 s.

Input: (25.0,)

Expected Output: 3.1

Explanation: Largest acceptable buffer (25 m): the maximal documented margin; triggers at t=3.1 s, still an interior step.

Input: (100.0,)

Expected Output: None

Explanation: Edge case: an unrealistically large 100 m buffer never clears within the 10 s horizon, so no trigger occurs and the simulation returns None.

Hints

  1. Mirror the per-step order from the prompt: first evaluate whether the lane change is safe NOW (which entities are inside the buffer ahead of Hero), then compute ax, then advance the kinematics. The trigger time is the t at the START of the first step where no entity blocks the buffer.
  2. An entity blocks the lane change only when BOTH conditions hold: it is ahead of or beside Hero (x_entity >= x_hero) AND it is within the buffer (x_entity - x_hero <= safety_buffer). The first entity starts 5 m ahead, so it blocks at t=0 for any reasonable buffer.
  3. calculateAx returns min(velocityController(vx, speed_limit), fallBehindController(gap, buffer, vx_rel) for each relevant target). 'Most conservative' means the smallest (most decelerating) value, since a smaller ax keeps Hero further back.
  4. After picking the smallest ax, clamp it so Hero's next speed stays in [0.5 * speed_limit, speed_limit]: if vx + ax*dt would exceed the limit, reduce ax to exactly hit the limit; if it would fall below half the limit, raise ax to hit that floor.
  5. Advance with constant-acceleration kinematics: x += vx*dt + 0.5*ax*dt*dt and vx += ax*dt for Hero; entities just do x += vx*dt because their ax stays 0. Hero falls behind the faster lead car, the gap opens, and the change eventually commits.
Last updated: Jun 24, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Compute Roller Coaster Scores - Zoox (medium)
  • Write Transaction Analytics SQL Queries - Zoox (medium)
  • Write SQL revenue and anomaly queries - Zoox (medium)
  • Can a Car Meet a Truck? - Zoox (hard)
  • Choose fastest way to transfer 2 TB - Zoox (easy)