我让 Claude 控制笔式绘图仪


基本信息


导语

将 AI 生成代码与物理硬件结合,是探索数字创作落地的一种有趣尝试。本文记录了作者将 Claude 接入笔式绘图仪的完整过程,重点讨论了如何通过迭代调试,将大语言模型生成的代码转化为精确的物理图形。对于对生成式 AI 边际应用或硬件自动化感兴趣的读者,这篇文章提供了一份关于人机协作与容错处理的一手实践参考。


评论

中心观点: 文章通过将大语言模型(LLM)Claude 与物理世界中的绘图仪连接,展示了 LLM 在具备工具调用能力后,能够跨越数字边界,通过“代码即行动”的方式直接操控物理硬件,从而在创意工作流中实现从“数字构思”到“物理实现”的自动化闭环

支撑理由与评价:

  1. 从“对话”到“行动”的范式转移

    • 事实陈述: 文章记录了作者通过 API 让 Claude 生成 HPGL 绘图代码,并直接驱动绘图仪作画的过程。
    • 深度评价: 这篇文章在技术层面上验证了 LLM 的 Function Calling(函数调用) 能力在物理计算领域的应用潜力。传统的 LLM 应用多局限于文本生成或信息检索,而本文展示了 LLM 作为“逻辑中枢”控制物理设备的能力。这不仅是简单的代码生成,而是 LLM 理解物理约束(如绘图仪的边界、笔的颜色切换逻辑)并转化为精确指令的过程。
  2. 创意工作流中的“人机共生”

    • 作者观点: 作者认为 Claude 能够处理繁琐的坐标计算和路径规划,让人类专注于艺术构思。
    • 实用价值: 对于创意编程和生成式艺术领域,这具有极高的参考价值。它提供了一种新的工作模式:人类提供高维度的抽象描述(如“画一个分形树”),AI 负责降维实现(生成具体的 G-code 或 HPGL)。这降低了物理计算(Physical Computing)的门槛,让不懂底层硬件协议的创作者也能利用硬件。
  3. 非确定性系统与确定性硬件的冲突与调和

    • 你的推断: 文章隐含了一个核心矛盾——LLM 的生成具有概率性(非确定性),而绘图仪的运动需要精确的确定性指令。
    • 技术分析: 评价该实验的关键在于观察 Claude 如何处理“幻觉”。如果 Claude 生成了错误的坐标,绘图仪会直接在纸上表现出来,这种“物理层面的报错”比屏幕上的 Bug 更直观。文章展示了通过迭代提示词来修正物理错误的过程,这对未来调试 LLM 控制机器人的策略具有启示意义。

反例与边界条件:

  1. 实时性瓶颈: 这种基于 LLM 的控制模式并不适用于高实时性场景(如工业焊接或无人机飞行)。LLM 的推理延迟(Token 生成时间)可能导致秒级的指令滞后,无法满足闭环控制的硬实时要求。
  2. 成本与效率问题: 对于简单的重复性绘图任务,硬编码的脚本效率远高于 LLM。使用 Claude 生成代码需要消耗 Token 成本,且每次生成都可能不同,缺乏工业自动化所需的稳定性和可复现性。
  3. 错误容忍度低: 绘图仪画错线条只是浪费纸张,但如果控制的是激光切割机或机械臂,LLM 的轻微幻觉可能导致昂贵的设备损坏或安全事故。

行业影响与争议点:

  • 行业影响: 该实验是“Agentic Workflow”(智能体工作流)在硬件领域的微观缩影。它预示着未来个人助理将不仅限于整理文件,还能直接操控物理环境(如智能家居、3D 打印、数控机床)。
  • 争议点: 社区对于 LLM 是否真正“理解”几何存在争议。Claude 可能只是在训练数据中记住了 HPGL 代码的模式,而非建立了空间几何模型。当面临极其复杂的非标准几何约束时,它可能会生成看似合理但物理上无法执行的代码(如笔尖移动速度过快导致跳纸)。

实际应用建议:

  1. 中间件层验证: 在实际部署中,不应直接将 LLM 的输出发送给硬件,必须加入一个验证层(或沙箱),模拟运行代码以检查是否存在“越界”或“指令冲突”。
  2. 混合编程模式: 将 LLM 用于生成高层逻辑或参数化配置,而底层的精确运动控制仍由确定性代码库(如 Python 库)执行,LLLM 仅作为生成代码片段的辅助工具。

