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

servoJ 与 7000 端口共用 ​

servoJ 的喂点、队列模式、状态查询与状态回调都走 7000 端口。很多客户会问「要不要为 servoJ 再开一条连接」「7000 上能不能同时挂状态回调」,本页给出连接组织方式与完整示例。

一句话结论

一根 7000 连接就够用:servoJ 喂点、servoJ 队列、get_robot_state、robot_state_callback 都在 7000 上;而清错、上下电、伺服使能、读坐标必须回到 6001。

一、两个端口各管什么 ​

端口承载典型接口
6001命令 / 状态通道connect_robot、clear_error、set_servo_state、set_servo_poweron、get_servo_state、get_current_position、get_current_mode
7000伺服跟踪 / 上位机服务open_servoJ、set_servoJ_pos、close_servoJ、open_servoJ_queue_mode、append_servoJ_pos_to_queue、close_servoJ_queue_mode、get_robot_state、robot_state_callback

servoJ 系列接口只接受 7000 句柄,传 6001 的句柄会返回 -2(DISCONNECT),这是最常见的失败原因。

二、连接与调用顺序 ​

cpp
SOCKETFD fdCmd   = connect_robot(ip, "6001");   // 命令 / 状态
SOCKETFD fdServo = connect_robot(ip, "7000");   // servoJ + 7000 侧功能

clear_error(fdCmd);                 // 1. 清错
set_servo_state(fdCmd, 1);          // 2. 就绪
set_servo_poweron(fdCmd);           // 3. 上电(返回 0 不等于已上电)
// 4. 轮询 get_servo_state(fdCmd) 到 3
open_servoJ(fdServo, vmax, amax, jmax);   // 5. 打开跟踪
// 6. 逐点 set_servoJ_pos(fdServo, q) 或队列 append
close_servoJ(fdServo);              // 7. 退出跟踪(必须先关)
set_servo_poweroff(fdCmd);          // 8. 下电

顺序不能颠倒:open_servoJ 之前控制器必须已经处于运行状态(3),否则会返回状态类错误。

三、7000 上同时挂状态回调 + 喂点 ​

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

std::atomic<int> g_robotState{-1};

// 状态回调:只记录,不做耗时操作、不下发命令
void onRobotState(int state)
{
    g_robotState.store(state);
}

int main()
{
    SOCKETFD fdCmd   = connect_robot("192.168.1.13", "6001");
    SOCKETFD fdServo = connect_robot("192.168.1.13", "7000");
    if (fdCmd <= 0 || fdServo <= 0) { return 1; }

    // 1) 上电到状态 3(略,见「上电与下电流程」)
    // 2) 7000 上先挂状态回调,再打开 servoJ —— 两者共用同一句柄
    robot_state_callback(fdServo, onRobotState);
    std::vector<double> vmax(7, 10.0), amax(7, 50.0), jmax(7, 200.0);
    open_servoJ(fdServo, vmax, amax, jmax);

    // 3) 同一句柄上按周期喂点
    std::vector<double> q(7, 0.0);
    int coord = 0;
    get_current_position(fdCmd, coord, q);   // 起点取实际位置

    const int cycleMs = 10;
    const double stepDeg = 0.05;             // ≤ vmax * cycleMs/1000
    for (int i = 0; i < 200; ++i) {
        q[0] += stepDeg;
        set_servoJ_pos(fdServo, q);
        std::this_thread::sleep_for(std::chrono::milliseconds(cycleMs));
    }

    close_servoJ(fdServo);
    disconnect_robot(fdServo);
    disconnect_robot(fdCmd);
    return 0;
}

回调签名以你的包内 nrc_interface.h 为准;本页只用来说明「同一 7000 句柄可以既挂回调又喂点」。

四、队列模式:一次给一组点 ​

逐点喂点要求上位机严格定时;点已经算好一段(视觉给轮廓、离线插补结果)时改用队列模式:

cpp
open_servoJ(fdServo, vmax, amax, jmax);          // 必须先打开跟踪
open_servoJ_queue_mode(fdServo, 10);             // 每点 10 ms
std::vector<std::vector<double>> pts;            // 每个内层 7 个元素(度)
append_servoJ_pos_to_queue(fdServo, pts);
close_servoJ_queue_mode(fdServo);
close_servoJ(fdServo);

每点位移要跟周期配套:每点位移(°) ≤ vmax(°/s) × cycle_time_ms / 1000。

周期vmax=10°/s 时每点最大位移说明
10 ms0.1°官方示例的默认节奏
20 ms0.2°点少一半,轨迹更粗
5 ms0.05°需要很高采样率时用

五、停止与完成判定 ​

你以为的实际含义
set_servoJ_pos 返回 0命令已写进 socket,不代表控制器已收、更不代表在动
close_servoJ 返回 0退出跟踪模式,机器人停在当前位置并保持使能(这是唯一确定的「停」)
「运动完成」servoJ 没有完成回调;只能读 get_current_position 与目标比对,误差进入容差且连续若干周期不变才算到位

六、常见问题 ​

现象原因处理
open_servoJ 返回 -2用了 6001 句柄,或 7000 没连上确认 connect_robot(ip, "7000") 成功
返回 0 但不动伺服未到状态 3;每周期增量太小;没连续发先轮询状态 3,再小步长试跑
状态回调收不到回调注册在 6001 句柄上,或没先连接成功状态回调走 7000 句柄
开第二条 7000 连接后异常并发连接数限制未明确([待核])优先复用同一根连接
跑完还在跟踪模式只关了队列模式,没关 close_servoJ两个都要关

七、待核 ​

  • 控制器对 7000 并发连接数是否有限制、一根连接上同时跑 servoJ 与状态回调是否有线程安全要求。
  • 「错误 / 警告消息回调」(set_receive_error_or_warnning_message_callback)应注册在哪个端口,文档未明确。