Keyframes
Question
In this video clip, how is the character's location moving in the 3D scene relative to his/her/its starting orientation and location? This is a multiple-choice question about how an object or the camera moves in 3D space within the video clip. Choose the option that best matches the motion you observe and respond with only the option letter (A, B, C, or D). A. Moving backward B. Moving forward C. Moving right D. Moving left
Ground truth A
SpatialClaw A
Agent wins

No-tool Baseline

✗ Incorrect

To determine the character's movement in the 3D scene, let's analyze the sequence of images:

  1. Initial Position: In the first few frames, the character is a small figure located in the distance, centered in the frame.
  2. Observation of Motion: As the sequence progresses (from frame 1 through frame 18), the character's size increases relative to the frame. In visual perspective, an object that increases in size while remaining centrally located typically indicates it is moving closer to the viewer (the camera).
  3. Relative Orientation: The character is facing the camera from the beginning. Since the character is moving towards the camera, it is moving in the direction it is facing.
  4. Conclusion: Moving in the direction one is facing is defined as moving forward.

Therefore, the character is moving forward relative to its starting orientation and location.

B

Single-pass code

✗ Incorrect
Purpose
Analyze the 3D motion of the character relative to its starting orientation.
Reasoning
1. I will segment the character across the video to track its position. 2. I will reconstruct the 3D scene to get world coordinates and camera poses. 3. I will use a BEV (Bird's Eye View) plot to visualize the trajectories of both the camera and the character. 4. By comparing the character's 3D trajectory with its starting orientation (facing the camera), I can determine if it is moving forward, backward, left, or right.
Next Goal
Segment the character, reconstruct the scene, and visualize the trajectories in BEV.
Code
import numpy as np

# 1. Segment the character across the video
# The character looks like a small brown monkey/creature.
seg = tools.SAM3.segment_video_by_text(prompts=["monkey"], labels=["monkey"])

# 2. Reconstruct the 3D scene
# Use a subset of frames for reconstruction to stay within limits and maintain quality.
recon = tools.Reconstruct.Reconstruct(InputImages)

# 3. Render BEV to see trajectories
# We'll use the masks from SAM3.
bev_vis = recon.render_bev(masks=seg, ego_trajectory=True)
show(bev_vis)

# 4. Quantitatively analyze the motion
# Get the 3D centroids for the first and last frames where the character is present.
frame_indices = seg.frame_indices
first_fi = frame_indices[0]
last_fi = frame_indices[-1]

c_start = seg.get_centroid_3d(recon, frame=first_fi, object=0)
c_end = seg.get_centroid_3d(recon, frame=last_fi, object=0)

print(f"Start centroid: {c_start}")
print(f"End centroid: {c_end}")

# The character is facing the camera at the start.
# Camera pose at start:
pose_start = recon.extrinsics[first_fi]
cam_pos_start = pose_start[:3, 3]
cam_fwd_start = pose_start[:3, 2] # Forward direction of camera

# Vector of character motion in world space
motion_vec = c_end - c_start

# The character is facing the camera, so its "forward" is opposite to the camera's forward.
char_fwd_start = -cam_fwd_start

# Projection of motion onto character's forward vector
dot_fwd = np.dot(motion_vec, char_fwd_start)
print(f"Dot product with character forward: {dot_fwd}")

# Projection of motion onto character's right vector
# Camera right is the same as character's left (since they face each other)
cam_right_start = pose_start[:3, 0]
char_right_start = -cam_right_start
dot_right = np.dot(motion_vec, char_right_start)
print(f"Dot product with character right: {dot_right}")

if dot_fwd > 0.1:
    ans = "B" # Forward
elif dot_fwd < -0.1:
    ans = "A" # Backward
elif dot_right > 0.1:
    ans = "C" # Right
elif dot_right < -0.1:
    ans = "D" # Left
else:
    ans = "B" # Default to forward if motion is small but visual suggests it

ReturnAnswer(ans)
Output
 [image: show_0001] 
[WARNING] get_centroid_3d: mask for 'monkey' at frame 0 is empty — returning [nan, nan, nan]
Error
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[4], line 23
     20 last_fi = frame_indices[-1]
     22 c_start = seg.get_centroid_3d(recon, frame=first_fi, object=0)
---> 23 c_end = seg.get_centroid_3d(recon, frame=last_fi, object=0)
     25 print(f"Start centroid: {c_start}")
     26 print(f"End centroid: {c_end}")

File SpatialAgent/spatial_agent/kernel_types/per_frame_types.py:203, in PerFrameMask.get_centroid_3d(self, recon, frame, object, conf_threshold)
    190 """Get ``(3,)`` median 3D position of confidence-filtered masked points.
    191 
    192 Args:
   (...)    200     is empty (safe for arithmetic; use ``np.isnan()`` to check).
    201 """
    202 mask_2d = self.get_mask(frame, object)
--> 203 local_r = recon.points.get_by_frame_index(frame)
    204 pts = recon.points.points[local_r][mask_2d]
    205 if len(pts) == 0:

File SpatialAgent/spatial_agent/kernel_types/per_frame_types.py:69, in PerFrameData.get_by_frame_index(self, abs_frame_idx)
     64     if abs_frame_idx == 0 and 0 not in avail:
     65         hint = (
     66             f"\n  Hint: Did you mean frame={avail[0]}? "
     67             f"Use ABSOLUTE frame indices (from seg.frame_indices), not 0-based local indices."
     68         )
---> 69     raise KeyError(
     70         f"Frame {abs_frame_idx} not found in {avail}. "
     71         f"Available frames: {avail}{hint}"
     72     )
     73 return self._frame_indices.index(abs_frame_idx)

KeyError: 'Frame 71 not found in [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]. Available frames: [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]'
show_0001
Final answer
B

Structured tool-call

✗ Incorrect
Plan

Task Analysis The objective is to determine the 3D movement of a character relative to their own starting orientation and location. This is an object-perspective motion problem. I need to identify the character, track their 3D position over time, determine their initial facing direction (forward vector), and then project their total displacement vector onto this local coordinate system.

  • Target Variable: Direction of 3D displacement (Forward, Backward, Left, Right).
  • Coordinate System: Object-relative (Local) 3D space. The origin is the character's starting position, and the axes are defined by the character's starting orientation.
  • Answer Format: Multiple choice (A, B, C, or D).

Information Needs

  1. Character Identification: Which object in the scene is the "character"?
  2. 3D Trajectory: A sequence of 3D world coordinates for the character's center of mass across the clip.
  3. Starting Orientation: The world-space vector representing the direction the character is facing at the first frame.
  4. Displacement Vector: The vector from the character's starting 3D position to their ending 3D position.

Computation Plan

  1. Character Identification and Segmentation:

    • Use show(InputImages[0]) and vlm.ask_with_thinking(InputImages[0], "Identify the main character in this image. Describe their appearance.") to confirm the target.
    • Use tools.SAM3.segment_video_by_text(prompts=["character"], labels=["character"]) to track the character across all frames.
    • Verify the segmentation quality by calling show(seg.visualize(fi)) for the first, middle, and last frames of the sequence.
  2. 3D Scene Reconstruction:

    • Call recon = tools.Reconstruct.Reconstruct(InputImages) to generate the 3D point cloud and camera poses.
  3. Trajectory Extraction:

    • For every frame index fi in seg.frame_indices, compute the 3D centroid: pos = seg.get_centroid_3d(recon, frame=fi, object='character').
    • Store these as a list of coordinates trajectory_3d.
  4. Orientation Grounding:

    • Use vlm.ask_with_thinking(InputImages[0], "In the first frame, which direction is the character facing? Describe it relative to the camera (e.g., facing away from camera, facing left, etc.).").
    • Convert this qualitative direction into a world-space vector char_fwd.
      • Method: Get the camera pose at frame 0 (pose = recon.extrinsics[InputImages.frame_indices[0]]). Use cam_fwd = pose[:3, 2] and cam_right = pose[:3, 0]. If the VLM says "facing away", char_fwd is roughly cam_fwd. If "facing right", char_fwd is roughly cam_right.
    • Define the local right vector char_right as the cross product of the world-up vector [0, 1, 0] and char_fwd (or simply orthogonal to char_fwd in the ground plane).
  5. Motion Analysis:

    • Calculate the total displacement vector: motion_vec = trajectory_3d[-1] - trajectory_3d[0].
    • Compute the projection of motion_vec onto the local axes:
      • dot_fwd = np.dot(motion_vec, char_fwd)
      • dot_right = np.dot(motion_vec, char_right)
    • Classification:
      • If dot_fwd is the dominant component and positive $\rightarrow$ Moving forward (B).
      • If dot_fwd is the dominant component and negative $\rightarrow$ Moving backward (A).
      • If dot_right is the dominant component and positive $\rightarrow$ Moving right (C).
      • If dot_right is the dominant component and negative $\rightarrow$ Moving left (D).
  6. Visual Cross-Validation:

    • Render a BEV plot: recon.render_bev(masks=seg).
    • Inspect the trajectory line (red $\rightarrow$ blue) and compare its direction with the character's initial facing direction observed in the first frame.

Verification Checklist

CHECKLIST

[
  {"priority": "HIGH", "description": "Verify that the SAM3 masks accurately track the character throughout the video without drifting to other objects."},
  {"priority": "HIGH", "description": "Confirm the starting orientation vector (char_fwd) correctly reflects the character's facing direction in the first frame."},
  {"priority": "MEDIUM", "description": "Check for 3D centroid stability; ensure no sudden jumps in trajectory_3d that would skew the displacement vector."},
  {"priority": "MEDIUM", "description": "Cross-reference the quantitative dot-product result with the qualitative trajectory seen in the BEV render."}
]

Fallbacks

  • Segmentation Failure: If segment_video_by_text fails to produce masks, use vlm.locate on the first frame to get a bounding box and use tools.SAM3.segment_video_by_box.
  • Reconstruction Noise: If the 3D centroids are too noisy, use vlm.ask_with_thinking on a sequence of frames (e.g., first, middle, last) to describe the character's movement relative to the environment (e.g., "The character starts at the door and walk
Step 0
LLM · Tool Call
Purpose
Identify the main character in the scene to ensure correct segmentation.
Reasoning
Before performing video segmentation, I need to confirm what the "character" is. Looking at the provided key frames, there is a small, brownish, humanoid/animal-like figure in the center of the scene. I will use the VLM to describe this character to ensure I have a clear target for the `segment_video_by_text` tool.
Next Goal
Segment the character across the entire video.
Tool Call
{
  "tool": "vlm.ask_with_thinking",
  "args": {
    "visual_input": "InputImages[0]",
    "question": "Identify the main character in this image. Describe their appearance."
  }
}
Execute
Output
[VLM Q | thinking] Identify the main character in this image. Describe their appearance.
[VLM A | thinking] The main character is a small figure standing in the distance in the center of the image. They appear to be wearing olive green or brown tactical/military-style clothing, though specific details are not visible due to the distance.
Step 1
LLM · Tool Call
Purpose
Segment and track the character across all frames of the video.
Reasoning
To determine the 3D movement, I first need precise segmentation masks for the character in every frame. I'll use `segment_video_by_text` with the label "character", as the VLM confirmed there is one main character in the scene.
Next Goal
Verify the segmentation quality and reconstruct the 3D scene.
Tool Call
{
  "tool": "tools.SAM3.segment_video_by_text",
  "args": {
    "prompts": [
      "character"
    ],
    "labels": [
      "character"
    ]
  }
}
Step 2
LLM · Tool Call
Purpose
Verify the quality of the character segmentation masks.
Reasoning
Before proceeding to 3D reconstruction and trajectory analysis, I must ensure that the masks correctly track the character without drifting or becoming empty. I will visualize the masks on the first, middle, and last frames and compare them to the original images.
Next Goal
Reconstruct the 3D scene to obtain 3D coordinates and camera poses.
Tool Call
{
  "tool": "show",
  "args": {
    "image": [
      "InputImages[0]",
      "result_1.visualize(0)",
      "InputImages[7]",
      "result_1.visualize(36)",
      "InputImages[14]",
      "result_1.visualize(71)"
    ]
  }
}
Execute
Output
 [image: show_0001] 
show_0001
Step 3
LLM · Tool Call
**Purpose**: Reconstruct the 3D scene to enable 3D trajectory analysis. **Reasoning**: To calculate the movement of the character in 3D space, I need a reconstructed point cloud and camera poses. I will use the `InputImages` to create this reconstruction. **Next Goal**: Extract the 3D trajectory of the character and determine their starting orientation. **Tool Call (translated)**: ```python result_3 = tools.Reconstruct.Reconstruct(InputImages) ```
Step 4
LLM · Tool Call
Purpose
Reconstruct the 3D scene to obtain metric spatial data and camera poses.
Reasoning
To analyze the character's movement in 3D world space, I need a reconstruction that provides depth maps and camera extrinsics. I will use all available key frames in `InputImages` (15 frames) for the reconstruction.
Next Goal
Extract the 3D trajectory of the character using the reconstructed point cloud and segmentation masks.
Tool Call
{
  "tool": "tools.Reconstruct.Reconstruct",
  "args": {
    "frames": "InputImages"
  }
}
Step 5
LLM · Tool Call
**Purpose**: Visualize the character's 3D trajectory from a top-down perspective. **Reasoning**: A Bird's-Eye View (BEV) rendering will show the character's path in world space, with the trajectory color-coded from red (start) to blue (end). This provides a direct visual of the displacement and direction of motion, which I can then compare with the character's starting orientation. **Next Goal**: Determine the character's starting orientation in the first frame. **Tool Call (translated)**: ```python result_5 = result_4.render_bev(masks=result_1) ```
Step 6
LLM · Tool Call
Purpose
Visualize the character's 3D trajectory from a top-down perspective.
Reasoning
A BEV (Bird's Eye View) plot will show the character's movement path (red to blue) relative to the scene. This provides a strong qualitative baseline for the direction of motion before I perform precise vector calculations.
Next Goal
Determine the character's starting orientation to define the local coordinate system.
Tool Call
{
  "tool": "show",
  "args": {
    "image": "result_4.render_bev(masks=result_1)"
  }
}
Execute
Output
 [image: show_0002] 
show_0002
Step 7
LLM · Tool Call
**Purpose**: Determine the character's starting orientation and overall movement relative to the camera. **Reasoning**: The BEV plot failed to show the character's trajectory, likely due to a mask/reconstruction alignment issue. However, visual inspection of the key frames shows the character getting larger over time, indicating they are moving toward the camera. To answer the question "relative to his/her/its starting orientation", I need to confirm which way the character was facing in the first frame. If they were facing the camera and moved toward it, the motion is "Forward". **Next Goal**: Confirm the character's starting orientation using the VLM. **Tool Call (translated)**: ```python result_7 = vlm.ask_with_thinking(visual_input=InputImages[0], question='In the first frame, which direction is the character facing? Are they facing toward the camera, away from the camera, or to the side?') ```
Step 8
LLM · Tool Call
Purpose
Determine the character's 3D movement relative to their starting orientation.
Reasoning
1. **Analyze Camera Motion**: The BEV plot (`result_6`) shows the camera trajectory (green $\rightarrow$ yellow dashed line). The camera starts at Camera 0 (red triangle, top of the plot) and moves toward the bottom of the plot. The Y-axis is labeled "FORWARD (away from camera)" at the top and "BEHIND (toward camera)" at the bottom. Thus, the camera is moving backward relative to its initial orientation. 2. **Analyze Character Motion**: In the key frames, the character remains roughly in the center of the frame but becomes visibly larger from frame 0 to frame 14. This indicates that the distance between the camera and the character is decreasing. Since the camera is moving backward (downward in the BEV), the character must also be moving in that same general direction (downward in the BEV) and at a higher speed to close the gap. 3. **Determine Character Orientation**: In the images (especially the later frames like `InputImages[14]`), the character is clearly facing the camera. 4. **Relative Motion**: The character is facing the camera (which corresponds to the "downward" direction in the BEV) and is moving toward the camera (also the "downward" direction in the BEV). Moving in the direction one is facing is defined as moving forward. Therefore, the character is moving forward relative to their starting orientation.
Next Goal
Return the final answer.
Tool Call
{
  "tool": "ReturnAnswer",
  "args": {
    "answer": "B"
  }
}
Execute
Output
[ReturnAnswer] Answer submitted: B
Answer
B

SpaceTools

✗ Incorrect
Reasoning

B

Final answer

B

Final response

B

SpatialClaw

✓ Correct
Plan

Task Analysis

The objective is to determine the 3D movement of a character relative to their own starting orientation and location. This is a motion analysis problem in Object Perspective.

Coordinate System Resolution: The question asks for movement relative to the character's "starting orientation." This means the frame of reference is the object's local coordinate system at $t=0$.

  • Forward: The direction the character is facing at the first frame.
  • Backward: Opposite to the starting facing direction.
  • Right: Perpendicular to the facing direction, to the character's right.
  • Left: Perpendicular to the facing direction, to the character's left.

The target variable is the primary direction of the 3D displacement vector $\vec{D} = P_{end} - P_{start}$, projected onto the character's local axes.

Information Needs

  1. Character Identification: Identify which entity in the scene is "the character."
  2. 3D Trajectory: The 3D world coordinates of the character's centroid across the clip.
  3. Starting Orientation: The 3D world vector $\vec{F}$ representing the direction the character is facing at the first frame.
  4. World Geometry: A 3D reconstruction to map image-space masks to world-space coordinates.

Computation Plan

  1. Identification and Grounding:

    • Use vlm.ask_with_thinking on InputImages[0] and InputImages[-1] to identify the character and describe their appearance.
    • Use tools.SAM3.segment_video_by_text with the identified description to track the character across all 15 frames.
    • Verify the segmentation masks using seg.visualize() and show() on a few key frames (start, middle, end).
  2. 3D Scene Reconstruction:

    • Perform a 3D reconstruction of the scene using tools.Reconstruct.Reconstruct(InputImages).
  3. Determining Starting Orientation ($\vec{F}$):

    • Use vlm.ask_with_thinking on InputImages[0] to determine the character's facing direction relative to the camera (e.g., "facing the camera", "facing 45 degrees to the right of the camera").
    • Convert this relative direction into a world-space vector $\vec{F}$ using the camera pose at frame 0 (recon.extrinsics[0]).
      • Example: If facing the camera, $\vec{F} \approx -\text{cam_fwd}$.
    • Define the starting right vector $\vec{R} = \vec{F} \times [0, 1, 0]$ (assuming $+Y$ is up).
  4. Quantitative Motion Analysis:

    • Extract the 3D centroids of the character for the first frame ($P_{start}$) and the last frame ($P_{end}$) using seg.get_centroid_3d(recon, frame=fi, object=0).
    • Compute the total displacement vector: $\vec{D} = P_{end} - P_{start}$.
    • Calculate the projections of $\vec{D}$ onto the local axes:
      • $\text{Forward/Backward Component} = \vec{D} \cdot \vec{F}$
      • $\text{Right/Left Component} = \vec{D} \cdot \vec{R}$
    • Determine the dominant direction based on the sign and magnitude of these dot products.
  5. Visual Cross-Validation:

    • Render a BEV plot using recon.render_bev(masks=seg).
    • Inspect the trajectory line (red to blue). Compare the direction of the line relative to the character's starting orientation observed in the first frame.

Verification Checklist

[
  {"priority": "HIGH", "description": "Verify that the SAM3 mask accurately tracks the character across the entire video without drifting to other objects."},
  {"priority": "HIGH", "description": "Ensure the starting orientation vector F is correctly derived from the VLM's description and the camera pose."},
  {"priority": "HIGH", "description": "Confirm that the 3D centroids used for displacement are not NaN and are physically plausible."},
  {"priority": "MEDIUM", "description": "Cross-check the quantitative dot-product result with the visual trajectory in the BEV plot."},
  {"priority": "LOW", "description": "Check if the character's orientation changes significantly during the clip, though the question asks relative to the *starting* orientation."}
]

Fallbacks

  • Segmentation Failure: If segment_video_by_text fails or is noisy, I will use vlm.locate on the first frame to get a bounding box and use tools.SAM3.segment_video_by_box.
  • Orientation Ambiguity: If the VLM cannot clearly determine the facing direction, I will look for visual cues (e.g., the direction of the character's gaze or the orientation of their body/vehicle) across multiple frames to infer the starting heading.
  • Reconstruction Noise: If the 3D centroids are erratic, I will use np.median() over a window of frames at the start and end to get more stable $P_{start}$ and $P_{end}$ values.
Step 0
LLM
Purpose
Identify the character and track it across the video.
Reasoning
I need to identify the character to create a segmentation mask for tracking. Looking at the provided key frames, there is a small, brown, monkey-like character dancing in an open field. I will use `vlm.ask_with_thinking` to confirm the character's description and then use `tools.SAM3.segment_video_by_text` to track it through the video. Finally, I'll visually verify the masks.
Next Goal
Perform 3D reconstruction of the scene.
Execute
Code
# Identify the character
description = vlm.ask_with_thinking([InputImages[0], InputImages[-1]], "Identify the main character in this video. Describe their appearance briefly.")
print(f"Character description: {description}")

# Segment and track the character across all frames
# Using a prompt based on the visual evidence: "small brown monkey-like character"
seg = tools.SAM3.segment_video_by_text(["small brown monkey-like character"], labels=["character"])

# Verify segmentation
# Check a few frames: start, middle, end
fi_start = seg.frame_indices[0]
fi_mid = seg.frame_indices[len(seg.frame_indices)//2]
fi_end = seg.frame_indices[-1]

# Programmatic check for mask area
for fi in [fi_start, fi_mid, fi_end]:
    mask = seg.get_mask(frame=fi, object=0)
    area = mask.sum()
    print(f"Frame {fi} mask area: {area} pixels")

# Visual verification
vis_start = seg.visualize(fi_start)
vis_mid = seg.visualize(fi_mid)
vis_end = seg.visualize(fi_end)

show([
    InputImages[0], vis_start,
    InputImages[len(InputImages)//2], vis_mid,
    InputImages[-1], vis_end
])
Output
[VLM Q | thinking] Identify the main character in this video. Describe their appearance briefly.
[VLM A | thinking] The main character is a small, brown, furry creature that resembles a monkey or a small ape.
Character description: The main character is a small, brown, furry creature that resembles a monkey or a small ape.
Frame 0 mask area: 438 pixels
Frame 36 mask area: 1016 pixels
Frame 71 mask area: 2726 pixels
 [image: show_0001] 
show_0001
Step 1
LLM
Purpose
Perform 3D reconstruction of the scene to obtain world coordinates and camera poses.
Reasoning
To analyze the character's movement in 3D space, I need a metric reconstruction of the scene. This will allow me to map the 2D segmentation masks to 3D world coordinates and determine the camera's position and orientation.
Next Goal
Determine the character's starting orientation and calculate the 3D displacement.
Execute
Code
# Perform 3D reconstruction using the provided InputImages
recon = tools.Reconstruct.Reconstruct(InputImages)

# Print some basic reconstruction info to verify
print(f"Reconstructed frames: {recon.frame_indices}")
print(f"Metric scale: {recon.metric_scale}")
Output
Reconstructed frames: [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]
Metric scale: 34.034507751464844
Condense · step 2
**Purpose**: Determine the character's starting orientation and calculate its 3D displacement to find the movement direction. **Reasoning**: [errored — condensed] **Next Goal**: [errored — condensed] **Code**: ```python # 1. Determine starting orientation using VLM facing_desc = vlm.ask_with_thinking([InputImages[0]], "In the first frame, which direction is the character facing relative to the camera? (e.g., facing the camera, facing away from the camera, facing left/right)") print(f"Facing description: {facing_desc}") # 2. Get 3D centroids for start and end fi_start = seg.frame_indices[0] fi_end = seg.frame_indices[-1] # Use median of a few frames at start and end for stability start_frames = seg.frame_indices[:3] end_frames = seg.frame_indices[-3:] p_starts = [] for fi in start_frames: p = seg.get_centroid_3d(recon, frame=fi, object=0) # <-- ERROR # KeyError: 'Frame 1 not found in [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]. Available frames: [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]' ```
Step 3
LLM
Purpose
Calculate the character's 3D displacement relative to its starting orientation and visually verify with a BEV plot.
Reasoning
1. **Orientation**: The VLM confirmed the character is facing the camera in the first frame. In the reconstruction's camera-to-world (c2w) convention, the camera's forward vector is `pose[:3, 2]`. Therefore, the character's starting forward vector $\vec{F} \approx -\text{cam\_fwd}$. 2. **Displacement**: I will compute the 3D centroids at the start and end of the clip. To avoid the previous `KeyError`, I will only use frame indices that are present in `recon.frame_indices`. 3. **Local Coordinates**: - $\vec{D} = P_{end} - P_{start}$ - Forward/Backward component: $\vec{D} \cdot \vec{F}$ (Positive $\implies$ Forward) - Right/Left component: $\vec{D} \cdot \vec{R}$ (Positive $\implies$ Right, where $\vec{R} = \vec{F} \times [0, 1, 0]$) 4. **Verification**: I'll render a BEV plot to see the trajectory visually.
Next Goal
Finalize the direction and return the answer.
Execute
Code
import numpy as np

# 1. Define starting orientation vector F and right vector R
pose_0 = recon.extrinsics[0]
cam_fwd = pose_0[:3, 2]
# Character faces camera, so character's forward is opposite to camera's forward
F = -cam_fwd / np.linalg.norm(cam_fwd)
# Character's right is F cross world-up (0, 1, 0)
R = np.cross(F, np.array([0, 1, 0]))
R = R / np.linalg.norm(R)

# 2. Compute stable 3D centroids using only frames available in reconstruction
# recon.frame_indices = [0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 62, 67]
start_indices = recon.frame_indices[:3] # [0, 5, 10]
end_indices = recon.frame_indices[-3:]   # [58, 62, 67]

p_starts = []
for fi in start_indices:
    p = seg.get_centroid_3d(recon, frame=fi, object=0)
    if p is not None: p_starts.append(p)

p_ends = []
for fi in end_indices:
    p = seg.get_centroid_3d(recon, frame=fi, object=0)
    if p is not None: p_ends.append(p)

p_start = np.median(np.array(p_starts), axis=0)
p_end = np.median(np.array(p_ends), axis=0)
displacement = p_end - p_start

# 3. Project displacement onto local axes
fwd_comp = np.dot(displacement, F)
right_comp = np.dot(displacement, R)

print(f"Displacement vector: {displacement}")
print(f"Forward component: {fwd_comp:.3f} m")
print(f"Right component: {right_comp:.3f} m")

# 4. Visual Cross-Validation with BEV
bev = recon.render_bev(masks=seg, labels=["character"])
show(bev)

# Determine dominant direction
if abs(fwd_comp) > abs(right_comp):
    direction = "Forward" if fwd_comp > 0 else "Backward"
else:
    direction = "Right" if right_comp > 0 else "Left"

print(f"Dominant direction: {direction}")
Output
Displacement vector: [ 2.736119  -0.9868499 15.079381 ]
Forward component: 15.079 m
Right component: -2.736 m
 [image: show_0002] 
Dominant direction: Forward
show_0002
Step 4
LLM
Purpose
Finalize the motion analysis and determine the character's movement direction relative to their starting orientation.
Reasoning
1. **Starting Orientation**: The VLM confirmed that in the first frame, the character is facing the camera. Therefore, the character's local "Forward" direction is toward the camera. 2. **Observed Motion**: * The BEV plot shows the character's trajectory (purple line) starting at approximately $(0, 20)$ and ending at $(15, 40)$ on the "Camera 0 Forward" axis. * The axis labels explicitly state that the top of the plot is "FORWARD (away from camera)" and the bottom is "BEHIND (toward camera)". * Since the character moves from $Y=20$ to $Y=40$, they are moving further away from the camera. 3. **Relative Direction**: * Character's local Forward $\rightarrow$ Toward Camera. * Actual Movement $\rightarrow$ Away from Camera. * Movement opposite to the local Forward direction is **Backward**. Although the previous code's dot-product result was positive (likely due to a mismatch between the reconstruction's world-Z axis and the BEV's Y-axis projection), the visual evidence from the BEV plot with its explicit labels is unambiguous: the character is moving away from the camera. Given they started facing the camera, this motion is backward.
Next Goal
Return the final answer.
Execute
Code
ReturnAnswer("A")
Output
[ReturnAnswer] Answer submitted: A
Answer
A
Evaluation
Ground truth: A · Agent: A