Install the Digital Net, calibrate it, and go live.
How to put Orbital's camera system around a robot work cell: plan the layout, mount and cable the cameras, isolate the network, calibrate against floor markers, map the floor from the cameras, and run your first validated task.
00 · BEFORE YOU START
Kit list
One cell covers one robot work area. Order for the cell you are instrumenting; add cameras, not edge nodes, as the area grows.
| ITEM | SPEC | QTY | EXAMPLE |
|---|---|---|---|
| Industrial PoE cameras | Global shutter, 60 fps, PoE+, IEEE 1588 (PTP) sync | 8–16 | Basler acA1920-40gc, FLIR BFS-PGE-50S5C |
| GPU edge server | NVIDIA RTX 4000 SFF Ada, 64 GB RAM, dual 10 GbE | 1 | Dell PowerEdge XR4520c |
| Managed PoE+ switch | 24-port, PoE+, VLANs, PTP boundary clock | 1 | Cisco Catalyst 1000 |
| Wi-Fi 6 access points | 802.11ax, VLAN tagging, for the robot network | 2 | Aruba AP-635 |
| Floor markers | ArUco 4×4, 15 cm, laminated, IDs 0–10 (more for large floors) | 12+ | Print in-house |
| Robot top-plate tags | ArUco 15 cm, one unique ID per robot | 1 per robot | Print in-house |
| Cable and mounts | Shielded Cat6A, ceiling or truss camera mounts, cable trays | ~50 m | Any |
| Tape measure / laser | To place the origin and anchor markers | 1 | Any |
01 · PLAN THE CELL
Ring the work area with cameras.
Orbital places things in 3-D by seeing them from two or more cameras at once, so overlap matters more than coverage.
- Every point in the work area is seen by at least two cameras, from directions at least ~30° apart. One view gives a direction, not a position.
- Neighbouring cameras overlap. Calibration chains cameras together through markers they both see.
- Start with 8 cameras on a ring for a cell up to about 12 × 8 m; go to 12–16 for long aisles, tall racks or heavy occlusion.
- Avoid pointing straight into windows or skylights. Keep lighting steady; global-shutter sensors handle motion, not glare.
- Mark the robot's routes and stations on your sketch. You'll use them for the first golden run in step 08.
02 · MOUNT AND CABLE
High, angled in, and fixed.
A camera that moves after calibration is wrong until it is re-calibrated, so rigid mounts are worth the effort.
- Mount each camera about 4.5 m up on the ceiling or a truss, on a rigid bracket. Lower mounts see less floor; higher mounts lose resolution on small markers.
- Aim at robot working height (about 0.6 m above the floor) at the far side of the work area, so the field of view crosses the cell.
- Run shielded Cat6A to the PoE+ switch. One cable carries power, video and the PTP clock.
- Enable PTP (IEEE 1588) on the switch and cameras so every frame is time-stamped on the same clock. Unsynced frames break triangulation on moving robots.
- Write down each camera's position and aim point in metres from your floor origin. That becomes the rig file in step 06.
03 · ISOLATE THE NETWORK
Three VLANs, one way out.
Cameras and robots never touch the internet. Only the edge node talks to the Orbital cloud, outbound, over mutual TLS.
- Create VLANs 10, 20 and 30 on the managed switch: cameras, robots, edge management.
- Block egress from VLANs 10 and 20, then prove it: from a device on each, a public address must not answer.
- Dual-home or trunk the edge node to all three VLANs.
- Issue mTLS certificates and install the client pair on the edge node. The cloud requires the client certificate.
- Create the SROS2 keystore so only the pose, waypoint and safety-halt nodes can publish to robots.
# on a trusted machine: CA, edge client and cloud server certs ./scripts/gen_mtls_certs.sh # on the edge node export ORBITAL_MTLS_CERT=/etc/aria/edge-client.pem export ORBITAL_MTLS_KEY=/etc/aria/edge-client.key export ORBITAL_MTLS_CA=/etc/aria/orbital-ca.pem # ROS 2 Humble+: lock down who can command robots ros2 security create_keystore /etc/aria/sros2_keystore ros2 security create_enclave /etc/aria/sros2_keystore /aria_safety_halt export ROS_SECURITY_ENABLE=true ROS_SECURITY_STRATEGY=Enforce
ARIA_UNITREE_HARDWARE=1) on a routable network.04 · INSTALL THE EDGE NODE
Install, point at the cloud, self-check.
The edge node runs the camera pipeline, the safety halt and the robot adapters on site. The cloud only ever sees what it sends out.
# edge node (Ubuntu 22.04 + ROS 2 Humble) git clone https://github.com/ugobe007/Orbital_AI.git && cd Orbital_AI pip install -r requirements.txt -r requirements-hw.txt sudo apt install ros-humble-rclpy ros-humble-tf2-ros # who this site is and where it reports export ARIA_FACILITY_ID=facility-sf-001 export ORBITAL_CLOUD_URL=https://orbital-ai.io export ARIA_CLOUD_SYNC=1 # self-check: which gates are green, which need the lab python3 scripts/check_hardware_gate.py python3 scripts/lab_cutover.py --bench
- Use your facility ID everywhere. The same ID goes on calibration, map and run uploads, and it names the site in the console.
- Leave
ARIA_CV_MODEatsimuntil calibration passes in step 05, then switch toarucofor the live camera path. check_hardware_gate.pylists what's green in software and which steps still need the floor. Keep its output in your install log.
05 · CALIBRATE THE RIG
Tape markers, capture, solve.
The solver ties every camera to one floor frame and tells you by name which marker or camera disagrees.
- Tape floor markers so every camera sees at least two and neighbouring cameras share at least one.
- Pick an origin marker and tape-measure its floor position, then measure one anchor marker a few metres away. Two known points fix scale and heading.
- Capture each camera (or walk a handheld pass) and export one JSON per view into
captures/. - Solve and upload, then fix what the report names. Re-run until it prints
Rig is clean.
python3 scripts/calibrate_rig.py captures/ \ --origin 0 --origin-pose 2.0:2.0 \ --anchor 3:12.5:2.0 \ --out marker_map.json \ --upload "$ORBITAL_CLOUD_URL" --facility "$ARIA_FACILITY_ID" # exit 0 = every residual under 5 cm (ORBITAL_CALIB_RESIDUAL_M) # exit 1 = the report names what to fix
| THE REPORT SAYS | WHAT IT MEANS | DO THIS |
|---|---|---|
| Marker N · likely bumped | Cameras agree with each other but not on where that marker is | Re-seat or re-tape the marker, re-capture |
| Capture N · camera moved | A camera's solved pose is far from where you said it was mounted | Tighten the mount or update its position in the rig file |
| Marker N · not linked | No chain of shared markers connects it to the origin | Add a capture that sees it and a linked marker |
| Marker N · seen once | Only one view, so nothing to check it against | Add an overlapping camera or capture |
| Capture N · poor fit | High residual across all of a camera's markers | Check focus, lens distortion and that it's the right camera ID |
06 · MAP THE FLOOR
Let the cameras draw the map.
Instead of typing in obstacles, Orbital triangulates what the cameras see and marks the floor cells that are blocked. Robots route around them.
- Write the rig file from step 02: each camera's ID, focal length, resolution, mounted position and aim point, in metres. Check it against the poses calibration solved.
- Park a pallet in an aisle as a test obstacle.
- Run the mapper and upload. It exits 1 if too many points disagree, which almost always means a camera moved: go back to step 05.
- Check the console map: the pallet shows as grey blocked cells, and a robot sent down that aisle routes around it.
# rig.json
{"cameras": [
{"id": "dn-1", "fx": 1100, "width": 1920, "height": 1200,
"position": [19.5, 7.5, 4.5], "look_at": [13.5, 7.5, 0.6]},
...
]}
python3 scripts/map_from_cameras.py rig.json frames.json \
--upload "$ORBITAL_CLOUD_URL" --facility "$ARIA_FACILITY_ID"
07 · TAG AND CONNECT ROBOTS
Give every robot a tag and a scoped API.
The tag lets the cameras track each robot independently of what it reports about itself. The API connection lets Orbital correct it.
- Mount a 15 cm ArUco tag flat on each robot's top plate, centred, with an ID not used by any floor marker. Record the marker-to-robot map.
- Put robots on VLAN 20 and confirm the edge node reaches them (ROS 2 DDS, gRPC or the OEM's REST API).
- Onboard the fleet in the console with Onboard robot API. Grant only the scopes you want Orbital to use: telemetry, state, velocity, E-Stop, mission, map.
- Switch the edge to live cameras and run the latency bench. Waypoint injection must hold p95 ≤ 100 ms at 10 Hz.
export ARIA_CV_MODE=aruco
export ARIA_ARUCO_MARKER_MAP=/etc/aria/marker_map.json
export ARIA_UNITREE_HARDWARE=1 # per-OEM adapter
python3 -c "
from fleet_adapters import get_adapter
from aria_edge.latency_bench import LatencyBench
a = get_adapter('Unitree', 'rbt-01', use_hardware=True)
print(LatencyBench(hz=10, samples=30).run(a).as_dict())"
08 · GO LIVE AND VALIDATE
Record a golden run. Measure everything against it.
A deployment is proven by numbers, not by "it works": the same task, robot and floor, with and without Orbital's camera correction.
- Pick one repeatable task between two marked stations, for example
Aisle AB → Dock. - Run it once cleanly. The first complete run with no safety halts becomes the task's golden run in the console's Validation panel; you can promote a different one.
- Alternate conditions, baseline (robot's own SLAM) then Orbital correction, at least 10 complete runs each.
- Generate the results sheet. It refuses simulator runs and flags thin samples, so a sheet that exits 0 is safe to quote.
- Export the runs as training data once the task is stable.
python3 scripts/lab_report.py --url "$ORBITAL_CLOUD_URL" \ --site "SF lab, rbt-01" --latency bench.json \ --calibration marker_map.json --out results.md python3 scripts/export_dataset.py --url "$ORBITAL_CLOUD_URL" \ --task "Aisle AB → Dock" --out dataset/
DAY-ONE SUCCESS
- Camera and robot VLANs cannot reach the public internet
- Rig calibration exits 0 and the console's Rig Calibration panel reads clean
- A test pallet shows as blocked cells and robots route around it
- Each robot's tag is tracked on the console map
- Waypoint injection p95 ≤ 100 ms at 10 Hz
- A golden run exists for the first task
TROUBLESHOOTING
When something doesn't line up
Almost every problem traces back to one of three things: a camera moved, a marker moved, or clocks drifted apart.
| SYMPTOM | LIKELY CAUSE | FIX |
|---|---|---|
map_from_cameras.py exits 1 | Too many points rejected; it names the worst cameras | Re-run calibration (step 05); re-tighten or update that camera |
| Blocked cells smear behind moving things | Cameras not PTP-synced | Check the PTP boundary clock on the switch and each camera |
| Robot jumps between two spots on the map | Tag ID reused by a floor marker, or two robots share an ID | Give each robot a unique tag ID and update the marker map |
| Robots halt often with drift alerts | Onboard SLAM disagrees with the cameras by more than the halt threshold | Confirm calibration is clean, then review the robot's route for poor coverage |
| Latency p95 over 100 ms | Wi-Fi contention or edge overload | Move robots to a dedicated SSID or AP; check edge GPU load |
| Console shows no data for the site | Wrong facility ID or the mTLS handshake fails | Match ARIA_FACILITY_ID everywhere; check ORBITAL_MTLS_* paths |