Skip to content

lusipad/plcopen

Repository files navigation

plcopen

现代 C++ 的 PLCopen 运动控制库 —— 嵌入到你的控制器里,不替代你的控制器。

A modern C++ motion-control library implementing core PLCopen Part 1 building blocks and selected Part 2 concepts. Embed it in your controller, not replace your controller.

License Windows CI Linux CI C++17 Version

项目状态:当前工作集版本为 v0.6.0。项目现在具备 CI、自动化测试、Linux 构建、CMake 包导出、单轴与 homing 的 jerk-aware 规划、基础 IEC 61131-3 功能块、单轴管理/运动功能块、以及最小可用的 gear/cam 多轴同步功能块;在 v1.0 前 API 仍可能变化。

详情见 ROADMAP.md;长期方向见 VISION.md


这是什么

plcopen 是一个 C++17 运动控制库,实现 PLCopen Motion Control Part 1 的核心功能块与状态机,并逐步补齐 Part 2 的选定能力。它被设计成可嵌入的库,不是完整的 PLC 运行时。

适合你,如果你……

  • 正在做工业机器人、自动化设备、定制控制器的 C++ 工程师
  • 需要一个实现了 PLCopen 状态机 + 运动规划的库
  • 希望把标准运动控制算法嵌入到自己的系统里,而不是部署一整套 PLC