可验证的检查方式:

  1. 复现实验指标: 使用相同提示词复现实验,统计 Claude 生成代码的一次成功率(即代码无需修改即可被绘图仪完美执行的比例)。
  2. 错误模式分析: 收集失败案例,分析错误类型分布(是语法错误、逻辑错误还是物理约束违反),以评估 LLM 对硬件协议的理解深度。
  3. 延迟测试: 测量从发出指令到绘图仪开始动作的端到端延迟,评估该交互模式在用户体验上的可接受度(通常 < 5秒为佳)。

代码示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 示例1:基础绘图控制
import serial
import time

def draw_line(port='/dev/ttyUSB0', x1=0, y1=0, x2=100, y2=100):
    """
    控制绘图仪绘制直线
    :param port: 串口设备路径
    :param x1, y1: 起点坐标
    :param x2, y2: 终点坐标
    """
    try:
        # 初始化串口连接(根据实际设备调整波特率)
        plotter = serial.Serial(port, 9600, timeout=1)
        
        # 发抬笔命令(具体指令需参考设备手册)
        plotter.write(b'MU\n')  # Move Up
        time.sleep(0.5)  # 等待动作完成
        
        # 移动到起点
        plotter.write(f'MA {x1},{y1}\n'.encode())
        time.sleep(0.5)
        
        # 下笔
        plotter.write(b'MD\n')  # Move Down
        time.sleep(0.5)
        
        # 绘制到终点
        plotter.write(f'MA {x2},{y2}\n'.encode())
        time.sleep(1)
        
        # 抬笔结束
        plotter.write(b'MU\n')
        plotter.close()
        print("绘图完成")
    except Exception as e:
        print(f"错误: {e}")

# 使用示例
draw_line('/dev/ttyUSB0', 0, 0, 100, 100)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 示例2:批量绘制图形
import matplotlib.pyplot as plt
import numpy as np

def generate_plotter_code(fig, output_file='plotter_commands.txt'):
    """
    将matplotlib图形转换为绘图仪命令
    :param fig: matplotlib图形对象
    :param output_file: 输出文件路径
    """
    with open(output_file, 'w') as f:
        # 遍历图形中的所有线条
        for line in fig.get_lines():
            x_data, y_data = line.get_data()
            
            # 转换坐标并生成命令
            for i in range(len(x_data)-1):
                x1, y1 = x_data[i], y_data[i]
                x2, y2 = x_data[i+1], y_data[i+1]
                
                # 写入绘图命令(格式需根据设备调整)
                f.write(f"PU;PA{x1},{y1};PD;PA{x2},{y2};PU;\n")
    
    print(f"绘图命令已保存到 {output_file}")

# 使用示例
fig, ax = plt.subplots()
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), 'b-')
generate_plotter_code(fig)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 示例3:实时绘图监控
import serial
import threading
import queue

class PlotterMonitor:
    def __init__(self, port='/dev/ttyUSB0'):
        self.port = port
        self.command_queue = queue.Queue()
        self.running = False
        
    def send_command(self, command):
        """发送命令到队列"""
        self.command_queue.put(command)
        
    def _worker(self):
        """工作线程处理命令队列"""
        try:
            with serial.Serial(self.port, 9600, timeout=1) as plotter:
                while self.running:
                    try:
                        cmd = self.command_queue.get(timeout=0.1)
                        plotter.write(cmd.encode())
                        print(f"执行命令: {cmd.strip()}")
                    except queue.Empty:
                        continue
        except Exception as e:
            print(f"串口错误: {e}")
            
    def start(self):
        """启动监控线程"""
        self.running = True
        self.thread = threading.Thread(target=self._worker)
        self.thread.start()
        
    def stop(self):
        """停止监控"""
        self.running = False
        self.thread.join()

# 使用示例
monitor = PlotterMonitor('/dev/ttyUSB0')
monitor.start()
monitor.send_command("PU;PA100,100;PD;PA200,200;PU;")
monitor.stop()

案例研究

1:Inkscape 软件的 AxiDraw 驱动扩展

1:Inkscape 软件的 AxiDraw 驱动扩展

背景: Inkscape 是一款开源的矢量图形编辑软件,而 AxiDraw 是一款流行的个人绘图仪设备。用户希望在 Inkscape 中设计图形后,能直接控制绘图仪进行物理绘制,而无需导出文件并在其他程序中转换。

