The AY-Robots SO-100 hub page, the starting point for building, teleoperating and training a low-cost SO-100 robot arm
Warehouse pickingSO-100ThroughputSmolVLAIndustrial robotsBenchmarks

Warehouse Picking With Cheap Arms: The Throughput You Get

AY-Robots ResearchAugust 23, 202622 min read

A published SO-100 pick-and-place cycle runs 9.7 seconds, about 370 attempts an hour. Here is how that compares to 400-600 for a human picker and 1,200 for a piece-picking cell.

A published pick-and-place cycle on an SO-100 takes 9.7 seconds. That figure comes from the SmolVLA paper, measured over ten trials with the cube starting in five different positions, with the model running in asynchronous mode. Synchronous mode took 13.75 seconds for the same task. Those two numbers are the honest starting point for any conversation about warehouse picking on cheap hardware, because everything else people say about low-cost arms is either a demo video or a press release.

9.7 seconds per cycle is about 371 attempts per hour if the arm never stops moving. A human order picker runs 400 to 600 picks per hour. A production piece-picking cell quotes a three second cycle. A packaging delta robot does a 25/305/25 mm cycle in 0.36 seconds with a 1 kg payload. So the low-cost arm is not off the chart. It is on the chart, at the bottom of it, on a much easier task than any of the others were measured on. This article works through where exactly it lands and what the gap is made of.

The short version

  • The best published SO-100 pick-and-place cycle is 9.7 s (async) versus 13.75 s (sync), from the SmolVLA paper. That is roughly 370 versus 260 attempts per hour before any success discount.
  • Multiply by the reported 75 percent Pick-Place score and you land near 270 successful transfers per hour, in the same band as the 2017 Amazon Robotics Challenge best of 272 picks per hour and below Dex-Net 4.0's 300 mean picks per hour.
  • Those benchmarks were on cluttered bins of novel objects. The SO-100 number was one known cube into one fixed box. Same order of magnitude, very different difficulty.
  • Cycle time is set by how fast your demonstrations were, not by GPU speed. Inference latency only costs you the idle frames, and asynchronous inference removes most of those.
  • The hard gap is not throughput. It is payload (well under 200 g), no published repeatability, no IP rating, no safety-rated stop functions, and no duty cycle spec.
  • An SO-100 is 110 to 150 EUR in parts. A UR5e lists at roughly 39,000 to 43,500 USD from a distributor. In a picking cell, neither number is the dominant cost.

Everyone publishes a different picks-per-hour

Picks per hour is the metric warehouses use, and it is close to useless without the conditions attached. Mean picks per hour (MPPH) as Berkeley uses it counts successful grasps per hour over a bin-clearing run, so failures already cost you throughput. A vendor machine rate counts the arm cycling between two totes with nothing going wrong. A challenge score counts items moved inside a fixed time window. Here are the figures I could verify, each with what it actually measured.

SystemRateTask it was measured onSource
ABB IRB 360-1/1130 delta0.36 s per cycle at 1 kg (10,000/h on paper); ABB text says up to 100 cycles/min for the 8 kg variant25/305/25 mm cycle, item presented in a known pose on a conveyorABB datasheet ROB0082EN_F, May 2013
RightHand Robotics RightPickas fast as a 3 s cycle, so about 1,200/hTote to tote piece picking, vendor machine raterighthandrobotics.com product page
Human order picker400 to 600 picks/h (400/h average cited)Real shelves, real ordersIEEE Spectrum and The Robot Report
Dex-Net 4.0 on an ABB YuMiover 300 MPPH at over 95 percent reliabilityBins of up to 25 novel objects, suction plus parallel jawScience Robotics, January 2019
Amazon Robotics Challenge 2017, bestup to 272 picks/h; stowing 25 to 160/hMixed items from clutter, unknown posesThe Robot Report, August 2017
Amazon Picking Challenge 2016 winnerabout 100 picks/h at a 17 percent failure rateShelf picking, mixed itemsThe Robot Report, August 2017
SO-100 with SmolVLA, async9.7 s per cycle, so about 371 attempts/hOne known cube, five start positions, one fixed box, no clutterSmolVLA paper, arXiv 2506.01844
SO-100 with SmolVLA, sync13.75 s per cycle, so about 262 attempts/hSame taskSmolVLA paper, arXiv 2506.01844

