Skip to content

Navigation Challenge

Difficulty: Easy Time Limit: 30 seconds Status: Active

Overview

The Navigation scenario is a beginner-friendly challenge where a robot arm must move its end-effector to reach a target location. This is the simplest scenario - no manipulation required, just movement control.

Objective

Move the robot's end-effector (yellow sphere) to touch the target marker (green sphere).

Environment

Scene Layout

┌─────────────────────────────────────────┐
│                                         │
│              🟢  ← Target (green)       │
│                                         │
│                                         │
│                                         │
│   🤖══════🟡   ← End-effector (yellow)  │
│                                         │
└─────────────────────────────────────────┘

Components

  • Target: A green sphere that appears at a random location each episode
  • End-effector: The yellow sphere at the tip of the robot arm
  • Success: End-effector within 5cm of the target center

Robot

  • Type: 3-DOF planar arm (same as other scenarios)
  • Joints: Base rotation, shoulder, elbow
  • Control: Joint torque control
  • Strategy: Move end-effector through joint coordination

Observations

Your policy receives:

observation = {
    # Joint positions (3 values)
    'joint_positions': np.array([base, shoulder, elbow]),

    # Joint velocities (3 values)
    'joint_velocities': np.array([base_vel, shoulder_vel, elbow_vel]),

    # End-effector position (3 values)
    'end_effector_pos': np.array([x, y, z]),

    # Target position (3 values)
    'target_pos': np.array([x, y, z]),

    # Distance to target (scalar)
    'distance_to_target': float,

    # Whether target is reached (boolean)
    'target_reached': bool,
}

Actions

Return a 3D action vector (joint torques):

action = np.array([
    base_torque,      # Base joint torque (-10 to 10)
    shoulder_torque,  # Shoulder joint torque (-10 to 10)
    elbow_torque      # Elbow joint torque (-10 to 10)
])

Scoring

Verdict Criteria

Verdict Criteria
PASS End-effector reached within 5cm of target
FAIL End-effector did not reach the target

Reward Calculation

Target reached (< 5cm): +100 points
Close to target (< 10cm): +20 points
Distance reward: +10 / (1 + distance * 10)
Velocity penalty: -0.01 * |joint_velocities|

Tips

Strategy

  1. Calculate Direction: Find the vector from end-effector to target
  2. Map to Torques: Convert Cartesian direction to joint torques
  3. Add Damping: Reduce oscillation by penalizing velocity
  4. Slow Down: Reduce speed when approaching target

Key Insight

The main challenge is mapping Cartesian (XYZ) movement to joint torques: - Base joint: Controls rotation in the XY plane - Shoulder joint: Controls forward reach and some height - Elbow joint: Controls reach extension and height

Common Mistakes

  • Oscillation: Moving too fast without damping
  • Overshoot: Not slowing down near the target
  • Wrong Mapping: Confusing which joint affects which direction

Example Approach

import numpy as np

def policy(observation: dict) -> np.ndarray:
    ee_pos = observation['end_effector_pos']
    target_pos = observation['target_pos']
    distance = observation['distance_to_target']
    velocities = observation['joint_velocities']

    # Already there? Stop.
    if observation['target_reached']:
        return np.zeros(3)

    # Direction to target
    direction = target_pos - ee_pos
    direction = direction / (np.linalg.norm(direction) + 1e-6)

    # Scale based on distance (slow down when close)
    gain = min(distance * 20, 5.0)

    # Map Cartesian direction to joint torques
    # This is approximate - proper solution uses inverse kinematics
    base_torque = direction[1] * gain * 3.0      # Y movement
    shoulder_torque = -direction[0] * gain       # X movement
    elbow_torque = direction[2] * gain * 2.0     # Z movement

    # Add velocity damping to prevent oscillation
    damping = 0.3
    base_torque -= velocities[0] * damping
    shoulder_torque -= velocities[1] * damping
    elbow_torque -= velocities[2] * damping

    action = np.array([base_torque, shoulder_torque, elbow_torque])
    return np.clip(action, -10, 10)

Why Start Here?

Navigation is the recommended first scenario because:

  1. Simple Objective: Just reach the target, no manipulation
  2. Clear Feedback: Distance tells you how well you're doing
  3. Foundation Skills: Learn joint control before manipulation
  4. Quick Iterations: Fast episodes let you experiment rapidly

Once you can consistently reach targets, move on to: - Object Sorting (Easy) - Add pushing mechanics - Messy Room (Medium) - More complex manipulation - Block Stacking (Hard) - Precise grasping and placement

Local Testing

Test your policy locally before submitting:

from botmanifold import BotManifoldClient

client = BotManifoldClient()

# Load scenario locally
env = client.load_scenario("navigation_v1")

# Run your policy
observation = env.reset()
done = False

while not done:
    action = policy(observation)
    observation, reward, done, info = env.step(action)

print(f"Distance to target: {observation['distance_to_target']:.3f}m")
print(f"Target reached: {observation['target_reached']}")

Leaderboard

View current rankings at botmanifold.com/arena/leaderboard?scenario=navigation_v1

Video Example

Watch an example of a successful policy completing this scenario on the scenario detail page.