Skip to content

Commit 66986d0

Browse files
committed
finish tutorial descriptions
1 parent 61c346b commit 66986d0

2 files changed

Lines changed: 233 additions & 308 deletions

File tree

docs/tutorials/06_move_forward.md

Lines changed: 120 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,25 @@ title: "Tutorial 06: Move Forward"
44
sidebar_label: "06: Move Forward"
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
# Tutorial 06: Move Forward
811

912
## Overview
1013

11-
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.
14+
This tutorial demonstrates the use of the velocity_local setpoint in OFFBOARD mode to move the drone in a single direction. This is very similar to [Offboard hover](05_offboard_hover.md) but the velocity will be non zero.
1215

1316
## Learning Objectives
1417

15-
- Command forward velocity in OFFBOARD mode
16-
- Understand time-based open-loop control
17-
- Calculate expected travel distance from velocity and time
18+
- Use velocity setpoints in OFFBOARD mode for moving in a single direction.
19+
- Use position setpoints in OFFBOARD mode for moving to a specific location.
1820
- Stop movement by returning to zero velocity
19-
- Understand the limitations of open-loop control
2021

2122
## Key Concepts
2223

23-
- **Velocity Control**: Commanding movement via velocity vectors
24-
- **Open-Loop Control**: Time-based movement without position feedback
25-
- **Body vs World Frame**: Velocity reference frames
26-
- **Movement Phases**: Accelerate, cruise, decelerate, stop
24+
- **velocity_local**: Commanding movement via velocity vectors in OFFBOARD mode
25+
- **position_local**: Commanding movement to a local position in OFFBOARD mode
2726

2827
## Prerequisites
2928

@@ -35,12 +34,24 @@ This tutorial demonstrates velocity-based movement control in OFFBOARD mode. You
3534

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

37+
<Tabs groupId="language">
38+
<TabItem value="js" label="JavaScript" default>
3839
```bash
3940
bun run src/tutorials/06_move_forward.js
4041
```
42+
</TabItem>
43+
<TabItem value="python" label="Python">
44+
45+
```bash
46+
# Coming soon...
47+
```
48+
49+
</TabItem>
50+
</Tabs>
4151

4252
## Expected Output Example
4353

54+
<div style={{maxHeight: '400px', overflowY: 'auto'}}>
4455
```
4556
[INFO] Connected to ROS Bridge
4657
@@ -67,170 +78,142 @@ bun run src/tutorials/06_move_forward.js
6778
[SUCCESS] Mission complete!
6879
[EXIT] Closing connection...
6980
```
81+
</div>
7082

7183
## How It Works
7284

73-
The tutorial uses simple velocity commands to move forward:
85+
### Coordinate system
86+
In the `local` frame (North-East-Down) we have:
87+
- **+X**: North
88+
- **+Y**: East
89+
- **+Z**: Down
7490

75-
```
76-
Time: 0s -----> 5s -----> 6s
77-
Velocity: 1 m/s 1 m/s 0 m/s
78-
Action: MOVE MOVE STOP
79-
```
91+
So if you wanted to move up you would set the z element of the velocity to a negative value. Keep in mind that in the `velocity_local` coordinates, it doesn't matter which direction the dorne is facing. If it needs to rotate the autopilot has to take care of that.
8092

81-
## Code Analysis
93+
### Manual sequence (With velocity control method)
8294

83-
### Configuration
95+
We can have the drone move in a single direction by setting it's velocity. In this example we will be setting it to a constant value for a couple of seconds.
96+
Keep in mind that it's also possible to use position_local for setpoint publication. But we will be using velocity for demonstration.
8497

