Skip to main content

Tutorial 06: Move Forward

Overview

This tutorial demonstrates velocity-based movement control in OFFBOARD mode. You'll learn how to command the drone to move forward using timed velocity commands - a fundamental building block for autonomous navigation.

Learning Objectives

  • Command forward velocity in OFFBOARD mode
  • Understand time-based open-loop control
  • Calculate expected travel distance from velocity and time
  • Stop movement by returning to zero velocity
  • Understand the limitations of open-loop control

Key Concepts

  • Velocity Control: Commanding movement via velocity vectors
  • Open-Loop Control: Time-based movement without position feedback
  • Body vs World Frame: Velocity reference frames
  • Movement Phases: Accelerate, cruise, decelerate, stop

Prerequisites

  • Active TensorFleet VM with MAVROS running
  • Simulation restarted (as described in Preparation)
  • Completed OFFBOARD hover tutorial (Tutorial 05)

Running the Tutorial

This tutorial moves the drone forward for 5 seconds at 1 m/s, then lands.

bun run src/tutorials/06_move_forward.js

Expected Output Example

[INFO] Connected to ROS Bridge

[ARM] Sending arm command...
[ARM] Drone is now armed!

[TAKEOFF] Setting GUIDED mode...
[TAKEOFF] Sending takeoff command to 3m...
[TAKEOFF] Target altitude reached!

[OFFBOARD] Pre-streaming setpoints...
[OFFBOARD] OFFBOARD mode active!

[MOVE] Moving forward at 1 m/s for 5s
[MOVE] Expected distance: ~5 meters

[MOVE] Stopping...

[MOVE] Movement complete

[LAND] Sending land command...
[LAND] Drone has landed and disarmed!

[SUCCESS] Mission complete!
[EXIT] Closing connection...

How It Works

The tutorial uses simple velocity commands to move forward:

Time:     0s -----> 5s -----> 6s
Velocity: 1 m/s 1 m/s 0 m/s
Action: MOVE MOVE STOP

Code Analysis

Configuration

const TARGET_ALTITUDE = 3.0;   // meters
const FORWARD_VELOCITY = 1.0; // m/s
const MOVE_DURATION = 5.0; // seconds
const SETPOINT_HZ = 20;

Creating Forward Velocity Message

const forwardVel = new ROSLIB.Message({
header: { frame_id: "map" },
twist: {
linear: { x: FORWARD_VELOCITY, y: 0.0, z: 0.0 },
angular: { x: 0.0, y: 0.0, z: 0.0 }
}
});

The velocity vector:

  • x: 1.0 - Move forward at 1 m/s
  • y: 0.0 - No lateral movement
  • z: 0.0 - Maintain altitude

Movement Loop

console.log(`[MOVE] Moving forward at ${FORWARD_VELOCITY} m/s for ${MOVE_DURATION}s`);
console.log(`[MOVE] Expected distance: ~${FORWARD_VELOCITY * MOVE_DURATION} meters`);

const endTime = Date.now() + MOVE_DURATION * 1000;
const intervalMs = 1000 / SETPOINT_HZ;

while (Date.now() < endTime) {
velPub.publish(forwardVel);
await sleep(intervalMs);
}

Stopping

console.log("[MOVE] Stopping...\n");
const zeroVel = new ROSLIB.Message({
header: { frame_id: "map" },
twist: {
linear: { x: 0.0, y: 0.0, z: 0.0 },
angular: { x: 0.0, y: 0.0, z: 0.0 }
}
});

// Stream zero velocity for 1 second to ensure stop
for (let i = 0; i < SETPOINT_HZ; i++) {
velPub.publish(zeroVel);
await sleep(intervalMs);
}

Understanding Velocity Control

Coordinate System (ENU)

In the map frame (East-North-Up):

  • +X: East (forward in default heading)
  • +Y: North (left)
  • +Z: Up

Velocity Components

ComponentDirectionExample
linear.xForward/Backward1.0 = forward, -1.0 = backward
linear.yLeft/Right1.0 = left, -1.0 = right
linear.zUp/Down1.0 = up, -1.0 = down
angular.zYaw rotation0.5 = turn left, -0.5 = turn right

Example Velocity Commands

// Move forward
{ linear: { x: 1.0, y: 0.0, z: 0.0 } }

// Move backward
{ linear: { x: -1.0, y: 0.0, z: 0.0 } }

// Strafe left
{ linear: { x: 0.0, y: 1.0, z: 0.0 } }

// Ascend
{ linear: { x: 0.0, y: 0.0, z: 0.5 } }

// Move forward while turning right
{ linear: { x: 1.0, y: 0.0, z: 0.0 }, angular: { z: -0.3 } }

Open-Loop vs Closed-Loop Control

This tutorial uses open-loop control:

  • Command velocity for a set time
  • No position feedback
  • Actual distance may vary due to wind, drift, response time

Limitations:

  • Cannot guarantee exact position
  • Drift accumulates over time
  • No obstacle awareness

When to use:

  • Simple movement tests
  • When approximate positioning is acceptable
  • As building blocks for more complex control

The next tutorial introduces closed-loop control with position feedback.

Experimenting

Try modifying the constants:

// Slower, shorter movement
const FORWARD_VELOCITY = 0.5; // m/s
const MOVE_DURATION = 3.0; // seconds

// Faster, longer movement
const FORWARD_VELOCITY = 2.0; // m/s
const MOVE_DURATION = 10.0; // seconds

Common Issues

IssueCauseSolution
Drone doesn't moveStill in hover modeVerify OFFBOARD is active
Movement is diagonalHeading not alignedUse body frame or align yaw first
Drone overshoots stopMomentumStream zero velocity longer
Altitude changesWind/disturbanceNormal - altitude hold maintains approximate height

Next Steps

Open-loop velocity control is useful but limited. Next, learn:

  • Position-based waypoint navigation
  • Closed-loop control with feedback
  • Precise positioning using local coordinates

Velocity control is the foundation of drone movement. Understanding this enables building any autonomous behavior from simple patterns to complex missions.