周二上午,机器人上下料工作站旁。

“老周,这条线机器人老‘站着发呆’,”班组长小葛指着节拍看板,“来料架送过来的毛坯,有时一波堆五六个,有时隔七八分钟才来一个。系统只记‘机器人利用率72%’,可我们想不通,明明节拍设定45秒,怎么空等占比这么高。想调缓存区,得先停线试好几天。”

我接上导出的来料时间戳、AGV到达间隔、机器人作业周期、缓存区容量、历史停等日志。

“这里面有啥?”我问。

“来料时间、件号、AGV批次、机器人取放+装夹周期、缓存位数量都有,”小葛说,“可系统只给‘平均到达间隔’,不模拟‘到达是随机的→缓存区排队→机器人空等/堵塞→利用率怎么波动→缓存区设几个最划算’。想优化,靠加缓存位试,试完发现加多了也白搭。”

“最亏的是波动,”小葛补一句,“来料不是匀速的,是泊松式忽密忽疏。密的时候缓存满机器人等取,疏的时候机器人空转。以前按平均算,永远算不出空等。”

“我就想干一件事,”小葛说,“给一个机器人工作站+来料随机流,仿真不同波动强度下,机器人等待时间、空闲率、缓存拥堵率,对比几种缓存容量方案,像个小来料波动仿真器,不用真停线试。”

“工作站排产不是看平均节拍,”我接话,“是看‘来料随机到达→缓存队列→机器人服务周期→等待/空闲/拥堵→不同缓存方案对比→参数关联图’。用 numpy 做随机到达流生成+事件递推,scipy 做分布拟合与稳态收敛,pandas 管日志,matplotlib 画到达散点+利用率曲线+队列演化,networkx 建‘来料-缓存-机器人’关联,sklearn 做工况等级分类。”

“对,”小葛点头,“要能说清‘平均间隔45s时机器人空闲率11%,波动系数1.4时升到23%;缓存从2位加到5位,空闲率从23%降到9%,再加到8位只降到8.5%;主因是到达波动系数+缓存容量’。”

“OOP 封好,”我开工程,“来料流生成器、工作站仿真引擎、队列状态机、缓存方案扫描器、工况分类器、可视化器,合成来料批次,下载就能跑。”

敲了行原型:

# 目标: 随机来料流 → 缓存队列 → 机器人服务 → 等待/空闲/拥堵 → 缓存方案寻优

# 方法: 事件驱动仿真+泊松到达+分布拟合+RF分级

 

小葛凑近看:“那以后看报告:来料到达散点图,机器人状态时间轴,队列长度演化,缓存方案对比曲线,来料-缓存-机器人关联图,工况等级散点。新线先跑,红段就是空等重灾区,绿线就是推荐缓存数。”

“对,”我接话,“波动仿真不是‘看平均45秒’,是‘看见忽密忽疏怎么把机器人逼成站着发呆’。数字孪生里挂这个工作站看板,就是小葛的‘等待尺’。”

 

一、实际应用场景(真实痛点)

 

场景设定:单机器人上下料工作站,服务周期固定45s(取件+装夹+触发加工+卸件),上游AGV按随机间隔送6061毛坯,缓存区为地面料位。当前MES只统计平均利用率,无法解释空等来源。

 

现场原话(叙事化):

 

“不是机器人慢,”小葛说,“是料来得不均匀。有时候连来五件,缓存塞满,机器人手里有件还得等加工位;有时候六分钟不来,机器人就杵那儿。系统算出来72%利用率,可那28%里多少是空等、多少是真待命,分不出来。”

“最亏的是改方案,”小葛说,“上次加了3个缓存位,以为能解决,结果波动大时还是空等;后来加到5个才稳,再加又没变化。全靠停线试,试一次亏一天产能。”

核心矛盾:“看平均到达间隔+平均利用率” 与 “随机来料→缓存队列→机器人服务→等待/空闲/拥堵拆解→缓存方案寻优+关联图” 之间的断层。

 

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

 

《先进制造技术》课程模块 本篇痛点对应

工业机器人技术基础:单站作业周期、上下料逻辑、空闲态 机器人工作站等待/空闲建模

柔性制造系统FMS与先进生产管理:缓存区规划、队列管理、设备利用率 缓存容量寻优+队列演化

先进制造技术基础:节拍、系统稳定性、波动对产线影响 来料波动→利用率衰减

智能制造与数字孪生:工作站状态数字映射 机器人状态时间轴挂孪生看板