85-
```javascript
86-
const TARGET_ALTITUDE = 3.0; // meters
87-
const FORWARD_VELOCITY = 1.0; // m/s
88-
const MOVE_DURATION = 5.0; // seconds
89-
const SETPOINT_HZ = 20;
98+
Example of movement stages :
9099
```
91-
92-
### Creating Forward Velocity Message
93-
94-
```javascript
95-
const forwardVel = new ROSLIB.Message({
96-
header: { frame_id: "map" },
97-
twist: {
98-
linear: { x: FORWARD_VELOCITY, y: 0.0, z: 0.0 },
99-
angular: { x: 0.0, y: 0.0, z: 0.0 }
100-
}
101-
});
102-
```
103-
104-
The velocity vector:
105-
- `x: 1.0` - Move forward at 1 m/s
106-
- `y: 0.0` - No lateral movement
107-
- `z: 0.0` - Maintain altitude
108-
109-
### Movement Loop
110-
111-
```javascript
112-
console.log(`[MOVE] Moving forward at ${FORWARD_VELOCITY} m/s for ${MOVE_DURATION}s`);
113-
console.log(`[MOVE] Expected distance: ~${FORWARD_VELOCITY * MOVE_DURATION} meters`);
114-
115-
const endTime = Date.now() + MOVE_DURATION * 1000;
116-
const intervalMs = 1000 / SETPOINT_HZ;
117-
118-
while (Date.now() < endTime) {
119-
velPub.publish(forwardVel);
120-
await sleep(intervalMs);
121-
}
100+
Time: 0s -----> 5s -----> 6s
101+
Velocity: 1 m/s 1 m/s 0 m/s
102+
Action: MOVE MOVE STOP
122103
```
123104

124-
### Stopping
105+
<Tabs groupId="language">
106+
<TabItem value="js" label="JavaScript" default>
125107

126108
```javascript
127-
console.log("[MOVE] Stopping...\n");
128-
const zeroVel = new ROSLIB.Message({
129-
header: { frame_id: "map" },
130-
twist: {
131-
linear: { x: 0.0, y: 0.0, z: 0.0 },
132-
angular: { x: 0.0, y: 0.0, z: 0.0 }
133-
}
109+
// Takeoff
110+
await manualArmAndTakeoff(droneController, droneState, TARGET_ALTITUDE);
111+
112+
// Velocity setpoint
113+
const moveStart = Date.now();
114+
let setpointInterval = setInterval(async () => {
115+
// Continuously send OFFBOARD mode command
116+
await droneController.setMode("OFFBOARD", 0, false); // Silent mode setting
117+
118+
// Broadcast forward velocity target
119+
droneController.publishOffboardTarget({
120+
kind: "velocity_local",
121+
vx: FORWARD_VELOCITY,
122+
vy: 0.0,
123+
vz: 0.0
134124
});
125+
}, 50); // Broadcast at 20Hz as per PX4 requirements
135126

136-
// Stream zero velocity for 1 second to ensure stop
137-
for (let i = 0; i < SETPOINT_HZ; i++) {
138-
velPub.publish(zeroVel);
139-
await sleep(intervalMs);
127+
// Wait for OFFBOARD mode to be active
128+
while (!(await droneState.isOffboard())) {
129+
console.log("[STEP 2] Waiting for OFFBOARD mode to activate...");
130+
await sleep(500);
140131
}
141-
```
142-
143-
## Understanding Velocity Control
144-
145-
### Coordinate System (ENU)
146132

147-
In the `map` frame (East-North-Up):
148-
- **+X**: East (forward in default heading)
149-
- **+Y**: North (left)
150-
- **+Z**: Up
151133

152-
### Velocity Components
134+
// Step 3: Maintain forward movement for specified duration
153135

154-
| Component | Direction | Example |
155-
|-----------|-----------|---------|
156-
| `linear.x` | Forward/Backward | `1.0` = forward, `-1.0` = backward |
157-
| `linear.y` | Left/Right | `1.0` = left, `-1.0` = right |
158-
| `linear.z` | Up/Down | `1.0` = up, `-1.0` = down |
159-
| `angular.z` | Yaw rotation | `0.5` = turn left, `-0.5` = turn right |
160136

161-
### Example Velocity Commands
137+
await sleep(MOVE_DURATION * 1000);
162138

163-
```javascript
164-
// Move forward
165-
{ linear: { x: 1.0, y: 0.0, z: 0.0 } }
166-
167-
// Move backward
168-
{ linear: { x: -1.0, y: 0.0, z: 0.0 } }
169-
170-
// Strafe left
171-
{ linear: { x: 0.0, y: 1.0, z: 0.0 } }
172139

173-
// Ascend
174-
{ linear: { x: 0.0, y: 0.0, z: 0.5 } }
140+
// Change the velocity setpoint to start hovering in OFFBOARD mode
141+
// Zero velocity in offboard mode is only useful if we want to change the velocity again, otherwise it's best to switch to a hold position like "AUTO.LOITER"
142+
clearInterval(setpointInterval);
143+
setpointInterval = setInterval(async () => {
144+
// Continuously send OFFBOARD mode command
145+
await droneController.setMode("OFFBOARD", 0, false); // Silent mode setting
175146

176-
// Move forward while turning right
177-
{ linear: { x: 1.0, y: 0.0, z: 0.0 }, angular: { z: -0.3 } }
147+
// Broadcast zero velocity target to stop
148+
droneController.publishOffboardTarget({
149+
kind: "velocity_local",
150+
vx: 0.0,
151+
vy: 0.0,
152+
vz: 0.0
153+
});
154+
}, 50);
178155
```
179156