Read the fourth column before the second. The delta robot is fast because the item arrives in a known pose and the arm never has to decide anything. Dex-Net 4.0 and the challenge entries are slow because they are solving perception in clutter. The SO-100 number sits near the challenge entries while doing far less work, which tells you the bottleneck on cheap hardware is not the same bottleneck as in a warehouse.

One number in the SmolVLA paper does not reconcile, and that is worth knowing

The paper also reports a fixed-time experiment: asynchronous inference completed 19 successful pick-and-place cycles against 9 for synchronous, with the time limit written as "e.g., 60 seconds". Nineteen cycles in 60 seconds implies a 3.2 s cycle, which contradicts the 9.7 s mean from the same section. Treat the roughly 2x ratio as the reliable claim and the 9.7 s mean as the reliable absolute. Do not quote 19 cycles per minute at anyone.

What an SO-100 class arm actually is, next to the alternatives

The interesting thing about the SO-100 spec sheet is that there is no spec sheet. The build repository lists servos, gear ratios and prices. It does not publish a payload, a reach, a repeatability figure, a duty cycle or an ingress rating, because the arm was designed as a research and teaching platform, not as a machine you buy against a requirement. Compare that to what the two industrial reference points publish.

SO-100 / SO-101Universal Robots UR5eABB IRB 360-1/1130
Costabout 110 to 150 EUR in parts (SO-100), 130 to 170 EUR (SO-101)roughly 39,083 to 43,544 USD, distributor list, arm and controllernot publicly listed
Payloadnot published5 kg1 kg (3 kg and 8 kg variants exist)
Reachnot published850 mm1130 mm work area diameter
Repeatabilitynot publishedplus or minus 0.03 mm per ISO 92830.1 mm position repeatability
Mass3D printed plastic plus six bus servos20.6 kg arm including cable120 kg (145 kg stainless)
Ingress protectionnoneIP54 arm, IP44 control boxIP55, IP67 or IP69K depending on build
Safety functionsnone21 configurable, EN ISO 13849-1 PLd Cat 3, EN ISO 10218-1dual-circuit e-stop with supervision, 3-position enabling device
ActuationFeetech STS3215 bus servos at 7.4 Vharmonic-drive joints, built-in force/torque sensorparallel-kinematic delta, IRC5 controller

The row that ends the conversation for most warehouse deployments is the safety row, not the payload row. A UR5e ships 21 configurable safety functions certified to EN ISO 13849-1 PLd Category 3. An SO-100 ships none, because it is six hobby servos on a serial bus. You cannot put it next to a picker without a risk assessment that concludes it cannot hurt anyone, and the honest way to reach that conclusion is a fence or a cell.

7.4 V servos, and 12 V will destroy them

The SO-100 and SO-101 use Feetech STS3215 bus servos on a 7.4 V rail. There is a 12 V variant of the same servo with a higher stall torque, and the two look identical. Feeding 12 V into 7.4 V servos destroys them, quietly and permanently. Check the label on every servo before you power the bus for the first time, and check it again after any replacement. The Koch v1.1 uses Dynamixel motors on 5 V and 12 V rails, so if you own both arms you have two incompatible supplies on the same bench.

There is no payload figure, so do the arithmetic yourself

The build repository does give you one number to work from: the 7.4 V STS3215 has a stall torque of 16.5 kg.cm measured at 6 V, while the 12 V version is rated 30 kg.cm. Stall torque is not usable torque. A servo held near stall heats up and either derates or dies, so plan on a fraction of it. Reach is not published either, so measure your own arm.

python
# Static payload budget for the shoulder servo of a 7.4 V SO-100.
# Only input taken from a published source:
#   SO-ARM100 README: 7.4 V STS3215 stall torque 16.5 kg.cm (measured at 6 V).
stall_kgcm = 16.5

# Everything below is an assumption you should replace with your own measurement.
duty_fraction = 0.30          # what you dare hold continuously without cooking the servo
lever_cm      = 25.0          # horizontal shoulder-axis to gripper distance, arm extended

usable_kgcm = stall_kgcm * duty_fraction        # 4.95 kg.cm
payload_kg  = usable_kgcm / lever_cm            # 0.198 kg

print(f"{payload_kg*1000:.0f} g at full extension, BEFORE subtracting the mass")
print("of the forearm, wrist, gripper and cable that hang off the same joint.")
Replace duty_fraction and lever_cm with your own numbers. The point is the order of magnitude, not the third digit.

