xcore_api 介绍
xcore_api 是控制器插件开发使用的 C++ 接口集合,插件通过这些接口接入控制器内部能力。典型用途包括:插件生命周期管理、自定义 RL 指令注册、运动指令下发、机器人状态查询、IO 和寄存器读写、EtherCAT/现场总线通信、客户端插件与控制器插件通信、日志上报等。
当前头文件版本为 0.0.3,对应控制器版本以接口包内 README.md 说明为准。开发时应确保插件使用的 xcore_api 版本与目标控制器版本匹配。
使用方式概览
控制器插件通常按以下方式使用 xcore_api:
- 在插件工程中包含需要的头文件,例如
launch/launch_api.hpp、rl_cmd/morden_rl_cmd_api.hpp。 - 实现一个入口模块,继承
xcore_api::launch::LaunchAPI。 - 在
Init()阶段完成配置加载、日志初始化、Hook 注册等初始化动作。 - 在
Start()阶段注册指令、注册服务、注册日志码或启动必要的后台任务。 - 在
Stop()阶段释放资源,停止线程或关闭总线连接。 - 使用
LAUNCH_MODULE或LAUNCH_MODULE_PRIORITY宏将入口模块自动注册到控制器。
入口模块示例:
#include "launch/launch_api.hpp"
class ExamplePlugin : public xcore_api::launch::LaunchAPI {
public:
void Init() override {
// 插件初始化,例如读取配置、初始化日志
}
void Start() override {
// 所有插件 Init 完成后执行,例如注册指令、服务、Hook
}
void Stop() override {
// 控制器停止插件时执行资源释放
}
};
LAUNCH_MODULE(ExamplePlugin)
模块总览
| 模块目录 | 主要头文件 | 作用 |
|---|---|---|
launch | launch_api.hpp | 插件入口和生命周期管理。 |
rl_cmd | morden_rl_cmd_api.hpp | 注册自定义 RL 指令,解析指令参数,返回执行结果。 |
motion_cmd | motion_cmd_api.hpp | 生成并下发运动指令,支持直线、关节、圆弧、螺旋等运动类型。 |
sdk | sdk_cmd_api.hpp | SDK 自定义指令接口,支持运动指令和非运动指令进入 SDK 指令队列。 |
hooks | hooks_api.hpp、hooks_args_api.hpp | 注册控制器事件回调,例如点位变化、程序跳转、开始、暂停、急停等。 |
states | states_api.hpp | 查询和设置控制器状态,例如自动/手动、上下电、任务空间、仿真模式等。 |
rl_task | rl_task_api.hpp | 查询和控制 RL 任务,例如开始、暂停、停止、跳转行、获取执行指针等。 |
io | analog_api.hpp | 读写 AI/AO/DI/DO/GI/GO 信号以及内部寄存器。 |
registers | function_code_api.hpp | 扩展寄存器功能码,支持自定义寄存器读写逻辑。 |
ethercat | ecat_base_api.hpp | 操作 EtherCAT 从站 PDO/SDO。 |
fieldbus | fieldbus_api.hpp | 创建和操作现场总线设备,如 Modbus、Profinet、EIP、CC-Link 等。 |
endtool | endtool_api.hpp | 通过末端协议透传控制电爪等末端工具,当前主要封装 Modbus RTU。 |
service | service_api.hpp | 注册控制器插件服务,用于客户端插件与控制器插件之间传递 JSON 协议。 |
log | log_api.hpp | 初始化插件独立日志,并提供插件日志宏。 |
user_log | user_log_api.hpp | 注册和上报多语言用户日志、运行日志。 |
const_data | pose_api.hpp、ecat_api.hpp | 定义位姿、点位、速度、工具、工件、触发器、PDO/SDO 等通用数据结构。 |
utils | filesystem_api.hpp、thread_pool_api.hpp、singleton_api.hpp | JSON/文件读写、线程池、单例模板等通用工具。 |
launch:插件入口模块
launch 模块用于把插件中的入口对象注册到控制器。入口类需要继承 LaunchAPI 并实现 Init()、Start()、Stop() 三个生命周期函数。
执行顺序如下:
- 控制器加载插件动态库,构造插件入口对象。
- 按优先级依次执行所有插件入口模块的
Init()。 - 所有
Init()完成后,按优先级执行Start()。 - 控制器停止或卸载插件时,执行
Stop()。 - 插件对象析构。
常用接口和宏:
| 接口/宏 | 说明 |
|---|---|
LaunchAPI::Init() | 初始化阶段,适合加载配置、初始化日志、准备数据结构。 |
LaunchAPI::Start() | 启动阶段,适合注册指令、服务、日志码等。 |
LaunchAPI::Stop() | 停止阶段,适合释放资源、停止线程、关闭设备连接。 |
LaunchAPI::Register(priority, ptr) | 注册入口模块,priority 越高越先执行。 |
LAUNCH_MODULE(ClassName) | 以默认优先级 0 注册入口模块。 |
LAUNCH_MODULE_PRIORITY(ClassName, priority) | 以指定优先级注册入口模块。 |
rl_cmd:自定义 RL 指令
rl_cmd 模块用于把 C++ 实现注册为 RL 程序中可调用的自定义指令。插件可声明指令名称、参数类型、默认参数、前瞻行为、任务限制、步退行为,并在执行函数中读取参数、调用控制器能力或设置返回值。
核心概念:
| 类型/接口 | 说明 |
|---|---|
ValueTypeAPI | 指令参数类型,例如 VALUE_INT、VALUE_DOUBLE、VALUE_STRING、VALUE_POSE、VALUE_TOOL、VALUE_WOBJ 等。 |
ArgTypeAPI | 描述单个参数类型,可设置是否允许缺省以及默认值。 |
RLCmdConfigAPI | 指令配置,包含函数名、前瞻类型、任务限制、步退行为。 |
ModernRLCmdAPI | 自定义指令构造器,用于设置参数和执行函数。 |
RLCallFrameAPI | 获取当前指令运行上下文,例如任务名、文件名、行号,也可设置返回值。 |
SymbolVarBaseAPI | 指令参数访问对象,可读取基础类型、点位、速度、工具、工件等。 |
RegPluginCmdsAPI() | 将指令注册到控制器。 |
常见执行结果:
| 返回值 | 含义 |
|---|---|
CMD_PROCESS_SUCCESS | 指令执行成功,RL 继续运行。 |
CMD_PROCESS_ERROR | 指令执行失败,暂停当前任务。 |
CMD_PROCESS_FATAL | 致命错误,RL 停止。 |
CMD_PROCESS_IGNORE | 异步指令,任务进入异步等待。 |
CMD_PROCESS_EXTRA | 额外执行的指令,常用于运动指令。 |
CMD_PROCESS_RESCHEDULE | 请求重新调度。 |
简化示例:
#include "rl_cmd/morden_rl_cmd_api.hpp"
void RegisterExampleCmd() {
xcore_api::rl_cmd::RLCmdConfigAPI cfg;
cfg.SetFuncName("ExampleCmd");
cfg.SetLookAhead(xcore_api::rl_cmd::WAIT_MOVE_PAUSE);
BEGIN_COMMAND_API(cfg)
PARAMS_API(xcore_api::rl_cmd::ArgTypeAPI(xcore_api::rl_cmd::ValueTypeAPI::VALUE_INT))
xcore_api::rl_cmd::RLCmdActionAPI action =
[](std::shared_ptr<xcore_api::rl_cmd::RLCallFrameAPI> frame,
std::vector<std::shared_ptr<xcore_api::rl_cmd::SymbolVarBaseAPI>> args) {
return [frame, args]() {
int value = args[0]->GetIntVal();
// 在此处执行插件逻辑
return xcore_api::rl_cmd::CMD_PROCESS_SUCCESS;
};
};
EXECUTE_API(action)
REGISTER_COMMAND_API
}
使用建议:
- 指令注册建议在入口模块
Start()阶段完成。 - 指令参数类型应与 RL 调用方式保持一致,读取前先明确参数类型。
- 涉及运动的指令应正确设置前瞻行为,避免破坏控制器调度逻辑。
- 需要返回值时,通过
RLCallFrameAPI::SetReturnValue()设置。
motion_cmd:运动指令
motion_cmd 模块用于构造并发送运动轨迹。它通常与自定义 RL 指令配合使用:RL 指令解析参数后,将点位、速度、工具、工件、转弯区等信息封装为 MotionCmdArgsAPI,再通过 MotionCmdAPI 发送给控制器运动队列。
支持的运动类型包括:
| 类型 | 说明 |
|---|---|
MOVE_ABSJ | 关节绝对运动。 |
MOVE_J | 关节运动。 |
MOVE_L | 直线运动。 |
MOVE_C | 圆弧运动。 |
MOVE_CF | 全圆运动,需要设置全圆额外参数。 |
MOVE_T | 摆线运动,需要设置摆线参数。 |
MOVE_SP | 螺旋线运动,需要设置螺旋参数。 |
常用配置:
| 接口 | 说明 |
|---|---|
SetTargetPoint() | 设置目标点。 |
SetAuxPoint() | 设置辅助点,圆弧等多点运动会用到。 |
SetMoveType() | 设置运动类型。 |
SetTool() / SetWobj() | 设置工具和工件。 |
SetSpeed() / SetZone() | 设置速度和转弯区。 |
SetTriggers() | 设置轨迹触发器。 |
SetCallback() | 设置运动开始、暂停、完成、错误回调。 |
SetFinishInAdvance() | 提前终止轨迹,可配合 Trigger/IO 实现搜索类指令。 |
SendCmd() | 发送单条运动指令。 |
SendSegmentCmds() | 发送多段间断连续运动。 |
SendStepBackCmd() | 生成步退指令。 |
注意事项:
- 位姿、速度、距离等数据采用国际单位,位置单位为米,角度通常为弧度。
MOVE_CF、MOVE_T、MOVE_SP需要设置对应的扩展参数。- 自定义运动指令要关注前瞻、转弯区和回调执行时机。
- 多段轨迹应根据业务选择
SendCmd()或SendSegmentCmds()。
sdk:SDK 自定义指令
sdk 模块用于把插件定义的 SDK 指令加入控制器 SDK 指令队列。它同时支持运动指令和非运动指令。
核心接口:
| 接口 | 说明 |
|---|---|
SDKCmdAPI | 非运动 SDK 指令基类。 |
BeforeProcess() | 指令执行前回调,可选实现。 |
DerivedProcess() | 指令核心执行逻辑,返回 SUCCESS、PENDING 或 ERROR。 |
AfterProcess() | 指令执行后回调,可选实现。 |
MordenSDKCmdAPI::SendSDKMotionCmd() | 发送 SDK 运动指令。 |
MordenSDKCmdAPI::SendSDKCmd() | 发送 SDK 普通指令。 |
MordenSDKCmdAPI::SetFinalSDKCmd() | 设置打断前瞻的指令。 |
hooks:控制器事件回调
hooks 模块用于监听控制器内部事件。插件注册 Hook 后,当控制器发生对应事件时,会回调插件提供的函数。
支持的事件包括:
| 事件 | 说明 |
|---|---|
POINT_CHANGE | 点位增加、删除、修改。 |
PP_TO_MAIN | 程序指针跳转到主程序。 |
PP_TO_LINE | 程序指针跳转到指定行。 |
B_START_RUN | 开始运行。 |
B_PAUSE_RUN | 暂停运行。 |
E_STOP_RUN | 急停。 |
运行方式:
| 运行方式 | 说明 |
|---|---|
SYNC_RUN | 同步执行,会阻塞控制器对应事件。 |
ASYNC_RUN_IN_THREAD_POOL | 在线程池中异步执行。 |
ASYNC_RUN_IN_RT_THREAD | 在实时线程中执行。 |
注册流程:
- 创建
HookDataAPI。 - 调用
SetEvent()设置事件。 - 调用
SetHook()设置回调函数。 - 调用
SetRunType()设置同步或异步运行方式。 - 调用
SetPriority()设置优先级。 - 调用
RegisterHooksAPI()注册。
注意:Hook 注册不接受插件 Start() 之后的动态注册。同步 Hook 中不要执行耗时操作,避免阻塞控制器事件流程。
states:机器人和控制器状态
states 模块用于查询或设置控制器运行状态。
常用能力:
| 接口 | 说明 |
|---|---|
IsAutoMode() / SetAutoMode() | 查询或设置自动/手动模式。 |
IsPowerOn() / SetPowerOn() | 查询或设置上下电状态。 |
IsTaskSpaceReady() / SetTaskSpace() | 查询或占用任务空间。 |
IsRobotBusy() / SetRobotBusy() | 查询或设置机器人忙状态。 |
GetRunningState() | 获取当前运行阶段,如开始、暂停、单步、碰撞、急停等。 |
IsSimuMode() | 查询当前是否为仿真模式。 |
使用建议:
- 修改控制器状态前应确认当前模式和任务状态。
SetRobotBusy()、SetTaskSpace()这类占用状态需要成对释放,否则可能影响其他模块使用机器人。- 与运动或任务控制组合使用时,应先判断当前是否允许执行。
rl_task:RL 任务控制
rl_task 模块用于控制和查询 RL 程序任务。
常用接口:
| 接口 | 说明 |
|---|---|
PPToMain() | 重置程序指针到主程序。 |
IsProgramResetDone() | 判断程序复位是否完成。 |
PPToLine() | 跳转到指定任务、文件、行。 |
PPToFunc() | 跳转到指定函数,主要用于调试。 |
ModifyProgramLoop() | 修改程序循环模式。 |
AlarmRLTask() | 唤醒指定任务。 |
StartRun() / PauseRun() / StopRun() | 开始、暂停、停止程序。 |
PauseRunAndWaitIdle() | 暂停程序并等待机器人停止。 |
GetPointedLine() / SetPointedLine() | 获取或设置程序指针。 |
GetExecLine() / SetExecLine() | 获取或设置运动指针。 |
IsTaskExists() / IsTaskRunning() | 查询任务是否存在或正在运行。 |
注意:跳转失败后解释器状态可能不可控,必要时需要重新加载任务。
io:信号和寄存器
io 模块当前主要由 Analog 单例提供 AI/AO/DI/DO/GI/GO 信号和内部寄存器访问能力。
信号接口:
| 信号类型 | 读取接口 | 写入接口 |
|---|---|---|
| AI | GetAIValue() | 不支持 |
| AO | GetAOValue() | SetAOValue() |
| DI | GetDIValue() | 不支持 |
| DO | GetDOValue() | SetDOValue() |
| GI | GetGIValue() | 不支持 |
| GO | GetGOValue() | SetGOValue() |
寄存器接口:
| 数据类型 | 读取接口 | 写入接口 |
|---|---|---|
int16 | ReadInt16Register() | WriteInt16Register() |
bool | ReadBoolRegister() | WriteBoolRegister() |
float | ReadFloatRegister() | WriteFloatRegister() |
bit | ReadBitRegister() | WriteBitRegister() |
int32 | ReadInt32Register() | WriteInt32Register() |
byte | ReadByteRegister() | WriteByteRegister() |
辅助接口:
| 接口 | 说明 |
|---|---|
IsAiExist() / IsAoExist() | 判断模拟量信号是否存在。 |
IsDiExist() / IsDoExist() | 判断数字量信号是否存在。 |
IsGiExist() / IsGoExist() | 判断组信号是否存在。 |
RegisterType() | 查询寄存器类型。 |
RegisterWriteable() | 查询寄存器是否可写。 |
CheckRegisterCanUsedAsIO() | 判断寄存器能否作为指定 IO 类型替代使用。 |
registers:寄存器功能码
registers 模块用于扩展寄存器功能码。插件可以声明一个功能码类,定义支持的寄存器类型、长度、读写属性,并实现实际执行逻辑。
核心类型:
| 类型/接口 | 说明 |
|---|---|
RegTypeAPI | 寄存器数据类型:BIT、BOOL、BYTE、INT16、INT32、FLOAT。 |
FuncCodeCfgAPI | 功能码配置,包含名称、支持类型、长度、是否可写。 |
FuncCodeAPI | 功能码基类,需要实现 ExecFuncCode() 和 Clone()。 |
ReadIntRegValue() / ReadFloatRegValue() | 读取功能码关联的寄存器值。 |
WriteIntRegValue() / WriteFloatRegValue() | 写入功能码关联的寄存器值。 |
RegFuncCodeAPI() | 注册功能码到控制器。 |
可使用 DECLARE_FUNCTION_CODE_API 和 FUNCTION_CODE_EXECUTE_API 宏简化声明和实现。
ethercat:EtherCAT 从站访问
ethercat 模块用于操作 EtherCAT 从站的 PDO 和 SDO。
数据结构在 const_data/ecat_api.hpp 中定义:
| 数据结构 | 说明 |
|---|---|
PdoAPI | PDO 数据描述,包括 baseIndex、byteOffs、byteSize、name。 |
SdoAPI | SDO 数据描述,包括 index、subIndex、dateLen、timeOut、回调函数等。 |
核心接口:
| 接口 | 说明 |
|---|---|
EcatBaseAPI(slave_id) | 创建指定从站 ID 的 EtherCAT 操作对象。 |
GetPdoValue() / SetPdoValue() | 读取或写入 PDO 值。 |
GetSdoValue() / SetSdoValue() | 读取或写入 SDO 值。 |
RegisterPdo() / RegisterSdo() | 注册 PDO/SDO 到对应偏移或索引。 |
注意:读取或写入 PDO/SDO 时,传入的数据指针空间需要与对象长度匹配。
fieldbus:现场总线
fieldbus 模块封装现场总线设备的创建、配置、打开、关闭、寄存器读写和 DI/DO 访问。
支持的设备类型:
| 类型 | 说明 |
|---|---|
MODBUS_TCP_MASTER / MODBUS_TCP_SLAVER | Modbus TCP 主站/从站。 |
MODBUS_RTU_MASTER / MODBUS_RTU_SLAVER | Modbus RTU 主站/从站。 |
PROFINET_SLAVER | Profinet 从站。 |
EIP_SLAVER | EtherNet/IP 从站。 |
CCLINK_IE_SLAVER / CCLINK_ECAT_SLAVER | CC-Link 相关从站。 |
配置类:
| 配置类 | 说明 |
|---|---|
FieldbusCfgAPI | 总线基础配置,包含设备类型、设备名、大小端。 |
ModbusCfgAPI | Modbus 配置,包括 IP、端口、串口、从站 ID、寄存器起始地址和数量。 |
ProfinetCfgAPI | Profinet 配置,包括站点名、网卡、更新周期、槽模块 ID。 |
EipCfgAPI | EIP 配置,包括读写寄存器数量、网卡。 |
CCLinkCfgAPI | CC-Link 配置,包括协议类型、网卡、占用站数、波特率、协议版本。 |
FieldbusAPI 提供统一访问接口:
| 接口 | 说明 |
|---|---|
Open() / Close() | 打开或关闭总线设备。 |
ReadRegisters() / WriteRegisters() | 读取或写入寄存器。 |
GetDINum() / GetDONum() | 获取 DI/DO 数量。 |
GetDI() / SetDO() | 读取 DI 或设置 DO。 |
endtool:末端工具
endtool 模块用于通过末端协议透传控制电爪等设备。当前 ModbusRTUEndtoolAPI 封装了 Modbus RTU 常用功能码:
| 接口 | Modbus 功能码 | 说明 |
|---|---|---|
RWData() | 透传 | 直接发送和接收原始数据。 |
ReadCoil_01() | 01 | 读线圈。 |
ReadDiscreteInput_02() | 02 | 读离散输入。 |
ReadRegister_03() | 03 | 读保持寄存器。 |
ReadRegister_04() | 04 | 读输入寄存器。 |
WriteCoil_05() | 05 | 写单个线圈。 |
WriteRegister_06() | 06 | 写单个寄存器。 |
WriteCoil_0F() | 15 | 写多个线圈。 |
WriteRegister_10() | 16 | 写多个寄存器。 |
该模块适合封装电爪、工具快换、传感器等末端设备的私有协议。
service:客户端与控制器插件通信
service 模块用于在控制器插件中注册自定义服务协议。客户端插件向控制器发送指定 plugin_name 和 key 的 JSON 请求后,控制器会调用已注册的回调函数,并返回回调生成的 JSON 数据。
接口:
int RegServiceAPI(
const std::string& plugin_name,
const std::string& key,
const std::function<Json::Value(const Json::Value&)>& func
);
使用场景:
- 客户端插件读取控制器插件状态。
- 客户端插件向控制器插件下发配置。
- 控制器插件向客户端返回设备状态、诊断信息或业务数据。
- 用 JSON 自定义协议实现轻量级插件间通信。
log 与 user_log:日志能力
log 模块用于初始化插件独立日志,并提供日志宏:
| 宏 | 说明 |
|---|---|
LOG_DEBUG | 调试日志。 |
LOG_INFO | 普通信息日志。 |
LOG_WARNING | 警告日志。 |
LOG_ERROR | 错误日志。 |
LOG_FATAL | 致命错误日志。 |
初始化接口:
xcore_api::log::InitLogAPI("log_dir", 10, 5);
参数含义为日志目录、单个日志文件大小上限(单位 MB)和日志文件数量。日志存储总量不能超过接口约束。
user_log 模块用于向控制器注册和上报用户日志:
| 接口 | 说明 |
|---|---|
ConfigReportLogAPI() | 配置插件多语言日志。 |
ConfigEnglishReportLogAPI() | 配置英文兜底日志。 |
RegisterReportLogAPI() | 将日志配置注册到控制器并生效。 |
ReportUserLogAPI() | 上报多语言用户日志。 |
ReportRunLogAPI() | 上报用户运行日志。 |
建议在 Init() 阶段加载日志配置,在 Start() 阶段注册日志码。
const_data:通用数据结构
const_data/pose_api.hpp 定义控制器插件常用的运动数据结构,采用国际单位:
| 数据结构 | 说明 |
|---|---|
PositionAPI | 位置,单位为米。 |
QuaternionAPI | 姿态四元数。 |
ConfDataAPI | 机器人构型数据,用于确定到达目标点的解。 |
PoseAPI | 位姿/坐标系,支持右乘和求逆。 |
PointAPI | 点位信息,可表示笛卡尔点或关节点。 |
ZoneAPI | 转弯区,包含距离和百分比。 |
SpeedAPI | 速度,包含 TCP 速度、姿态速度、臂角速度、百分比等。 |
LoadAPI | 负载,包含质量、质心和转动惯量。 |
TriggerAPI | 轨迹触发器,支持距离或时间触发。 |
ToolAPI | 工具坐标系和工具负载。 |
WobjAPI | 工件坐标系、用户坐标系和工件负载。 |
const_data/ecat_api.hpp 定义 EtherCAT PDO/SDO 数据结构,供 ethercat 模块使用。
utils:通用工具
utils 模块提供插件开发中的常用工具能力。
文件和 JSON:
| 接口 | 说明 |
|---|---|
WriteBinaryToFileAPI() / ReadBinaryFromFileAPI() | 二进制文件写入和读取。 |
LoadFromFileAPI() / SaveToFileAPI() | JSON 文件读取和保存。 |
LoadFromStringAPI() / SaveToStringAPI() | JSON 字符串解析和序列化。 |
SaveToStringInLineAPI() | 将 JSON 按行保存为字符串。 |
CreateEmptyJsonFileAPI() | 创建空 JSON 文件。 |
IsJsonFileAPI() | 判断文件是否为 JSON 文件。 |
GetPluginNameAPI() | 获取当前插件名称。 |
线程池:
| 接口 | 说明 |
|---|---|
RunInThreadPoolAPI() | 在线程池中执行无返回值函数。 |
RunInThreadPoolIntAPI() | 在线程池中执行返回 int 的函数。 |
单例:
| 接口/宏 | 说明 |
|---|---|
SingletonBaseAPI<T> | 单例基类模板。 |
DECLARE_SINGLETON(type) | 在类内声明单例友元。 |
SINGLETON_INSTANCE(type) | 获取单例指针。 |
INIT_SINGLETON(type) | 初始化单例。 |
开发注意事项
- 插件入口模块应通过
LAUNCH_MODULE或LAUNCH_MODULE_PRIORITY自动注册,避免手动调用未约定的初始化逻辑。 - 需要注册到控制器的能力,例如 RL 指令、Hook、Service、日志码,应放在合适的生命周期阶段。
- 同步 Hook、自定义指令执行函数和运动回调中不要执行长时间阻塞操作;耗时任务建议使用线程池。
- 涉及运动、上下电、任务空间、机器人忙状态的接口需要谨慎调用,调用前应检查控制器状态。
- 读写 IO、寄存器、总线、EtherCAT 数据时,应确认名称、地址、数据长度、数据类型和目标架构一致。
- 插件日志建议使用
log模块提供的日志宏,便于按插件过滤和排查问题。 - 插件使用的 API 版本、控制器版本和编译架构需要匹配,避免运行时加载失败或接口行为不一致。