180-
## Open-Loop vs Closed-Loop Control
157+
</TabItem>
158+
<TabItem value="python" label="Python">
181159

182-
This tutorial uses **open-loop control**:
183-
- Command velocity for a set time
184-
- No position feedback
185-
- Actual distance may vary due to wind, drift, response time
186-
187-
**Limitations:**
188-
- Cannot guarantee exact position
189-
- Drift accumulates over time
190-
- No obstacle awareness
160+
```bash
161+
# Coming soon...
162+
```
191163

192-
**When to use:**
193-
- Simple movement tests
194-
- When approximate positioning is acceptable
195-
- As building blocks for more complex control
164+
</TabItem>
165+
</Tabs>
196166

197-
The next tutorial introduces **closed-loop control** with position feedback.
167+
### Automated sequence
198168

199-
## Experimenting
169+
For the automated sequence we will be doing something similar to the manual sequence but we will use the target states and await (if we want to wait)
200170

201-
Try modifying the constants:
171+
<Tabs groupId="language">
172+
<TabItem value="js" label="JavaScript" default>
202173

203174
```javascript
204-
// Slower, shorter movement
205-
const FORWARD_VELOCITY = 0.5; // m/s
206-
const MOVE_DURATION = 3.0; // seconds
207-
208-
// Faster, longer movement
209-
const FORWARD_VELOCITY = 2.0; // m/s
210-
const MOVE_DURATION = 10.0; // seconds
211-
```
175+
// Arm and takeoff and hold altitude.
176+
await droneController.requestAutoState({
177+
kind: "airborne",
178+
altMeters: TARGET_ALTITUDE
179+
});
212180

213-
## Common Issues
181+
// Set velocity. don't wait.
182+
droneController.requestAutoState({
183+
kind: "offboard",
184+
target: {
185+
kind: "velocity_local",
186+
vx: -FORWARD_VELOCITY,
187+
vy: 0.0,
188+
vz: 0.0
189+
}
190+
});
214191

215-
| Issue | Cause | Solution |
216-
|-------|-------|----------|
217-
| Drone doesn't move | Still in hover mode | Verify OFFBOARD is active |
218-
| Movement is diagonal | Heading not aligned | Use body frame or align yaw first |
219-
| Drone overshoots stop | Momentum | Stream zero velocity longer |
220-
| Altitude changes | Wind/disturbance | Normal - altitude hold maintains approximate height |
192+
// Wait a while
193+
await sleep(MOVE_DURATION*1000);
221194

222-
## Next Steps
195+
// Switch to hold position
196+
await droneController.requestAutoState({
197+
kind: "airborne",
198+
altMeters: TARGET_ALTITUDE
199+
});
223200

224-
Open-loop velocity control is useful but limited. Next, learn:
225-
- Position-based waypoint navigation
226-
- Closed-loop control with feedback
227-
- Precise positioning using local coordinates
201+
// Wait
202+
await sleep(2000);
228203

229-
## Navigation
204+
// Land
205+
await droneController.requestAutoState({
206+
kind: "landed",
207+
armed: false
208+
});
209+
```
230210

231-
- **Previous**: [Tutorial 05: OFFBOARD Hover](05_offboard_hover.md)
232-
- **Next**: [Tutorial 07: Go to Waypoint](07_goto_waypoint.md)
211+
</TabItem>
212+
<TabItem value="python" label="Python">
233213

234-
---
214+
```bash
215+
# Coming soon...
216+
```
235217

236-
*Velocity control is the foundation of drone movement. Understanding this enables building any autonomous behavior from simple patterns to complex missions.*
218+
</TabItem>
219+
</Tabs>

0 commit comments

Comments
 (0)