Under 200 g at full extension, before the arm carries its own forearm and gripper. In practice that means small parts, empty boxes, blister packs, cable ties and lab samples. It does not mean a 500 g shampoo bottle, and it certainly does not mean a case. If your pick list has a mass distribution, plot it before you plan anything else. The SO-100 against SO-101 comparison goes through where the newer arm helps, and it is mostly assembly and smoothness rather than load.

Cycle time is set by your demonstrations, not by your GPU

This is the part people get backwards. A policy trained by imitation learning moves at the speed of the data it was shown. If you teleoperated the demonstrations at a comfortable human pace, the policy reproduces that pace. Buying a faster card does not make the arm move faster; it only shortens the pause between action chunks.

The five policies you can train differ a lot in inference latency per action step, but action chunking amortises that cost. One forward pass produces a whole sequence of actions, which the arm then plays out at the recording frame rate. The table below shows what each model's latency costs as a share of a 50-action chunk played at 30 fps, which is the LeRobot async default.

PolicyLatency per action stepShare of a 50-action chunk at 30 fps (1.67 s)GPU tierMin episodes
ACT20 msabout 1 percentRTX 4090 or any 24 GB card50
GR00T N1.7152 msabout 9 percentA100 80 GB or H100 80 GB50
GR00T N1.5165 msabout 10 percentA100 80 GB or H100 80 GB50
SmolVLA245 msabout 15 percentRTX 4090 or any 24 GB card30
Pi0.5485 msabout 29 percentA100 80 GB or H100 80 GB50

Two readings follow from that column. First, none of these models is latency-bound for a slow pick cycle: even Pi0.5 finishes the next chunk with 70 percent of the current chunk still queued. Second, Pi0.5 is the one where a network hop starts to matter. Add 100 ms of public-internet round trip and it is using 35 percent of the window. The side-by-side policy comparison has the rest of the numbers.

The AY-Robots policies page showing the five trainable policies side by side with parameter counts, GPU tier, inference latency and minimum episode counts
The /policies comparison table. Latency per action step is the column that decides whether remote inference is viable for your cycle.
Asynchronous inference is the one free throughput win

In synchronous mode the arm sits still while the policy thinks, then executes the whole chunk, then sits still again. Asynchronous inference computes the next chunk while the current one is still playing, so the idle frames disappear. That is the entire difference between the SmolVLA paper's 13.75 s and 9.7 s cycles, roughly 30 percent, with no change to the model or the hardware. LeRobot ships it as lerobot.async_inference.policy_server and lerobot.async_inference.robot_client, with --actions_per_chunk defaulting to 50 and --chunk_size_threshold to 0.7.

So if you want a shorter cycle, the lever is the data. Record demonstrations faster, at the edge of what you can teleoperate cleanly. The cost is that fast motion produces motion blur and fewer frames per unit of travel, which makes the task harder to learn. There is a real trade-off there, and the data collection guide covers how to find the edge without falling off it.

Measure your own cycle before you trust anyone's number