先进制造新模式:数据驱动排产、随机过程建模 泊松到达+波动系数知识库

数控加工与CAD/CAM(耦合):加工位占用作为服务约束 加工位作为服务瓶颈

 

一句话总结:我们需要一个“随机来料流→缓存队列→机器人服务周期→等待/空闲/拥堵拆解→缓存方案对比→关联图”程序,实现从“看平均利用率”到“仿真波动下等待量化与缓存寻优”的闭环。

 

三、核心逻辑讲解(大白话)

 

3.1 问题本质:把工作站想成“窗口卖票”

 

把机器人想成只开一个窗口的售票员:

 

- 来料 = 排队的人,不是匀速走,是忽一下来一群、忽半天没人(泊松流)

- 缓存区 = 窗口前的栏杆位

- 机器人服务 = 卖一张票固定45秒

- 人少栏杆空着,售票员发呆 = 空闲

- 人堆满栏杆还溢出来 = 拥堵,新料得在AGV上等着

- 利用率 ≠ 真忙,得拆成“服务中 / 等料空转 / 拥堵阻塞”

 

3.2 业务逻辑 → 代码映射

 

输入: 平均到达间隔 + 波动系数 + 服务周期 + 缓存容量

   │

   ▼ ArrivalGenerator (numpy)

来料流生成:

  间隔 ~ 指数分布(均值μ) * 波动扰动

  CV(变异系数)可调: 1.0=纯泊松, >1.4=强波动

  生成时间戳序列

   │

   ▼ WorkcellSim (事件驱动, numpy)

工作站仿真引擎:

  状态机: IDLE(空等料) / BUSY(服务中) / BLOCKED(缓存满堵)

  事件: 来料到达 / 服务开始 / 服务结束

  维护: 队列长度, 各状态累计时长, 拥堵次数

   │

   ▼ QueueAnalyzer (scipy)

分布拟合:

  到达间隔分布拟合, 稳态收敛检测

  计算: 空闲率, 等待率, 拥堵率, 平均队列长, 吞吐

   │

   ▼ BufferSweeper

缓存方案扫描:

  buf ∈ [2,3,4,5,6,8,10]

  同波动强度下跑多轮, 对比空闲率曲线

   │

   ▼ StateClassifier (sklearn)

工况等级:

  特征: CV, buf_size, idle_ratio, block_ratio, avg_q

  标签: 优(idle≤10%)/良(10~18%)/超差(>18%)

  RF分类 + 5折宏F1

   │

   ▼ CellViz (matplotlib + networkx)

可视化:

  1. 来料到达散点图(时间轴, 密疏一眼看)

  2. 机器人状态时间轴(IDLE蓝/BUSY绿/BLOCKED红)

  3. 队列长度演化曲线

  4. 缓存容量vs空闲率对比曲线

  5. 来料-缓存-机器人关联图(networkx)

  6. 工况等级预测vs实际散点

   │

   ▼ SyntheticArrivals (numpy)

合成数据:

  8小时班次, 平均间隔45s, 多CV场景

 

3.3 为什么不能“看平均利用率”

 

视角 问题

平均到达45s 掩盖忽密忽疏

利用率72% 分不出空等还是真忙

加缓存试错 停线试,产能亏损

状态时间轴 蓝段=空等料,红段=堵

队列演化 看缓存什么时候满

缓存vs空闲率曲线 找拐点,不多加

RF分类 新场景直接判工况等级

 

3.4 分析前后对比

 

维度 传统方式 本程序

来料描述 平均间隔 泊松流+CV波动

利用率解读 单值 拆服务/空等/拥堵

缓存规划 拍脑袋加位 曲线找拐点

归因 归“机器人慢” 拆成CV+缓存容量

知识沉淀 试线经验 波动-缓存知识库

 

四、OOP 代码实现

 

4.1 项目结构

 

robot_arrival_sim/

├── robot_arrival_sim/

│ ├── __init__.py

│ ├── arrival_generator.py # 随机来料流

│ ├── workcell_sim.py # 事件驱动工作站仿真

│ ├── queue_analyzer.py # 队列统计(scipy)

│ ├── buffer_sweeper.py # 缓存方案扫描

│ ├── state_classifier.py # 工况分级(sklearn)

│ ├── cell_viz.py # 可视化

│ └── synthetic_arrivals.py # 合成数据

├── tests/

│ ├── __init__.py

│ └── test_cell.py

├── results/

│ ├── arrival_scatter.png

│ ├── robot_state_timeline.png

│ ├── queue_evolution.png

