跳到主要内容

弧焊 C++ SDK 使用示例

文档约定

以下各节结构统一为:

  1. 适用情况 — 何时需要本场景
  2. 目标 — 做完后系统应处于的状态
  3. 推荐步骤 — 顺序化操作要点;
  4. 常用接口与类型 — 便于检索 SDK 符号,非完整参数表
  5. 注意事项 — 常见易错点

通用编程约定

  1. 通过 robot.arcWelding() 取得 ArcWelding 引用,在其上调用工艺参数与焊机相关接口;运动队列仍在 robot 上操作。
  2. 各 API 均带 error_code &ec(或等价重载),每次调用后检查 ec
  3. 涉及「压队列再启动」的焊接轨迹,通常配合 MotionControlMode::NrtCommandmoveAppend / moveStart;与纯参数下发场景区分开。

公共代码前提(各场景「实现代码」共用)

以下与 SDK 包内 arcwelding_example.cpp 第 10–60 行一致(含 print_helper.hpp、匿名命名空间内的robot / arcWeld() / waitForFinish 等)。

#include "rokae/arcwelding.h"
#include "rokae/robot.h"
#include "print_helper.hpp"
#include "rokae/data_types.h"
#include <unordered_map>
#include <thread>
#include <iostream>
#include <chrono>
#include <future>

using namespace rokae;
using namespace std;

#define ROKAE_EXE(CMD) \
CMD; \
if(ec) { print(std::cerr, __LINE__, __FUNCTION__, ":", ec.message()); }

namespace {
xMateRobot robot;
ArcWelding& arcWeld() {
static ArcWelding v = robot.arcWelding();
return v;
}

void waitForFinish(BaseRobot &robot, const std::string &traj_id, int index){
using namespace rokae::EventInfoKey::MoveExecution;
error_code ec;
while(true) {
auto info = robot.queryEventInfo(Event::moveExecution, ec);
auto _id = std::any_cast<std::string>(info.at(ID));
auto _index = std::any_cast<int>(info.at(WaypointIndex));
if(auto _ec = std::any_cast<error_code>(info.at(Error))) {
print(std::cout, "路径", _id, ":", _index, "错误:", _ec.message());
return;
}
if(_id == traj_id && _index == index) {
if(std::any_cast<bool>(info.at(ReachTarget))) {
print(std::cout, "路径", traj_id, ":", index, "已完成");
}
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}

std::ostream &operator<<(std::ostream &os, const ArcWelding::WelderStatus &data) {
os << "Name: " << data.welding_name << ", Current: " << data.current << ", Voltage: " << data.voltage
<< ", Distance: " << data.welding_distance << ", Path num: " << data.welding_path_num << std::endl;
return os;
}
}

场景一:首次接机器人与焊机

适用情况 新工作站第一次跑弧焊程序,或更换焊机 / 总线配置后需要确认控制器与焊机侧就绪。

目标 机器人已连接;弧焊工艺包可用;焊机型号与通信参数与现场一致;必要时完成 IO 与 ENI 期望配置。

推荐步骤

关键步骤关系如下(与下文分步说明对应):

  1. connectToRobot 建立与控制器连接。

  2. getWelderStatus 查看焊机侧状态:若 state"disabled" 等表示尚未建立有效连接;为 "ok" 等表示已就绪(具体枚举以接口说明为准)。

  3. 若已连接:可用 getWelderSetting 读取当前协议、品牌 mfr、型号 model、电流规格 current_type 等。

  4. 若要更换焊机或重配参数:先 disconnectFromWelder,再按下方 EtherCAT模拟量 分支配置后重新 connectToWelder

  5. EtherCAT 焊机:需要setIsEniHaveWeld 需设为 true(与HMI上是否连接物理焊机等效),然后在HMI软件上上传该焊机对应的ENI文件。在 setWelder(或 WelderSetting)中设置 protocol 为 EtherCAT 对应取值(如 "ethercat",以 SDK 约定为准)、mfr 为下表中的厂商键名model 为下表中的型号键名current_type 必须为该机型的 current_range 中的某一档(与工艺包一致)。若该机型还提供 wire_diametershielding_gasprogram_numberdry_extensionfirmware_version 等约束,则 setWelder 时相应字段只能取自下列允许集合。

    厂商 / 型号与电流档位(及可选约束)一览(下发时 mfrmodel 字符串需与键名一致):

{
"aotai": {
"RL/RPL": { "current_range": [350, 500, 630, 800] },
"RP/RPH": { "current_range": [350, 500, 630, 800] }
},
"megmeet": {
"Artsen Plus": { "current_range": [350, 400, 500] },
"Artsen Pro": { "current_range": [350, 400, 500] },
"Ehave2": { "current_range": [350, 500, 630] },
"Artsen3": { "current_range": [400, 500] },
"Dex2": { "current_range": [350, 400, 500] },
"Dex2 Ultra": { "current_range": [400] },
"Megwave": { "current_range": [350, 400, 500] },
"Megwave 400AC": { "current_range": [400] },
"MetaTig": { "current_range": [315, 400, 500] },
"RevoTig": { "current_range": [315, 400, 500] }
},
"riland": {
"TiTans Low Spatter": {
"current_range": [500],
"wire_diameter": [0.8, 1.0, 1.2, 1.6],
"shielding_gas": ["CO2", "80%Ar+20%CO2"]
},
"TiTans DP": {
"current_range": [400, 500, 600],
"wire_diameter": [0.8, 1.0, 1.2, 1.6],
"shielding_gas": ["CO2", "80%Ar+20%CO2"]
}
},
"panasonic": {
"GS6": {
"current_range": [350, 500],
"program_number": [1, 97],
"dry_extension": [10, 12, 15, 20, 25, 30, 35]
}
},
"tayor": {
"RB-350P": { "current_range": [350] },
"RB-500P": { "current_range": [500] }
},
"headux": {
"headux": { "current_range": [550] }
},
"beijingtime": {
"time": { "current_range": [1000] }
},
"hugong": {
"NVPM": { "current_range": [500] }
},
"ewm": {
"TIG": { "current_range": [1000], "program_number": [0, 15] },
"Plasma": { "current_range": [1000], "program_number": [0, 15] },
"Phoenix": { "current_range": [1000], "program_number": [0, 15] },
"alpha Q": { "current_range": [1000], "program_number": [0, 15] }
},
"bohler": {
"URANOS NX": {
"current_range": [3000, 4000, 5000],
"firmware_version": ["v.14-v.24", "v.25"]
}
},
"esab": {
"Aristo 500ix": { "current_range": [500] }
}
}

示例(奥太 RL/RPL、500A 档):mfr = "aotai"model = "RL/RPL"current_type = 500(须在 [350,500,630,800] 内)。

  1. 模拟量焊机:须按顺序完成下面三步,再 setWelder

    • ① IO 绑定:先调用 setIOSetting,将起弧、送丝、送丝回退、检气、电流/电压设定与回读、焊机就绪、故障等信号绑定到实际 DI/DO 或寄存器。 用 getIOSetting 进行核对。
    • ② 电流 / 电压曲线:使用 setCurrentCharacteristicCurveDatasetVoltageCharacteristicCurveData(及需要时的 calculateCurrentCurve / calculateVoltageCurve)在控制器中建立曲线数据并命名。
    • setWelder:协议设为模拟量(具体字符串以 SDK / 工艺包为准,如 "analog" 等);品牌 mfr 只能为 "manual_welding""aotai"型号 model 等与模拟量方案约定一致;current_filevoltage_file 填步骤 ② 中已下发的电流曲线数据名电压曲线数据名。其余字段按接口说明使用默认值或留空。
  2. 调用 connectToWelder 建立与焊机的连接并启用焊机功能;调试结束或更换焊机前可用 disconnectFromWelder

实现代码

模拟量焊机配置见同文件 setIOSettingsetCharacteristicCurveData

// 选择焊机,启用焊接功能,断开焊机
void setWelderAndConnect() {
cout << "enter setWelder" << endl;
error_code ec;

auto printWelderSetting = [](const ArcWelding::WelderSetting &welderSetting) {
cout << "protocol: " << welderSetting.protocol << endl;
cout << "mfr: " << welderSetting.mfr << endl;
cout << "model: " << welderSetting.model << endl;
cout << "current_type: " << welderSetting.current_type << endl;
cout << "current_file: " << welderSetting.current_file << endl;
cout << "voltage_file: " << welderSetting.voltage_file << endl;
cout << "wire_diameter: " << welderSetting.wire_diameter << endl;
cout << "shielding_gas: " << welderSetting.shielding_gas << endl;
cout << "program_number: " << welderSetting.program_number << endl;
cout << "dry_extension: " << welderSetting.dry_extension << endl;
};

auto welderSetting = arcWeld().getWelderSetting(ec);// 获取当前焊机设置,部分参数如果该焊机不涉及可以忽略
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printWelderSetting(welderSetting);

welderSetting.protocol = "ethercat";
welderSetting.mfr = "aotai";
welderSetting.model = "RL/RPL";
welderSetting.current_type = 500;
welderSetting.current_file = "current2";
welderSetting.voltage_file = "voltage2";
welderSetting.wire_diameter = 0.8;
welderSetting.shielding_gas = "CO2";
welderSetting.program_number = 10;
welderSetting.dry_extension = 10;
arcWeld().setWelder(welderSetting, ec);// 设置焊机(方式一),部分参数如果该焊机不涉及可以忽略
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

welderSetting = arcWeld().getWelderSetting(ec);// 验证设置是否成功
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printWelderSetting(welderSetting);

arcWeld().setWelder("ethercat", "aotai", "RL/RPL", 500, ec);// 设置焊机(方式二)
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

arcWeld().connectToWelder(ec);// 启用和连接焊机
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

arcWeld().disconnectFromWelder(ec);// 断开和禁用焊机
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 读取和设置是否连接物理焊机(切换ENI文件)
void setEniHaveWeld(){
cout << "enter setEniHaveWeld" << endl;
error_code ec;
auto ret = arcWeld().isEniHaveWeld(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "isEniHaveWeld: " << ret << endl;

arcWeld().setIsEniHaveWeld(true, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ret = arcWeld().isEniHaveWeld(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "isEniHaveWeld: " << ret << endl;

arcWeld().setIsEniHaveWeld(false, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ret = arcWeld().isEniHaveWeld(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "isEniHaveWeld: " << ret << endl;
}

常用接口与类型

getWelderStatusgetWelderSettingsetWelderWelderSettingconnectToWelderdisconnectFromWelderisEniHaveWeldsetIsEniHaveWeldsetIOSettinggetIOSettingIOSettingIODatasetCurrentCharacteristicCurveDatasetVoltageCharacteristicCurveDatagetCurrentCharacteristicCurveDatagetVoltageCharacteristicCurveDatacalculateCurrentCurvecalculateVoltageCurve

注意事项

更换焊机参数时,若已在弧焊连接状态,想要切换焊机,需先断开焊机连接再改参。

场景二:设置焊接运行参数

适用情况 需要统一调整空运行笛卡尔速度手动送/退丝速度气体检测时间等与焊接过程相关的全局运行选项(与单条起弧/焊接命名数据不同)。

目标 ArcWeldRunningParam 已写入控制器,空运行、送退丝、无参检气等行为与现场习惯一致。

推荐步骤

  1. 构造 ArcWeldRunningParam:按工艺包范围设置 test_run_speed(mm/s)、wire_feed_speed(m/min)、gas_detect_time(s)等(字段含义与取值范围见 附录:数据结构 中「运行参数 ArcWeldRunningParam」)。
  2. 调用 setRunningParam 下发;用 getRunningParam 读回核对。
  3. 无参重载 detectGas() 的检气持续时间与运行参数中的 gas_detect_time 相关;带时间与使能的重载则按调用传入(见 接口说明)。

实现代码

// 读写运行参数
void setRunningParam()
{
cout << "enter setRunningParam" << endl;
error_code ec;
ArcWelding::ArcWeldRunningParam runningParam{100, 2, 10};

arcWeld().setRunningParam(runningParam, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getRunningParam(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

cout << "test_run_speed: " << data.test_run_speed << endl;
cout << "wire_feed_speed: " << data.wire_feed_speed << endl;
cout << "gas_detect_time: " << data.gas_detect_time << endl;
}

常用接口与类型

setRunningParamgetRunningParamArcWeldRunningParamdetectGas

注意事项

手动送/退丝速度 取决于焊机是否可以设置该功能

场景三:设置防碰撞(碰枪检测)

适用情况 现场使用碰枪 / 防撞 DI,需要由程序配置信号名、是否启用、屏蔽与倒计时,并在上位机或逻辑中订阅防撞状态。

目标 防碰撞参数已下发;可通过查询或事件回调获取 signalenableblockcountdown 等与 HMI 或联锁一致。

推荐步骤

  1. 确定用于防撞的 DI 信号名(如 "DI0_0")。
  2. 调用 setAnticollision(signal, enable, block, countdown)enable 为是否启用,block 为屏蔽开关,countdown 为倒计时(秒级语义以工艺包为准)。
  3. 需要界面或逻辑联动时,使用 getAnticollisionState 读取当前状态;或注册 setEventWatcher(Event::anticollisionState, callback, ec),在回调中解析 EventInfoKey::AnticollisionState 各键(与 附录:数据结构AnticollisionState 对应)。

实现代码

void printAnticollisionState(const EventInfo& info) {
using namespace rokae::EventInfoKey::AnticollisionState;
cout << "anticollision: \n"
<< "signale: " << std::any_cast<std::string>(info.at(Signal))
<< "\nenable: " << std::any_cast<bool>(info.at(Enable))
<< "\nblock: " << std::any_cast<bool>(info.at(Block))
<< "\ncountdown: " << std::any_cast<int>(info.at(Countdown)) << std::endl;
}
void SetAnticollision() {
error_code ec;
robot.setEventWatcher(Event::anticollisionState, printAnticollisionState, ec);
if (ec)
cout << "setEventWatcher" << ec.message() << std::endl;

arcWeld().setAnticollision("DI0_0", true, false, 30, ec);
if (ec)
cout << "setAnticollision" << ec.message() << std::endl;

auto ret = arcWeld().getAnticollisionState(ec);
if (ec)
cout << "getAnticollisionState" << ec.message() << std::endl;
cout << "anticollision: \n"
<< "signale: " << ret.signal << "\nenable: " << ret.enable << "\nblock: " << ret.block << "\ncountdown: " << ret.countdown << std::endl;
}

常用接口与类型

setAnticollisiongetAnticollisionStateEvent::anticollisionStateEventInfoKey::AnticollisionStatesetEventWatcher

注意事项

绑定的DI信号需要确保没有被其他系统功能占用

场景四:在程序中维护工艺参数

适用情况 希望由上位机或离线工具下发 / 修改起弧、焊接、收弧、摆动、间断焊等命名工艺数据,或与示教器 HMI 中已有参数名保持一致。

目标 控制器内保存在一组可引用的参数名,供后续 ArcOnCommand 等指令或示教程序使用。

推荐步骤

  1. 构造对应结构体(如 ArcOnDataArcDataArcOffDataWeaveDataSegData 等),填写 name 及工艺字段。
  2. 调用 setXxxData 写入;用 getXxxData(name, ec) 读回校验。
  3. 删除单条用 removeXxxData(name);批量删除可传入名称列表重载。
  4. 对示教器已有名称:可先 get 再改字段后 set,实现覆盖或微调。

实现代码

以下按类分别摘录 setArcOnData(起弧)、setArcData(焊接)、setArcOffData(收弧)、setWeaveData(摆焊)、setSegData(间断焊)。各函数中的 printArcOnData / printArcData / printArcOffData / printWeaveData 定义于同文件更前处(约第 63–147 行),需与这些 void 函数置于同一编译单元。

// 读写起弧参数arcondata
void setArcOnData()
{
cout << "enter setArcOnData" << endl;
error_code ec;
// 默认参数
ArcWelding::ArcOnData arcOnData;
arcWeld().setArcOnData(arcOnData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getArcOnData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "default" << endl;
printArcOnData(data);

data = arcWeld().getArcOnData("aaa", ec); // 如果获取不存在的参数,提示-272
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

// 自定义参数
ArcWelding::ArcOnData arcOnData2 = {
"example_arcondata", "example_annotation", "low_spatter", "wire_feed", "unified", 100, 2, 0, 300, 4000, 500, 600, 0, 2, 300, 100, {true, 10, 100, 200, 15, 5}, // re_arcon
{true, 50, 100, 20} // scaratch_arcon
};
arcWeld().setArcOnData(arcOnData2, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

data = arcWeld().getArcOnData(arcOnData2.name, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "example_arcondata" << endl;
printArcOnData(data);

// 删除参数
arcWeld().removeArcOnData("default",ec);
data = arcWeld().getArcOnData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 批量删除
arcOnData.name = "remove1";
arcWeld().setArcOnData(arcOnData, ec);
arcOnData.name = "remove2";
arcWeld().setArcOnData(arcOnData, ec);
arcWeld().removeArcOnData(std::vector<std::string>({"remove1", "remove2"}), ec);
data = arcWeld().getArcOnData("remove1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
data = arcWeld().getArcOnData("remove2", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 可以对hmi工艺包的参数进行修改
data = arcWeld().getArcOnData("arcondata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcOnData(data);

arcOnData.name = "arcondata1";
arcWeld().setArcOnData(arcOnData, ec);
data = arcWeld().getArcOnData("arcondata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcOnData(data);

arcWeld().removeArcOnData("arcondata1",ec);
data = arcWeld().getArcOnData("arcondata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
}
// 读写焊接参数arcdata
void setArcData()
{
cout << "enter setArcData" << endl;
error_code ec;
// 默认参数
ArcWelding::ArcData arcData;
arcWeld().setArcData(arcData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getArcData(arcData.name, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "default" << endl;
printArcData(data);

// 自定义参数
ArcWelding::ArcData arcData2 = {
"example_arcdata", "example_annotation", "low_spatter", "wire_feed", "unified", 100, 20, 0, 30, 400, {500, "auto_arc_reignition", 15}};
arcWeld().setArcData(arcData2, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

data = arcWeld().getArcData(arcData2.name, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "example_arcdata" << endl;
printArcData(data);

// 删除参数
arcWeld().removeArcData("default", ec);
data = arcWeld().getArcData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 批量删除
arcData.name = "remove1";
arcWeld().setArcData(arcData, ec);
arcData.name = "remove2";
arcWeld().setArcData(arcData, ec);
arcWeld().removeArcData(std::vector<std::string>({"remove1", "remove2"}), ec);
data = arcWeld().getArcData("remove1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
data = arcWeld().getArcData("remove2", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 可以对hmi工艺包的参数进行修改
data = arcWeld().getArcData("arcdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcData(data);

arcData.name = "arcdata1";
arcWeld().setArcData(arcData, ec);
data = arcWeld().getArcData("arcdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcData(data);

arcWeld().removeArcData("arcdata1", ec);
data = arcWeld().getArcData("arcdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
}
// 读写收弧参数arcoffdata
void setArcOffData()
{
cout << "enter setArcOffData" << endl;
error_code ec;
// 默认参数
ArcWelding::ArcOffData arcOffData;
arcWeld().setArcOffData(arcOffData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getArcOffData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "default" << endl;
printArcOffData(data);

// 自定义参数
ArcWelding::ArcOffData arcOffData2 = {
"example_arcoffdata", "example_annotation", "low_spatter", "wire_feed", "unified", 100, 20, 0, 300, 400, 5500, 600, 700, {true, 20, 15, 100}};
arcWeld().setArcOffData(arcOffData2, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

data = arcWeld().getArcOffData(arcOffData2.name, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "example_arcoffdata" << endl;
printArcOffData(data);

// 删除参数
arcWeld().removeArcOffData("default", ec);
data = arcWeld().getArcOffData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 批量删除
arcOffData.name = "remove1";
arcWeld().setArcOffData(arcOffData, ec);
arcOffData.name = "remove2";
arcWeld().setArcOffData(arcOffData, ec);
arcWeld().removeArcOffData(std::vector<std::string>({"remove1", "remove2"}), ec);
data = arcWeld().getArcOffData("remove1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
data = arcWeld().getArcOffData("remove2", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 可以对hmi工艺包的参数进行修改
data = arcWeld().getArcOffData("arcoffdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcOffData(data);

arcOffData.name = "arcoffdata1";
arcWeld().setArcOffData(arcOffData, ec);
data = arcWeld().getArcOffData("arcoffdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printArcOffData(data);

arcWeld().removeArcOffData("arcoffdata1", ec);
data = arcWeld().getArcOffData("arcoffdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
}
// 读写摆动参数
void setWeaveData()
{
cout << "enter setWeaveData" << endl;
error_code ec;
// 默认参数
ArcWelding::WeaveData weaveData;
arcWeld().setWeaveData(weaveData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getWeaveData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "default" << endl;
printWeaveData(data);

// 自定义参数
ArcWelding::WeaveData weaveData2 = {
"example_weavedata", "example_annotation", "cycle", "sine", 1, {2, 2}, "weave_stop", {10, 0, 20}, 5, true, "v_pattern", {0, 0}, 0, 1, 10};
arcWeld().setWeaveData(weaveData2, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

data = arcWeld().getWeaveData(weaveData2.name, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

cout << "example_weavedata" << endl;
printWeaveData(data);

// 删除参数
arcWeld().removeWeaveData("default", ec);
data = arcWeld().getWeaveData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 批量删除
weaveData.name = "remove1";
arcWeld().setWeaveData(weaveData, ec);
weaveData.name = "remove2";
arcWeld().setWeaveData(weaveData, ec);
arcWeld().removeWeaveData(std::vector<std::string>({"remove1", "remove2"}), ec);
data = arcWeld().getWeaveData("remove1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
data = arcWeld().getWeaveData("remove2", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 可以对hmi工艺包的参数进行修改
data = arcWeld().getWeaveData("weavedata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printWeaveData(data);

weaveData.name = "weavedata1";
arcWeld().setWeaveData(weaveData, ec);
data = arcWeld().getWeaveData("weavedata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
printWeaveData(data);

arcWeld().removeWeaveData("weavedata1", ec);
data = arcWeld().getWeaveData("weavedata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
}
// 读写间断焊参数
void setSegData(){
cout << "enter setSegData" << endl;
error_code ec;
ArcWelding::SegData segdata{"segdata1","segannotation","normal","v10",10,20};
arcWeld().setSegData(segdata, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

auto data = arcWeld().getSegData("segdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "name: " << data.name << "\n"
<< "annotation: " << data.annotation << "\n"
<< "seg_type: " << data.seg_type << "\n"
<< "non_welded_speed: " << data.non_welded_speed << "\n"
<< "welded_distance: " << data.welded_distance << "\n"
<< "non_welded_distance: " << data.non_welded_distance << endl;

// 删除参数
arcWeld().removeSegData("segdata1", ec);
data = arcWeld().getSegData("segdata1", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272

// 批量删除
segdata.name = "segdata2";
arcWeld().setSegData(segdata, ec);
segdata.name = "segdata3";
arcWeld().setSegData(segdata, ec);
arcWeld().removeSegData(std::vector<std::string>({"segdata2","segdata3"}), ec);
data = arcWeld().getSegData("segdata2", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl; // -272
}

常用接口与类型

按「设置 / 读取 / 删除」分组的命名工艺数据接口如下(签名与重载详见 接口说明附录:方法)。

  • 起弧 / 焊接 / 收弧 / 摆焊 / 间断焊
    setArcOnData / getArcOnData / removeArcOnData setArcData / getArcData / removeArcDataenableArcData
    setArcOffData / getArcOffData / removeArcOffData
    setWeaveData / getWeaveData / removeWeaveData
    setSegData / getSegData / removeSegData
    setWeaveAdaptiveData / getWeaveAdaptiveData

  • 多层多道
    setLayerData / getLayerData / removeLayerData
    setLayerCoutMpmlPathCheckGetLayerStartPoint

  • 激光跟踪 / 激光寻位(命名参数)
    setLaserTrackData / getLaserTrackData / removeLaserTrackData
    setLaserSearchData / getLaserSearchData / removeLaserSearchData

  • 电弧跟踪(命名参数)
    setArcTrackParam / getArcTrackParam / removeArcTrackParam

  • 电流 / 电压特性曲线(命名曲线数据)
    setCurrentCharacteristicCurveData / getCurrentCharacteristicCurveData
    setVoltageCharacteristicCurveData / getVoltageCharacteristicCurveData
    calculateCurrentCurvecalculateVoltageCurve(仅计算、不落库)

注意事项

按名读取不存在的参数时,控制器可能返回约定错误码(如 -272),需在逻辑中处理。

场景五:选择焊接模式,并对照手动 / 自动行为

适用情况 需要空运行验轨迹仿真验节拍与摆动、或实焊出弧,并理解示教器手动单步、手动连续、自动下的差异(起弧与否、速度滑条、间断焊、摆焊、电弧跟踪等)。

目标 当前焊接模式与产线阶段匹配(调试 → 仿真 → 实焊)。

推荐步骤

  1. 调用 setWeldMode,在 WeldMode::TestRun(空运行)、Simu(仿真)、Real(实焊)之间切换。
  2. getWeldMode 读回确认。
  3. 结合现场示教器运行方式,对照下表理解现象(与工艺包说明一致)。

实现代码

// 读写焊接模式
void setWeldMode()
{
cout << "enter setWeldMode" << endl;
error_code ec;
// 切换为空运行模式
arcWeld().setWeldMode(ArcWelding::WeldMode::TestRun, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
auto mode = arcWeld().getWeldMode(ec); // 读取当前模式
cout << "mode: " << mode << endl;
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

// 切换为仿真模式
arcWeld().setWeldMode(ArcWelding::WeldMode::Simu, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
mode = arcWeld().getWeldMode(ec);
cout << "mode: " << mode << endl;
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

// 切换为实焊模式
arcWeld().setWeldMode(ArcWelding::WeldMode::Real, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
mode = arcWeld().getWeldMode(ec);
cout << "mode: " << mode << endl;
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}

焊接模式与运行方式组合(示意)

焊接模式具体定义

常用接口与类型

setWeldModegetWeldModeArcWelding::WeldMode

注意事项

场景六:典型焊缝——「起弧 → 直线/圆弧 焊接段 → 收弧」

适用情况 最常见的直线或圆弧焊缝:在非实时指令模式下,将普通运动与弧焊工艺指令按顺序压入同一队列并启动。

目标 机器人按序执行:接近段(可选)→ 起弧与焊接参数生效 → 带或不带摆动的焊接轨迹 → 收弧。

推荐步骤

  1. 需要先通过场景一启用焊机
  2. setMotionControlMode(NrtCommand, ec)
  3. 确认焊机已配置并 connectToWelder(与场景一一致)。
  4. 构造 ArcOnCommand,绑定已下发的起弧参数名、焊接参数名(如与示教器同名)。
  5. 构造焊接段:WMoveLCommand / WMoveCCommand 等;
  6. 构造 ArcOffCommand 并绑定收弧参数名。
  7. 使用同一队列 id 多次 moveAppend 按顺序入队;上电后 moveStart 执行。
  8. 需要暂停 / 继续时,可配合 stop 与再次 moveStart(以运动控制文档为准)。

实现代码

// 指令示例
void exampleCommand()
{
cout << "enter exampleCommand" << endl;
error_code ec;

ArcWelding::ArcOnCommand arcon;
arcon.setArcOnData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

arcon.setArcData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::ArcOffCommand arcoff;
arcoff.setArcOffData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::WMoveLCommand wml({0.556769, -0.15, 0.4872, -M_PI, 0, M_PI}, 10, 1); // 直线摆动
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

MoveLCommand ml({0.556769, -0.15, 0.4872, -M_PI, 0, M_PI}, 10, 1); // 直线

ArcWelding::WMoveCCommand wmc({0.786, 0, 0.431, 3, 0.98, 3}, {0.786, 0, 0.431, 3, 0.98, 3}, 10, 1); // 圆弧摆动

robot.setMotionControlMode(MotionControlMode::NrtCommand, ec);
string id;

robot.moveAppend(arcon, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(wml, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(arcoff, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.setPowerState(true,ec);

robot.moveStart(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(1));
robot.stop(ec); // 暂停
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveStart(ec);// 继续
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}

常用接口与类型

ArcOnCommandArcOffCommandWMoveLCommandWMoveCCommandmoveAppendmoveStartMoveLCommand

注意事项

点位、速度、Conf 需适配本机型。 mvoeStart() 是非阻塞接口,要注意避免直接退出程序。 在 arconarcoff 之前,必须要用普通的 MoveCommand 指令;在他们中间,必须要用 WMoveCommand。 在调用 moveAppend(arcon, id, ec); 时,需要保证控制器已经保存好arcon中对应的起弧参数和焊接参数,不要在这一行代码的上一行或者临近用 setArcOnData 保存数据,避免由于控制器的处理延迟导致调用报错。 如果是飞行起弧,就是 ArcOnData 中的提前起弧时间设置了不为0,则需要在 arcon 前面添加一条 MoveLCommand 指令。

场景七:焊接过程中使用 arc_set_opt(ArcSet)修改工艺参数

适用情况 已在起弧后的某一条焊缝上,希望某一段直线或圆弧改用另一套 arcdata,而不结束电弧、不拆程序。

目标 在压入队列的 WMoveLCommand / WMoveCCommand 等焊接运动上,通过 arc_set_opt 指定切换后的焊接参数名称。

推荐步骤

  1. 预先 setArcData 维护多套命名工艺(如 arcdata1arcdata2)。
  2. 直线WMoveLCommand圆弧WMoveCCommand,在指令成员上设置 arc_set_opt

实现代码

/**
* @brief 示例 - 焊接过程中设置焊接参数。点位适用机型XMS5
*/
void arcSetExample() {
std::string cmd_id;
error_code ec;
ArcWelding::ArcOnCommand arc_on_command("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arc_off_command("arcoffdata1");
MoveAbsJCommand absj {{0, M_PI / 6, -M_PI_2, 0, -M_PI / 3, 0}, 1000};
MoveLCommand l {{0.614, 0.136, 0.389, -M_PI, 0, M_PI }, 500};
ArcWelding::WMoveLCommand wmovel1 {{0.553, -0.107, 0.309, -M_PI, 0, M_PI}, 20};
ArcWelding::WMoveLCommand wmovel2 {{0.553, 0.107, 0.309, -M_PI, 0, M_PI}, 20};
wmovel2.arc_set_opt = { "arcdata2", true, 80 };

robot.setPowerState(true, ec);

robot.moveAppend(absj, cmd_id, ec);
robot.moveAppend(l, cmd_id, ec);
robot.moveAppend(arc_on_command, cmd_id, ec);
robot.moveAppend({wmovel1, wmovel2}, cmd_id, ec);
robot.moveAppend(arc_off_command, cmd_id, ec);
robot.moveStart(ec);
while(getchar() != '\n');

robot.setPowerState(false, ec);
}

常用接口与类型

WMoveLCommand::arc_set_optWMoveCCommand::arc_set_optsetArcData

场景八:直线 / 圆弧耦合摆动焊接

适用情况 平角或立角等焊缝需要在直线段圆弧段上叠加摆动(Weave),由工艺包按摆动数据名解析摆幅、频率等。

目标 摆动数据已下发并与焊接运动绑定;可用 WeaveOnCommand / WeaveOffCommand 包络多段

推荐步骤

  1. setWeaveData 写入摆动工艺名(如 weavedata1)。
  2. 创建 WeaveOnCommand WeaveOffCommand
  3. 直线:构造 WMoveLCommand 后调用 setWeaveData("…", ec),或使用带摆动索引的构造函数重载(以 SDK 为准)。
  4. 圆弧:构造 WMoveCCommand,同样 setWeaveData;辅助点、目标点与速度须满足机型与工艺包约束。
  5. 典型片段:ArcOnCommandWeaveOnCommand → 若干 WMoveL / WMoveCWeaveOffCommandArcOffCommand

实现代码

void weaveOnExample() {
error_code ec;

ArcWelding::ArcOnCommand arcon;
arcon.setArcOnData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

arcon.setArcData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::ArcOffCommand arcoff;
arcoff.setArcOffData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::WMoveLCommand wml({0.556769, -0.15, 0.4872, -M_PI, 0, M_PI}, 10, 1); // 直线摆动
wml.setWeaveData("default", ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "wml: " << wml.getWeaveData() << endl;

ArcWelding::WeaveOnCommand weaveon;
weaveon.setWeaveData("aaa", ec);

ArcWelding::WeaveOffCommand weaveoff;

robot.setMotionControlMode(MotionControlMode::NrtCommand, ec);
string id;

robot.moveAppend(arcon, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(weaveon, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(wml, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(weaveoff, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveAppend(arcoff, id, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.setPowerState(true,ec);

robot.moveStart(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(1));
robot.stop(ec); // 暂停
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

robot.moveStart(ec);// 继续
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}

常用接口与类型

setWeaveDataWMoveLCommandWMoveCCommandWeaveOnCommandWeaveOffCommand

注意事项

  1. 需要摆动的轨迹必须放在 WeaveOnCommandWeaveOffCommand之间,如果只单独给WMoveLCommandWMoveCCommand设置摆动参数则不会生效
  2. WeaveOnCommandWeaveOffCommand之间的轨迹如果不带摆动参数会默认执行WeaveOnCommand中的摆动参数

场景九:直线 / 圆弧耦合间断焊

适用情况 仅在部分轨迹上需要「焊—停—焊」节拍;不要求摆动,或摆动由其它段单独处理。

目标SegOnCommandSegOffCommand 之间,WMoveL / WMoveCSegData 执行间断节奏;区间外为连续焊或普通焊接运动。

推荐步骤

  1. setSegData 写入间断焊参数名(如 segdata1)。
  2. 队列:ArcOnCommand →(可选空移或非间断段)→ SegOnCommand("segdata1") → 一条或多条直线/圆弧焊接运动 → SegOffCommand → 后续连续焊或收弧。

实现代码

// 间断焊。适用CR机型,SR机型需要调整偏移量
void segOnExample(){
error_code ec;

// 根据起始轴角度,计算笛卡尔位姿
auto model = robot.model();
std::array<double, 6> drag_posture = {0, M_PI / 6, -M_PI_2, 0, -M_PI / 3, 0};
auto p_start = model.calcFk(drag_posture, ec);
print(std::cout, "start pose: ", p_start);

// 设置间断焊参数
ArcWelding::SegData segdata {"segdata1", "segannotation", "normal","v5",15,30};
arcWeld().setSegData(segdata, ec);
// 开始间断焊指令,设置间断焊参数为segdata1
ArcWelding::SegOnCommand segOnCmd("segdata1");
ArcWelding::SegOffCommand segOffCmd;
// 几条焊接运动指令
ArcWelding::WMoveLCommand non_seg_wmovel0(p_start, 20, 0);
non_seg_wmovel0.offset.type = CartesianPosition::Offset::Type::offs;
non_seg_wmovel0.offset.frame.trans = {0.01, 0.03, -0.02};
ArcWelding::WMoveLCommand seg_wmovel0(p_start, 20, 0);
seg_wmovel0.offset.type = CartesianPosition::Offset::Type::offs;
seg_wmovel0.offset.frame.trans = {0, -0.01, -0.02};
seg_wmovel0.arc_set_opt = { "arcdata2", true, 0 };
ArcWelding::WMoveLCommand seg_wmovel1(p_start, 20, 0);
seg_wmovel1.offset.type = CartesianPosition::Offset::Type::offs;
seg_wmovel1.offset.frame.trans = {0, 0.08, -0.02};
seg_wmovel1.arc_set_opt = { "arcdata3", true, 0 };
ArcWelding::WMoveCCommand seg_wmc(p_start, p_start, 10, 0);
seg_wmc.targetOffset.type = CartesianPosition::Offset::Type::offs;
seg_wmc.targetOffset.frame.trans = {0, -0.05, 0.01};
seg_wmc.auxOffset.type = CartesianPosition::Offset::Type::offs;
seg_wmc.auxOffset.frame.trans = {0, 0.070, 0};

ArcWelding::WMoveLCommand non_seg_wmovel1(p_start, 20, 1);
non_seg_wmovel1.offset.type = CartesianPosition::Offset::Type::offs;
non_seg_wmovel1.offset.frame.trans = {-0.05, 0, 0};
non_seg_wmovel1.arc_set_opt = { "arcdata1", true, 0 };

ArcWelding::ArcOnCommand arcOnCmd("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arcOffCmd("arcoffdata1");
MoveAbsJCommand absj {{0, M_PI / 6, -M_PI_2, 0, -M_PI / 3, 0}, 500};

string id;

robot.setPowerState(true, ec);
robot.moveAppend(absj, id, ec);
robot.moveAppend(arcOnCmd, id, ec);
robot.moveAppend({non_seg_wmovel0}, id, ec);
robot.moveAppend(segOnCmd, id, ec);
robot.moveAppend({seg_wmovel0, seg_wmovel1}, id, ec);
robot.moveAppend(seg_wmc, id, ec);
robot.moveAppend(segOffCmd, id, ec);
robot.moveAppend(non_seg_wmovel1, id, ec);
robot.moveAppend(arcOffCmd, id, ec);
robot.moveStart(ec);

while(getchar() != '\n');
}

常用接口与类型

setSegDataSegOnCommandSegOffCommandWMoveLCommandWMoveCCommand

场景十:直线 / 圆弧耦合间断焊 + 摆动

适用情况 间断节拍与摆动同时作用在同一电弧区间。

目标 WeaveOn 包络与 SegOnSegOff 区间在队列中顺序正确,且各 WMoveL / WMoveCarc_set_opt、偏移等与现场标定一致。

推荐步骤

  1. 同时完成 setWeaveDatasetSegData
  2. 参考 segOnExample 的典型顺序:ArcOnCommandWeaveOnCommand → 非间断的过渡 WMoveL(可选)→ SegOnCommand → 间断区间内的多条 WMoveL / WMoveCSegOffCommand → 后续运动 → WeaveOffCommandArcOffCommand
  3. 若间断段与连续段工艺不同,在对应指令上分别设置 arc_set_opt
  4. 圆弧段目标点、辅助点偏移建议与示例一致地在指令的 offset / targetOffset 等成员上配置(以 SDK 头文件为准)。

实现代码

/**
* @brief 示例 - 间断焊。适用CR机型,SR机型需要调整偏移量
*/
void segOnExample(){
error_code ec;

// 根据起始轴角度,计算笛卡尔位姿
auto model = robot.model();
std::array<double, 6> drag_posture = {0, M_PI / 6, -M_PI_2, 0, -M_PI / 3, 0};
auto p_start = model.calcFk(drag_posture, ec);
print(std::cout, "start pose: ", p_start);

// 设置间断焊参数
ArcWelding::SegData segdata {"segdata1", "segannotation", "normal","v5",15,30};
arcWeld().setSegData(segdata, ec);
// 开始间断焊指令,设置间断焊参数为segdata1
ArcWelding::SegOnCommand segOnCmd("segdata1");
ArcWelding::SegOffCommand segOffCmd;
// 几条焊接运动指令
ArcWelding::WMoveLCommand non_seg_wmovel0(p_start, 20, 0);
non_seg_wmovel0.offset.type = CartesianPosition::Offset::Type::offs;
non_seg_wmovel0.offset.frame.trans = {0.01, 0.03, -0.02};
ArcWelding::WMoveLCommand seg_wmovel0(p_start, 20, 0);
seg_wmovel0.offset.type = CartesianPosition::Offset::Type::offs;
seg_wmovel0.offset.frame.trans = {0, -0.01, -0.02};
seg_wmovel0.arc_set_opt = { "arcdata2", true, 0 };
ArcWelding::WMoveLCommand seg_wmovel1(p_start, 20, 0);
seg_wmovel1.offset.type = CartesianPosition::Offset::Type::offs;
seg_wmovel1.offset.frame.trans = {0, 0.08, -0.02};
seg_wmovel1.arc_set_opt = { "arcdata3", true, 0 };
ArcWelding::WMoveCCommand seg_wmc(p_start, p_start, 10, 0);
seg_wmc.targetOffset.type = CartesianPosition::Offset::Type::offs;
seg_wmc.targetOffset.frame.trans = {0, -0.05, 0.01};
seg_wmc.auxOffset.type = CartesianPosition::Offset::Type::offs;
seg_wmc.auxOffset.frame.trans = {0, 0.070, 0};

ArcWelding::WMoveLCommand non_seg_wmovel1(p_start, 20, 1);
non_seg_wmovel1.offset.type = CartesianPosition::Offset::Type::offs;
non_seg_wmovel1.offset.frame.trans = {-0.05, 0, 0};
non_seg_wmovel1.arc_set_opt = { "arcdata1", true, 0 };

ArcWelding::ArcOnCommand arcOnCmd("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arcOffCmd("arcoffdata1");
MoveAbsJCommand absj {{0, M_PI / 6, -M_PI_2, 0, -M_PI / 3, 0}, 500};
ArcWelding::WeaveOnCommand weave_on_command("weavedata1");
ArcWelding::WeaveOffCommand weaveOffCmd;

string id;

robot.setPowerState(true, ec);
robot.moveAppend(absj, id, ec);
robot.moveAppend(arcOnCmd, id, ec);
robot.moveAppend(weave_on_command, id, ec);
robot.moveAppend({non_seg_wmovel0}, id, ec);
robot.moveAppend(segOnCmd, id, ec);
robot.moveAppend({seg_wmovel0, seg_wmovel1}, id, ec);
robot.moveAppend(seg_wmc, id, ec);
robot.moveAppend(segOffCmd, id, ec);
robot.moveAppend(non_seg_wmovel1, id, ec);
robot.moveAppend(weaveOffCmd, id, ec);
robot.moveAppend(arcOffCmd, id, ec);
robot.moveStart(ec);

while(getchar() != '\n');
}

常用接口与类型

场景八场景九所列类型组合使用。

注意事项

顺序错误可能导致摆动或间断未按预期生效;务必在仿真/空运行下先验证再实焊。

场景十一:钟摆形轨迹焊接

适用情况 焊缝几何由工艺定义为钟摆形路径(专用钟摆运动指令)。

目标 正确使用 WMoveLPendulumCommand 的起点、辅助点、目标点及速度等参数;需要切换规范时在成员上设置 arc_set_opt

推荐步骤

  1. 按工艺包与示教数据填入 WMoveLPendulumCommand 各点(与 arcSetPendulumExample 一致)。
  2. ArcOnCommand / ArcOffCommand 组合方式与普通焊接运动相同,压入非实时队列后 moveStart
  3. 若同程序中还有普通摆焊,注意与场景八区分:钟摆为独立运动类型,一般不混用 WeaveOn 包络同一段钟摆(以工艺包说明为准)。

实现代码

/**
* @brief 示例 - 焊接钟摆过程中设置焊接参数。
*/
void arcSetPendulumExample() {
std::string cmd_id;
error_code ec;
// 设置起弧/收弧
ArcWelding::ArcData arcData;
arcData.name = "arcdata1";
arcWeld().setArcData(arcData, ec);

arcData.name = "arcdata2";
arcData.current = 20;
arcData.voltage = 15;
arcWeld().setArcData(arcData, ec);

arcData.name = "arcdata3";
arcData.current = 100;
arcData.voltage = 20;
arcData.weld_speed = 15;
arcWeld().setArcData(arcData, ec);

ArcWelding::ArcOnData arconData;
arconData.name = "arcondata1";
arcWeld().setArcOnData(arconData, ec);

ArcWelding::ArcOffData arcOffData;
arcOffData.name = "arcoffdata1";
arcWeld().setArcOffData(arcOffData, ec);

// 设置摆动
ArcWelding::WeaveData weaveData;
weaveData.weave_length_frequency = 3.5;
weaveData.amplitude.left = 6;
weaveData.amplitude.right = 4.5;
arcWeld().setWeaveData(weaveData, ec);

ArcWelding::ArcOnCommand arc_on_command("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arc_off_command("arcoffdata1");

MoveAbsJCommand absj{ {0.168,0.369, -0.883,-0.210,-0.637,-0.137}, 1000 };
// 使用栈上对象而不是堆上对象,避免内存泄漏
CartesianPosition start1{ 0.68015, -0.077702, 0.777555, -2.319, 1.112, -2.228 };
CartesianPosition startAux1{ 0.672849, -0.0777043, 0.777555, -2.319, 1.112, -2.228 };
CartesianPosition targetAux1{ 0.647849, -0.0943, 0.750882, -2.319, 1.112, -2.228 };
CartesianPosition target1{ 0.647849, -0.09473, 0.747882, -2.319, 1.112, -2.228 };

CartesianPosition targetAux2{ 0.437346, -0.2597, 0.793403, -2.319, 1.112, -2.228 };
CartesianPosition target2{ 0.435346, -0.2597, 0.796403, -2.319, 1.112, -2.228 };

CartesianPosition targetAux3{ 0.6117849, -0.14534, 0.666882, -2.319, 1.112, -2.228 };
CartesianPosition target3{ 0.599849, -0.14574, 0.667882, -2.319, 1.112, -2.228 };

MoveLCommand l{ start1, 500 };
// 钟摆
ArcWelding::WMoveLPendulumCommand wp1{ startAux1, target1, targetAux1, 20, 0.5, 100, 2 };

ArcWelding::WMoveLPendulumCommand wp2{ NULL, target2, targetAux2, 20, 3, 234, 1 };
wp2.arc_set_opt = { "arcdata2", true, 0 };

ArcWelding::WMoveLPendulumCommand wp3{ NULL, target3, targetAux3, USE_DEFAULT, 3.1, 4, 5 };
wp3.arc_set_opt = { "arcdata3", true, 0 };

robot.setPowerState(true, ec);
robot.moveAppend(absj, cmd_id, ec);
robot.moveAppend(l, cmd_id, ec);
robot.moveAppend(arc_on_command, cmd_id, ec);
robot.moveAppend(wp1, cmd_id, ec);
robot.moveAppend(wp2, cmd_id, ec);
robot.moveAppend(wp3, cmd_id, ec);
robot.moveAppend(arc_off_command, cmd_id, ec);
robot.moveStart(ec);
while (getchar() != '\n');

robot.setPowerState(false, ec);
}

常用接口与类型

WMoveLPendulumCommandWMoveLCommand::arc_set_opt

场景十二:电弧跟踪

适用情况 焊接过程中需根据电弧传感修正横向或高度方向

目标 指定轨迹段使用某套 ArcTrackParam;其它段不传跟踪名即不跟踪。

推荐步骤

  1. setArcTrackParam 下发跟踪参数名(如 arctrackdata1)。
  2. WMoveLCommand 等带摆动名的重载中传入跟踪数据名;圆弧若 SDK 提供同等重载,绑定方式相同(以头文件为准)。
  3. 典型队列:ArcOnCommandWeaveOnCommand → 多条带跟踪的焊接运动 → WeaveOffCommandArcOffCommand
  4. 等待运动结束并确认收弧完成(可结合场景十八事件订阅)。

实现代码

/**
* @brief 示例 - 电弧跟踪,点位适配机型NB4h-R580-XX
*/
void arcTrackExample() {
error_code ec;
//设置电弧跟踪参数
ArcWelding::ArcTrackParam param;
param.name = "arctrackdata1";
param.annotation = "test1";
param.delay_time = 5;//其他的值类似设置就行,这里直接使用默认值
arcWeld().setArcTrackParam(param,ec);

//获取对应的电弧跟踪参数
auto param_get = arcWeld().getArcTrackParam(param.name, ec);
std::cout << "name: " << param_get.name << " annotation: " << param_get.annotation << " delay_time: " << param_get.delay_time << std::endl;

//本例验证时运行于NB4h-R580-3B(注意点位匹配)
auto p0 = { 0.357487, 0.000633967, 0.222628, 3.0, 0.0685018, 3.12448 };
auto p1 = { 0.357487, 0.143835, 0.222628, 3.13197, 0.0685018, 3.12448 };
auto p2 = { 0.456268, 0.000634313, 0.222628, 3.13197, 0.0685026, 3.12448 };
auto p3 = { 0.456268, 0.143835, 0.222628, 3.13197, 0.0685024, 3.12448 };
auto p4 = { 0.456268, -0.103198, 0.222628, 3.13197, 0.068502, 3.12448 };

ArcWelding::ArcOnCommand arcon("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arcoff("arcoffdata1");
MoveJCommand mj(p0, 100, 1);
// 第一条,开启电弧跟踪,用跟踪参数arctrackdata1
ArcWelding::WMoveLCommand wml1(p1, 20, 1, "weavedata1", "arctrackdata1");
// 第二条,开启电弧跟踪,用跟踪参数arctrackdata2
ArcWelding::WMoveLCommand wml2(p2, 20, 1, "weavedata1", "arctrackdata2");
// 第三条,电弧跟踪参数为空,不跟踪
ArcWelding::WMoveLCommand wml3(p3, 20, 1, "weavedata1");
// 第四条和第五条,开启电弧跟踪,用跟踪参数arctrackdata2
ArcWelding::WMoveLCommand wml4(p4, 20, 1, "weavedata1", "arctrackdata2");
ArcWelding::WMoveLCommand wml5(p3, 20, 1, "weavedata1", "arctrackdata2");
// 第六条,不跟踪
ArcWelding::WMoveLCommand wml6(p2, 20, 1, "weavedata1"); // 直线摆动
ArcWelding::WeaveOnCommand weaveon("weavedata1");
ArcWelding::WeaveOffCommand weaveoff;
auto wmove_list = {wml1, wml2, wml3, wml4, wml5, wml6};

string id, move_id;
robot.setPowerState(true, ec);
robot.moveAppend(mj, move_id, ec);
robot.moveAppend(arcon, id, ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;
robot.moveAppend(weaveon, id, ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;
robot.moveAppend(wmove_list, move_id, ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;
robot.moveAppend(weaveoff, id, ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;
robot.moveAppend(arcoff, id, ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;
robot.moveStart(ec); if(ec) std::cout << __LINE__ << ":" << ec.message() << std::endl;

waitForFinish(robot, move_id, (int)wmove_list.size() - 1);
while(-1 != std::any_cast<int>(robot.queryEventInfo(Event::arcWeldState, ec).at(EventInfoKey::ArcWeldState::ArcWelding))) {
// waiting for arc off
std::this_thread::sleep_for(std::chrono::milliseconds (10));
}
print(std::cout, "Finish running");
}

常用接口与类型

setArcTrackParamgetArcTrackParamWMoveLCommand(带跟踪参数的重载)、ArcOnCommandWeaveOnCommandWeaveOffCommandArcOffCommand

注意事项

跟踪效果与焊机、焊丝、电流波形及机型有关;点位需在本机重新标定。 开电弧跟踪的时候必须要开摆动

场景十三:激光寻位

适用情况 在焊接主程序前或中途,需要用激光测量得到焊缝或特征点的位姿修正量。

目标 LaserSearchData 已下发,executeLaserSearch 在约定超时内返回结果;手眼数据名与指令中引用一致。

推荐步骤

  1. 传感器网络、手眼关系、设备连接等基础配置场景十四LaserSensorCfgsetHandeyeDataconnLaserSensorDev 等)。
  2. setLaserSearchData 维护寻位工艺名与工艺包约定字段。
  3. 构造 LaserSearchCommand(手眼数据名、寻位数据名、搜索位姿、速度等),调用 executeLaserSearch;同步/异步、超时与线程安全由应用保证。

实现代码

void LaserSearchExample() {
// 保存手眼标定参数
ArcWelding::HandeyeData handeyedata0;
handeyedata0.mode = true;
handeyedata0.xyz_abc = {29.456, -14.151, 70.047, 4.5006 / 180.0 * M_PI, 4.0438 / 180.0 * M_PI, -97.358 / 180.0 * M_PI};
handeyedata0.name = "laserhandeyedata1";
error_code ec;
arcWeld().setHandeyeData(handeyedata0, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
// 保存寻位参数
ArcWelding::LaserSearchData laserSearchData{"lasersearchdata1", 2, "point", "continuous", 3, "lap_joint"};
arcWeld().setLaserSearchData(laserSearchData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

CartesianPosition laserSearchPos;
laserSearchPos.rpy = {3.14, 0, 3.14};
laserSearchPos.trans ={0.563,0.3,0.43};
ArcWelding::LaserSearchCommand laserSearchCmd("laserhandeyedata1","lasersearchdata1",laserSearchPos, 10, 0);
bool isFound;
CartesianPosition pos;
std::tuple<bool, rokae::CartesianPosition> ret;
// 示例中选择同步等待寻位结果,设置超时时间为 30 秒。可根据轨迹速度和长度来设置超时时间。
std::chrono::seconds timeout(30);
// 一、单独运动
// 使用 std::async 启动一个线程执行 executeLaserSearch
auto future = std::async(std::launch::async,
[laserSearchCmd, timeout]() {
error_code _ec;
auto r = arcWeld().executeLaserSearch(laserSearchCmd, false, timeout, _ec);
cout << "executeLaserSearch ec: " << _ec.value() << ", " << _ec.message() << endl;
return r;
});
// 主线程执行 moveStart
std::this_thread::sleep_for(std::chrono::seconds(1)); // 注意处理异步之间的顺序,这里用延时代替
robot.moveStart(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
// 等待异步线程完成
ret = future.get();
isFound = std::get<0>(ret);
pos = std::get<1>(ret);
std::cout << "isFound: " << isFound << ", pos: ";
std::copy(pos.trans.begin(), pos.trans.end(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << "rpy: ";
std::copy(pos.rpy.begin(), pos.rpy.end(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << std::endl;

// 二、寻位并运动
robot.moveReset(ec);
ret = arcWeld().executeLaserSearch(laserSearchCmd, true,timeout, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
isFound = std::get<0>(ret);
pos = std::get<1>(ret);
std::cout << "isFound: " << isFound << ", pos: ";
std::copy(pos.trans.begin(), pos.trans.end(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << "rpy: ";
std::copy(pos.rpy.begin(), pos.rpy.end(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << std::endl;
}

常用接口与类型

setLaserSearchDataLaserSearchCommandexecuteLaserSearchHandeyeData(名在指令中引用)

场景十四:激光跟踪——传感器配置、连接与队列用法

适用情况 要在上位机维护激光 IP、周期、类型;连接设备;焊缝跟踪。

目标 设备可连接、可监控;跟踪段内 LaserTrackOnCommandLaserTrackOffCommand 与焊接运动同队列。

推荐步骤(配置与连接)

  1. 填写 LaserSensorCfgsetLaserSensorCfg;可选 setEventWatcher(Event::lasertrackState, …)
  2. connLaserSensorDev / disconnLaserSensorDev;不用时 removeLaserSensorCfg
  3. 手眼关系:setHandeyeData / getHandeyeData;自动标定:startHandeyeCalibrationcalibratePointcalibrateEnd
  4. 跟踪工艺名:setLaserTrackData(与工艺包字段一致)。

推荐步骤(焊缝跟踪队列)

  1. 连接设备后 openLaserTrack("sensor1", ec)
  2. 队列:ArcOnCommandLaserTrackOnCommandWMoveL / WMoveC 等 → LaserTrackOffCommandArcOffCommand
  3. closeLaserTrack,再按规范 disconnLaserSensorDev

实现代码

以下依次为同文件中的 printLaserSensorStatesetLaserSensorStateWatcher(供配置示例注册回调)、LaserSensorSettingExampleLaserTrackCommandExample(使用公共段中的 ROKAE_EXEwaitForFinish)。

//打印激光跟踪器状态
void printLaserSensorState(const EventInfo& info)
{
using namespace rokae::EventInfoKey::LaserTrackState;
print(std::cout, "[激光跟踪器状态信息] 设备名称: ", std::any_cast<std::string>(info.at(DeviceName)),
" 连接:", std::any_cast<bool>(info.at(Connect)) ? "YES " : "NO ",
"激光开启:", std::any_cast<bool>(info.at(LaserOn)) ? "YES " : "NO ",
"使能开启:", std::any_cast<bool>(info.at(PowerOn)) ? "YES " : "NO ");//注意:明图传感器没有使能状态,这里的使能状态无效
}
// 激光跟踪器状态监视
void setLaserSensorStateWatcher()
{
error_code ec;
robot.setEventWatcher(rokae::Event::lasertrackState, printLaserSensorState, ec);
if(ec) {
print(std::cerr, "Set laser state watcher failed:", ec);
}
}
/**
* @brief 示例 - 激光传感器相关设置
*/
void LaserSensorSettingExample() {
//设置激光跟踪器配置信息
ArcWelding::LaserSensorCfg cfg;
cfg.name = "sensor1";
cfg.ip = "192.168.2.3";
cfg.port = 502;
cfg.overtime = 800;
cfg.communication_cycle = 60;
cfg.type = ArcWelding::LaserSensorType::CRNT;//创想传感器
//cfg.type = ArcWelding::LaserSensorType::SMART_IMAGE;//明图传感器
//cfg.type = ArcWelding::LaserSensorType::INTELLIGENT;//英莱传感器

error_code ec;
//发送指令设置AddLaserSensorCfg
arcWeld().setLaserSensorCfg(cfg, ec);
if (ec) cout << ec.message()<<std::endl;

//查询设备配置信息
ArcWelding::LaserSensorCfg cfg_get = arcWeld().getLaserSensorCfg(cfg.name, ec);
cout << "name:" << cfg_get.name << " ip:" << cfg_get.ip << endl;
if (ec) cout << ec.message() << std::endl;

//设置传感器状态监控watch
setLaserSensorStateWatcher();

//连接激光跟踪器ConnLaserTrack
arcWeld().connLaserSensorDev(cfg.name, ec);
if (ec) cout << ec.message() << std::endl;

//断开连接DisConnLaserTrack
arcWeld().disconnLaserSensorDev(cfg.name,ec);
if (ec) cout << ec.message() << std::endl;

//删除设备配置信息RemoveLaserSensorCfg
arcWeld().removeLaserSensorCfg(cfg.name, ec);
if (ec) cout << ec.message() << std::endl;

//设置手眼标定结果
ArcWelding::HandeyeData handeyedata0;
handeyedata0.mode = true; // 使用XYZ_ABC的形式
handeyedata0.xyz_abc = { 29.456,-14.151,70.047,4.5006 / 180.0 * M_PI,4.0438 / 180.0 * M_PI,-97.358 / 180.0 * M_PI };
handeyedata0.name = "handeyedata0";
arcWeld().setHandeyeData(handeyedata0, ec);
if (ec) cout << ec.message() << std::endl;

//查询手眼标定结果
std::string name = "handeyedata0";
auto handeyedata0_get = arcWeld().getHandeyeData(name, ec);
if (ec) cout << ec.message() << std::endl;
cout << "name:" << handeyedata0_get.name << " xyz_abc:{" << handeyedata0_get.xyz_abc[0] << "," << handeyedata0_get.xyz_abc[2] << ","
<< handeyedata0_get.xyz_abc[2] << "," << handeyedata0_get.xyz_abc[3] << "," << handeyedata0_get.xyz_abc[4] << ","
<< handeyedata0_get.xyz_abc[5] << "}"<< endl;

//删除手眼标定结果
arcWeld().removeHandeyeData(name,ec);
if (ec) cout << ec.message() << std::endl;
}
/**
* @brief 示例 - 激光跟踪。点位适配机型XMS5
*/
void LaserTrackCommandExample(){
error_code ec;
// 设置传感器状态监控
setLaserSensorStateWatcher();
// 连接激光器
arcWeld().connLaserSensorDev("sensor1", ec);
if (ec) {
print(std::cerr, "Connected laser sensor failed", ec);
return;
}

ArcWelding::ArcOnCommand arcOnCmd("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arcOffCmd("arcoffdata1");
ArcWelding::LaserTrackOnCommand laserTrackOnCmd; // 默认手眼标定参数和激光跟踪参数名为"default",参考设置这两个参数的方式设置
ArcWelding::LaserTrackOffCommand laserTrackOffCmd;
MoveJCommand movej {{0.614, 0.136, 0.389, -M_PI, 0, M_PI }, 500};
ArcWelding::WMoveLCommand wmovel1 {{0.553, -0.107, 0.309, -M_PI, 0, M_PI}, 20};
ArcWelding::WMoveLCommand wmovel2 {{0.553, 0.107, 0.309, -M_PI, 0, M_PI}, 20};
string id, move_id;
robot.setOperateMode(rokae::OperateMode::automatic, ec);
robot.setPowerState(true, ec);
if(ec) {
print(std::cerr, "Set power state failed", ec);
return;
}

// 打开激光传感器
arcWeld().openLaserTrack("sensor1", ec);
if(ec) {
print(std::cerr, "Open laser sensor failed", ec);
return;
}

ROKAE_EXE(robot.moveAppend(movej, move_id, ec));
ROKAE_EXE(robot.moveAppend(arcOnCmd, id, ec));
ROKAE_EXE(robot.moveAppend(laserTrackOnCmd, id, ec));
ROKAE_EXE(robot.moveAppend({wmovel1, wmovel2}, move_id, ec));
ROKAE_EXE(robot.moveAppend(laserTrackOffCmd,id, ec));
ROKAE_EXE(robot.moveAppend(arcOffCmd, id, ec));
ROKAE_EXE(robot.moveStart(ec));
if(ec) return;

waitForFinish(robot, move_id, 1);
while(-1 != std::any_cast<int>(robot.queryEventInfo(Event::arcWeldState, ec).at(EventInfoKey::ArcWeldState::ArcWelding))) {
// waiting for arc off
std::this_thread::sleep_for(std::chrono::milliseconds (10));
}

// 关闭激光传感器
ROKAE_EXE(arcWeld().closeLaserTrack("sensor1", ec));

robot.setPowerState(false, ec);
robot.setOperateMode(rokae::OperateMode::manual, ec);
}

常用接口与类型

LaserSensorCfgsetLaserSensorCfgconnLaserSensorDevopenLaserTrackcloseLaserTracksetLaserTrackDataLaserTrackOnCommandLaserTrackOffCommandGetLaserPos

注意事项

场景十五:多层多道与层道偏移

适用情况 同一焊缝截面需要多道堆叠,或每层起点/姿态按 LayerData 偏移。

目标 层道参数已下发;可选先做可达性校验,再在下料队列中用 OffsetOnCommand / OffsetOffCommand 包络各层轨迹。

推荐步骤

  1. setLayerData 为每层道维护名称与偏移、辅助点等。
  2. 使用 MpmlPathCheck 对路径点组、运动类型列表与层道列表做校验,收集不可达层名。
  3. 需要时 GetLayerStartPoint 获取建议起弧位姿。
  4. 队列中在对应层轨迹前插入 OffsetOnCommand(layerName),层结束处 OffsetOffCommand

实现代码

// 点位适配机型XMC7-R850-B0X1A0
void arcLayerExample() {
std::string cmd_id;
error_code ec;

//设置多层多道参数
ArcWelding::LayerData layerData1;
layerData1.name = "layerdata1";
layerData1.start_offset = 10;
layerData1.end_offset = 01;
layerData1.y_offset = 10;
layerData1.z_offset = -0;
layerData1.tilt_angle = 0;
layerData1.travel_angle = 0;
layerData1.layer_reverse = false;
layerData1.offset_coord_system = 2;
layerData1.aux_type = 3;//三点法
//辅助点坐标值
layerData1.aux_point_1 = {514, -136, 410};
layerData1.aux_point_2 = {600, -120, 410};
layerData1.aux_point_3 = {500, -100, 410};
arcWeld().setLayerData(layerData1, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::LayerData layerData2;
layerData2.name = "layerdata2";
layerData2.start_offset = 0;
layerData2.end_offset = 20;
layerData2.y_offset = 50;
layerData2.z_offset = -0;
layerData2.tilt_angle = 0;
layerData2.travel_angle = 10;
layerData2.layer_reverse = true;
layerData2.offset_coord_system = 2;
layerData2.aux_type = 3;//三点法
//辅助点坐标值
layerData2.aux_point_1 = {514, -136, 410};
layerData2.aux_point_2 = {600, -120, 410};
layerData2.aux_point_3 = {500, -100, 410};
arcWeld().setLayerData(layerData2, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::LayerData layerData3;
layerData3.name = "layerdata3";
layerData3.start_offset = 0;
layerData3.end_offset = 0;
layerData3.y_offset = 100;
layerData3.z_offset = -0;
layerData3.tilt_angle = 10;
layerData3.travel_angle = 0;
layerData3.layer_reverse = true;
layerData3.offset_coord_system = 2;
layerData3.aux_type = 3;//三点法
//辅助点坐标值
layerData3.aux_point_1 = {514, -136, 410};
layerData3.aux_point_2 = {600, -120, 410};
layerData3.aux_point_3 = {500, -100, 410};
arcWeld().setLayerData(layerData3, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

ArcWelding::OffsetOnCommand offset_on_command1("layerdata1");
ArcWelding::OffsetOnCommand offset_on_command2("layerdata2");
ArcWelding::OffsetOnCommand offset_on_command3("layerdata3");
ArcWelding::OffsetOffCommand offset_off_command;
ArcWelding::ArcOnCommand arc_on_command("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arc_off_command("arcoffdata1");

CartesianPosition pos1_1{{0.600, -0.136, 0.589, -M_PI, 0, M_PI}};
CartesianPosition pos2_1{{0.500, -0.150, 0.489, -M_PI, 0, M_PI}};
CartesianPosition pos3_1{{0.400, -0.150, 0.489, -M_PI, 0, M_PI}};
CartesianPosition pos4_1{{0.300, -0.100, 0.489, -M_PI, 0, M_PI}};
CartesianPosition pos4_aux_1{{0.200, -0.150, 0.489, -M_PI, 0, M_PI}};
CartesianPosition pos5_1{{0.400, -0.150, 0.600, -M_PI, 0, M_PI}};
CartesianPosition pos1_2{{0.600, -0.136, 0.389, -M_PI, 0, M_PI}};
CartesianPosition pos2_2{{0.500, -0.150, 0.389, -M_PI, 0, M_PI}};
CartesianPosition pos3_2{{0.400, -0.150, 0.389, -M_PI, 0, M_PI}};
CartesianPosition pos1_3{{0.600, -0.136, 0.289, -M_PI, 0, M_PI}};
CartesianPosition pos2_3{{0.500, -0.150, 0.289, -M_PI, 0, M_PI}};
CartesianPosition pos3_3{{0.400, -0.150, 0.289, -M_PI, 0, M_PI}};
MoveJCommand movej_pos1_1{pos1_1, 100};
MoveLCommand movel_pos2_1{pos2_1, 20};
MoveLCommand movel_pos3_1{pos3_1, 20};
MoveLCommand movel_pos4_1{pos4_1, 20};
ArcWelding::WMoveCCommand movec_pos4_1{pos4_1, pos4_aux_1, 20};
movec_pos4_1.target.confData = {10, 25, -118, 0, -36, 6};
MoveLCommand movel_pos5_1{pos5_1, 20};
MoveJCommand movej_pos1_2{pos1_2, 100};
MoveLCommand movel_pos2_2{pos2_2, 20};
MoveLCommand movel_pos3_2{pos3_2, 20};
MoveJCommand movej_pos1_3{pos1_3, 100};
MoveLCommand movel_pos2_3{pos2_3, 20};
MoveLCommand movel_pos3_3{pos3_3, 20};
ArcWelding::WMoveLCommand arcwl1(pos3_1, 10, 1);


std::vector<std::vector<CartesianPosition>> point_groups = {
{pos2_1},
{pos3_1},
{pos4_aux_1, pos4_1},
};

std::vector<ArcWelding::MotionType> point_types = {
ArcWelding::MotionType::MOVE_LINEAR,
ArcWelding::MotionType::MOVE_LINEAR,
ArcWelding::MotionType::MOVE_CIRCLE,
};
std::vector<std::string> error_layer_list;
std::vector<ArcWelding::LayerData> layerdata_list;
// 模拟两层共计三道可达性校验
layerdata_list.push_back(layerData1);
layerdata_list.push_back(layerData2);
layerdata_list.push_back(layerData3);
bool check_res = arcWeld().MpmlPathCheck(point_groups, point_types, layerdata_list, error_layer_list, ec);
// 运动至起弧点示例
rokae::CartesianPosition start_position;
bool res = arcWeld().GetLayerStartPoint(point_groups, point_types, layerData2, start_position, ec);

robot.setPowerState(true, ec);
// 多层多道暂停|继续
int index = 1;
while (index < 4){
// 偏移启动
switch (++index) {
case 1:
robot.moveAppend(offset_on_command1, cmd_id, ec);
break;
case 2:
robot.moveAppend(offset_on_command2, cmd_id, ec);
break;
case 3:
robot.moveAppend(offset_on_command3, cmd_id, ec);
break;
default:
break;
}
if (index == 3)
robot.moveStart(ec, true);//暂停层道继续执行
robot.moveAppend(movej_pos1_1, cmd_id, ec);//0.600, -0.136, 0.589
robot.moveAppend(offset_on_command1, cmd_id, ec);
robot.moveAppend(movel_pos2_1, cmd_id, ec);//0.500, -0.150, 0.489
robot.moveAppend(arc_on_command, cmd_id, ec);
robot.moveAppend(arcwl1, cmd_id, ec);//0.400, -0.150, 0.489
robot.moveAppend(movec_pos4_1, cmd_id, ec);//0.400, -0.150, 0.600
robot.moveAppend(arc_off_command, cmd_id, ec);
robot.moveAppend(offset_off_command, cmd_id, ec);
if (index == 2)
robot.moveAppend(movel_pos4_1, cmd_id, ec, true);//0.400, -0.150, 0.589
else
robot.moveAppend(movel_pos4_1, cmd_id, ec);//0.400, -0.150, 0.589
robot.moveStart(ec);
index++;
}

robot.setPowerState(false, ec);
}

常用接口与类型

setLayerDatagetLayerDataremoveLayerDataLayerDataMpmlPathCheckGetLayerStartPointOffsetOnCommandOffsetOffCommand

场景十六:整圆与复杂空间曲线(摆动 / 间断 / 跟踪可选)

适用情况 焊缝为整圆或 MoveCF 类曲线,且可能叠加摆动、间断焊或电弧跟踪。

目标 使用 WMoveCFCommand 等与工艺指令组合;具体组合顺序与注释中的多种模式以工艺验证为准。

推荐步骤

  1. 将圆或曲线以工艺包要求的辅助点与目标点形式构造 WMoveCFCommand
  2. 按需 setWeaveDatasetSegDatasetArcTrackParam 后,在指令上绑定名称或在队列中插入 SegOnCommand 等。
  3. 在仿真或空运行下验证轨迹与姿态,再切实焊。

实现代码

void wmovecfExample() {
// 点位机型 XMC7-R850-W7G3B4C
cout << "enter exampleCommand" << endl;
auto rlPoint2sdkPoint = [](const std::vector<double> &rlPoint) -> std::array<double, 6> {
std::array<double, 6> sdkPoint;
for (int i = 0; i < 3; i++) {
sdkPoint[i] = rlPoint[i] / 1000.0;
}
for (int i = 3; i < 6; i++) {
sdkPoint[i] = rlPoint[i] / 180.0 * M_PI;
}
return sdkPoint;
};
error_code ec;
ArcWelding::ArcOnCommand arcon("arcondata1", "arcdata1");
ArcWelding::ArcOffCommand arcoff("arcoffdata1");
ArcWelding::SegOnCommand segon("segdata1");
ArcWelding::SegOffCommand segooff;
ArcWelding::WeaveOnCommand weaveon("weavedata1");
ArcWelding::WeaveOffCommand weaveoff;
std::vector<double> p1point({556.769126, 101.641184, 358.852436, 158.661084, -17.184105, -148.826026});
std::vector<double> p2point({590.049781, 101.641177, 358.852421, 158.66108, -17.184102, -148.826024});
std::vector<double> p3point({556.769146, 17.242862, 358.852448, 179.999964, -0.000009, -179.999957});
std::vector<double> p4point({556.769126, 101.641184, 358.852436, 179.999964, -0.000009, -179.999957});
std::vector<double> p5point({590.049781, 101.641177, 358.852421, 179.999964, -0.000009, -179.999957});
CartesianPosition p1(rlPoint2sdkPoint(p1point));
CartesianPosition p2(rlPoint2sdkPoint(p2point));
CartesianPosition p3(rlPoint2sdkPoint(p3point));
CartesianPosition p4(rlPoint2sdkPoint(p4point));
CartesianPosition p5(rlPoint2sdkPoint(p5point));
ArcWelding::WMoveLCommand wml(p3, 200, 1);
ArcWelding::WMoveCFCommand wmcf(p2, p1, 300 / 180.0 * M_PI);
ArcWelding::WMoveCFCommand wmcf2(p4, p5, 300 / 180.0 * M_PI);

// 设置旋转类型
// wmcf.rotType = MoveCFCommand::constPose;
wmcf.rotType = MoveCFCommand::constPose;
// wmcf.rotType = MoveCFCommand::rotAxis;

string id;

// 单独整圆运动
// robot.moveAppend(arcon, id, ec);
// robot.moveAppend(wmcf, id, ec);
// robot.moveAppend(arcoff, id, ec);
// robot.moveStart(ec);

// 搭配摆动运动
// wmcf.setWeaveData("weavedata1", ec);
// robot.moveAppend(arcon, id, ec);
// robot.moveAppend(weaveon, id, ec);
// robot.moveAppend(wmcf, id, ec);
// robot.moveAppend(weaveoff, id, ec);
// robot.moveAppend(arcoff, id, ec);
// robot.moveStart(ec);

// 搭配间断焊运动
// robot.moveAppend(arcon, id, ec);
// robot.moveAppend(segon, id, ec);
// robot.moveAppend(wmcf, id, ec);
// robot.moveAppend(segooff, id, ec);
// robot.moveAppend(arcoff, id, ec);
// robot.moveStart(ec);

// 搭配电弧跟踪,需要搭配摆动
// wmcf.setWeaveData("weavedata1", ec);
// wmcf.setTrackData("arctrackdata1", ec);
// robot.moveAppend(arcon, id, ec);
// robot.moveAppend(weaveon, id, ec);
// robot.moveAppend(wmcf, id, ec);
// robot.moveAppend(weaveoff, id, ec);
// robot.moveAppend(arcoff, id, ec);
// robot.moveStart(ec);

// arcdata中设置了断弧回退距离,暂停后继续运动会回退,需要有前置轨迹
// robot.setDefaultConfOpt(false,ec);
// robot.moveAppend(arcon, id, ec);
// robot.moveAppend(wml, id, ec);
// robot.moveAppend(wmcf, id, ec);
// robot.moveAppend(arcoff, id, ec);
// robot.moveStart(ec);
// std::this_thread::sleep_for(std::chrono::milliseconds(4000));
// robot.stop(ec); // 暂停
// std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// robot.moveStart(ec);// 继续
}

常用接口与类型

WMoveCFCommandMoveCFCommand::rotType

场景十七:现场辅助动作与焊机状态

适用情况 调枪、引弧前送丝 / 退丝 / 检气;短时点焊铆焊;读取焊机实时量或清报警;在不实际焊接时,通过 enableArcData 选择工作模式并将电流/电压模式与设定值下发至焊机,对照焊机面板核对已生效数据是否与上位机一致。

目标 不依赖完整焊接轨迹即可完成维护性动作;HMI 可展示焊机状态。

推荐步骤

  1. 送丝、退丝、检气:调用 feedOnWirefeedBackWiredetectGas 等,持续时间需满足工艺包最小阈值(如大于 0.1 s);停止动作使用对应重载中的使能参数(见附录方法)。
  2. 铆焊:startWelding / stopWelding,区分一元化与分别模式等(见接口说明)。
  3. 状态:getWelderStatus;报警可恢复时 clearWelderAlarm
  4. enableArcData:用于在焊机侧使能/生效一条焊接工艺数据(含工作模式、电流/电压模式及电流、电压等设定),该数据不会被保存。在不建立焊接过程的前提下调用后,对照焊机面板显示与上位机下发值是否一致,便于现场对表与联调(不能为虚拟机、须连接焊机等前提见下文代码注释)。

实现代码

以下依次为同文件中的 feedOnWirefeedBackWiredetectGasgetWelderStateexampleWeldingclearWelderAlarmenableArcData

// 送丝
void feedOnWire()
{
cout << "enter feedOnWire" << endl;
error_code ec;

double time = 0;
arcWeld().feedOnWire(time, ec); // 时间需要大于0.1,小于0.1错误码报错
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

time = 10;
arcWeld().feedOnWire(time, ec); // 时间大于0.1,错误码正常
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(2));

arcWeld().feedOnWire(time, ec,false); // 停止送丝
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 退丝
void feedBackWire()
{
cout << "enter feedBackWire" << endl;

error_code ec;
double time = 0;
arcWeld().feedBackWire(time, ec); // 时间需要大于0.1,小于0.1错误码报错
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

time = 10;
arcWeld().feedBackWire(time, ec); // 时间大于0.1,错误码正常
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(2));

arcWeld().feedBackWire(time, ec,false); // 停止退丝
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 送气
void detectGas()
{
cout << "enter detectGas" << endl;
error_code ec;

double time = 0;
arcWeld().detectGas(time, ec); // 时间需要大于0.1,小于0.1错误码报错
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

time = 2;
arcWeld().detectGas(time, ec); // 时间大于0.1,错误码正常
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(2));

arcWeld().detectGas(time, ec,false); // 停止检气
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 获取焊机状态
void getWelderState()
{
cout << "enter getWelderState" << endl;
error_code ec;

auto welderState = arcWeld().getWelderStatus(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
cout << "state: " << welderState.state << endl;
cout << "current: " << welderState.current << endl;
cout << "voltage: " << welderState.voltage << endl;
cout << "speed: " << welderState.speed << endl;
cout << "welding_name: " << welderState.welding_name << endl;
cout << "arc_welding: " << welderState.arc_welding << endl;
cerr << "runing_error: " << welderState.running_error.value() << "," << welderState.running_error.message() << endl;
cout << "distance: " << welderState.welding_distance << endl;
cout << "welding_time: " << welderState.welding_time << endl;
cout << "welding_wire_used: " << welderState.welding_wire_used << endl;
cout << "welding_path_num: " << welderState.welding_path_num << endl;
cout << "welder_error_code: " << welderState.welder_error_code << endl;
cout << "welder_ready: " << welderState.welder_ready << endl;
}
// 铆焊
void exampleWelding(){
error_code ec;
cout << "enter exampleWelding" << endl;
arcWeld().startWelding(100,0,ec); // 默认一元化
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

arcWeld().startWelding(100,10,ec,"separate"); // 分别模式
cout << "ec: " << ec.value() << ", " << ec.message() << endl;

std::this_thread::sleep_for(std::chrono::seconds(2));
arcWeld().stopWelding(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 清焊机面板告警
void clearWelderAlarm() {
error_code ec;
arcWeld().clearWelderAlarm(ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}
// 生效参数
void enableArcData(){
cout << "enter enableArcData" << endl;
// 不能为虚拟机并且需要连接焊机
ArcWelding::ArcData arcData = {
"example_arcdata", "example_annotation", "low_spatter", "wire_feed", "unified", 100, 20,0, 30, 400, {500, "auto_arc_reignition", 15}};
error_code ec;
arcWeld().enableArcData(arcData, ec);
cout << "ec: " << ec.value() << ", " << ec.message() << endl;
}

常用接口与类型

feedOnWirefeedBackWiredetectGasstartWeldingstopWeldinggetWelderStatusclearWelderAlarmenableArcData(用途说明见上文推荐步骤第 4 条;示例见上文代码块)、FeedOnWireCommandFeedBackWireCommand

场景十八:运行过程观测

适用情况 需要在程序中订阅焊接电流电压、弧焊状态、运动段完成等。

目标 异步回调或主动查询得到一致的状态快照;可按轨迹 id 与路点索引判断段结束。

推荐步骤

  1. setEventWatcher(Event::arcWeldState, callback, ec)设置焊机状态回调, 解析 EventInfoKey::ArcWeldState 各键。
  2. setEventWatcher(Event::moveExecution, ...) 或使用 queryEventInfo 轮询,结合业务定义的「段完成」条件(如轨迹 id + 路点索引)。
  3. 收弧是否完成可结合弧焊状态中的「是否仍在焊接」等字段判断(以工艺包与 SDK 键名为准)。

实现代码

以下依次为 printWeldStatesetArcWeldStateWatcherqueryWeldStateprintMoveStatesetMoveStateWatcher

void printWeldState(const EventInfo &info)
{
using namespace EventInfoKey::ArcWeldState;
double current = std::any_cast<double>(info.at(Current));
double voltage = std::any_cast<double>(info.at(Voltage));
string state = std::any_cast<string>(info.at(State));
int speed = std::any_cast<int>(info.at(Speed));
auto error = std::any_cast<error_code>(info.at(RunningError));
string weldingName = std::any_cast<string>(info.at(WeldingName));
int arcWelding = std::any_cast<int>(info.at(EventInfoKey::ArcWeldState::ArcWelding));
double distance = std::any_cast<double>(info.at(WeldingDistance));
double welding_time = std::any_cast<double>(info.at(WeldingTime));
double welding_wire_used = std::any_cast<double>(info.at(WeldingWireUsed));
int welder_error_code = std::any_cast<int>(info.at(WelderErrorCode));
bool welder_ready = std::any_cast<bool>(info.at(WelderReady));


cout << "[焊接状态] current: " << current << ", voltage: " << voltage << ", state: " << state << ", speed: " << speed << endl;
cout << "weldingName: " << weldingName << ", arcWelding: " << arcWelding << ", welding_time: " << welding_time << ", welding_wire_used: " << welding_wire_used
<< ", welder_error_code: " << welder_error_code << ", welder_ready: " << welder_ready << "." << endl;
if(info.count(WeldingPathNum)) {
int weldingPathNum = std::any_cast<int>(info.at(WeldingPathNum));
std::cout << "Distance: " << distance << " m, PathNum: " << weldingPathNum << "." << std::endl;
} else {
std::cout << "Distance: " << distance << " m." << std::endl;
}
if(error) {
std::cerr << "运行错误:" << error << std::endl;
}
}
void setArcWeldStateWatcher()
{
error_code ec;
robot.setEventWatcher(rokae::Event::arcWeldState, printWeldState, ec);
if(ec) {
print(std::cerr, "设置焊接状态监视失败:", ec);
}
}
void queryWeldState()
{
error_code ec;
auto info = robot.queryEventInfo(Event::arcWeldState, ec);
printWeldState(info);
}
void printMoveState(const EventInfo &info)
{
using namespace rokae::EventInfoKey::MoveExecution;
print(std::cout, "[运动执行信息] ID:", std::any_cast<std::string>(info.at(ID)), "Index:", std::any_cast<int>(info.at(WaypointIndex)),
"已完成: ", std::any_cast<bool>(info.at(ReachTarget)) ? "YES": "NO", std::any_cast<error_code>(info.at(Error)),
std::any_cast<std::string>(info.at(Remark)));
}
void setMoveStateWatcher()
{
error_code ec;
robot.setEventWatcher(rokae::Event::moveExecution, printMoveState, ec);
if(ec) {
print(std::cerr, "设置运动事件监视失败:", ec);
}
}

常用接口与类型

setEventWatcherqueryEventInfoEvent::arcWeldStateEvent::moveExecutionEventInfoKey::ArcWeldStateEventInfoKey::MoveExecution

注意事项

  1. 焊机状态回调的周期是500ms

场景十九:其它几何与工艺辅助(按需查阅)

适用情况 三点建用户参考、焊机支持模式查询、焊接中 Jog 偏置等;

目标 在程序中完成辅助几何计算或读取焊机能力列表。

推荐步骤

  1. 按业务调用 getRefBy3PointsgetWelderWorkModesweldOffsetJog 等;

实现代码

以下依次为 getRefBy3PointsExamplegetWelderWorkModesweldingJogOffsetExample

void getRefBy3PointsExample() {
error_code ec;
// auto ret = robot.posture(CoordinateType::endInRef,ec);
CartesianPosition pos1{0.55676914536239797, -0.15000000000000005, 0.35885244785437498, -3.1415926535897931, 3.8857805861880484e-16, -3.1415926535897931};
CartesianPosition pos2{0.71096662191265758, -0.14999999687989679, 0.35885244769618885, -3.1415921387343229, 8.5631816663676866e-07, 3.1415926369370966};
CartesianPosition pos3{0.71096662302702562, 0.0055997244168811289, 0.35885244730431071, -3.1415926429162764, 7.8093868108499471e-07, -3.1415918107904255};
bool with_origin = false;
ArcWelding::DirType dir = ArcWelding::DirType::X_Plus_Y_Plus;
auto ret = arcWeld().getRefBy3Points(std::vector<CartesianPosition>{pos1, pos2, pos3}, with_origin, dir, ec);
cout << "getRefBy3PointsExample: ec: " << ec.value() << ", " << ec.message() << endl;
for (auto &p : ret.trans) {
cout << p << " ";
}
for (auto &p : ret.rpy) {
cout << p << " ";
}
}
void getWelderWorkModes() {
error_code ec;
auto ret = arcWeld().getWelderWorkModes(ec);
cout << "getWelderWorkModes: ec: " << ec.value() << ", " << ec.message() << endl;
cout << "work modes: ";
for (auto &p : ret) {
cout << p << " ";
}
cout << endl;
}
void weldingJogOffsetExample() {
error_code ec;
arcWeld().weldOffsetJog(ArcWelding::WeldOffsetJogDir::Y_PLUS,ec);
arcWeld().weldOffsetJog(ArcWelding::WeldOffsetJogDir::Y_MINUS,ec);
arcWeld().weldOffsetJog(ArcWelding::WeldOffsetJogDir::Z_PLUS,ec);
arcWeld().weldOffsetJog(ArcWelding::WeldOffsetJogDir::Z_MINUS,ec);
cout << "weldingJogOffset: ec: " << ec.value() << ", " << ec.message() << endl;
}

常用接口与类型

getRefBy3PointsgetWelderWorkModesweldOffsetJog

与详细文档的对应关系

需求文档
接口列表与参数含义接口说明
类型与数据结构附录:类型附录:数据结构
方法签名与重载细节附录:方法
错误码与异常错误码和异常