Everything above is somebody else's cell, gripper and object. The only number that matters for your pick list is the one you measure. This is the shortest honest path from a bare arm to a cycle time, using the current LeRobot command-line tools as they exist in the repository's docs today.

  1. 1
    Find the port and set the servo IDs

    Every STS3215 leaves the factory with the same bus ID, so you write IDs once, per arm. Run the port finder with the arm unplugged, then plugged in, and it tells you which device appeared.

    bash
    lerobot-find-port
    
    lerobot-setup-motors \
        --robot.type=so101_follower \
        --robot.port=/dev/tty.usbmodem585A0076841
  2. 2
    Calibrate both arms

    Calibration writes the joint limits and zero offsets to a file keyed by --robot.id. Skip it and the policy will learn your offsets as part of the task, which is one of the classic reasons a policy only works in one setup.

    bash
    lerobot-calibrate \
        --robot.type=so101_follower \
        --robot.port=/dev/tty.usbmodem58760431551 \
        --robot.id=picker_follower
    
    lerobot-calibrate \
        --teleop.type=so101_leader \
        --teleop.port=/dev/tty.usbmodem575E0031751 \
        --teleop.id=picker_leader
  3. 3
    Record the pick, timed to your actual cycle

    The defaults are --dataset.episode_time_s=60, --dataset.reset_time_s=60 and --dataset.num_episodes=50, which is 100 minutes of wall clock. If your pick takes 12 seconds, cut the episode to 20 s and the reset to 10 s and you record the same 50 episodes in 25 minutes.

    bash
    lerobot-record \
        --robot.type=so101_follower \
        --robot.port=/dev/tty.usbmodem585A0076841 \
        --robot.id=picker_follower \
        --robot.cameras="{ top: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30} }" \
        --teleop.type=so101_leader \
        --teleop.port=/dev/tty.usbmodem575E0031751 \
        --teleop.id=picker_leader \
        --dataset.repo_id=${HF_USER}/tote-transfer \
        --dataset.single_task="Pick the part from the left tote and drop it in the right tote" \
        --dataset.num_episodes=50 \
        --dataset.episode_time_s=20 \
        --dataset.reset_time_s=10 \
        --dataset.fps=30
  4. 4
    Check the cadence report before you train

    lerobot-record paces the loop at --dataset.fps and prints what it actually achieved, per episode and for the session. If your effective cadence is well under target, the dataset already encodes stalls that the policy will learn to imitate.

    text
    Cadence (episode 0): 29.88 Hz vs 30 Hz target - 600 ticks, 20.0 s measured
      8/599 ticks over the 33.3 ms budget (work mean 18.4 ms, worst 45.1 ms)
  5. 5
    Train, then roll out for a fixed duration and count

    lerobot-rollout takes a --duration in seconds. Run it for 600 s, count the successful transfers, and multiply by six. That is your picks per hour, measured the same way the benchmarks above measure theirs.

    bash
    lerobot-train \
      --dataset.repo_id=${HF_USER}/tote-transfer \
      --policy.type=smolvla \
      --policy.device=cuda \
      --policy.repo_id=${HF_USER}/tote-policy
    
    lerobot-rollout \
      --strategy.type=base \
      --policy.path=${HF_USER}/tote-policy \
      --robot.type=so101_follower \
      --robot.port=/dev/tty.usbmodem585A0076841 \
      --task="Pick the part from the left tote and drop it in the right tote" \
      --duration=600
  6. 6
    Repeat with the async stack and compare

    Start the policy server, point the robot client at it, and run the same 600 s window. The delta between the two runs is your version of the 13.75 s to 9.7 s result.

    bash
    # terminal 1, on the machine with the GPU
    python -m lerobot.async_inference.policy_server \
         --host=127.0.0.1 \
         --port=8080
    
    # terminal 2, on the machine holding the arm
    python -m lerobot.async_inference.robot_client \
        --server_address=127.0.0.1:8080 \
        --robot.type=so101_follower \
        --robot.port=/dev/tty.usbmodem585A0076841 \
        --robot.id=picker_follower \
        --policy_type=smolvla \
        --pretrained_name_or_path=${HF_USER}/tote-policy \
        --policy_device=cuda \
        --actions_per_chunk=50 \
        --chunk_size_threshold=0.7 \
        --task="Pick the part from the left tote and drop it in the right tote"

If the arm sags between cycles or a joint stops short of where the demonstration went, stop and fix the hardware before you blame the policy. The failure-mode pages for an arm that twitches then sags and for a gripper that will not close cover the two that eat the most time on a picking task, because both look exactly like a bad policy from the outside.

Two routes to the same measured number

Everything above runs on your own machine. You need the arms built and calibrated, a GPU that fits the model, and the patience to keep a recording session consistent for an hour.

  1. Build or buy the arm. The parts bill is public, and the build repository lists every servo, screw and 3D printed part with sources.
  2. Install LeRobot, wire the servo IDs with lerobot-setup-motors, calibrate with lerobot-calibrate.
  3. Record 30 to 50 episodes with lerobot-record, watching the cadence report.
  4. Train with lerobot-train --policy.type=smolvla or act on a local 24 GB card, or rent one.
  5. Roll out with lerobot-rollout --duration=600 and count successes by hand.
  6. Repeat under lerobot.async_inference to recover the idle frames.
The part that eats the day

A LeRobot v3.0 dataset crashes the GR00T loader. If you record with a current LeRobot and then decide to try GR00T, you have to convert the dataset down to v2.1 first. Nothing warns you before the run fails. GR00T's fine-tuning entry point (Isaac-GR00T launch_finetune.py, a tyro CLI) also exposes no seed, so two GR00T runs on identical data are not bit-for-bit reproducible. lerobot's default seed is 1000.