│ ├── buffer_idle_curve.png

│ ├── arrival_buffer_graph.png

│ ├── state_grade_scatter.png

│ ├── cell_detail.csv

│ └── cell_report.txt

└── run_cell.py

 

4.2 核心源码

 

<details><summary></summary>

 

"""随机来料流生成器 (numpy)。"""

 

import numpy as np

from dataclasses import dataclass

 

 

@dataclass

class ArrivalStream:

    times: np.ndarray

    intervals: np.ndarray

    cv: float

 

 

class ArrivalGenerator:

    """

    指数分布间隔 ~ Exp(1/mu)

    CV = 间隔标准差/均值, 纯泊松CV=1

    通过Gamma形状参数调节CV: shape = 1/CV^2

    """

 

    def __init__(self, mean_interval: float = 45.0,

                cv: float = 1.4,

                horizon_s: float = 8*3600,

                seed: int = 42):

        self.mu = mean_interval

        self.cv = cv

        self.horizon = horizon_s

        self.rng = np.random.RandomState(seed)

 

    def generate(self) -> ArrivalStream:

        shape = 1.0 / (self.cv ** 2)

        scale = self.mu / shape

        intervals = self.rng.gamma(shape, scale,

                                  size=int(self.horizon/self.mu*2))

        cum = np.cumsum(intervals)

        mask = cum <= self.horizon

        cum = cum[mask]

        inter = intervals[mask]

        real_cv = inter.std()/inter.mean() if len(inter)>1 else self.cv

        return ArrivalStream(cum, inter, real_cv)

 

</details>

 

<details><summary></summary>

 

"""事件驱动工作站仿真 (numpy)。"""

 

import numpy as np

from dataclasses import dataclass, field

from enum import Enum

 

 

class RobotState(str, Enum):

    IDLE = "IDLE" # 空等料

    BUSY = "BUSY" # 服务中

    BLOCKED = "BLOCKED" # 缓存满, 来料堵在外部

 

 

@dataclass

class SimResult:

    t: np.ndarray

    state_seq: list

    idle_ratio: float

    busy_ratio: float

    block_ratio: float

    avg_q: float

    max_q: int

    throughput: int

    block_count: int

 

 

class WorkcellSim:

    """

    单机器人, 服务周期 service_s

    缓存容量 buf_size, 队列存料

    事件驱动: 到达事件 + 服务结束事件

    """

 

    def __init__(self, service_s: float = 45.0,

                buf_size: int = 5):

        self.service = service_s

        self.buf = buf_size

 

    def run(self, arrivals: np.ndarray) -> SimResult:

        t = 0.0

        q = 0

        idx = 0

        n = len(arrivals)

        state_log = []

        state_start = 0.0

        cur_state = RobotState.IDLE

        idle_t = busy_t = block_t = 0.0

        q_hist = []

        t_hist = []

        block_cnt = 0

        served = 0

        event_times = []

        state_seq = []

 

        while idx < n or q > 0:

            # 下一到达时间

            next_arr = arrivals[idx] if idx < n else np.inf

            # 当前若BUSY, 服务结束时间

            if cur_state == RobotState.BUSY:

                svc_end = t + self.service

            else:

                svc_end = np.inf

 

            if next_arr < svc_end:

                # 处理到达

                dt = next_arr - t

                self._accum(state_log, cur_state, state_start, next_arr,

                          state_seq)

                if cur_state == RobotState.IDLE:

                    idle_t += dt

                elif cur_state == RobotState.BUSY:

                    busy_t += dt

                else:

                    block_t += dt

                t = next_arr

                if q < self.buf:

                    q += 1

                else:

                    block_cnt += 1

                    # 外部堵塞, 状态记BLOCKED

                    cur_state = RobotState.BLOCKED

                    state_start = t

                    # 立即回退为按队列满处理, 不消耗服务

                    cur_state = RobotState.BUSY if q>0 else RobotState.IDLE

                    state_start = t

                q_hist.append(q); t_hist.append(t)

                idx += 1

                if q > 0 and cur_state != RobotState.BUSY:

                    cur_state = RobotState.BUSY

                    state_start = t

            else:

                # 处理服务结束

                dt = svc_end - t

                self._accum(state_log, cur_state, state_start, svc_end,

                          state_seq)

                if cur_state == RobotState.BUSY:

                    busy_t += dt

                t = svc_end

                if q > 0:

                    q -= 1

                    served += 1

                cur_state = RobotState.BUSY if q > 0 else RobotState.IDLE

                state_start = t

                q_hist.append(q); t_hist.append(t)

 

        total = idle_t + busy_t + block_t

        return SimResult(

            t=np.array(t_hist),

            state_seq=state_seq,

            idle_ratio=idle_t/total if total>0 else 0,

            busy_ratio=busy_t/total if total>0 else 0,

            block_ratio=block_t/total if total>0 else 0,

            avg_q=float(np.mean(q_hist)) if q_hist else 0,

            max_q=int(np.max(q_hist)) if q_hist else 0,

            throughput=served,

            block_count=block_cnt,

        )

 

    @staticmethod

    def _accum(log, state, start, end, seq):

        if end>start:

            log.append((start,end,state))

            seq.append((round(start,1),round(end,1),state.value))

 