不适合你,如果你……

  • 需要完整的 PLC 编程 IDE(看 Beremiz
  • 需要 IEC 61131-3 编译器(ST / LD / FBD,看 MatIEC
  • 需要面向 Arduino / 树莓派的入门 PLC(看 OpenPLC
  • 需要生产就绪的商业 PLC 平台(看 CODESYS / TwinCAT)

为什么不用现有方案

项目 定位 不同点
plcopen(本项目) C++ PLCopen 运动控制库 现代 C++、可嵌入、运动为主
CODESYS 商业完整 PLC 平台 闭源、授权费高
Beremiz Python + IDE 全功能开源 PLC 完整系统,不是可嵌入的库
OpenPLC Arduino/RPi 入门 PLC 面向教学 / DIY
LinuxCNC CNC 机床 G-code 控制器 不是通用 PLC,不含 PLCopen 功能块
MatIEC IEC 61131-3 编译器 只有编译器,不含运行时和运动控制

plcopen 想填补的空白是**"现代 C++ 的可嵌入 PLCopen 运动控制库"**——这块目前缺人做。


当前状态

已实现(截至 v0.6.0)

能力 说明
轴状态机 PLCopen 标准的 8 状态机(Disabled、Standstill、DiscreteMotion 等)
单轴管理/运动功能块 MC_Power、MC_Reset、MC_ReadStatus、MC_ReadAxisError、MC_ReadActualPosition、MC_ReadCommandPosition、MC_ReadActualVelocity、MC_ReadCommandVelocity、MC_ReadParameter、MC_SetPosition、MC_SetOverride、MC_MoveAbsolute、MC_MoveRelative、MC_MoveAdditive、MC_MoveSuperimposed、MC_MoveVelocity、MC_Stop、MC_Halt、MC_Home、MC_TorqueControl
基础 IEC 功能块 R_TRIG、F_TRIG、SR、RS、TON、TOF、TP、CTU、CTD、CTUD
多轴同步功能块 MC_CamTableSelect、MC_CamIn / MC_CamOut、MC_GearIn / MC_GearOut
运动规划 梯形 + 单轴 jerk-aware S 曲线
Buffer mode Aborting / Buffered 等缓冲切换
调度器 单线程周期调度(用户负责在 tick 里调用 runCycle()
示波器 demo 可视化轴状态变化
CMake 构建 Windows + Visual Studio 2022

v0.6.0 亮点

  • 单轴功能块面补齐 MC_ReadParameterMC_SetPositionMC_SetOverrideMC_MoveSuperimposedMC_TorqueControl

  • 公开多轴同步功能块补齐 MC_CamTableSelectMC_CamIn / MC_CamOutMC_GearIn / MC_GearOut

  • 新增最小 CamTable 公共类型与多轴 Catch2 回归,真实验证主从同步与脱开

  • MC_SetOverride 当前明确作用于新规划的运动命令;MC_MoveSuperimposed 当前走单轴 additive 队列语义;MC_TorqueControl 当前直接透传到伺服抽象

  • 新增基础 IEC 61131-3 功能块首批实现:边沿检测、双稳态、定时器、计数器

  • 定时器明确采用显式 scan-cycle 语义,由调用方配置周期时间,不依赖墙钟时间

  • 新增 basic_fb_cycle demo 和独立 Catch2 回归,覆盖边沿、延时与计数边界

  • GitHub Actions CI(Windows + Linux)

  • Catch2 自动化测试覆盖轴状态机、轨迹规划器和单轴功能块

  • 覆盖率基线 >50%,并纳入发布门槛

  • Linux 构建脚本 build.shBUILD_LINUX.md

  • CMake install(EXPORT)find_package(plcopen)FetchContent 支持

  • 独立 plcopen-examples 消费者示例仓库

  • MC_Home 补齐 direct、MODE5/6/7/8、非法参数和 buffer 交互回归测试

  • Buffer mode 覆盖 ABORTING 与所有公开非 ABORTING 枚举的当前队列语义

  • 单轴 AxisMove 路径补齐非零 jerk 的 jerk-aware 轨迹规划与回归测试

  • MC_Home 规划已真正接入 mHomingJerk

  • 新增可选 docs target,未安装 Doxygen 时优雅降级并给出提示

  • docs 入口公开头文件已补齐 Doxygen 注释

  • 新增概念级双轴 sync / gear / cam demo

  • 新增可选 pyplcopen Python 单轴仿真绑定与 smoke test

  • pyplcopen::AxisSim 已补 move_velocity / halt / stop 与加速度读取

完整清单见 ROADMAP.md

暂不在路线图

以下能力属于长期愿景,当前不做

  • ST / IL / LD / FBD / SFC 编译器 & 编辑器
  • 工业通信协议(Modbus / OPC UA / EtherNet/IP)
  • IDE 和图形化调试器
  • Web HMI
  • SIL 安全认证、冗余、分布式 PLC
  • RT-PREEMPT 实时调度

每项何时启动,见 VISION.md 的解锁条件表


快速开始

环境要求

  • Windows:Visual Studio 2022 + CMake 3.21+
  • Linux:gcc 9+ 或 clang 10+ + CMake 3.21+(v0.2.0 起正式支持)
  • C++17 编译器

克隆与构建

git clone https://github.com/lusipad/plcopen.git
cd plcopen

# Windows(推荐使用 build.ps1,详见 BUILD_README.md)
.\build.ps1 -Test

# 跨平台通用命令
cmake -S . -B build
cmake --build build --config Release

生成 API 文档(可选)

cmake -S . -B build -DPLCOPEN_BUILD_DOCS=ON
cmake --build build --config Release --target docs

如果本机未安装 Doxygen,docs target 会打印安装提示并优雅退出。

构建 Python 绑定(可选)

cmake -S . -B build -DPLCOPEN_BUILD_PYTHON_BINDINGS=ON
cmake --build build --config Release
ctest --test-dir build --build-config Release -R pyplcopen_smoke --output-on-failure

最简示例:让一个轴从 0 走到 500

#include "FbSingleAxis.h"
#include "Scheduler.h"
#include <thread>
#include <chrono>

using namespace plcopen;

int main() {
    // 1. 建调度器和轴
    Scheduler sched;
    sched.setFrequency(100);                       // 100Hz 调度
    Axis* axis = sched.newAxis(1, new Servo());    // 轴 ID = 1

    // 2. 使能轴
    FbPower power;
    power.mAxis = axis;
    power.mEnable = true;
    power.mEnablePositive = true;
    power.mEnableNegative = true;

    // 3. 准备一次绝对运动:到位置 500,最大速度 400
    FbMoveAbsolute move;
    move.mAxis = axis;
    move.mPosition = 500;
    move.mVelocity = 400;
    move.mAcceleration = 500;
    move.mDeceleration = 500;

    // 4. 周期性调用(这里用 sleep 模拟实时 tick)
    while (!move.mDone) {
        sched.runCycle();
        power.call();
        move.call();

        if (power.mStatus && power.mValid && !move.mExecute)
            move.mExecute = true;    // 使能成功后触发运动

        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }

    sched.release();
    return 0;
}

完整示例见 src/demo/

  • basic_fb_cycle.cpp —— 基础 IEC 功能块的 scan-cycle 调用示例
  • axis_move.cpp —— 点到点运动 + Buffer mode
  • axis_homing.cpp —— 回零示例(已覆盖核心路径)
  • axis_move_oscilloscope.cpp —— 带状态示波器的演示
  • axis_sync.cpp —— 概念级 1:1 双轴同步 demo
  • axis_gear.cpp —— 概念级固定齿轮比 follow demo
  • axis_cam.cpp —— 概念级离散 cam table follow demo

这些 demo 现在与仓库里的 MC_Cam* / MC_Gear* 最小实现保持一致,用于展示当前公开同步块的基础用法与边界。


标准功能块支持

图例:✅ 已实现 / 📋 未实现

IEC 61131-3 基础功能块

功能块 描述 状态
R_TRIG 上升沿检测
F_TRIG 下降沿检测
SR 置位优先锁存器
RS 复位优先锁存器
TON 通电延时定时器
TOF 断电延时定时器
TP 脉冲定时器
CTU 加计数器
CTD 减计数器
CTUD 双向计数器

PLCopen 运动功能块

单轴管理功能块

功能块 描述 状态
MC_Power 使能/禁用轴
MC_Reset 清除轴错误
MC_ReadActualPosition 读取实际位置
MC_ReadCommandPosition 读取指令位置
MC_ReadActualVelocity 读取实际速度
MC_ReadCommandVelocity 读取指令速度
MC_ReadStatus 读取状态
MC_ReadMotionState 读取运动状态分类
MC_ReadAxisError 读取轴错误
MC_ReadParameter 读取已支持参数子集
MC_SetPosition 重映射当前用户坐标位置
MC_SetOverride 设置新规划运动的倍率
MC_EmergencyStop 触发伺服急停

单轴运动功能块

功能块 描述 状态
MC_MoveAbsolute 绝对位置运动
MC_MoveRelative 相对距离运动
MC_MoveAdditive 叠加位置偏移
MC_MoveSuperimposed 当前映射到 additive 队列语义
MC_MoveVelocity 连续速度运动
MC_Stop 停止运动
MC_Halt 立即停止
MC_Home 回零
MC_TorqueControl 伺服扭矩设定透传

多轴运动功能块

功能块 描述 状态
MC_CamTableSelect 选择凸轮表
MC_CamIn / MC_CamOut 凸轮同步
MC_GearIn / MC_GearOut 齿轮同步

架构

  ┌──────────────────────────────────────────┐
  │  功能块层 (src/fb/)                      │
  │  FbPower, FbMoveAbsolute, FbTon, ...    │
  └──────────────────────────────────────────┘
                     ▼
  ┌──────────────────────────────────────────┐
  │  轴控制层 (src/motion/axis/)             │
  │  Axis, AxisBase, 状态机, AxisMove, ...  │
  └──────────────────────────────────────────┘
                     ▼
  ┌──────────────────────────────────────────┐
  │  运动规划层 (src/motion/interpolation/)  │
  │  ProfilePlanner (梯形 + jerk-aware)      │
  └──────────────────────────────────────────┘
                     ▼
  ┌──────────────────────────────────────────┐
  │  调度层 (src/motion/Scheduler.*)         │
  │  单线程周期调度;轴由 runCycle 推进      │
  │  功能块由用户每周期显式 call()          │
  └──────────────────────────────────────────┘
                     ▼
  ┌──────────────────────────────────────────┐
  │  Servo 接口 (src/motion/Servo.*)         │
  │  对接真实伺服或仿真(由使用者实现)      │
  └──────────────────────────────────────────┘

设计文档见 doc/design/design_doc.md


已知边界

  • 当前实现中,所有非 ABORTING 的 Buffer mode 枚举共享同一套“排队、不立即打断前一条命令”的语义;细粒度 blending 行为尚未分化实现。
  • 基础 IEC 定时器按显式周期推进;调用方需要保证每 scan 调用一次,并通过 setCycleTime() 提供周期时间。
  • MC_SetOverride 当前作用于新规划的运动命令,不对已经运行中的 profile 做重规划。
  • MC_MoveSuperimposed 当前在单轴队列上按 additive 偏移语义实现,不是独立的并行叠加轨迹合成器。
  • MC_TorqueControl 当前把扭矩设定直接透传给伺服抽象;更深入的 torque-mode 闭环控制仍取决于具体伺服实现。
  • MC_Gear* / MC_Cam* 当前是单主单从的最小同步实现,不包含完整 AxesGroup、多从轴协调或高级平滑脱开策略。
  • MC_CamTableSelect 当前负责表校验和句柄传递;MC_CamIn 直接消费选定的 CamTable 句柄,不维护独立的控制器侧表仓库。
  • mStartSync 当前建模为同步建立成功时的一拍脉冲。
  • pyplcopen 当前只暴露单轴仿真 facade,不是完整 Python PLCopen SDK。

文档

文档 说明
README.md 本文档:项目概览
CHANGELOG.md 版本变化记录
VISION.md 长期愿景(3-5 年方向)
ROADMAP.md 近期路线(6-12 个月)
BUILD_README.md 详细构建指南
BUILD_LINUX.md Ubuntu 22.04 构建说明
src/fb/FbBasic.h 基础 IEC 功能块公开头文件
src/fb/FbMultiAxis.h 多轴同步功能块公开头文件
CLAUDE.md AI 协作的行为规范
doc/design/ 当前代码的设计文档
doc/reference/ PLCopen 标准原文(PDF)
doc/vision/ 愿景期探索性设计(非当前路线图)

贡献

欢迎各种形式的贡献:

  • Bug 修复、测试补充、文档改进:随时 PR
  • 当前路线图里的 issue-driven 修复或文档/测试补充:先看 ROADMAP.md 当前状态,再发 issue / PR
  • 不在路线图上的能力:先看 VISION.md 解锁条件,满足后开 issue 讨论,再动手

报告问题:GitHub Issues


项目历史

本项目 fork 自 i5cnc(原仓库已停止维护)。我们保留了运动控制核心,按 PLCopen 标准重构和完善。


License

Apache License 2.0


参考资料

  1. IEC 61131-3 国际标准
  2. PLCOpen Motion Control 资料(本仓库 doc/reference/ 下有 Part 1&2 原文)
  3. 设计模式:状态模式、观察者模式、工厂模式

联系


致谢

  • IEC 61131-3 国际标准
  • PLCOpen 组织的技术规范
  • i5cnc 原始项目
  • 工业自动化开源社区

About

一个基于 plcopen 运动控制标准实现的 C++ 库

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors