SOLUTIONS

Mini Automated Guided Vehicle (mini AGV) Robot

A mini AGV is a compact, self-driving vehicle that carries a light load from one point to another and hands it off on its own. Put a few on the floor, or a few hundred — the layout is software, not steelwork.

Handoffs0
Vehicles0
Stations0
FaultsNone
Illustration of fleet behaviour — not live data
/* ---------- palette + sizing (edit these) ---------- */ .magv{ --magv-height: 300px; --magv-deck: #CFD0CC; /* floor */ --magv-grid: #B4B6B1; /* floor markers, shadows */ --magv-accent: #E9A70B; /* the vehicles */ --magv-accent-d: #A0700A; /* vehicle detail + live figure */ --magv-ink: #16181A; --magv-ink-2: #5B6165; --magv-ink-3: #878C8F; --magv-line: #C4C6C1; /* borders */ --magv-surface: #F1F1EF; /* stats bar, pick-up station */ --magv-load: #C4B08B; /* the carried item */ --magv-load-2: #E2D6BC; /* its label */ --magv-station: #9EA3A0; --magv-station-2: #7E8481; --magv-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --magv-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace; } /* dark palette — applied when the visitor prefers dark and scheme is auto */ @media (prefers-color-scheme: dark){ .magv[data-scheme="auto"]{ --magv-deck: #1F2326; --magv-grid: #333A3E; --magv-accent: #F5B92B; --magv-accent-d: #F5B92B; --magv-ink: #ECEDEA; --magv-ink-2: #9BA1A5; --magv-ink-3: #6E7579; --magv-line: #2E3335; --magv-surface: #1B1E21; --magv-load: #9C8A68; --magv-load-2: #C4B593; --magv-station: #41474A; --magv-station-2: #2C3134; } } /* ...or when you force it */ .magv[data-scheme="dark"]{ --magv-deck: #1F2326; --magv-grid: #333A3E; --magv-accent: #F5B92B; --magv-accent-d: #F5B92B; --magv-ink: #ECEDEA; --magv-ink-2: #9BA1A5; --magv-ink-3: #6E7579; --magv-line: #2E3335; --magv-surface: #1B1E21; --magv-load: #9C8A68; --magv-load-2: #C4B593; --magv-station: #41474A; --magv-station-2: #2C3134; } /* ---------- structure ---------- */ .magv, .magv *{ box-sizing: border-box; } .magv{ width: 100%; font-family: var(--magv-font); } .magv__frame{ border: 1px solid var(--magv-line); border-radius: 14px; background: var(--magv-deck); overflow: hidden; } .magv__canvas{ display: block; width: 100%; height: var(--magv-height); max-width: 100%; } .magv__bar{ display: flex; flex-wrap: wrap; align-items: center; border-top: 1px solid var(--magv-line); background: var(--magv-surface); } .magv__stat{ display: flex; align-items: baseline; gap: 9px; padding: 11px 20px; border-right: 1px solid var(--magv-line); font-family: var(--magv-mono); font-size: 11px; line-height: 1.4; letter-spacing: .12em; text-transform: uppercase; color: var(--magv-ink-3); } .magv__stat b{ font-size: 14px; font-weight: 600; letter-spacing: .02em; color: var(--magv-ink); font-variant-numeric: tabular-nums; } .magv__stat--live b{ color: var(--magv-accent-d); } .magv__note{ margin-left: auto; padding: 11px 20px; font-family: var(--magv-mono); font-size: 10px; line-height: 1.4; letter-spacing: .09em; text-transform: uppercase; color: var(--magv-ink-3); } @media (max-width: 760px){ .magv__note{ margin-left: 0; width: 100%; border-top: 1px solid var(--magv-line); } .magv__stat{ padding: 10px 14px; } } (function () { 'use strict'; function initAll() { var nodes = document.querySelectorAll('.magv'); for (var i = 0; i < nodes.length; i++) init(nodes[i]); } function init(root) { if (root.getAttribute('data-magv-ready') === '1') return; // don't double-init root.setAttribute('data-magv-ready', '1'); var cv = root.querySelector('.magv__canvas'); if (!cv || !cv.getContext) return; var ctx = cv.getContext('2d'); var elCount = root.querySelector('[data-magv="count"]'); var elBots = root.querySelector('[data-magv="bots"]'); var elStations = root.querySelector('[data-magv="stations"]'); var motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); var W = 0, H = 0, dpr = 1; var deckTop = 0, deckBot = 0, rw = 30, rh = 20; var lanes = [], stations = [], pickup = { x: 0, y: 0, w: 0, h: 0 }; var bots = [], done = 0; var rafId = null, last = 0, running = false; var C = {}; function readTokens() { var s = getComputedStyle(root); function g(n) { return s.getPropertyValue(n).trim(); } C = { deck: g('--magv-deck'), grid: g('--magv-grid'), accent: g('--magv-accent'), accentD: g('--magv-accent-d'), ink: g('--magv-ink'), ink2: g('--magv-ink-2'), ink3: g('--magv-ink-3'), line: g('--magv-line'), surface: g('--magv-surface'), load: g('--magv-load'), load2: g('--magv-load-2'), station: g('--magv-station'), station2: g('--magv-station-2'), mono: g('--magv-mono') || 'monospace' }; } function rr(x, y, w, h, r) { r = Math.min(r, w / 2, h / 2); ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r); ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath(); } function layout() { var bandH = Math.max(38, Math.min(58, H * 0.19)); var pad = 9; var pickW = Math.max(58, Math.min(92, W * 0.085)); deckTop = bandH + pad; deckBot = H - bandH - pad; rw = Math.max(22, Math.min(34, W * 0.031)); rh = rw * 0.66; lanes = []; var n = 4, usable = deckBot - deckTop; for (var i = 0; i < n; i++) lanes.push(deckTop + usable * (i + 0.5) / n); var startX = pickW + 16; var avail = W - startX - 12; var gap = Math.max(9, W * 0.012); var target = Math.max(50, Math.min(76, W * 0.062)); var count = Math.max(3, Math.round((avail + gap) / (target + gap))); var cw = (avail - gap * (count - 1)) / count; stations = []; for (var s = 0; s < 2; s++) { for (var j = 0; j < count; j++) { stations.push({ x: startX + j * (cw + gap), w: cw, y: s === 0 ? pad : H - bandH - pad, h: bandH - pad, side: s === 0 ? 'top' : 'bot', id: (s === 0 ? 'A' : 'B') + (j + 1), fill: Math.random() * 0.55, flash: 0, swap: 0 }); } } pickup = { x: 7, y: deckTop, w: pickW - 14, h: deckBot - deckTop }; if (elStations) elStations.textContent = String(stations.length); } function assign(b) { var ahead = []; for (var i = 0; i b.x + rw) ahead.push(stations[i]); } var pool = ahead.length ? ahead : stations; var c = pool[(Math.random() * pool.length) | 0]; b.station = c; b.targetX = c.x + c.w / 2; b.edgeY = c.side === 'top' ? deckTop + rh * 0.62 : deckBot - rh * 0.62; return c; } function respawn(b, seed) { b.lane = (Math.random() * lanes.length) | 0; b.homeY = lanes[b.lane]; b.y = b.homeY; b.speed = 50 + Math.random() * 32; b.tipT = 0; b.state = 'carry'; if (seed) { b.x = pickup.x + pickup.w + Math.random() * Math.max(40, W - pickup.w - 60); b.alpha = 1; } else { b.x = pickup.x + pickup.w * 0.55; b.alpha = 0; } assign(b); if (seed && b.x > b.targetX) b.state = 'return'; } function build() { var want = Math.max(6, Math.min(14, Math.round(W / 82))); bots = []; for (var i = 0; i = b.targetX) { b.x = b.targetX; b.state = 'approach'; } } else if (b.state === 'approach') { var dy = b.edgeY - b.y; b.y += (dy > 0 ? 1 : -1) * Math.min(Math.abs(dy), 78 * dt); if (Math.abs(dy) = 1) { b.tipT = 1; b.state = 'return'; done++; b.station.flash = 1; b.station.fill += 0.11; if (b.station.fill >= 1) { b.station.fill = 0; b.station.swap = 1; } } } else { b.x += b.speed * 1.3 * dt; var d2 = b.homeY - b.y; b.y += (d2 > 0 ? 1 : -1) * Math.min(Math.abs(d2), 64 * dt); if (b.x > W + 40) respawn(b, false); } if (b.state === 'return' && b.x > W - 56) b.alpha = Math.max(0, (W + 24 - b.x) / 80); else b.alpha = Math.min(1, b.alpha + dt * 2.4); } function drawStation(c) { var openH = 6, top = c.y; ctx.fillStyle = C.station; rr(c.x, top, c.w, c.h, 4); ctx.fill(); if (c.fill > 0.02) { ctx.fillStyle = C.station2; var fh = (c.h - openH - 4) * c.fill; rr(c.x + 3, top + c.h - 3 - fh, c.w - 6, fh, 3); ctx.fill(); } ctx.fillStyle = C.station2; if (c.side === 'top') rr(c.x, top + c.h - openH, c.w, openH, 3); else rr(c.x, top, c.w, openH, 3); ctx.fill(); if (c.flash > 0.01) { ctx.strokeStyle = C.accent; ctx.globalAlpha = c.flash; ctx.lineWidth = 2; rr(c.x - 1, top - 1, c.w + 2, c.h + 2, 5); ctx.stroke(); ctx.globalAlpha = 1; } if (c.swap > 0.01) { ctx.fillStyle = C.accent; ctx.globalAlpha = c.swap * 0.35; rr(c.x, top, c.w, c.h, 4); ctx.fill(); ctx.globalAlpha = 1; } if (c.w > 40) { ctx.fillStyle = C.ink3; ctx.font = '600 9px ' + C.mono; ctx.textAlign = 'center'; ctx.textBaseline = c.side === 'top' ? 'top' : 'bottom'; ctx.fillText(c.id, c.x + c.w / 2, c.side === 'top' ? top + 5 : top + c.h - 5); } } function drawBot(b) { var t = b.state === 'tip' ? b.tipT : 0; var dir = b.station && b.station.side === 'top' ? -1 : 1; var tilt = t > 0 ? Math.sin(Math.PI * Math.min(1, t * 1.25)) * 0.34 * dir : 0; var carrying = b.state === 'carry' || b.state === 'approach' || b.state === 'tip'; var pw = rw * 0.6, ph = rh * 0.52, pOff = 0, pAlpha = 1; if (b.state === 'tip') { var e = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2; pOff = e * (rh * 0.5 + 30) * dir; pAlpha = 1 - Math.max(0, (t - 0.5) / 0.5); } ctx.save(); // shadow ctx.fillStyle = C.grid; ctx.globalAlpha = b.alpha * 0.35; ctx.beginPath(); ctx.ellipse(b.x, b.y + rh * 0.62, rw * 0.5, rh * 0.2, 0, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = b.alpha; // chassis (tilts when handing off) ctx.save(); ctx.translate(b.x, b.y); ctx.rotate(tilt); ctx.fillStyle = C.accent; rr(-rw / 2, -rh / 2, rw, rh, rh * 0.34); ctx.fill(); ctx.fillStyle = C.accentD; ctx.globalAlpha = b.alpha * 0.32; rr(-rw / 2 + 2.5, -rh / 2 + 2, rw - 5, rh - 4, rh * 0.26); ctx.fill(); ctx.globalAlpha = b.alpha; ctx.fillStyle = C.ink; ctx.globalAlpha = b.alpha * 0.7; rr(rw / 2 - 6, -1.4, 3.4, 2.8, 1.4); ctx.fill(); ctx.globalAlpha = b.alpha; ctx.restore(); // the load if (carrying) { ctx.globalAlpha = b.alpha * pAlpha; ctx.fillStyle = C.load; rr(b.x - pw / 2, b.y - ph / 2 + pOff, pw, ph, 2); ctx.fill(); ctx.fillStyle = C.load2; rr(b.x - pw / 2 + 2, b.y - ph / 2 + pOff + 1.5, pw * 0.42, ph * 0.4, 1); ctx.fill(); } ctx.restore(); } function draw() { ctx.clearRect(0, 0, W, H); ctx.fillStyle = C.deck; ctx.fillRect(0, 0, W, H); // floor markers ctx.strokeStyle = C.grid; ctx.lineWidth = 1; ctx.globalAlpha = 0.75; ctx.beginPath(); for (var gx = pickup.x + pickup.w + 15; gx < W; gx += 30) { for (var gy = deckTop + 4; gy < deckBot; gy += 30) { ctx.moveTo(gx - 2.5, gy); ctx.lineTo(gx + 2.5, gy); ctx.moveTo(gx, gy - 2.5); ctx.lineTo(gx, gy + 2.5); } } ctx.stroke(); ctx.globalAlpha = 1; // lane edges ctx.strokeStyle = C.grid; ctx.beginPath(); ctx.moveTo(0, deckTop - 3); ctx.lineTo(W, deckTop - 3); ctx.moveTo(0, deckBot + 3); ctx.lineTo(W, deckBot + 3); ctx.stroke(); // pick-up station ctx.fillStyle = C.surface; rr(pickup.x, pickup.y, pickup.w, pickup.h, 6); ctx.fill(); ctx.strokeStyle = C.line; ctx.stroke(); ctx.fillStyle = C.accent; rr(pickup.x + pickup.w - 4, pickup.y + 6, 3, pickup.h - 12, 1.5); ctx.fill(); ctx.save(); ctx.translate(pickup.x + pickup.w / 2 - 2, pickup.y + pickup.h / 2); ctx.rotate(-Math.PI / 2); ctx.fillStyle = C.ink2; ctx.font = '600 9px ' + C.mono; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('PICK-UP', 0, 0); ctx.restore(); for (var i = 0; i < stations.length; i++) drawStation(stations[i]); for (var j = 0; j < bots.length; j++) drawBot(bots[j]); } function frame(now) { if (!running) return; var dt = Math.min(0.05, (now - last) / 1000 || 0); last = now; for (var i = 0; i < bots.length; i++) step(bots[i], dt); for (var j = 0; j 0) stations[j].flash = Math.max(0, stations[j].flash - dt * 2.2); if (stations[j].swap > 0) stations[j].swap = Math.max(0, stations[j].swap - dt * 1.6); } draw(); if (elCount) { var txt = done.toLocaleString('en-US'); if (elCount.textContent !== txt) elCount.textContent = txt; } rafId = requestAnimationFrame(frame); } function start() { if (running || motionQuery.matches || !W) return; running = true; last = performance.now(); rafId = requestAnimationFrame(frame); } function stop() { running = false; if (rafId) cancelAnimationFrame(rafId); rafId = null; } function staticFrame() { for (var i = 0; i < bots.length; i++) { var b = bots[i]; b.x = pickup.x + pickup.w + 30 + (i / bots.length) * (W - pickup.w - 90); b.alpha = 1; if (i === 2) { b.state = 'tip'; b.tipT = 0.62; b.y = b.edgeY; } } done = 1284; draw(); if (elCount) elCount.textContent = done.toLocaleString('en-US'); } function resize() { var r = cv.getBoundingClientRect(); if (!r.width) return; dpr = Math.min(window.devicePixelRatio || 1, 2); cv.width = Math.round(r.width * dpr); cv.height = Math.round(r.height * dpr); ctx.setTransform(dpr, 0, 0, dpr, 0, 0); W = r.width; H = r.height; readTokens(); layout(); build(); if (motionQuery.matches) staticFrame(); else draw(); } var rt; window.addEventListener('resize', function () { clearTimeout(rt); rt = setTimeout(resize, 140); }); // keep canvas colours in step with the palette var darkQuery = window.matchMedia('(prefers-color-scheme: dark)'); function repaint() { readTokens(); if (!running) draw(); } if (darkQuery.addEventListener) darkQuery.addEventListener('change', repaint); if (window.MutationObserver) { new MutationObserver(repaint).observe(root, { attributes: true, attributeFilter: ['data-scheme'] }); } if (motionQuery.addEventListener) { motionQuery.addEventListener('change', function () { if (motionQuery.matches) { stop(); staticFrame(); } else { start(); } }); } document.addEventListener('visibilitychange', function () { if (document.hidden) stop(); else start(); }); // only animate while it is on screen if ('IntersectionObserver' in window) { new IntersectionObserver(function (entries) { if (entries[0].isIntersecting) start(); else stop(); }, { threshold: 0.02 }).observe(cv); } function boot() { resize(); if (!motionQuery.matches) start(); } if (document.fonts && document.fonts.ready) document.fonts.ready.then(boot).catch(boot); else boot(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAll); } else { initAll(); } })();

CARRY

Takes on a light load at a pick-up point and holds it steady in transit.

Navigate

Works out its own route and keeps clear of people and other vehicles.

Hand off

Places, tips or lifts the load at the destination without an operator.

Recharge

Returns to a charging point on its own and rejoins the fleet when ready.

The Basics

Somewhere between a conveyor and a forklift.

Two things define the category, and both follow from the size.

1.

Small enough to work in numbers

A mini AGV is built to be one of many rather than one of a few. Because each unit is light and inexpensive relative to fixed handling equipment, capacity is added by adding vehicles — not by rebuilding the system.

3.

Coordinated by a fleet controller

Individual vehicles are simple. The intelligence sits in software above them, which assigns jobs, keeps traffic moving and decides when a vehicle should go and charge.

2.

Guided, but not constrained

The vehicle follows a route rather than a rail. Change the destinations and the traffic pattern changes with them, usually without anyone picking up a tool.

4.

Light loads, many destinations

The economics work best where items are small and the number of possible destinations is high. Heavier or bulkier work stays with larger AGVs, tow tractors and lift trucks.

WHERE THEY FIT

Anywhere small things go to many places.

 

The pattern repeats across industries: high destination count, modest item weight, and demand that will not sit still long enough to justify fixed equipment.

Warehousing & Fulfilment

Moving totes, cartons and picked items between storage, pack and despatch without a person walking the distance.

Returns Processing

Work that arrives unsorted and unpredictable, where destinations need remapping by the shift rather than by the installation.

Manufacturing Supply

Feeding parts and kits to assembly stations, and clearing finished work away, on a rhythm set by the line itself.

Parcel & Post

Sorting items to route, round or driver at depots where the destination map changes far more often than the building does.

Hospitals & Labs

Carrying samples, supplies and records between departments — short, frequent trips that otherwise fall to trained staff.

Retail back-of-house

Replenishment between stockroom and shop floor in buildings never designed around material handling.

mini AGVs sorting through items 3DS
Mini AGVs transferring goods
OTHER SOLUTIONS

Anywhere small things go to many places.

 

The pattern repeats across industries: high destination count, modest item weight, and demand that will not sit still long enough to justify fixed equipment.

_______

LIBRA Stock Take Robot

Swiftly scan and track numerous RFID tagged items on shelves

_______

AI Vision Stock Take Robot

AI image processing algorithm automatically scans for efficient inventory management

____

Humanoid

Humanoid

brings human-like dexterity and mobility to tasks built for people

____

AI Robotic Arm

AI Robotic Arm

Automated Storage and Retrieval System (ASRS)

____

Autonomous Delivery Robot

Advanced navigation, obstacle avoidance, and intelligent route planning

______

Autonomous Cleaning Robot

Automatically scrubs, mops and navigates

____

Quadruped Robot

Quadruped Robot

handles terrain wheeled robots can't