问题: Inkscape 本身不支持直接控制 AxiDraw 硬件。用户面临的工作流程是:设计 -> 导出 SVG -> 使用命令行工具或专用软件转换 -> 发送至绘图仪。这一过程繁琐,且对于非技术背景的艺术家或设计师来说,命令行操作门槛过高。

解决方案: 开发团队编写了 Inkscape 的扩展插件(基于 Python),直接集成在 Inkscape 的“扩展”菜单中。该插件充当了中间层,将 Inkscape 内部的矢量路径数据实时解析为绘图仪(如 AxiDraw 或 EBB 驱动的设备)能理解的运动控制指令(通过串口通信)。

效果: 实现了“所见即所得”的绘图体验。用户无需离开设计软件即可完成绘制,极大地简化了工作流。该方案成为了 AxiDraw 官方推荐的入门方式,被广泛应用于生成艺术、手写贺卡和 PCB 制图原型制作中。


2:Sisyphus 桌面沙画艺术机

2:Sisyphus 桌面沙画艺术机

背景: Sisyphus 是一款 Kickstarter 众筹的桌面艺术设备,利用一个磁球在沙盘上绘制不断变化的几何图案。其核心是一个隐藏在沙子下方的两轴运动控制系统。

问题: 该项目需要能够将复杂的数学算法(如李萨如曲线、分形几何)实时转换为物理路径,并控制钢球的精确运动。同时,系统需要支持用户通过手机 App 上传自定义 SVG 图案,并自动将其优化为连续的绘图路径,以避免钢球在沙子中不必要的移动。

解决方案: 项目团队开发了一套完整的软件栈,包含后端路径处理引擎和硬件驱动。后端接收 SVG 文件,使用 Python 进行路径优化(路径合并、平滑处理),然后通过串口将 G-code 或底层指令发送给基于 Arduino 的控制器。控制器驱动两个步进电机,通过磁力牵引钢球运动。

效果: 创造了一种全新的动态艺术形式。用户不仅可以选择预设的算法艺术,还能将自己的手绘或设计转化为永不过时但不断变化的沙画。该案例展示了将绘图仪技术(Pen Plotter)从单纯的“笔在纸上”扩展到“磁铁在沙下”的创新应用,成功商业化并售出了数千台设备。


3:vpype 矢量绘图管道工具

3:vpype 矢量绘图管道工具

背景: 生成艺术家经常需要编写代码来生成复杂的几何图形,但这些图形通常是数学坐标或 SVG 格式,直接发送给绘图仪往往会出现线条重叠、落笔顺序不合理(导致绘制时间长或画面脏乱)的问题。

问题: 现有的绘图仪驱动软件通常侧重于 CAD 或工程领域,缺乏对艺术创作的支持。例如,它们无法方便地对线条进行随机化处理、分层处理或根据笔触粗细调整速度。艺术家需要一个灵活的命令行工具来作为“代码”和“画布”之间的桥梁。

解决方案: 开发者开发了 vpype,一个基于 Python 的命令行工具。它允许用户通过一系列命令(管道)来处理 SVG 路径。例如:vpype read input.svg rotate 45 smooth linesort write output.svg。它可以与 axidraw 模块深度集成,直接驱动硬件。此外,它被集成到了 Claude 等 AI 模型的工作流中,允许 AI 直接生成代码并调用 vpype 控制绘图仪。

效果: 成为了生成艺术领域的标准工具之一。它赋予了艺术家极高的控制权,使得从代码到实物的过程变得可编程且可重复。特别是结合 AI 使用时,用户只需描述需求,AI 即可生成 vpype 指令并控制实体绘图仪完成创作,极大地降低了技术门槛。


最佳实践

最佳实践指南

实践 1:建立安全的物理环境隔离

说明: 笔式绘图仪是一种机电一体化设备,Claude 作为纯软件 AI 无法直接感知物理世界。为了确保安全,必须在物理层面建立隔离机制,防止 AI 生成的异常指令导致设备损坏或人身伤害。

实施步骤:

  1. 将绘图仪放置在独立的、视线可及的工作区域内
  2. 确保设备周围有足够的操作空间,无障碍物
  3. 安装急停按钮并确保随时可触达
  4. 设置物理限位开关以防止机械臂超出工作范围

注意事项:

  • 首次运行代码时,人必须在场监护
  • 不要在无人值守的情况下让 AI 控制设备长时间运行

