Replay#
A replay drives a vehicle from a file or shows a recorded episode again. This tutorial gives the procedures for a command replay, a path replay, a drive script, an episode replay and a ROS 2 bag.
Before You Start#
- Build or install the packaged game: refer to Run the Packaged Game.
- For the bag procedure, build the ROS 2 workspace: refer to Build the ROS 2 Workspace.
- Do all commands in the repository root.
Select the replay type for your task.
| Replay | Input | Physics Models | Use |
|---|---|---|---|
| Command replay | A CSV file with speed and curvature. | They run. | To apply recorded commands to the vehicle without feedback. |
| Path replay | A CSV file with positions. | They run. | To follow a recorded or planned path with a speed profile. |
| Drive script | A JSON file with timed controls. | They run. | To make a demonstration or a test run that you can repeat. |
| Several replays | An agents file. | They run. | To give a different replay or script to each vehicle of a session. |
| Episode replay | An episode log. | They do not run. | To show an episode from a different camera, or to make its images later. |
| Bag replay | A ROS 2 bag. | No simulator. | To test ROS 2 nodes with recorded data. |
The Replay File#
A command replay and a path replay read a CSV file with a header row and two or more data rows.
The file can be the file tractor.csv of a session log, the session folder that contains it, or a file from a different program.
The game does not use the case of the column names. For each quantity, the first name of the table that the file contains applies.
| Quantity | Column Names | Unit | Necessary | Description |
|---|---|---|---|---|
| Time | time_s, t |
s | Yes | The time. It must increase. The first value can be different from 0. |
| Speed | speed_mps, v_forward_mps, v |
m/s | Yes | The forward speed. A negative value is reverse. |
| Curvature | curvature_1pm, curvature_command_1pm, curvature_measured_1pm, kappa |
1/m | Yes | The curvature of the path. Positive is left. |
| Position | ue_x_m and ue_y_m |
m | No | The position with x east and y south. |
| Position | east_m and north_m |
m | No | The position with x east and y north. The game uses these columns when the file has no ue_x_m and ue_y_m. |
| Heading | heading_deg |
deg | No | The heading, clockwise from north. It sets the start pose. |
| Implement | implement, harvest |
No | 1 lowers the implement or starts the harvest function. 0 lifts or stops it. | |
| Gear | gear |
No | The forward gear of the Maxxum, from 1 to 16. 0 lets the replay select the gear. |
The game applies these rules when it reads the file.
- It ignores a row that is less than 0.05 s after the last row that it kept. A session log of 120 Hz thus becomes a track of 20 Hz.
- It ignores a row with fewer fields than the header.
- It refuses the file when the time does not increase.
- It refuses the file when a speed is more than 20 m/s or a curvature is more than 1 per metre.
When the game refuses the file, the log contains ACRES_REPLAY_REJECTED with the cause.
Command Replay#
A command replay applies the speed and the curvature of the file as a function of time. The steering angle is \( \delta = \arctan(\kappa L) \) with the curvature \( \kappa \) and the wheelbase \( L \). The replay has no position feedback. The position error thus increases with time.
-
Write the command file
/data/commands.csv. -
Start the game with the file and a session log. The spawn options put the Maxxum on field F21, where it has space.
-
Close the game with Esc after the vehicle stopped. Then read the summary and the tracking file.
cat /data/replay-commands/replay-summary.json sed -n '1p;120p' /data/replay-commands/replay-tracking.csvExpected Result
The replay is complete. At 11.8 s the speed is 3.0 m/s and the steering angle follows the curvature of the file. A command file has no positions, thus the cross-track error is 0.
{"source":"/data/commands.csv","mode":"commands","reference_duration_s":25.000,"path_available":false, "rms_cross_track_m":0.0000,"max_cross_track_m":0.0000,"completed":true,"vehicle":"maxxum_150", "shift_east_north_m":[0.000,0.000]} time_s,ref_x_m,ref_y_m,x_m,y_m,cross_track_m,ref_speed_mps,speed_mps,ref_curvature_1pm,steer_rad 11.800,-33.791,-175.794,-33.791,-175.794,0.000,3.000,2.999,0.01640,0.04330
The replay holds the brake for the first 3 s and after the end of the file. A speed controller sets the throttle and the brake. On the Maxxum, the replay selects the highest gear that keeps the engine at 1500 rev/min or more. The Polaris gets the speed as a command to its ULC and the steering angle as a steering command.
Path Replay#
A path replay follows the positions of the file with a pure-pursuit controller. It reads the speed, the implement state and the gear at the position of the vehicle along the path, not at the time. The vehicle starts at the first position of the file.
-
Start the game with the path of the repository and the mode
path. -
Close the game with Esc when the vehicle stopped. Then read the summary and the tracking file.
Expected Result
The largest distance from the path is 8 mm.
{"source":"Demo/harvest_path.csv","mode":"path","reference_duration_s":43.000,"path_available":true, "rms_cross_track_m":0.0037,"max_cross_track_m":0.0077,"completed":false,"vehicle":"maxxum_150", "shift_east_north_m":[0.000,0.000]} 52.000,256.570,-86.870,253.081,-86.864,0.006,0.000,0.001,0.00000,0.00261
Note
The speed of the last row of this file is 0. The Maxxum thus stops 3.5 m before the last point, and completed stays false.
To replay a session, give its session folder: -ReplayFile=<session folder> -ReplayMode=path.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
-ReplayFile= |
path | no replay | The CSV file or the session folder. | |
-ReplayMode= |
string | commands |
commands or path. The mode path needs the position columns. |
|
-ReplayShift= |
two numbers | m | 0,0 |
A shift of the path to the east and to the north, as <east>,<north>. |
The controller of the path replay has these properties.
| Property | Value |
|---|---|
| Look-ahead distance | 2.5 m + 0.6 s × speed, 8 m maximum. |
| Speed | The lowest speed of the file in the braking distance and the look-ahead distance. |
| More than 1.5 m from the path | The speed is 2 m/s maximum until the vehicle is on the path again. |
| End | The replay is complete when the vehicle is less than 1.5 m from the last point. |
| Stall | After 10 s below 0.15 m/s with a target above 0.5 m/s, stop and report stalled. |
| Time limit | After three times the reference duration plus 30 s, stop and report time_limit. |
A failed path replay applies the brake, requests an implement lift and writes ACRES_REPLAY_FAILED to the log.
Its summary has completed=false and a failure reason. An empty failure string means that no failure was detected;
check completed as well, because the operator can end a session early.
The game writes two files into the session folder when the session ends.
| File | Content |
|---|---|
replay-tracking.csv |
One row each 0.1 s: time_s, ref_x_m, ref_y_m, x_m, y_m, cross_track_m, ref_speed_mps, speed_mps, ref_curvature_1pm, steer_rad. |
replay-summary.json |
source, mode, reference_duration_s, path_available, rms_cross_track_m, max_cross_track_m, completed, failure, vehicle, shift_east_north_m. |
In an agents file, the keys replay_file, replay_mode and replay_shift set the replay of one agent.
The menu has the same function: select Replay Simulation and then the tab Replay.
Drive Script#
A drive script is a JSON file with a list of keys. Each key has a time t and one or more fields.
The time is the physics time since the start of the session in seconds.
A field keeps its value until a later key sets it again.
-
Write the script
/data/drive.json. -
Start the game with the script.
Packaged/Linux/Acres.sh -VehicleDemo -DriveScript=/data/drive.json -SessionLog -VehicleOutput=/data/drive-scriptExpected Result
The Maxxum follows the path forward from its spawn pose and stops at 12 s. The camera moves to the side at 8 s. The game stops at 15 s. The session summary gives a distance of 16.3 m and a maximum speed of 1.56 m/s.
The top level of the file has these keys.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
keys |
object list | The timed keys. This list is necessary. | ||
frame |
string | spawn |
The frame of the points. spawn: metres forward and left of the spawn pose. world: x east and y south. |
|
path |
list of [x, y] |
m | none | The path that the steering follows. |
bales |
list of [x, y] |
m | none | Round bales for the loader. |
windrow |
list of [x, y] |
m | none | A hay windrow for the baler. |
A key can have these fields.
| Name | Type | Unit | Description |
|---|---|---|---|
t |
number | s | The time of the key. |
speed_kmh |
number | km/h | A speed that a controller holds with the throttle and the brake. |
pedal |
number | The throttle, from 0 to 1, when the key has no speed_kmh. |
|
hand_throttle |
number | The hand throttle, from 0 to 1. | |
brake |
number | The brake, from 0 to 1. | |
park |
boolean | true applies the brake fully. |
|
gear |
integer | The forward gear, from 1. | |
direction |
integer | 1 forward, -1 reverse. | |
steer |
number or string | deg | A fixed steering angle, positive left. The string path follows the path. |
diff_lock |
integer | 0 open, 1 rear, 2 front and rear. | |
raise, pto, transport |
boolean | The implement lift, the PTO and the transport position. | |
hitch_mode |
string | position, draft or float. |
|
depth_m |
number | m | The work depth of the implement. |
lever |
number | The hitch lever, from 0 to 1. | |
draft_setpoint_kn |
number | kN | The draft set-point. |
spray, meter, pickup, stabilizers |
boolean | The switches of the sprayer, the seed meter, the baler pickup and the backhoe stabilizers. | |
boom_fold |
number | The fold of the sprayer boom, from 0 to 1. | |
windrow_kg_m |
number | kg/m | The mass of the windrow for each metre. |
loader_lift, loader_curl |
number | The loader controls, from -1 to 1. | |
swing, boom, dipper, bucket |
number | The backhoe controls, from -1 to 1. | |
grab |
boolean | true takes the nearest round bale. false releases it. |
|
camera |
number list | deg, deg, m | The camera behind the vehicle: yaw, pitch and distance. |
camera_blend_s |
number | s | The time in which the camera moves to the new camera value. |
cab |
boolean | true selects the view from the cab. |
|
cab_look |
number list | deg | The yaw and the pitch of the view from the cab. |
view |
string | The name of the agent that the view follows. Agent 0 only. | |
exit |
boolean | true stops the game. |
With a path and without a steer key, the steering follows the path.
A script with only camera, view and exit fields does not change the steering. You can use it together with a replay or a vehicle bridge.
The scripts of the repository are in Demo/SoilWeather and Demo/Multi.
Several Replays in One Session#
In an agents file, each agent has its own keys replay_file, replay_mode, replay_shift and drive_script.
The exit field has an effect only in the script of agent 0.
-
Write the agents file
/data/agents.json. Agent 0 uses the drive script. Change the time of itsexitkey to 55 s.{"agents": [ {"name": "script", "vehicle": "maxxum", "drive_script": "/data/drive.json"}, {"name": "commands", "vehicle": "maxxum", "spawn": [480, 405, -90], "replay_file": "/data/commands.csv", "replay_mode": "commands"}, {"name": "path", "vehicle": "maxxum", "replay_file": "Demo/harvest_path.csv", "replay_mode": "path"} ]} -
Start the session.
Packaged/Linux/Acres.sh -VehicleDemo -Agents=/data/agents.json -SessionLog -VehicleOutput=/data/replay-sessionExpected Result
Three Maxxum tractors drive at the same time. The session folder has one folder for each agent.
ACRES_DRIVE_SCRIPT keys=5 path_points=2 file=/data/drive.json ACRES_REPLAY_READY rows=5 duration=25.0 s path=0 mode=commands source=/data/commands.csv ACRES_AGENT_SPAWNED index=1 name=commands vehicle=maxxum ACRES_REPLAY_READY rows=43 duration=43.0 s path=1 mode=path source=Demo/harvest_path.csv ACRES_AGENT_SPAWNED index=2 name=path vehicle=maxxum ACRES_DRIVE_SCRIPT_DONE t=55.00
The agents file is on the page Run Several Vehicles.
Episode Replay#
An episode replay shows an Episode Log in the game. Each vehicle follows its logged states, and the farm gets the logged contacts and events again. The physics models do not run, thus the replay shows the episode without a change.
| Item | Behaviour |
|---|---|
| Agents | Without -Vehicle=, -Vehicles= or -Agents=, the game makes the agents of the log at their first logged poses. |
| Sky | The replay starts with the date, the hour and the weather preset of the first conditions message. Then the weather model runs. |
| Farm | The game applies the logged farm stamps and farm events at their steps. |
| End | After the last logged step, the vehicles keep their last state. The log contains ACRES_REPLAY_DONE. |
| Cameras | All views are available: the chase view, the cab view (-CameraCab) and the camera fields of a drive script. |
| Sensors | The sensors operate on the replayed poses: -SensorRecord and -SensorStream= are available. |
The two procedures below show the two uses of an episode replay.
Render-Later#
Render-later records an episode log without images and makes the images later with an episode replay. ACRES Core runs the episode much faster than real time, and the game then shows it.
-
Record an episode with ACRES Core in Python. Refer to Headless Core Runs for the Python module.
import math import acres_core import numpy as np batch = acres_core.Batch(".", num_envs=1) batch.reset([0], np.array([[-38.71, -140.513, math.pi / 2, 0.0]])) batch.start_log(0, "/data/core-episode.mcap") for k in range(300): curvature = 0.08 * math.sin(2 * math.pi * k / 200) batch.step_curvature_speed(np.array([curvature]), np.array([2.0])) batch.stop_log(0)Expected Result
ACRES Core simulates 30 s in 0.06 s and writes 8405 messages into the file.
-
Show the episode in the game from the cab view and record a video. The option
-EpisodeReplayExitstops the game at the end of the log.Packaged/Linux/Acres.sh -VehicleDemo -EpisodeReplay=/data/core-episode.mcap -EpisodeReplayExit \ -CameraCab -RenderOffscreen -ResX=1280 -ResY=720 -CaptureVideo=/data/core-episode.mp4Expected Result
The game makes the Polaris of the log, shows the drive from the cab in real time and stops after 30 s.
ACRES_REPLAY_LOADED /data/core-episode.mcap states=3600 agents=1 farm_events=0 farm_stamps=3600 duration_s=29.99 ACRES_SIM_CONTROL_READY port=0 lockstep=0 replay=1 log= ACRES_CAPTURE_START /data/core-episode.mp4 1280x720 at 30 fps ACRES_REPLAY_DONE steps=3600 ACRES_CAPTURE_DONE /data/core-episode.mp4: 899 frames (30.0 s at 30 fps), 0 dropped -
Examine the video.
Images at Exact Steps#
With -Lockstep and -SimControl=, a replay advances only on step requests. Each image then belongs to an exact physics step.
This procedure uses an episode log of the game: the file run0.mcap of the procedure Lockstep Stepping.
-
Start the replay in lockstep.
-
Step to physics step 1200, read the pose and write the main view to a file.
import sys sys.path.insert(0, "Tools/SimControl") from sim_control import SimControl ctl = SimControl(5600) print(ctl.call("hello")["replay"]) reply = ctl.call("step", steps=1200) print(reply["step"], reply["time_s"]) print(ctl.call("get_entity_state", entity="polaris")["pose"]["position"]) ctl.call("screenshot", path="/data/step-1200.png") -
Stop the game.
Replay a ROS 2 Bag#
A bag of the ROS 2 bridge or of the real Polaris contains the sensor topics, the odometry and the transforms.
The launch file bag_replay.launch.py plays a bag with its clock and starts the description of the Polaris.
ROS 2 nodes and RViz then get the data as from the vehicle. This procedure does not use a simulator.
-
Record a bag from a session with the ROS 2 bridge: refer to Collect Data.
source ROS/Env/setup_env.sh ros2 bag record --use-sim-time -s mcap -o /data/bag /tf /tf_static /vehicle/odom /oxts/imu /lidar/pointsNote
Use
--use-sim-timefor a bag of the simulator and do not record/clock. The times in the bag are then simulation times, and the replay makes the clock from them. -
Examine the bag.
-
Play the bag with the description of the Polaris.
Expected Result
The launch file starts the robot state publisher and the path node, then it plays the bag after 4 s. The topic
/clockhas simulation time, and the transform fromodom_origintolidaris available.[robot_state_publisher-1] [INFO] [robot_state_publisher]: got segment base_footprint [robot_state_publisher-1] [INFO] [robot_state_publisher]: got segment lidar [ros2-3] [INFO] [rosbag2_player]: Set rate to 1 [odom_path-2] [INFO] [odom_path]: path origin odom_origin at (500434.63, 4479976.18, 181.52) in utm
Without rviz:=false, the launch file also starts RViz with the model of the Polaris, the LiDAR points and the path of the odometry.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
bag |
path | The folder of the bag. | ||
rate |
number | 1.0 | The speed of the replay. | |
loop |
boolean | false |
true plays the bag again and again. |
|
rviz |
boolean | true |
false starts no RViz. |
|
delay |
number | s | 4.0 | The time before the replay starts. |
An episode log is not a bag of sensor topics. To publish its messages, use ros2 bag play -s mcap: refer to Episode Log.
Next Steps#
- Episode Log: the format of the file and its channels.
- Simulator Control Channel: the options and the operation
record. - Lockstep Stepping: record an episode step by step.
- Collect Data: record sensor data during a replay.
- Plan Field Work: make a path file for a path replay.