The trade you are making is control against calendar time. Nobody is in your way, and nobody has set the hyperparameters for you either.

Where the gap actually is

Low-cost arms for picking work
What holds up
  • Throughput is in the right order of magnitude for slow, single-station transfer work: roughly 250 to 370 attempts per hour measured, against 400 to 600 for a human picker.
  • Perception generalisation comes from the model, not the arm. The SmolVLA paper reports 78.3 percent average across three SO-100 tasks against 61.7 for a 7x larger model and 48.3 for ACT.
  • The ACT result that started this whole line of work was explicitly about getting precise behaviour out of imprecise hardware, with 80 to 90 percent success on six tasks from ten minutes of demonstrations.
  • Capital risk is near zero. 110 to 150 EUR of parts lets you find out whether a task is learnable before anyone signs a purchase order.
  • Slow cycles make remote inference genuinely workable, which is the one case where cloud GPUs are not a latency problem.
  • A failed pilot costs a weekend, not a quarter.
What does not
  • Payload is well under 200 g at extension. Most warehouse SKUs are heavier than that.
  • No published repeatability, no ingress rating, no duty cycle, no thermal derating curve. You cannot write a requirement against a spec that does not exist.
  • No safety-rated stop functions at all, against 21 configurable ones on a UR5e certified to EN ISO 13849-1 PLd Cat 3.
  • Position is held by servo torque alone. Cut the power and the arm sags, along with whatever it was holding.
  • Published SO-100 results are single known objects into fixed containers. Nobody has shown cluttered-bin novel-object picking at these rates on this hardware.
  • The 9.7 s figure excludes tote presentation, barcode scanning, exception handling and the reset that a human performed between trials.

Notice which of those are hardware and which are evidence. The payload, the brakes and the safety functions are physics and certification, and no amount of training fixes them. The cluttered-bin gap is an evidence gap: it may well close, and the model arena, which tracks 85 VLA models across 332 benchmark results with every value linked to its paper or model card, is where you would see it close first.

The AY-Robots public dataset directory listing LeRobot-format datasets available for training
The /directory listing. Before recording your own picking data, check whether a comparable task is already in there.

The picking work a cheap arm does fit

Rather than asking whether a 130 EUR arm can replace a picker, ask which jobs have the shape it is good at: light parts, a fixed station, a slow rate, a human nearby anyway, and no consequence if a cycle fails. There are more of those in a real building than people expect.

  • Kitting light components into a tray. Fixed geometry, one SKU per run, parts under 200 g. This is the shape the published results actually match.
  • Feeding a test rig or an inspection station. The rate is set by the instrument, not the arm, and it is usually one item every 20 to 60 seconds.
  • Sample handling in a lab. Small, light, repetitive, already inside a fume hood or an enclosure, so the safety question is answered by the room.
  • Proving a task is learnable before buying a cell. Record 50 episodes, train, roll out for ten minutes, count. That answers the feasibility question for the price of a weekend.
  • Collecting demonstration data for a policy you intend to run on better hardware later. The cross-embodiment argument is that the data has value beyond the arm that recorded it.
  • Training and evaluating operators. A bench arm is a cheap way to find out who can teleoperate cleanly before you put them on real equipment.

What all six have in common is that they do not need the arm to be reliable in the industrial sense. They need it to be cheap enough that a 20 percent failure rate is an annoyance rather than a line stoppage. A vision-language-action model on a 130 EUR arm is a good answer to a feasibility question and a bad answer to a throughput question.

What the experiment costs

The arm is not the expensive part, and neither is the training. Both are rounding errors against the cost of a single day of somebody's time integrating anything.

ItemCostNote
SO-100 partsabout 110 to 150 EURFeetech STS3215 bus servos, 7.4 V, full support as the reference arm
SO-101 partsabout 130 to 170 EURSame servo family, easier assembly
Koch v1.1 partsabout 250 to 350 EURDynamixel XL330 / XL430, 5 V and 12 V rails, compatible
LeKiwi partsabout 400 to 500 EURMobile base, 7.4 V arm and 12 V base, compatible
One SmolVLA or ACT runabout 1 to 3 USDRTX 4090 or any 24 GB card, 2 to 5 hours at 0.30 to 0.60 USD/hour on the spot market
One GR00T or Pi0.5 runabout 4 to 12 USDA100 80 GB or H100 tier, 3 to 6 hours at 1.20 to 2.00 USD/hour
The AY-Robots pricing page showing what a training run costs by GPU tier
The /pricing page. Spot-market GPU rental means a run is priced in single-digit dollars, which is why a failed picking pilot is cheap.