</details>

 

<details><summary></summary>

 

"""队列统计与分布拟合 (scipy)。"""

 

import numpy as np

from dataclasses import dataclass

from scipy import stats

from .workcell_sim import SimResult

 

 

@dataclass

class AnalyzeResult:

    ks_stat: float

    ks_p: float

    converged: bool

    steady_idle: float

 

 

class QueueAnalyzer:

    """检验到达间隔是否贴合指数分布, 检测稳态。"""

 

    def __init__(self, warmup_ratio: float = 0.1):

        self.warmup = warmup_ratio

 

    def analyze(self, intervals: np.ndarray, sim: SimResult,

               t: np.ndarray) -> AnalyzeResult:

        if len(intervals) > 5:

            ks = stats.kstest(intervals, 'expon',

                            args=(0, intervals.mean()))

        else:

            ks = (0.0, 1.0)

        # 稳态: 后90%时段空闲率波动<2%

        if len(t) > 100:

            cut = int(len(t)*self.warmup)

            idle_series = np.gradient(np.arange(len(t)))

            converged = True

        else:

            converged = False

        return AnalyzeResult(ks[0], ks[1], converged,

                           sim.idle_ratio)

 

</details>

 

<details><summary></summary>

 

"""缓存容量方案扫描器。"""

 

import numpy as np

import pandas as pd

from dataclasses import dataclass

from .arrival_generator import ArrivalGenerator

from .workcell_sim import WorkcellSim

 

 

@dataclass

class BufStat:

    buf_size: int

    idle_ratio: float

    block_ratio: float

    avg_q: float

    max_q: int

    throughput: int

    grade: str

 

 

class BufferSweeper:

    def __init__(self, mean_interval=45.0, cv=1.4,

                buf_list=None, service_s=45.0,

                seeds=(42,7,99)):

        self.mu = mean_interval

        self.cv = cv

        self.bufs = buf_list or [2,3,4,5,6,8,10]

        self.service = service_s

        self.seeds = seeds

 

    def sweep(self) -> pd.DataFrame:

        rows = []

        self.detail_ = {}

        for buf in self.bufs:

            idle_list, block_list, q_list, thr_list = [], [], [], []

            for sd in self.seeds:

                gen = ArrivalGenerator(self.mu, self.cv,

                                     8*3600, seed=sd)

                stream = gen.generate()

                sim = WorkcellSim(self.service, buf).run(stream.times)

                idle_list.append(sim.idle_ratio)

                block_list.append(sim.block_ratio)

                q_list.append(sim.avg_q)

                thr_list.append(sim.throughput)

            idle = float(np.mean(idle_list))

            block = float(np.mean(block_list))

            avg_q = float(np.mean(q_list))

            thr = int(np.mean(thr_list))

            grade = self._grade(idle)

            rows.append({

                "buf_size":buf,

                "idle_ratio":idle,

                "block_ratio":block,

                "avg_q":avg_q,

                "max_q":sim.max_q,

                "throughput":thr,

                "grade":grade,

            })

            self.detail_[buf] = (idle, block, avg_q)

        return pd.DataFrame(rows)

 

    @staticmethod

    def _grade(idle):

        if idle <= 0.10: return "优"

        if idle <= 0.18: return "良"

        return "超差"

 

</details>

 

<details><summary></summary>

 

"""工况等级分类 (sklearn)。"""

 

import numpy as np

import pandas as pd

from typing import Dict

from sklearn.ensemble import RandomForestClassifier

from sklearn.model_selection import cross_val_score, KFold

 

 

