解决方案

微型自动导引车(mini AGV)机器人

微型AGV是一种结构紧凑的自动驾驶车辆,能够将轻型货物从一处运送到另一处并自主完成交接。无论是在车间部署几台,还是几百台——其布局由软件决定,而非钢结构。

交接0
车辆0
车站0
故障
车队行为示意图——非实时数据
/* ---------- 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

在装载点装载轻型货物,并在运输过程中将其稳稳固定。

导航

能够自主规划路线,并避开行人及其他车辆。

交接

在目的地将货物放置、调整位置或卸下,无需操作员。

充电

会自动返回充电点,并在准备就绪后重新加入车队。

基础知识

介于传送带和叉车之间。

有两点界定了这一类别,而这两点都源于其规模。

1.

体积小巧,适合批量使用

微型AGV的设计初衷是作为众多设备中的一员,而非仅作为少数几台设备中的一台。由于每台设备相对固定式搬运设备而言重量轻且成本低,因此只需增加车辆数量即可提升运力——而无需重建整个系统。

3.

由一名机队调度员负责协调

单个车辆的结构很简单。智能系统位于车辆之上的软件中,负责分配任务、维持交通畅通,并决定车辆何时出发以及何时充电。

2.

受到引导,但不受限制

该车辆沿路线行驶,而非沿轨道行驶。只要更改目的地,交通模式也会随之改变,通常无需任何人动用工具。

4.

轻便,目的地多

在货物体积小且可能的运输目的地较多的情况下,这种经济模式的效果最佳。较重或体积较大的货物仍应由大型自动导引车(AGV)、牵引车和叉车来处理。

适用场景

小东西们会去往各地。

 

这种模式在各行业中反复出现:配送目的地数量多、单件货物重量较轻,且需求变化频繁,难以支撑固定设备的投入。

仓储与订单履行

在仓储、包装和发货区域之间运输收纳箱、纸箱和已拣选的物品,无需人工走动。

退货处理

工作任务以未分类且难以预测的方式涌入,其目的地需要由当班人员重新规划,而非由系统自动分配。

制造业供应

按照生产线自身设定的节奏,将零部件和套件送至装配工位,并清理成品。

包裹与邮政

在那些目的地地图变更频率远高于仓库建筑本身变更频率的仓库中,将货物按路线、配送路线或司机进行分拣。

医院与实验室

在各部门之间运送样本、物资和记录——这些短距离且频繁的往返工作,通常由受过专业培训的工作人员负责。

零售后场

在最初设计时未考虑物料搬运需求的建筑物中,仓库与生产车间之间的补货。

微型AGV对物品进行分拣 3DS
微型自动导引车(AGV)正在运输货物
其他解决方案

其他人工智能机器人

了解其他人工智能机器人解决方案

_______

LIBRA 库存盘点机器人

快速扫描并追踪货架上大量带有RFID标签的商品

____

类人机器人

类人机器人

为专为人类设计的任务赋予了类人般的灵巧性和机动性

____

AI机械臂

AI机械臂

自动化仓储和检索系统(ASRS)

____

四足机器人

四足机器人

能够应对轮式机器人无法应对的地形

______

自主清洁机器人

自动刷洗、拖地和自主导航

_______

AI视觉盘点机器人

AI图像处理算法可自动扫描,实现高效的库存管理

____

自动配送机器人

高级导航、避障和智能路线规划