Five runs to find hyperparameters that work is 15 USD on the small tier. That budget is the actual argument for cheap arms in picking research: not that they will run your warehouse, but that finding out costs less than the meeting where you discuss whether to find out. The training documentation covers what the form sends, and the three ways to start without a robot covers the case where you do not have an arm on the bench yet.

What would have to change

If you want to know whether this gets better, watch four things rather than the demo videos. First, payload: a 12 V servo variant already exists at 30 kg.cm stall against 16.5, and a redesign around it moves the ceiling without changing the software. Second, cluttered-bin results on low-cost hardware, which is where the published evidence stops today. Third, whether async inference plus faster demonstrations pushes the measured cycle below about 6 seconds, which would put a single station near 600 attempts per hour. Fourth, safety, which is the one that cannot be solved by better models and will decide whether any of it ever leaves a fenced cell.

None of that is close. It is also not the reason to ignore the hardware. The reason to keep an SO-100 on the bench is that it turns an argument about feasibility into a measurement, for the price of a takeaway meal. If you want to see one move before you buy anything, there is a physical arm streaming with no signup, and the full SO-100 setup guide covers the build end to end.

Questions people actually ask

How many picks per hour can an SO-100 actually do?

The best published figure is 9.7 seconds per pick-and-place cycle with SmolVLA in asynchronous mode, from the SmolVLA paper, which is about 371 attempts per hour if the arm never stops. The same paper reports 13.75 seconds in synchronous mode, about 262 per hour. Apply the reported 75 percent Pick-Place score and you land near 270 successful transfers per hour. That was one known cube into one fixed box with a human resetting between trials, so treat it as a ceiling for an easy task rather than a warehouse rate.

Does a faster GPU give me a shorter cycle time?

Barely. The policy plays out a chunk of actions at the recording frame rate, so the arm moves at the speed of your demonstrations. A faster card only shortens the pause between chunks, and asynchronous inference removes most of that pause anyway. If you want a faster cycle, record faster demonstrations, and accept that motion blur and fewer frames per unit of travel make the task harder to learn.

How much can an SO-100 lift?

Nobody publishes a payload for it. Working from the one figure the build repository does give, a 16.5 kg.cm stall torque for the 7.4 V STS3215 measured at 6 V, and assuming you hold no more than 30 percent of stall at a 25 cm lever, you get under 200 g at full extension before the arm's own forearm and gripper are subtracted. Measure your own lever arm and redo the arithmetic; the order of magnitude is the point.

Can I run inference in the cloud for a picking task?

For a slow pick-and-place cycle, yes. The control loop is 20 to 485 ms per action step depending on the model, and action chunking means one inference covers seconds of motion, so a network round trip fits inside the window. For fast reactive motion it does not work: public-internet latency on top of a 485 ms Pi0.5 step turns a working policy into a hesitant one. Pods carry an idle watchdog and destroy themselves after an idle period, so a forgotten pod does not keep billing.

Is a low-cost arm safe to run next to warehouse staff?

Not without a risk assessment that you conduct yourself. A UR5e ships 21 configurable safety functions certified to EN ISO 13849-1 PLd Category 3 and EN ISO 10218-1. An SO-100 ships none, has no ingress rating, and holds position only while the servos are powered, so a power cut drops the arm and whatever it holds. The realistic deployment is inside a cell or an enclosure that answers the question on the arm's behalf.

Which policy should I train first for a picking task?

SmolVLA, because it needs only 30 episodes against 50 for the others, runs on an RTX 4090 or any 24 GB card, costs about 1 to 3 USD per run, and is the model the published SO-100 cycle-time numbers were measured with. ACT is the cheapest to serve at 20 ms per action step but has no base model, so it only exists after you train it on your task. Start with SmolVLA, then compare.

Find out what your pick cycle costs before you commit to anything

A SmolVLA or ACT run is 1 to 3 USD on a 24 GB card. A GR00T or Pi0.5 run is 4 to 12 USD on the A100 tier. Five runs to find working hyperparameters costs less than the meeting about whether to try.

See what a run costs

Ready for high-quality robotics data?

AY-Robots connects your robots to skilled operators worldwide.

Get Started