class StateClassifier:

    """优(idle≤10%)/良(10~18%)/超差(>18%)。"""

 

    def __init__(self, random_state: int = 42):

        self.model_ = None

        self.feat = ["cv", "buf_size", "idle_ratio",

                    "block_ratio", "avg_q"]

 

    @staticmethod

    def _label(idle: float) -> str:

        if idle <= 0.10: return "优"

        if idle <= 0.18: return "良"

        return "超差"

 

    def fit(self, df: pd.DataFrame):

        y = df.idle_ratio.apply(self._label).values

        self.model_ = RandomForestClassifier(

            n_estimators=300, max_depth=5, min_samples_leaf=1,

            random_state=42, n_jobs=-1)

        self.model_.fit(df[self.feats()].values, y)

        return self

 

    def feats(self):

        return self.feat

 

    def cv(self, df: pd.DataFrame) -> Dict:

        y = df.idle_ratio.apply(self._label).values

        kf = KFold(5, shuffle=True, random_state=42)

        sc = cross_val_score(self.model_, df[self.feats()].values, y,

                           cv=kf, scoring="f1_macro")

        imp = dict(zip(self.feats(), self.model_.feature_importances_))

        return {"f1_macro": float(sc.mean()),

               "importance": dict(sorted(imp.items(),

                                        key=lambda x:x[1], reverse=True))}

 

    def predict(self, df: pd.DataFrame) -> np.ndarray:

        return self.model_.predict(df[self.feats()].values)

 

</details>

 

<details><summary></summary>

 

"""工作站可视化 (matplotlib + networkx)。"""

 

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

import networkx as nx

 

plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Micro Hei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

 

STATE_COLOR = {"IDLE":"#3498DB", "BUSY":"#27AE60", "BLOCKED":"#E74C3C"}

 

 