实践 2:实现中间件抽象层

说明: 不要直接将绘图仪的底层控制接口(如串口指令)暴露给 AI。应构建一个中间件层,将原始指令转化为安全的、参数化的 API 调用,从而限制 AI 的操作范围。

实施步骤:

  1. 开发一个轻量级的服务端程序(使用 Python/Node.js 等)
  2. 定义一组安全的 API 端点,如 /plot/home/status
  3. 在中间件中实现指令队列和缓冲机制
  4. 添加指令校验逻辑,过滤掉非法参数

注意事项:

  • 中间件应具备超时机制,防止设备卡死
  • 记录所有通过中间件的指令日志以供调试

实践 3:严格的边界限制与参数校验

说明: AI 可能会生成超出设备物理极限的参数(如速度过快、坐标越界)。必须在软件层面强制执行物理约束。

实施步骤:

  1. 定义硬编码的物理边界(X/Y 轴最大最小值)
  2. 设置速度和加速度的上限
  3. 在执行任何 G 代码或 HPGL 指令前进行预解析
  4. 实现模拟模式,先在内存中运行路径检测碰撞

注意事项:

  • 即使 AI 理解了限制,也要在代码层面强制执行,不要依赖 AI 的自我约束
  • 定期校准绘图仪的坐标系

实践 4:分阶段权限授予与沙盒测试

说明: 采用渐进式信任模型。不要一开始就赋予 AI 完全的控制权,而是从只读权限开始,逐步过渡到受控的写入权限。

实施步骤:

  1. 阶段一(只读): 仅允许 AI 查询设备状态和规格文档
  2. 阶段二(预览): 允许 AI 生成代码,但强制使用 --dry-run 模式,仅生成绘图预览图
  3. 阶段三(受限写入): 允许执行,但需要人工确认(“Press Enter to continue”)
  4. 阶段四(自动执行): 仅在经过充分测试后,允许对特定任务自动执行

注意事项:

  • 任何涉及物理动作的代码变更都应回退到上一阶段
  • 保持详细的版本控制记录

实践 5:定义标准化的绘图协议

说明: AI 需要明确的上下文才能生成正确的指令。建立一套标准化的数据交换格式(如 JSON)和绘图原语( primitives),能显著提高成功率。

实施步骤:

  1. 定义标准的 JSON Schema 用于描述绘图任务(包含坐标、颜色、笔号等)
  2. 为 Claude 提供清晰的设备能力文档
  3. 编写示例库,展示如何将自然语言转化为 JSON 结构
  4. 实现一个转换器,将 AI 生成的 JSON 转换为绘图仪指令

注意事项:

  • 保持协议的向后兼容性
  • 在 Prompt 中明确要求 AI 遵循该协议

实践 6:实时状态反馈与错误处理

说明: 单向指令发送是不够的。必须建立反馈循环,让 AI 能够感知绘图仪的当前状态(如“笔抬起”、“纸张用尽”),从而做出动态调整。

实施步骤:

  1. 实现状态查询接口,定期获取设备状态
  2. 将错误信息(如 “Motor stalled”)翻译成自然语言反馈给 AI
  3. 允许 AI 在遇到错误时生成恢复脚本(如 “Re-home plotter”)
  4. 设置看门狗定时器,如果设备长时间未响应则自动暂停

注意事项:

  • 错误信息应尽可能具体,帮助 AI 定位问题
  • 避免因状态轮询过于频繁而阻塞控制线程

学习要点

  • 通过限制模型只能调用底层绘图指令(如移动、抬笔、落笔),成功让 Claude 3.5 Sonnet 掌握了从未见过的硬件设备的控制方法。
  • 在没有提供任何设备文档或示例的情况下,模型仅通过函数定义就能推断出坐标系原点、方向以及如何组合指令来绘制图形。
  • 模型展现出了强大的调试能力,能够根据绘图结果自主分析错误原因,并通过修改代码来修正坐标偏差和逻辑漏洞。
  • 相比于直接生成复杂的 SVG 文件,将绘图任务分解为基础的向量运动指令,能显著降低模型出现幻觉或语法错误的概率。
  • 该案例验证了 LLM 具备“零样本”学习物理硬件的能力,表明通过软件 API 接口,大模型可以灵活地操控现实世界中的机器。
  • 虽然模型在处理简单的几何形状时表现出色,但在涉及更复杂的物理约束(如处理笔架延迟)时仍存在局限性。
  • 这一实验展示了“软件定义硬件”的潜力,即通过标准化的函数接口,无需编写特定驱动即可实现 AI 对各类硬件的通用控制。

