feat: 实现 Axis 核心属性与 MC_Power 功能块

- Axis: 新增运动学/功率/错误管理属性(_position 等 10+ 项)
- Axis: 新增 doPower()/readState()/cycle() 接口骨架
- MC_Power: 实现功率使能功能块(边沿检测 + 状态输出)
- GlobalResource: 新增 CreateAxis/GetAxisRefById 全局轴管理
- App/CMakeLists.txt: 添加 GlobalResource.cpp 源文件
- docs: 更新 Axis 属性清单与 MC_Power 设计文档
This commit is contained in:
chen
2026-07-03 10:01:06 +00:00
parent 7f73fb48ef
commit 0587f7ac6c
13 changed files with 685 additions and 94 deletions
+110 -75
View File
@@ -2,11 +2,31 @@
`Axis` 是 PLCopen 运动控制库的核心仿真类,实现 IEC 61131-3 单轴状态机与运动学。
## 设计决策
### 可见性:运动学属性为 `private`
功能块不直接读写轴内部状态,而是通过 `AXIS_REF` 调用公开接口。这是 IEC 61131-3 的标准模式——轴是功能块黑盒:
```
功能块 (MC_MoveAbsolute) Axis
───────────────────── ─────────────
AXIS_REF → axis private: position_, velocity_, ...
axis.acceptCommand(cmd) ──────→ 只有 cycle() 能写运动学数据
axis.readActualPosition() ←─── public: getter 只读
```
> 运动控制线程定时调用 `cycle()` 独占写权限,避免数据竞争。
### 数值类型:浮点 `REAL` (double)
遵循 IEC 61131-3 / PLCopen 规范,使用 `double` 表示物理量(mm、°/s 等)。`double` 有 52 位尾数(约 15 位十进制有效数字),以 10ms 周期运行 1 小时,累积的浮点舍入误差在 $10^{-10}$ 量级,工程上可完全忽略。若未来对接真实驱动器,在数据交换层做脉冲数换算即可。
---
## 1. 当前已实现
### 1.1 轴标识与自引用 — `AXIS_REF ref_`
### 1.1 轴标识与自引用 — `AXIS_REF _ref` (private)
| 字段 | 类型 | 说明 |
|------|------|------|
@@ -14,47 +34,54 @@
| `axisName` | `std::string` | 轴名称,默认 `"Axis1"` |
| `axis` | `Axis*` | 指向自身实例的指针,供功能块间接访问轴对象 |
> `AXIS_REF` 在 IEC 61131-3 中是 `VAR_IN_OUT` 参数,本实现中构造时自绑定。
### 1.2 轴状态 — `MC_AXIS_STATE _state` (private)
### 1.2 轴状态 — `MC_AXIS_STATE state_`
当前状态,初始值 `Disabled`。新增辅助状态 `_resultingState` 用于记录指令完成后的目标状态。
当前状态机状态,初始值为 `Disabled`。可能的取值:
状态转换由 `cycle()` 方法驱动(逻辑待实现)。
```
Disabled → Standstill → DiscreteMotion / ContinuousMotion / Homing
→ Stopping
ErrorStop
SynchronizedMotion (预留)
```
### 1.3 运动学属性 (private) ✅
状态转换由 `cycle()` 方法驱动(尚未实现)
### 1.3 构造函数
```cpp
explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
```
初始化 `ref_` 并自绑定 `axis` 指针,`state_` 默认 `Disabled`
---
## 2. 必须扩展的属性(待实现)
按照 PLCopen 规范,完整的轴模型还需以下属性。
### 2.1 运动学属性
`cycle()` 独占写入;外部通过 `readXxx()` 只读访问
| 属性 | 类型 | 说明 |
|------|------|------|
| `position_` | `REAL` | 当前指令位置 |
| `actualPosition_` | `REAL` | 当前实际位置 |
| `velocity_` | `REAL` | 当前速度 |
| `actualVelocity_` | `REAL` | 实际速度 |
| `acceleration_` | `REAL` | 当前加速度 |
| `deceleration_` | `REAL` | 当前速度 |
| `_position` | `REAL` | 当前指令位置 |
| `_actualPosition` | `REAL` | 当前实际位置(含跟随误差仿真) |
| `_velocity` | `REAL` | 当前指令速度 |
| `_actualVelocity` | `REAL` | 当前实际速度 |
| `_acceleration` | `REAL` | 当前指令加速度 |
| `_actualAcceleration` | `REAL` | 当前实际加速度 |
| `_deceleration` | `REAL` | 减速度(尚未添加) |
### 2.2 活动指令 — `MotionCommand activeCommand_`
### 1.4 功率与使能 (private) ✅
| 属性 | 类型 | 说明 |
|------|------|------|
| `_powerEnabled` | `BOOL` | 功率级是否使能 |
| `_homed` | `BOOL` | 是否已完成回零 |
### 1.5 错误管理 (private) ✅
| 属性 | 类型 | 说明 |
|------|------|------|
| `_errorId` | `MC_ERROR_ID` | 当前错误码,`mcNoError` 表示正常 |
| `_errorStop` | `BOOL` | 是否触发错误停止 |
### 1.6 构造函数 & cycle() (public)
```cpp
explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
void cycle(); // 骨架已生成,逻辑待实现
```
初始化 `_ref` 并自绑定 `axis` 指针,`_state` 默认 `Disabled`
---
## 2. 待实现的属性与方法
### 2.1 活动指令 — `MotionCommand _activeCommand` (private)
当前正在执行的运动指令参数快照,类型为 `MotionCommand`
@@ -69,61 +96,69 @@ explicit Axis(UINT axisNo = 1, std::string name = "Axis1");
| `homePosition` | `REAL` | 回零位置 |
| `resultingState` | `MC_AXIS_STATE` | 指令完成后要进入的状态 |
### 2.3 功率与使能
### 2.2 待补充的运动学属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `powerEnabled_` | `BOOL` | 功率级是否使能 |
| `homed_` | `BOOL` | 是否已完成回零 |
| 属性 | 说明 |
|------|------|
| `_deceleration` | 减速度(已有 `_acceleration`,缺独立减速参数) |
### 2.4 错误管理
| 属性 | 类型 | 说明 |
|------|------|------|
| `errorId_` | `MC_ERROR_ID` | 当前错误码,`mcNoError` 表示正常 |
| `errorStop_` | `BOOL` | 是否触发错误停止 |
### 2.5 轴状态机方法 — `cycle()`
### 2.3 轴状态机方法 — `cycle()` (public, 实现待完成)
```cpp
void cycle(REAL deltaTime);
void cycle();
```
每周期由应用层调用,执行
1. 根据 `activeCommand_` 计算运动学输出
2. 更新 `position_` / `velocity_`
每周期由运动控制线程调用,待实现逻辑
1. 根据 `_activeCommand` 计算运动学输出
2. 更新 `_position` / `_velocity`
3. 评估状态转换条件
4. 在离散运动到达目标时自动切换到 `Standstill`
### 2.6 功能块交互接口
### 2.4 功能块交互接口 (public, 全部待实现)
| 方法 | 说明 |
|------|------|
| `acceptCommand(const MotionCommand&)` | 接收功能块下发的运动指令 |
| `doPower(BOOL enable)` | 功率使能/去使能 |
| `doStop()` / `doHalt()` | 停止 / 暂停 |
| `doReset()` | 从 ErrorStop 恢复 |
| `doHome(REAL homePos)` | 发起回零 |
| `readStatus()` | 读取当前状态快照 |
| `readError()` | 读取当前错误码 |
| 方法 | 可见性 | 说明 |
|------|--------|------|
| `acceptCommand(const MotionCommand&)` | public | 接收功能块下发的运动指令 |
| `doPower(BOOL enable)` | public | 功率使能/去使能 |
| `doStop()` / `doHalt()` | public | 停止 / 暂停 |
| `doReset()` | public | 从 ErrorStop 恢复 |
| `doHome(REAL homePos)` | public | 发起回零 |
| `readStatus()` | public | 读取当前状态快照 |
| `readActualPosition()` | public | 读取实际位置 |
| `readActualVelocity()` | public | 读取实际速度 |
| `readError()` | public | 读取当前错误码 |
---
## 3. 完整属性清单(含待实现)
## 3. 完整属性清单
```
private
───────
Axis
├── ref_ (AXIS_REF) ✅ 已实现
├── state_ (MC_AXIS_STATE) ✅ 已实现
├── position_ (REAL) ⬜ 位置
├── actualPosition_ (REAL) ⬜ 实际位置
├── velocity_ (REAL) ⬜ 速度
├── actualVelocity_ (REAL) ⬜ 实际速度
├── acceleration_ (REAL) ⬜ 加速度
├── deceleration_ (REAL) ⬜ 减速度
├── activeCommand_ (MotionCommand) ⬜ 活动指令
├── powerEnabled_ (BOOL) ⬜ 功率使能
├── homed_ (BOOL) ⬜ 回零完成
├── errorId_ (MC_ERROR_ID) ⬜ 错误码
── errorStop_ (BOOL) ⬜ 错误停止
├── _ref (AXIS_REF)
├── _state (MC_AXIS_STATE)
├── _resultingState (MC_AXIS_STATE) ✅ 指令完成目标状态
├── _position (REAL)
├── _actualPosition (REAL)
├── _velocity (REAL)
├── _actualVelocity (REAL)
├── _acceleration (REAL)
├── _actualAcceleration (REAL) ✅
├── _deceleration (REAL) ⬜ 待添加
├── _powerEnabled (BOOL)
├── _homed (BOOL) ✅
── _errorId (MC_ERROR_ID) ✅
├── _errorStop (BOOL) ✅
└── _activeCommand (MotionCommand) ⬜ 活动指令
public
──────
Axis(axisNo, name) ✅
cycle() 🟡 骨架已就绪
acceptCommand(cmd) ⬜
doPower / doStop / doHalt ⬜
doReset / doHome ⬜
readStatus / readActualPosition ⬜
readActualVelocity / readError ⬜
```