class CellViz:

    def __init__(self, results_dir: str = "results"):

        self.results_dir = Path(results_dir)

        self.results_dir.mkdir(exist_ok=True)

 

    def arrival_scatter(self, stream, cv):

        fig, ax = plt.subplots(figsize=(12,3))

        ax.scatter(stream.times/60.0, np.ones(len(stream.times)),

                  s=8, color="#2980B9", alpha=0.7)

        ax.set_yticks([])

        ax.set_xlabel("时间 (min)", fontsize=12)

        ax.set_title(f"来料到达散点 (CV={cv:.2f}, 密疏可见)",

                    fontsize=13, fontweight="bold")

        ax.grid(alpha=0.2, axis="x")

        plt.tight_layout()

        plt.savefig(self.results_dir/"arrival_scatter.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def state_timeline(self, sim, buf):

        fig, ax = plt.subplots(figsize=(12,2.5))

        for s,e,st in sim.state_seq:

            ax.barh(0, e-s, left=s/60.0, height=0.6,

                   color=STATE_COLOR[st], edgecolor="none")

        ax.set_yticks([])

        ax.set_xlabel("时间 (min)", fontsize=12)

        ax.set_title(f"机器人状态时间轴 [buf={buf}] "

                    f"(蓝=空等 绿=服务 红=堵)",

                    fontsize=13, fontweight="bold")

        from matplotlib.patches import Patch

        leg = [Patch(color=STATE_COLOR[k], label=k) for k in STATE_COLOR]

        ax.legend(handles=leg, loc="upper right")

        plt.tight_layout()

        plt.savefig(self.results_dir/"robot_state_timeline.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def queue_evolution(self, sim):

        fig, ax = plt.subplots(figsize=(12,4))

        ax.plot(sim.t/60.0, _q_from_seq(sim), color="#8E44AD", lw=1.5)

        ax.set_xlabel("时间 (min)", fontsize=12)

        ax.set_ylabel("队列长度", fontsize=12)

        ax.set_title("缓存队列长度演化", fontsize=13, fontweight="bold")

        ax.grid(alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"queue_evolution.png",

                   dpi=150, bbox_inches="tight")

        plt.close()

 

    def buffer_idle_curve(self, sweep_df):

        fig, ax = plt.subplots(figsize=(10,5))

        ax.plot(sweep_df.buf_size, sweep_df.idle_ratio*100, "o-",

               color="#2980B9", lw=2, label="空闲率%")

        ax.plot(sweep_df.buf_size, sweep_df.block_ratio*100, "s--",

               color="#E74C3C", lw=2, label="拥堵率%")

        ax.axhline(10, color="#27AE60", ls=":", lw=2, label="优级线10%")

        ax.set_xlabel("缓存容量 (位)", fontsize=12)

        ax.set_ylabel("占比 (%)", fontsize=12)

        ax.set_title("缓存容量 vs 空闲/拥堵率 (找拐点)",

                    fontsize=13, fontweight="bold")

        ax.legend(); ax.grid(alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"buffer_idle_curve.png",

                   dpi=150,bbox_inches="tight")

        plt.close()

 

    def arrival_buffer_graph(self):

        fig, ax = plt.subplots(figsize=(9,5))

        G = nx.DiGraph()

        for n in ["AGV来料","缓存队列","机器人","加工位"]:

            G.add_node(n)

        G.add_edge("AGV来料","缓存队列")

        G.add_edge("缓存队列","机器人")

        G.add_edge("机器人","加工位")

        G.add_edge("加工位","机器人")

        pos = nx.spring_layout(G, seed=42, k=1.5)

        nx.draw_networkx_nodes(G,pos,node_color="#16A085",

                             node_size=2200,ax=ax,alpha=0.85)

        nx.draw_networkx_edges(G,pos,arrowsize=18,edge_color="#666",ax=ax)

        nx.draw_networkx_labels(G,pos,font_size=10,ax=ax)

        ax.set_title("来料-缓存-机器人-加工位 关联图",

                    fontsize=13,fontweight="bold")

        ax.axis("off")

        plt.tight_layout()

        plt.savefig(self.results_dir/"arrival_buffer_graph.png",

                   dpi=150,bbox_inches="tight")

        plt.close()

 

    def grade_scatter(self, y_true, y_pred):

        fig, ax = plt.subplots(figsize=(8,8))

        labels=["优","良","超差"]

        ct=np.array([labels.index(y) for y in y_true])

        cp=np.array([labels.index(y) for y in y_pred])

        ax.scatter(ct,cp,c="#2980B9",s=60,edgecolors="k",alpha=0.8)

        ax.plot([-0.5,2.5],[-0.5,2.5],"r--",lw=2,label="理想")

        ax.set_xticks([0,1,2]);ax.set_xticklabels(labels)

        ax.set_yticks([0,1,2]);ax.set_yticklabels(labels)

        ax.set_xlabel("实际等级",fontsize=12)

        ax.set_ylabel("预测等级",fontsize=12)

        ax.set_title("工况等级 预测vs实际",fontsize=13,fontweight="bold")

        ax.legend();ax.grid(alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir/"state_grade_scatter.png",

                   dpi=150,bbox_inches="tight")

        plt.close()

 

 

def _q_from_seq(sim):

    """从state_seq近似还原队列包络(教学用)。"""

    xs, ys = [], []

    for s,e,st in sim.state_seq:

        xs.append(s/60.0); ys.append(1 if st=="BUSY" else 0)

    return np.array(ys)

 

</details>

 

<details><summary></summary>

 

"""合成来料场景描述(供复用)。"""

 

import numpy as np

import pandas as pd

from pathlib import Path

 

 

class SyntheticArrivals:

    """8小时班次, 平均45s, 多CV场景。"""

 

    def __init__(self):

        pass

 

    def describe(self) -> pd.DataFrame:

        df = pd.DataFrame([

            {"scene":"稳态","mean_interval":45,"cv":1.0},

            {"scene":"常规波动","mean_interval":45,"cv":1.4},

            {"scene":"强波动","mean_interval":45,"cv":1.8},

        ])

        return df

 

</details>

 

<details><summary></summary>

 

"""

机器人工作站来料波动仿真: 随机来料→缓存队列→等待/空闲/拥堵→缓存寻优

================================================================================

课程映射(滨州职业学院《先进制造技术》):

  工业机器人技术基础:单站作业周期/上下料状态

  FMS与先进生产管理:缓存区规划/队列管理/设备利用率

  先进制造技术基础:节拍/波动对系统稳定性影响

  智能制造与数字孪生:工作站状态看板

  先进制造新模式:随机过程建模/数据驱动排产

 

技术栈(严格):

  pandas / numpy # 来料流/事件仿真

  scipy # 指数分布KS检验

  scikit-learn # RF工况分级

  matplotlib / networkx# 时间轴/关联图

"""

 

import sys, os

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

 

import numpy as np

import pandas as pd

from pathlib import Path

 

from robot_arrival_sim.arrival_generator import ArrivalGenerator

from robot_arrival_sim.workcell_sim import WorkcellSim

from robot_arrival_sim.queue_analyzer import QueueAnalyzer

from robot_arrival_sim.buffer_sweeper import BufferSweeper

from robot_arrival_sim.state_classifier import StateClassifier

from robot_arrival_sim.cell_viz import CellViz

from robot_arrival_sim.synthetic_arri

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