常见问题

1: 什么是笔式绘图仪,它与普通喷墨打印机有何不同?

1: 什么是笔式绘图仪,它与普通喷墨打印机有何不同?

A: 笔式绘图仪是一种通过计算机控制的输出设备,它使用物理笔尖在纸张或其他介质上进行绘制。与喷墨打印机的主要区别在于原理:喷墨打印机通过喷射墨点来形成图像,属于光栅设备;而绘图仪通过移动笔臂绘制矢量线条。绘图仪通常用于工程制图、建筑蓝图或艺术创作,其优势在于线条极其精确、清晰,且可以使用钢笔、马克笔等不同工具,但绘制速度较慢,不适合打印大面积色块。


2: 作者提到的 “Claude” 指的是什么?

2: 作者提到的 “Claude” 指的是什么?

A: 这里的 “Claude” 指的是由 Anthropic 公司开发的先进人工智能助手。作者通过编程接口(API)或特定的脚本,将 Claude 与他的物理硬件(笔式绘图仪)连接起来。这意味着 Claude 不仅仅是生成文本或代码,它能够直接发送指令控制物理机器的运动,让 AI 具备了创造物理艺术品的能力。


3: Claude 是如何控制物理绘图仪的?

3: Claude 是如何控制物理绘图仪的?

A: 虽然 AI 模型本身运行在云端服务器上,无法直接连接 USB 设备,但作者通常采用以下工作流:Claude 根据指令生成特定的绘图代码(如 HPGL 语言、G-code 或 Python 脚本),然后将这些代码发送到作者的本地计算机。本地计算机运行一个接收程序,解析这些指令并通过串口或 USB 接口驱动绘图仪的步进电机,从而控制笔的抬落、移动和绘制。


4: 让 AI 控制物理机器存在哪些风险?

4: 让 AI 控制物理机器存在哪些风险?

A: 主要风险在于 AI 可能会生成超出物理设备承受范围的指令。例如,AI 可能会指令绘图仪移动到超出其物理边界的坐标,或者尝试以过高的速度移动,导致电机失步或机械碰撞。此外,如果 AI 生成了极其复杂的路径(如数百万条微小的线段),可能会导致绘图仪长时间空转或笔尖过热。因此,在实现这种连接时,通常需要在硬件驱动层设置限位开关和软件层面的边界检查。


5: 这种应用场景属于 “生成式 AI” 的哪一类?

5: 这种应用场景属于 “生成式 AI” 的哪一类?

A: 这属于生成式 AI 在 “物理世界控制” 或 “创意编程” 领域的应用。它结合了代码生成和创意设计。Claude 在这里扮演了 “创意代理” 的角色,它不仅理解用户的自然语言描述(如 “画一个分形图案”),还需要将其转化为机器可执行的精确逻辑。这展示了 AI 从纯数字内容生成向物理制造延伸的趋势。


6: 普通用户能复现这个项目吗?需要什么技术门槛?

6: 普通用户能复现这个项目吗?需要什么技术门槛?

A: 对于具备一定编程基础的用户是可行的。技术门槛主要包括:1. 拥有一台支持串口通信的旧式或现代笔式绘图仪(如 AxiDraw 或 HP 绘图仪);2. 熟悉 Python 等编程语言,能够编写调用 Claude API 的脚本;3. 了解绘图仪所使用的矢量指令集。虽然不需要精通 AI 模型的底层原理,但需要具备调试硬件接口和解析 AI 输出结果的能力。


思考题

## 挑战与思考题

### 挑战 1: 基础绘图逻辑

问题**: 假设你需要通过 API 向绘图仪发送指令绘制一个边长为 100mm 的正方形。请写出最基础的底层控制指令序列(假设使用 HP-GL 语言),并解释为什么在物理绘图时必须考虑“落笔”和“抬笔”的时机。

提示**: 回顾基本的坐标几何逻辑。绘图仪的笔架在移动时分为“绘图状态”和“移动状态”,你需要明确切换这两个状态的指令(通常是 PUPD),并思考如果不抬笔直接移动到下一个起点会发生什么物理现象。


引用

注:文中事实性信息以以上引用为准;观点与推断为 AI Stack 的分析。



站内链接

相关文章