How to Set Up and Program Cruise Sequence Waypoints with Motion Tracking on ATOM Swing

The atomcam_tools firmware enables automated cruise sequences through a semicolon-separated command list in hack.ini, where move, detect, follow, and sleep commands drive the ATOM Swing camera through programmable waypoints with optional motion detection and object tracking.

The mnakada/atomcam_tools project provides a complete cruise sequence waypoints with motion tracking system for ATOM Swing cameras. By combining a simple INI-based configuration, a Vue-based web editor, and native motion-detection hooks, the camera can autonomously patrol between positions, pause for events, and track moving objects in real time.

Enabling Cruise Mode in hack.ini

Cruise functionality is controlled by the hack.ini file stored on the SD card (mounted at /tmp/hack.ini during runtime). To activate the feature, add the following line:

CRUISE=on

When the camera boots, the initialization script /etc/init.d/S62webcontrol starts cruise.sh (line 9 of the init script). The shell script checks for CRUISE=on at line 13; if enabled, it enters an infinite loop that parses and executes the waypoint list.

Programming Waypoint Sequences with CRUISE_LIST

The CRUISE_LIST parameter defines the patrol route as a semicolon-separated string of commands. Each command follows a strict syntax supported by the runtime engine in overlay_rootfs/scripts/cruise.sh.

Move Commands

Use the move command to position the camera before waiting or detecting motion:

move <pan> <tilt> [<speed>]
  • Pan: 0–355 degrees
  • Tilt: 0–180 degrees
  • Speed: Optional, 1 (slow) to 9 (fast)

Detection and Tracking Modes

Two commands handle motion-aware pauses: detect and follow.

Detect pauses execution and waits for motion events:

detect <wait> <timeout>

The script calls the native waitMotion command (exposed via TCP port 4000) with the specified wait interval. If no motion occurs within timeout seconds, the cruise proceeds to the next waypoint.

Follow adds automatic tracking:

follow <wait> <timeout> [<speed>]

When motion is detected, the script issues an additional move command targeting the detected object's coordinates (extracted from the waitMotion response) using the specified speed.

Sleep Intervals

For simple delays without motion handling, use:

sleep <wait>

Configuration Example

A complete CRUISE_LIST that centers the camera, watches for motion, shifts to a new angle, tracks any detected object at high speed, then rests:

CRUISE=on
CRUISE_LIST=move 180 90;detect 5 10;move 210 90;follow 5 10 8;sleep 10;

Motion Tracking Implementation Details

The motion-tracking pipeline spans three layers: the shell script controller, the native command handler, and the video OSD callback.

waitMotion Command Handler

When cruise.sh executes waitMotion <timeout>, it sends the string over localhost port 4000. The WaitMotion function in libcallback/wait_motion.c (line 35) registers the requesting file descriptor (WaitMotionFd) and stores the timeout value. The function returns NULL to keep the socket open until motion occurs or the timer expires.

OSD Callback Integration

Each video frame triggers local_sdk_video_osd_update_rect. The hook in wait_motion.c (line 55) checks if a motion request is pending (WaitMotionFd >= 0). If the camera motors have been idle for at least 0.5 seconds, the callback reads the current pan/tilt position and the motion-rectangle coordinates, then builds a response string:


detect <left> <right> <top> <bottom> <pan> <tilt>

This string is sent back to cruise.sh via CommandResponse (line 84). If no motion is present, the callback transmits "clear".

Cruise Script Logic

Inside cruise.sh, the follow block parses the response (stored in variable motion). If the response starts with "detect", the script extracts the sixth and seventh fields ($6 $7) representing the target pan and tilt, then issues:

echo "move $6 $7 $speed" | nc localhost 4000

If waitMotion returns "timeout", the loop breaks and the script advances to the next waypoint in CRUISE_LIST.

Web UI Configuration

While manual INI editing works, the Vue-based interface provides a graphical editor. The component web/source/vue/SettingCruise.vue renders individual waypoint rows for setting pan, tilt, speed, wait times, and detection modes. The parent Setting.vue (around line 1306) serializes the waypoint array back into the semicolon-separated CRUISE_LIST string before writing to hack.ini.

Debugging and Log Files

The cruise engine logs all activity to /tmp/log/cruise.log (line 65 of cruise.sh). Each executed command and motion event is timestamped, allowing verification that waypoints are reached and that waitMotion responses are received correctly.

Summary

  • Enable cruise mode by setting CRUISE=on in /tmp/hack.ini on the SD card.
  • Define waypoints using the CRUISE_LIST syntax with move, detect, follow, and sleep commands.
  • Motion tracking relies on the waitMotion command registered in libcallback/command.c and implemented in libcallback/wait_motion.c, which bridges OSD motion rectangles with shell-scriptable camera movements.
  • Speed values range from 1 (slow) to 9 (fast) for motorized moves.
  • Logs are written to /tmp/log/cruise.log for troubleshooting sequence execution.

Frequently Asked Questions

Which camera models support cruise waypoints and motion tracking?

The cruise feature is exclusive to the ATOM Swing model, as it requires motorized pan/tilt hardware. The motion-tracking logic specifically depends on the local_sdk_video_osd_update_rect callback available in the Swing’s firmware variant.

Can I run a cruise sequence without motion detection?

Yes. Omit detect and follow commands from CRUISE_LIST and use only move and sleep commands. The camera will patrol between angles and pause for fixed intervals without invoking the waitMotion handler.

What are the valid ranges for pan, tilt, and speed values?

According to the parser in cruise.sh, pan accepts 0–355 degrees, tilt accepts 0–180 degrees, and speed accepts 1–9. Values outside these ranges may cause the motor driver to ignore the command or return an error over the command socket.

Why does motion tracking fail to trigger even when movement is visible?

First, verify that motion detection is enabled in the camera’s base settings and that the OSD rectangle is being drawn. The wait_motion.c hook requires the camera motors to be idle for at least 0.5 seconds before reporting coordinates; if the camera is still moving from a previous move command, the callback will not fire. Check /tmp/log/cruise.log to confirm that waitMotion calls are being issued and whether "timeout" or "detect" responses are returned.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →