Skip to content
🤖 AI 助手 / 自动化工具:先读 《AI 助手先读》 《Agent 开发指引》 《生成前信息采集清单》;机器可读入口 /llms.txt;技能包(SKILL)直链:SKILL.md

断线重连与状态恢复 ​

上位机长时间运行时,网线拔插、交换机重启、控制器重启都会让连接断开。重连回来不等于可以继续干活:控制器侧的伺服状态、运行模式、队列状态可能已经被复位。本页给出可直接套用的重连与恢复顺序。

先记住三件事

  1. set_reconnect 默认关闭,不显式打开,断线后不会自动重连,后续调用一路返回 -2。
  2. 重连回调是 C 函数指针 void(*)(),只在重连成功后触发;回调里不要做耗时操作,也不要直接下发运动命令。
  3. 重连后必须重新读状态:get_servo_state / get_current_mode / queue_motion_get_status,确认再继续。

一、两种做法 ​

做法适用说明
SDK 自动重连网络短暂抖动、交换机重启set_reconnect(fd, true) + set_reconnect_callback(fd, cb),SDK 内部重试
业务层重连控制器重启、需要换 IP、要控制重试节奏自己 disconnect_robot + connect_robot,可控但要多写循环

两者可以叠加:先用 SDK 自动重连兜住短抖动,连续失败超过设定次数再由业务层重建连接。

二、接口 ​

cpp
// 打开/关闭断开后自动重连(默认关闭)
Result set_reconnect(SOCKETFD socketFd, bool reconnect);

// 设置重连成功后的回调(C 函数指针,无参数)
Result set_reconnect_callback(SOCKETFD socketFd, void (*function)());

三、恢复顺序(重连成功后按这个走) ​

步骤调用判据
1get_servo_state(fd, state)读到状态值,确认连接真的可用
2clear_error(fd)有报警先清;返回非 0 也要继续读状态确认
3set_servo_state(fd, 1)伺服置「就绪」;状态为 2(报警)或 3(运行)时该调用会返回 -4
4set_servo_poweron(fd)返回 0 只代表命令下发,必须继续轮询状态
5轮询 get_servo_state 直到 3超时(建议 5 s)则放弃本次恢复,报警给上层
6get_current_mode(fd, mode)确认当前是示教/运行/远程中的哪一个,再决定能否下发运动
7queue_motion_get_status(fd, on)用到队列的再确认队列模式是否还开着(断线时通常已被关闭)

四、完整示例 ​

cpp
#include <chrono>
#include <iostream>
#include <thread>
#include "cpp/interface/nrc_api.h"

namespace {

const char* kIp = "192.168.1.13";
const char* kPort = "6001";     // 命令 / 状态通道

volatile bool g_reconnected = false;

// 回调里只置标志,不做任何 SDK 调用、不做耗时操作
void onReconnected()
{
    g_reconnected = true;
}

bool waitServoRunning(SOCKETFD fd, int timeoutMs)
{
    const int step = 100;
    for (int waited = 0; waited <= timeoutMs; waited += step) {
        int state = -1;
        if (get_servo_state(fd, state) == SUCCESS && state == 3) {
            return true;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(step));
    }
    return false;
}

// 重连后的状态恢复;返回 false 表示需要人工介入
bool recoverAfterReconnect(SOCKETFD fd)
{
    int state = -1;
    if (get_servo_state(fd, state) != SUCCESS) {
        std::cout << "读状态失败,连接不可用" << std::endl;
        return false;
    }
    if (state == 3) {
        std::cout << "仍在运行状态,无需重新上电" << std::endl;
        return true;
    }

    clear_error(fd);            // 有报警先清
    set_servo_state(fd, 1);     // 就绪
    set_servo_poweron(fd);      // 上电(返回 0 不等于已上电)

    if (!waitServoRunning(fd, 5000)) {
        std::cout << "上电超时,放弃本次恢复" << std::endl;
        return false;
    }

    int mode = -1;
    get_current_mode(fd, mode);
    std::cout << "恢复完成,当前模式 = " << mode << std::endl;
    return true;
}

} // namespace

int main()
{
    SOCKETFD fd = connect_robot(kIp, kPort);
    if (fd <= 0) {
        std::cout << "连接失败: " << fd << std::endl;
        return 1;
    }

    set_reconnect(fd, true);
    set_reconnect_callback(fd, onReconnected);

    // 业务主循环:只在连接可用时下发指令
    while (true) {
        if (g_reconnected) {
            g_reconnected = false;
            std::cout << "检测到重连,开始恢复状态" << std::endl;
            if (!recoverAfterReconnect(fd)) {
                std::cout << "恢复失败,转人工处理" << std::endl;
                break;
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    disconnect_robot(fd);
    return 0;
}

五、常见现象对照 ​

现象原因处理
断线后所有调用都返回 -2没开 set_reconnect,或句柄已失效开启自动重连;业务层检测到连续 -2 就重建连接
重连成功但机器人不动伺服状态被复位(不再是 3),或模式被切走按上面第三节重新上电 + 读模式
重连后第一次运动报 -4队列/追加模式已被关闭,或机器人停在急停态重新开队列模式;确认急停已释放
重连回调里崩溃在回调线程里调了阻塞接口或直接发运动回调只置标志,所有 SDK 调用回到业务线程
PC 能 ping 通但连不上控制器侧服务端口未监听(不是网络问题)换端口/查服务状态,属于控制器侧问题,按现场支持流程处理

六、注意 ​

  • set_reconnect_callback 只传函数指针,不能带上下文;多连接场景需要自己用全局映射把 socketFd 和业务对象对上(回调本身不带 fd,[待核] 是否会在回调中传入句柄以你的版本头文件为准)。
  • 重连后不要复用断线前的运动指令:位置可能已经变了,按当前位置重新计算。
  • 断线期间控制器可能仍在执行最后一条运动指令,恢复前先确认机器人已停止。