发布时间: 2026-01-16

CS 机器人 C++ SDK 快速使用手册


CS 机器人 C++ SDK 快速使用手册

1. 简介

本手册着重于使用SDK的环境配置。

1.1 SDK 概述

此SDK是艾利特机器人CS系列机械臂的C++库,借助该库,开发者可以基于C++实现驱动程序,从而充分利用艾利特机器人CS系列机械臂的多功能性来开发外部应用程序。

1.1.1 支持的操作系统

此SDK支持Windows与Linux操作系统,具体使用参考后文。

1.1.2 支持的机器人软件版本

SDK版本与适配的机器人软件版本的对应关系如下:
SDK版本
机器人软件
v1.1.0
>=2.10.x
v1.2.0
>= 2.13.4 或 >= 2.14.2
v1.3.0
>= 2.15.0
如果在表中没有找到你的SDK版本,可以到github仓库选择你的SDK版本的tag,查阅README文件了解所需的机器人软件版本,如下图所示:

1.1.3 支持的C++标准

本SDK最低支持C++14标准。
注意:C++14标准下SDK在使用过程中依赖boost库(headonly),而C++17以上标准则不需要。

2. 环境准备

2.1 Ubuntu 安装SDK

对于不同的Ubuntu发行版,推荐采用以下安装方式:

2.1.1 使用apt安装

对于 Ubuntu 发行版:Ubuntu 20.04 至 Ubuntu 24.04 我们已将SDK上传至ppa源中,支持 x86_64 以及 arm64 架构,可以使用下面的指令直接安装:
sudo add-apt-repository ppa:elite-robots/cs-robot-series-sdk
​
sudo apt update
​
sudo apt install elite-cs-series-sdk
如果需要卸载,推荐使用下面的指令:
sudo dpkg --remove elite-cs-series-sdk
如果要升级SDK,建议先卸载,再执行sudo apt install elite-cs-series-sdk重新安装。
注意:此方法安装的SDK的C++编译标准为C++17。

2.1.2 Ubuntu 使用预编译包安装

对于 Ubuntu 发行版:Ubuntu 18.04 与 Ubuntu 16.04 我们提供了 X86_64 的预编译版本,在此处可以下载。下载完成后使用下面指令进行解压:
tar -zxvf <package.name.tar.gz>
使用下面指令将库拷贝到系统路径中(建议逐条执行,注意替换解压后的路径):
cd <package.name.directory/>
​
sudo cp -r cmake/elite-cs-series-sdk /usr/local/lib/cmake/
​
sudo cp -r include/Elite /usr/local/include/
​
sudo cp lib/libelite-cs-series-sdk.* /usr/local/lib/
​
sudo mkdir /usr/local/share/Elite/
​
sudo cp resource/external_control.script /usr/local/share/Elite/
​
sudo ldconfig
使用下面指令安装依赖库:
sudo apt install libboost-dev libssh-dev
注意:此方法安装的SDK的C++编译标准为C++14。
可能遇到的问题
  • 在执行拷贝指令的过程中,如果出现/usr/local/目录下的Not a directory类似的报错,直接创建一个对应的目录就行,例如:如果出现cp: cannot create regular file '/usr/local/lib/cmake/': Not a directory 的报错,就直接创建目录:sudo mkdir /usr/local/lib/cmake/

2.2 其余Linux发行版

对于其余的Linux发行版,目前还没有安装包或者预编译包的支持,需要用户编译安装。

2.3 Linux 上的编译安装

此处以 Ubuntu 为例,与其他Linux发行版的区别只存在于安装依赖、编译工具等的方式不同。
执行下面指令安装编译工具:
sudo apt update
​
sudo apt install build-essential cmake git
执行下面指令安装依赖:
sudo apt install libboost-dev libssh-dev
执行下面指令下载代码(建议逐条执行):
git clone https://github.com/Elite-Robots/Elite_Robots_CS_SDK.git
​
cd Elite_Robots_CS_SDK/
​
git checkout vX.Y.Z # 替换为你需要的版本例如 v1.2.0
执行下面的指令编译并安装(建议逐条执行,执行过程中没有出现报错可视为成功):
mkdir build && cd build
​
cmake -DELITE_COMPILE_EXAMPLES=TRUE ..
​
make -j4
​
sudo make install
可能遇到的问题
  • 执行cmake -DELITE_COMPILE_EXAMPLES=TRUE ..出现类似下面的报错:
    CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
        CMake 3.16 or higher is required.  You are running version 3.xx
    此问题是cmake版本低于设置的版本,可以尝试下面步骤:
    1. 执行cmake --version获取你的cmake版本
    2. 修改SDK根目录下的“CMakeLists.txt”文件顶部cmake_minimum_required(VERSION 3.16)语句,将版本号修改为你的cmake版本号
    3. 再次执行cmake -DELITE_COMPILE_EXAMPLES=TRUE ..
      如果出现了其他错误,则需要将SDK根目录下的“CMakeLists.txt”文件复原,然后升级你的cmake版本大于等于3.16。
  • 执行make -j4出现下面的报错:
    error: ‘variant’ in namespace ‘std’ does not name a template type
    此问题是你的编译器不支持C++17标准或支持得不完善,建议升级支持完整C++17标准的编译器。如果无法升级,则可以使用下面指令编译安装:
    cmake -DELITE_COMPILE_EXAMPLES=TRUE -DCMAKE_CXX_STANDARD=14 ..
    ​
    make -j4
    ​
    sudo make install
    注意: C++14标准下使用SDK需要依赖boost库(headonly)。

2.4 Linux 中使用 SDK

复制下面代码,使用你习惯的文本编辑器,粘贴到dashboard_example.cpp中:
#include <iostream>
#include <memory>
#include <string>
#include <Elite/DashboardClient.hpp>
​
using namespace ELITE;
​
int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cout << "Must provide robot IP. Example: ./dashboard_example aaa.bbb.ccc.ddd" << std::endl;
        return 1;
    }
    std::string robot_ip = argv[1];
​
    std::unique_ptr<DashboardClient> my_dashboard;
    my_dashboard.reset(new DashboardClient());
​
    if (!my_dashboard->connect(robot_ip)) {
        std::cout << "Could not connect to robot" << std::endl;
        return 1;
    } else {
        std::cout << "Connect to robot" << std::endl;
    }
​
    // Power on
    if (!my_dashboard->powerOn()) {
        std::cout << "Could not send Power on command" << std::endl;
        return 1;
    } else {
        std::cout << "Power on" << std::endl;
    }
​
    // Brake release
    if (!my_dashboard->brakeRelease()) {
        std::cout << "Could not send BrakeRelease command" << std::endl;
        return 1;
    } else {
        std::cout << "Brake release" << std::endl;
    }
​
    my_dashboard->disconnect();
​
    return 0;
}
使用下面指令编译此代码,注意如果你的编译器不支持C++17,需要修改下面指令中C++标准:
g++ dashboard_example.cpp -o dashboard_example -lelite-cs-series-sdk --std=c++17
如果没有报错,则表示编译成功了。要执行编译出来的程序,请跳转机器人配置章节继续阅读。

2.5 Windows 使用预编译包

对于 Windows 我们提供了 X86_64 的预编译版本,在此处可以下载。下载完成后解压得到如下的文件,后文配置SDK到Visual Studio工程会使用到这些文件:
  • include
    • Elite: SDK 的头文件
  • lib
    • Debug:debug版本的库文件(dll、lib)
    • Release:release版本的库文件(dll、lib)
  • resource
    • external_control.script :控制脚本。
导入 Visual Studio 的步骤可参考后文。

2.6 Windows 下编译SDK

2.6.1 安装工具

  1. 通过连接下载 Visual Studio。
    注意,安装时需要勾选“使用C++的桌面开发”
  2. 通过连接下载并安装 CMake。
  3. 通过连接下载并安装 git。

2.6.2 安装依赖

使用 vcpkg 来作为Windows平台下的包管理器,在Windows的终端中运行下面指令下载vcpkg:
git clone https://github.com/microsoft/vcpkg.git

cd vcpkg

.\bootstrap-vcpkg.bat
如果没有输出 error 则代表成功安装了vcpkg,成功的输出大致如下:
Downloading https://github.com/microsoft/vcpkg-tool/releases/download/2025-07-21/vcpkg.exe -> C:\Users\cc\vcpkg\vcpkg.exe (using IE proxy: 127.0.0.1:7890)... done.
Validating signature... done.

vcpkg package management program version 2025-07-21-d4b65a2b83ae6c3526acd1c6f3b51aff2a884533

See LICENSE.txt for license information.
Telemetry
---------
vcpkg collects usage data in order to help us improve your experience.
The data collected by Microsoft is anonymous.
You can opt-out of telemetry by re-running the bootstrap-vcpkg script with -disableMetrics,
passing --disable-metrics to vcpkg on the command line,
or by setting the VCPKG_DISABLE_METRICS environment variable.

Read more about vcpkg telemetry at docs/about/privacy.md
使用下面指令安装依赖库:
.\vcpkg install boost-asio 

.\vcpkg install boost-program-options

.\vcpkg install libssh
如果安装成功会输出:All requested installations completed successfully in: 4.26 ms
执行下面指令配置到 Visual Studio:
.\vcpkg integrate install
配置成功将会输出:
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=C:/Users/cc/vcpkg/scripts/buildsystems/vcpkg.cmake"

All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available.
此处提示CMake projects should use,复制你的输出里“=”号后面的路径,以上面的输出为例是:C:/Users/cc/vcpkg/scripts/buildsystems/vcpkg.cmake

2.6.3 下载代码并编译

执行下面指令下载代码(建议逐条执行):
git clone https://github.com/Elite-Robots/Elite_Robots_CS_SDK.git

cd Elite_Robots_CS_SDK/

git checkout vX.Y.Z # 替换为你需要的版本例如 v1.2.0
执行下面的指令,注意将/your/path替换成刚刚复制的路径:
mkdir build

cd build

cmake -DCMAKE_TOOLCHAIN_FILE=/your/path -DELITE_COMPILE_EXAMPLES=TRUE ..

cmake --build . --config Release # 编译 release 版本

cmake --build . --config Debug # 编译 debug 版本
如果没有error输出,则代表成功。成功后需要留意以下文件,后文配置sdk到visual-studio工程会使用到这些文件:
  • ./Debug:debug版本的库文件(dll、lib)
  • ./Release:release版本的库文件(dll、lib)
  • ./include/Elite:SDK 的头文件
  • ../source/resources/external_control.script:控制脚本。

2.7 配置SDK到Visual Studio工程

  1. 打开Visual Studio,选择创建新项目。
  2. 选择语言为C++,选择控制台应用,最后点击下一步。
  3. 设置项目名称、保存路径等,点击创建
  4. 拷贝库到项目里
    • 在项目目录中新建一个文件夹elite-cs-sdk
    • 对于下载预编译包的用户:
      • 拷贝lib中的DebugRelease文件夹到elite-cs-sdk
      • 拷贝resourceelite-cs-sdk
      • 拷贝include中的Elite文件夹到elite-cs-sdk
    • 对于手动编译的用户(Elite_Robots_CS_SDK根目录):
      • 拷贝build/Debugbuild/Release文件夹到elite-cs-sdk
      • 拷贝source/resourceelite-cs-sdk
      • 拷贝build/include/Elite文件夹到elite-cs-sdk
    • 拷贝完成后,elite-cs-sdk文件夹的结构如下:
      .
      ├── Debug
      ├── Elite
      ├── Release
      └── resources
  5. 菜单栏选择“项目” --> “属性”
  6. 选择“配置”:“所有配置”,选择“常规”,设置C++标准为C++17
  7. 选择“VC++ 目录” --> 外部包含目录 --> 编辑
  8. 设置路径为第四步中的elite-cs-sdk文件夹
  9. 调整配置为“Debug”,选择“VC++ 目录”,选择“库目录”
  10. 设置路径为第四步中的elite-cs-sdk/Debug文件夹
  11. 调整配置为“Release”,选择“VC++ 目录”,选择“库目录”
  12. 设置路径为第四步中的elite-cs-sdk/Release文件夹
  13. 调整配置为“所有配置”,选择“链接器” --> “输入” --> “附加依赖项目”
  14. 填入elite-cs-series-sdk.lib
  15. 复制下面代码,粘贴到VS中:
    #include <iostream>
    #include <memory>
    #include <string>
    #include <Elite/DashboardClient.hpp>
    
    using namespace ELITE;
    
    int main(int argc, char* argv[]) {
        if (argc < 2) {
            std::cout << "Must provide robot IP. Example: ./dashboard_example aaa.bbb.ccc.ddd" << std::endl;
            return 1;
        }
        std::string robot_ip = argv[1];
    
        std::unique_ptr<DashboardClient> my_dashboard;
        my_dashboard.reset(new DashboardClient());
    
        if (!my_dashboard->connect(robot_ip)) {
            std::cout << "Could not connect to robot" << std::endl;
            return 1;
        } else {
            std::cout << "Connect to robot" << std::endl;
        }
    
        // Power on
        if (!my_dashboard->powerOn()) {
            std::cout << "Could not send Power on command" << std::endl;
            return 1;
        } else {
            std::cout << "Power on" << std::endl;
        }
    
        // Brake release
        if (!my_dashboard->brakeRelease()) {
            std::cout << "Could not send BrakeRelease command" << std::endl;
            return 1;
        } else {
            std::cout << "Brake release" << std::endl;
        }
    
        my_dashboard->disconnect();
    
        return 0;
    }
  16. 菜单栏选择“生成”-->“生成解决方案”,编译成功将不会报错。编译完成后,在解决方案的目录下会出现x64的文件夹。
  17. 拷贝elite-cs-sdk\Debug\目录下的所有文件到x64\Debug\目录下。要执行编译出来的程序,请跳转机器人配置章节继续阅读。
如果你的编译模式是 Release 则路径中的 Debug 要换为 Release

3. 机器人配置

3.1 网络配置

3.1.1 CS 控制柜

对于 CS 标准系列控制柜需要将FB1、FB2两个网口接入到局域网中,并设置好IP。
可能存在的疑问
  • 为什么要连接两个网口?因为此系列控制柜使用了双处理器的分布式架构,FB1和FB2各对应一个处理器,与SDK进行通讯的控制软件运行在FB2处理器上,而机器人的 dashboard 功能运行在FB1处理器上,因此需要连接两个网口。不过在 2.14.3 版本后,使用 SDK 的 headless 模式(此模式后文介绍)可以只连接FB2网口。

3.1.2 CS_X 控制柜

对于 CS_X 系列控制柜,只有一个网口,因此只要连接着一个网口就可以。

3.2 设置远程控制模式

点击示教器右上角的汉堡菜单,选择设置:
启用/禁用远程控制模式,然后点击左下角退出按钮:
如果选择了启用远程控制模式,此时的界面的右侧栏会出现“本地控制”的选项,切换到“远程控制”。
tips:CS 系列机器人如果远程控制模式是禁用状态,则会处于“混合模式”,即既可以接收外部的控制,也可以接收示教器本地的控制,因此在上面步骤中,远程控制模式可以设为禁用。

3.3 测试网络连接

此处提供了两种可以测试SDK是否能和机器人通讯的方式:
推荐使用第一种方法,如果方法1能跑通,那机器人的配置基本就没有问题了。

3.3.1 使用机器人脚本(推荐)

  1. 在要运行SDK的操作系统中执行下面指令:
    • Linux
      ifconfig
    • Windows:
      ipconfig
      记录下与机器人相连网口的IP,记为 Local IP。
    可能遇到的问题
    • Linux中执行ifconfig时可能会出现找不到命令的提示,此时需要安装一下此指令,例如在Ubuntu中使用sudo apt install net-tools指令安装。
  2. 点击示教器左侧栏的“任务”。
  3. 点击“占位节点”,点击“高级”-->“脚本”。
  4. 点击左侧下拉框,选择“文件”,点击“编辑”

  5. 将下面内容写入文本编辑器中,注意,替换IP地址为刚刚记下的 Local IP:
    socket_open("Your.Robot.IP.Addr", 50001)
    socket_send_string("Hello SDK\n")
    sleep(1)
  6. 点击保存,并设置文件名

  7. 可以用你习惯的方式,在要运行SDK的操作系统中创建一个端口为50001的TCP服务。这里提供了一个python脚本,你可以把它复制到“sdk_connection_test.py”的文件中,然后执行python3 sdk_connection_test.py 执行运行此脚本。
import socket

def start_tcp_server(host='localhost', port=50001):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    try:
        # 设置accept超时(1秒)
        server_socket.settimeout(1.0)
        
        server_socket.bind((host, port))
        server_socket.listen(5)
        print(f"TCP服务器启动在 {host}:{port},等待客户端连接...")
        
        while True:
            try:
                # 接受客户端连接(现在会超时,让出控制权)
                client_socket, client_address = server_socket.accept()
                print(f"客户端 {client_address} 已连接")
                
                try:
                    while True:
                        data = client_socket.recv(1024)
                        if not data:
                            print(f"客户端 {client_address} 已断开连接")
                            break
                        
                        received_string = data.decode('utf-8')
                        print(f"来自 {client_address} 的数据: {received_string}")
                        
                except ConnectionResetError:
                    print(f"客户端 {client_address} 异常断开连接")
                except Exception as e:
                    print(f"处理客户端 {client_address} 时发生错误: {e}")
                finally:
                    client_socket.close()
                    
            except socket.timeout:
                # 超时是正常的,继续循环
                continue
                
    except KeyboardInterrupt:
        print("\n服务器被用户中断")
    except Exception as e:
        print(f"服务器发生错误: {e}")
    finally:
        server_socket.close()
        print("服务器已关闭")

if __name__ == "__main__":
    start_tcp_server()
  1. 点击示教器上的任务运行按钮,如果一切正常,会看到TCP服务器接收到“Hello SDK”的一行字符串。
可能遇到的问题
  1. 如果在创建TCP服务时失败,可能是你的系统中有其他程序占用了“50001”端口,如需换成别的端口,机器人脚本中的端口也要替换。
  2. 示教器提示:“socket_send_string”:未连接服务端“socket_0”。出现这个异常的原因是,机器人无法连接SDK的TCP服务端口。可能有下面的原因:
    • 如果你使用了虚拟机,需要你把虚拟机的网卡设置为桥接,并桥接到与机器人相连的网卡上,然后设置好IP。
    • 如果是CS 控制柜的用户,可能是没有连接FB2网口。
    • 你的局域网将连接关闭了,建议将机器人与运行SDK的电脑直接连接,如果是CS控制柜用户,可以使用一个交换机将运行SDK的电脑、控制柜FB1、控制柜FB2接到一起。
    • IP设置不正确,运行SDK的电脑的IP,与控制柜网口的IP没有在同一网段。
    • 你的电脑开启了 VPN,建议关闭。
    • 服务器没有启动成功,你的系统里的某些应用将50001端口占用,可以换一个端口,注意,不光服务器端口要改,机器人脚本的socket_open指令里的端口号也要改。
    • 服务器被关闭,有可能在你接收到“Hello SDK”的一行字符串后,你关闭了服务器,但此时机器人还在循环执行脚本。
    • 如果上述情况确保没问题,但还是连不上,可以重启一下控制柜再尝试。

3.3.2 使用bash指令

在要运行SDK的操作系统中输入下面指令:
  • Linux
    ifconfig
  • Windows:
    ipconfig
记录下与机器人相连网口的IP,记为 Local IP。
可能遇到的问题
  • Linux中执行ifconfig时可能会出现找不到命令的提示,此时需要安装一下此指令,例如在Ubuntu中使用sudo apt install net-tools指令安装。
在要运行SDK的操作系统中运行下面指令,使用ssh登录到机器人的操作系统里,注意替换aaa.bbb.ccc.ddd为机器人IP(如果是CS系列控制,则为FB2的IP),密码为elibot
ssh root@aaa.bbb.ccc.ddd
登录上去之后输入下面指令,注意替换aaa.bbb.ccc.ddd为刚刚记录下的Local IP,此操作可简单检查机器人是否能连接上SDK。
ping aaa.bbb.ccc.ddd
如果能ping通,则会有类似下面的输出:
PING 192.168.1.110 (192.168.1.110): 56 data bytes
64 bytes from 192.168.1.110: seq=0 ttl=64 time=0.373 ms
64 bytes from 192.168.1.110: seq=1 ttl=64 time=0.409 ms
64 bytes from 192.168.1.110: seq=2 ttl=64 time=0.397 ms
64 bytes from 192.168.1.110: seq=3 ttl=64 time=0.432 ms
如果无法ping通,则需要检查网络设置,例如:IP地址是否冲突,SDK所在系统、机器人是否在同一个网段里,所在的局域网环境。
输入exit退出登录,回到要运行SDK的操作系统中,执行下面指令,简单检查SDK是否能连接上机器人,注意替换aaa.bbb.ccc.ddd为机器人IP(如果是CS 标准系列控制柜,需要ping通FB1和FB2)。
ping aaa.bbb.ccc.ddd

4. SDK 使用

4.1 执行先前的编译结果

“环境准备”章节中我们编译了一个简单的代码,现在我们来运行那个程序。为了更好的展示运行效果,建议将机械臂下电:

4.1.1 Linux

在前面的步骤中,已经将dashboard_example.cpp编译为dashboard_example可执行程序,使用下面指令运行这个程序,注意替换机器人IP地址:
./dashboard_example Your.Robot.IP.Addr
如果执行成功,会看到机器人上电并释放抱闸。

4.1.2 Windows

  1. 在前面的步骤中,已经编译好了程序,在Visual Studio界面中,右键点击右侧栏你的项目名称,选择属性:
  2. 选择“配置属性”-->“调试”-->“命令参数”,设置参数为机器人IP,点击确定:
  3. 点击“本地 Windows 调试器”运行此程序:
  4. 程序成功运行后将会给机器人上电并释放抱闸。

4.1.3 简单说明

艾利特CS系列机器人提供了一个名为 Dashboard 的接口,提供了大量的界面操作接口,例如上下电,加载任务等。SDK封装了此功能。刚刚所运行的程序,就是调用了Dashboard的上电和释放抱闸两个接口。

4.2 使用SDK控制机器人运动

4.2.1 Linux

参考2.4章节,复制下面代码,使用你习惯的文本编辑器,粘贴到move_example.cpp中:
#include <Elite/DataType.hpp>
#include <Elite/EliteDriver.hpp>
#include <Elite/Log.hpp>
#include <Elite/DashboardClient.hpp>
#include <Elite/RtsiIOInterface.hpp>

#include <future>
#include <iostream>
#include <memory>
#include <thread>

using namespace ELITE;

class TrajectoryControl {
   private:
    std::unique_ptr<EliteDriver> driver_;
    
    std::unique_ptr<DashboardClient> dashboard_;
    EliteDriverConfig config_;

   public:
    TrajectoryControl(const EliteDriverConfig& config) {
        config_ = config;
        driver_ = std::make_unique<EliteDriver>(config);
        dashboard_ = std::make_unique<DashboardClient>();

        ELITE_LOG_INFO("Connecting to the dashboard");
        if (!dashboard_->connect(config.robot_ip)) {
            ELITE_LOG_FATAL("Failed to connect to the dashboard.");
            throw std::runtime_error("Failed to connect to the dashboard.");
        }
        ELITE_LOG_INFO("Successfully connected to the dashboard");
    }

    ~TrajectoryControl() {
        if (dashboard_) {
            dashboard_->disconnect();
        }
        driver_->stopControl();
    }

    bool startControl() {
        ELITE_LOG_INFO("Start powering on...");
        if (!dashboard_->powerOn()) {
            ELITE_LOG_FATAL("Power-on failed");
            return false;
        }
        ELITE_LOG_INFO("Power-on succeeded");

        ELITE_LOG_INFO("Start releasing brake...");
        if (!dashboard_->brakeRelease()) {
            ELITE_LOG_FATAL("Brake release failed");
            return false;
        }
        ELITE_LOG_INFO("Brake released");

        if (config_.headless_mode) {
            if (!driver_->isRobotConnected()) {
                if (!driver_->sendExternalControlScript()) {
                    ELITE_LOG_FATAL("Fail to send external control script");
                    return false;
                }
            }
        } else {
            ELITE_LOG_FATAL("Must use headless mode");
            return false;
        }

        ELITE_LOG_INFO("Wait external control script run...");
        while (!driver_->isRobotConnected()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        ELITE_LOG_INFO("External control script is running");
        return true;
    }

    bool moveTrajectory(const std::vector<vector6d_t>& target_points, float point_time, float blend_radius, bool is_cartesian) {
        std::promise<TrajectoryMotionResult> move_done_promise;
        driver_->setTrajectoryResultCallback([&](TrajectoryMotionResult result) { move_done_promise.set_value(result); });

        ELITE_LOG_INFO("Trajectory motion start");
        if(!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::START, target_points.size(), 200)) {
            ELITE_LOG_ERROR("Failed to start trajectory motion");
            return false;
        }

        for (const auto& joints : target_points) {
            if (!driver_->writeTrajectoryPoint(joints, point_time, blend_radius, is_cartesian)) {
                ELITE_LOG_ERROR("Failed to write trajectory point");
                return false;
            }
            // Send NOOP command to avoid timeout.
            if(!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::NOOP, 0, 200)) {
                ELITE_LOG_ERROR("Failed to send NOOP command");
                return false;
            }
        }

        std::future<TrajectoryMotionResult> move_done_future = move_done_promise.get_future();
        while (move_done_future.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready) {
            // Wait for the trajectory motion to complete, and send NOOP command to avoid timeout.
            if(!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::NOOP, 0, 200)) {
                ELITE_LOG_ERROR("Failed to send NOOP command");
                return false;
            }
        }
        auto result = move_done_future.get();
        ELITE_LOG_INFO("Trajectory motion completed with result: %d", result);

        if(!driver_->writeIdle(0)) {
            ELITE_LOG_ERROR("Failed to write idle command");
            return false;
        }

        return result == TrajectoryMotionResult::SUCCESS;
    }

    bool moveTo(const vector6d_t& point, float time, bool is_cartesian) {
        return moveTrajectory({point}, time, 0, is_cartesian);
    }
};

int main(int argc, const char** argv) {
    EliteDriverConfig config;
    if (argc == 2) {
        config.robot_ip = argv[1];
    } else if (argc == 3) {
        config.robot_ip = argv[1];
        config.local_ip = argv[2];
    } else {
        std::cout << "Must provide robot IP. Example: ./trajectory_example aaa.bbb.ccc.ddd <eee.fff.ggg.hhh>" << std::endl;
        return 1;
    }
    config.headless_mode = true;
    config.script_file_path = "external_control.script";
    std::unique_ptr<TrajectoryControl> trajectory_control = std::make_unique<TrajectoryControl>(config);
    std::unique_ptr<RtsiIOInterface> rtsi_client = std::make_unique<RtsiIOInterface>("output_recipe.txt", "input_recipe.txt", 250);

    ELITE_LOG_INFO("Connecting to the RTSI");
    if (!rtsi_client->connect(config.robot_ip)) {
        ELITE_LOG_FATAL("Fail to connect or config to the RTSI.");
        throw std::runtime_error("Fail to connect or config to the RTSI");
    }
    ELITE_LOG_INFO("Successfully connected to the RTSI");

    ELITE_LOG_INFO("Starting trajectory control...");
    if(!trajectory_control->startControl()) {
        ELITE_LOG_FATAL("Failed to start trajectory control.");
        return 1;
    }
    ELITE_LOG_INFO("Trajectory control started");

    vector6d_t actual_joints = rtsi_client->getActualJointPositions();
    actual_joints[3] = -1.57;

    ELITE_LOG_INFO("Moving joints to target: [%lf, %lf, %lf, %lf, %lf, %lf]",
                   actual_joints[0], actual_joints[1], actual_joints[2], actual_joints[3], actual_joints[4], actual_joints[5]);
    if(!trajectory_control->moveTo(actual_joints, 3, false)) {
        ELITE_LOG_FATAL("Failed to move joints to target.");
        return 1;
    }
    ELITE_LOG_INFO("Joints moved to target");


    vector6d_t actual_pose = rtsi_client->getAcutalTCPPose();
    std::vector<vector6d_t> trajectory;

    actual_pose[2] -= 0.2;
    trajectory.push_back(actual_pose);


    actual_pose[1] -= 0.2;
    trajectory.push_back(actual_pose);

    actual_pose[1] += 0.2;
    actual_pose[2] += 0.2;
    trajectory.push_back(actual_pose);

    ELITE_LOG_INFO("Moving joints to target");
    if(!trajectory_control->moveTrajectory(trajectory, 3, 0, true)) {
        ELITE_LOG_FATAL("Failed to move trajectory.");
        return 1;
    }
    ELITE_LOG_INFO("Joints moved to target");

    return 0;
}
使用下面指令编译此代码,注意如果你的编译器不支持C++17,需要修改下面指令中C++标准:
g++ move_example.cpp -o move_example -lelite-cs-series-sdk --std=c++17
编译完成后,会出现名为move_example的可执行文件。
复制下面文本,使用你习惯的文本编辑器,粘贴到output_recipe.txt中:
timestamp
payload_mass
payload_cog
script_control_line
target_joint_positions
target_joint_speeds
actual_joint_torques
actual_joint_positions
actual_joint_speeds
actual_joint_current
actual_TCP_pose
actual_TCP_speed
actual_TCP_force
target_TCP_pose
target_TCP_speed
actual_digital_input_bits
actual_digital_output_bits
joint_temperatures
robot_mode
joint_mode
safety_status
speed_scaling
target_speed_fraction
actual_robot_voltage
actual_robot_current
runtime_state
elbow_position
robot_status_bits
safety_status_bits
analog_io_types
standard_analog_input0
standard_analog_input1
standard_analog_output0
standard_analog_output1
io_current
tool_mode
tool_analog_input_types
tool_analog_output_types
tool_analog_input
tool_analog_output
tool_output_voltage
tool_output_current
tool_temperature
tool_digital_mode
tool_digital0_mode
tool_digital1_mode
tool_digital2_mode
tool_digital3_mode
output_bit_registers0_to_31
output_bit_registers32_to_63
input_bit_registers0_to_31
input_bit_registers32_to_63
复制下面文本,使用你习惯的文本编辑器,粘贴到input_recipe.txt中:
speed_slider_mask
speed_slider_fraction
standard_digital_output_mask
standard_digital_output
configurable_digital_output_mask
configurable_digital_output
tool_digital_output_mask
tool_digital_output
standard_analog_output_mask
standard_analog_output_type
standard_analog_output_0
standard_analog_output_1
external_force_torque
input_bit_registers0_to_31
input_bit_registers32_to_63
如果你使用系统的包管理工具安装SDK,如 Ubuntu 的 apt,那么通常你可以在/usr/share/Elite/路径下找到external_control.script文件,拷贝这个文件到与move_example同一目录。
如果使用预编译包安装或编译安装SDK,那么通常可以在/usr/local/share/Elite/路径下找到external_control.script文件,拷贝这个文件到与move_example同一目录。
执行ifconfig指令,获取本机IP。
执行下面指令来运行此程序,注意替换机器人IP和本机IP,以及确认机器人周围环境安全:
./move_example Your.Robot.IP.Addr Your.Local.IP.Addr
运行成功,机器人将会以当前位姿为起点,运行一个三角形轨迹。
可能出现的异常:
  1. 机器人没有运动,示教器提示:“socket_read_binary_integer”:未连接服务端“reverse_socket”。出现这个异常的原因是,机器人无法连接SDK的TCP服务端口。可以参考 “3.3.1 测试网络连接——使用机器人脚本” 章节最后的可能遇到的问题部分的描述。
  2. 机器人运动结束,示教器提示:“socket_read_binary_integer”:未连接服务端“script_command_socket”。此现象是程序在退出时出现了意外的问题,可以尝试升级SDK。此现象可以不用过多关注。
  3. 机器人运动过程中中断,机器人示教器日志栏提示:“Socket timed out waiting for command on reverse_socket. The script will exit now.”,或者提示:“socket_read_binary_integer”:未连接服务端“xxx_socket”。此现象是触发了SDK控制机器人的超时机制。可能有如下原因:
    • 运行SDK的电脑无法支撑与控制柜的数据传输速度。
    • 网络传输出现异常,例如网线松脱。
  4. 如果程序抛出端口被占用的异常,可以用下面指令查看是哪个端口被占用,然后关闭对应进程:
    netstat -ano |grep 50001
    netstat -ano |grep 50002
    netstat -ano |grep 50003
    netstat -ano |grep 50004
  5. 示教器提示:目标位姿为奇异位姿,机器人不可达。出现此现象,可以使用示教器手动调整机器人位姿到一个合理的范围内。

4.2.2 Windows

参考2.7 配置SDK到Visual Studio工程章节,创建一个新的工程叫“MoveExample”,这里不多赘述。
拷贝下面代码到VS中:
#include <Elite/DataType.hpp>
#include <Elite/EliteDriver.hpp>
#include <Elite/Log.hpp>
#include <Elite/DashboardClient.hpp>
#include <Elite/RtsiIOInterface.hpp>

#include <future>
#include <iostream>
#include <memory>
#include <thread>

using namespace ELITE;

class TrajectoryControl {
private:
    std::unique_ptr<EliteDriver> driver_;

    std::unique_ptr<DashboardClient> dashboard_;
    EliteDriverConfig config_;

public:
    TrajectoryControl(const EliteDriverConfig& config) {
        config_ = config;
        driver_ = std::make_unique<EliteDriver>(config);
        dashboard_ = std::make_unique<DashboardClient>();

        ELITE_LOG_INFO("Connecting to the dashboard");
        if (!dashboard_->connect(config.robot_ip)) {
            ELITE_LOG_FATAL("Failed to connect to the dashboard.");
            throw std::runtime_error("Failed to connect to the dashboard.");
        }
        ELITE_LOG_INFO("Successfully connected to the dashboard");
    }

    ~TrajectoryControl() {
        if (dashboard_) {
            dashboard_->disconnect();
        }
        driver_->stopControl();
    }

    bool startControl() {
        ELITE_LOG_INFO("Start powering on...");
        if (!dashboard_->powerOn()) {
            ELITE_LOG_FATAL("Power-on failed");
            return false;
        }
        ELITE_LOG_INFO("Power-on succeeded");

        ELITE_LOG_INFO("Start releasing brake...");
        if (!dashboard_->brakeRelease()) {
            ELITE_LOG_FATAL("Brake release failed");
            return false;
        }
        ELITE_LOG_INFO("Brake released");

        if (config_.headless_mode) {
            if (!driver_->isRobotConnected()) {
                if (!driver_->sendExternalControlScript()) {
                    ELITE_LOG_FATAL("Fail to send external control script");
                    return false;
                }
            }
        }
        else {
            if (!dashboard_->playProgram()) {
                ELITE_LOG_FATAL("Fail to play program");
                return false;
            }
        }

        ELITE_LOG_INFO("Wait external control script run...");
        while (!driver_->isRobotConnected()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        ELITE_LOG_INFO("External control script is running");
        return true;
    }

    bool moveTrajectory(const std::vector<vector6d_t>& target_points, float point_time, float blend_radius, bool is_cartesian) {
        std::promise<TrajectoryMotionResult> move_done_promise;
        driver_->setTrajectoryResultCallback([&](TrajectoryMotionResult result) { move_done_promise.set_value(result); });

        ELITE_LOG_INFO("Trajectory motion start");
        if (!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::START, target_points.size(), 200)) {
            ELITE_LOG_ERROR("Failed to start trajectory motion");
            return false;
        }

        for (const auto& joints : target_points) {
            if (!driver_->writeTrajectoryPoint(joints, point_time, blend_radius, is_cartesian)) {
                ELITE_LOG_ERROR("Failed to write trajectory point");
                return false;
            }
            // Send NOOP command to avoid timeout.
            if (!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::NOOP, 0, 200)) {
                ELITE_LOG_ERROR("Failed to send NOOP command");
                return false;
            }
        }

        std::future<TrajectoryMotionResult> move_done_future = move_done_promise.get_future();
        while (move_done_future.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready) {
            // Wait for the trajectory motion to complete, and send NOOP command to avoid timeout.
            if (!driver_->writeTrajectoryControlAction(ELITE::TrajectoryControlAction::NOOP, 0, 200)) {
                ELITE_LOG_ERROR("Failed to send NOOP command");
                return false;
            }
        }
        auto result = move_done_future.get();
        ELITE_LOG_INFO("Trajectory motion completed with result: %d", result);

        if (!driver_->writeIdle(0)) {
            ELITE_LOG_ERROR("Failed to write idle command");
            return false;
        }

        return result == TrajectoryMotionResult::SUCCESS;
    }

    bool moveTo(const vector6d_t& point, float time, bool is_cartesian) {
        return moveTrajectory({ point }, time, 0, is_cartesian);
    }
};

int main(int argc, const char** argv) {
    EliteDriverConfig config;
    if (argc == 2) {
        config.robot_ip = argv[1];
    }
    else if (argc == 3) {
        config.robot_ip = argv[1];
        config.local_ip = argv[2];
    }
    else {
        std::cout << "Must provide robot IP. Example: ./trajectory_example aaa.bbb.ccc.ddd <eee.fff.ggg.hhh>" << std::endl;
        return 1;
    }
    config.headless_mode = true;
    config.script_file_path = "external_control.script";
    std::unique_ptr<TrajectoryControl> trajectory_control = std::make_unique<TrajectoryControl>(config);
    std::unique_ptr<RtsiIOInterface> rtsi_client = std::make_unique<RtsiIOInterface>("output_recipe.txt", "input_recipe.txt", 250);

    ELITE_LOG_INFO("Connecting to the RTSI");
    if (!rtsi_client->connect(config.robot_ip)) {
        ELITE_LOG_FATAL("Fail to connect or config to the RTSI.");
        throw std::runtime_error("Fail to connect or config to the RTSI");
    }
    ELITE_LOG_INFO("Successfully connected to the RTSI");

    ELITE_LOG_INFO("Starting trajectory control...");
    if (!trajectory_control->startControl()) {
        ELITE_LOG_FATAL("Failed to start trajectory control.");
        return 1;
    }
    ELITE_LOG_INFO("Trajectory control started");

    vector6d_t actual_joints = rtsi_client->getActualJointPositions();
    actual_joints[3] = -1.57;

    ELITE_LOG_INFO("Moving joints to target: [%lf, %lf, %lf, %lf, %lf, %lf]",
        actual_joints[0], actual_joints[1], actual_joints[2], actual_joints[3], actual_joints[4], actual_joints[5]);
    if (!trajectory_control->moveTo(actual_joints, 3, false)) {
        ELITE_LOG_FATAL("Failed to move joints to target.");
        return 1;
    }
    ELITE_LOG_INFO("Joints moved to target");


    vector6d_t actual_pose = rtsi_client->getAcutalTCPPose();
    std::vector<vector6d_t> trajectory;

    actual_pose[2] -= 0.2;
    trajectory.push_back(actual_pose);


    actual_pose[1] -= 0.2;
    trajectory.push_back(actual_pose);

    actual_pose[1] += 0.2;
    actual_pose[2] += 0.2;
    trajectory.push_back(actual_pose);

    ELITE_LOG_INFO("Moving joints to target");
    if (!trajectory_control->moveTrajectory(trajectory, 3, 0, true)) {
        ELITE_LOG_FATAL("Failed to move trajectory.");
        return 1;
    }
    ELITE_LOG_INFO("Joints moved to target");

    return 0;
}
参考2.7 配置SDK到Visual Studio工程章节,编译项目,并拷贝相关库文件。
拷贝external_control.script编译结果“MoveExample.exe”的目录下。external_control.script文件在源代码的source/resources路径下。如果使用预编译包,此文件在resources目录下。
在编译结果“MoveExample.exe”目录下,创建output_recipe.txt文件,拷贝下面文本内容到文件中:
timestamp
payload_mass
payload_cog
script_control_line
target_joint_positions
target_joint_speeds
actual_joint_torques
actual_joint_positions
actual_joint_speeds
actual_joint_current
actual_TCP_pose
actual_TCP_speed
actual_TCP_force
target_TCP_pose
target_TCP_speed
actual_digital_input_bits
actual_digital_output_bits
joint_temperatures
robot_mode
joint_mode
safety_status
speed_scaling
target_speed_fraction
actual_robot_voltage
actual_robot_current
runtime_state
elbow_position
robot_status_bits
safety_status_bits
analog_io_types
standard_analog_input0
standard_analog_input1
standard_analog_output0
standard_analog_output1
io_current
tool_mode
tool_analog_input_types
tool_analog_output_types
tool_analog_input
tool_analog_output
tool_output_voltage
tool_output_current
tool_temperature
tool_digital_mode
tool_digital0_mode
tool_digital1_mode
tool_digital2_mode
tool_digital3_mode
output_bit_registers0_to_31
output_bit_registers32_to_63
input_bit_registers0_to_31
input_bit_registers32_to_63
创建input_recipe.txt文件,拷贝下面文本内容到文件中:
speed_slider_mask
speed_slider_fraction
standard_digital_output_mask
standard_digital_output
configurable_digital_output_mask
configurable_digital_output
tool_digital_output_mask
tool_digital_output
standard_analog_output_mask
standard_analog_output_type
standard_analog_output_0
standard_analog_output_1
external_force_torque
input_bit_registers0_to_31
input_bit_registers32_to_63
在Windows终端中执行下面指令运行结果,注意替换机器人IP和本机IP,以及确认机器人周围环境安全:
.\MoveExample.exe Your.Robot.IP.Addr Your.Local.IP.Addr
运行成功,机器人将会以当前位姿为起点,运行一个三角形轨迹。
可能出现的异常:
  1. 机器人没有运动,示教器提示:“socket_read_binary_integer”:未连接服务端“reverse_socket”。出现这个异常的原因是,机器人无法连接SDK的TCP服务端口。可以参考 “3.3.1 测试网络连接——使用机器人脚本” 章节最后的可能遇到的问题部分的描述。
  2. 机器人运动结束,示教器提示:“socket_read_binary_integer”:未连接服务端“script_command_socket”。此现象是程序在退出时出现了意外的问题,可以尝试升级SDK。此现象可以不用过多关注。
  3. 机器人运动过程中中断,机器人示教器日志栏提示:“Socket timed out waiting for command on reverse_socket. The script will exit now.”,或者提示:“socket_read_binary_integer”:未连接服务端“xxx_socket”。此现象是触发了SDK控制机器人的超时机制。可能有如下原因:
    • 运行SDK的电脑无法支撑与控制柜的数据传输速度。
    • 网络传输出现异常,例如网线松脱。
  4. 如果出现弹窗报告异常,可能有下面原因:
    • MoveExample.exe 同一目录下,是否正确拷贝了output_recipe.txtinput_recipe.txtexternal_control.script三个文件。
    • 分别使用下面指令查看端口是否被占用(注意,是TCP的端口):
      netstat -ano | findstr :50001
      netstat -ano | findstr :50002
      netstat -ano | findstr :50003
      netstat -ano | findstr :50004
      如果被占用了,需要结束掉占用的进程。
  5. 示教器提示:目标位姿为奇异位姿,机器人不可达。出现此现象,可以使用示教器手动调整机器人位姿到一个合理的范围内。

5. SDK示例

此SDK提供了主要功能的使用示例,可以通过连接获取到这些示例。
注意:这里的例子编译与运行依赖 boost 库的 program_options。
下面将对这些示例做简单的说明。
    • 功能:测试机器人与SDK是否可以连接。如果正常,将输出“Success, robot connected to PC”。
    • 运行:./connect_robot_test <--robot-ip=ip> [--local-ip=""]
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
    • 例子:./connect_robot_test --robot-ip=192.168.1.200 --local-ip=192.168.1.100
    • 功能:连接机器人的dashboard端口后进行如下操作:验证dashboard响应,机械臂下电、上电、释放抱闸,加载“test”任务,运行任务,暂停任务,停止任务,输出任务是否被保存。
    • 运行:./dashboard_example <--robot-ip=ip>
    • 参数:
      • --robot-ip arg :机器人IP
    • 例子:./dashboard_example --robot-ip=192.168.1.200
    • 功能:让机器人进入拖动模式。注意此示例需要手动将机器人上电与释放抱闸。
    • 运行:./freedrive_example <--robot-ip=ip> [--local-ip=""] [--use-headless-mode=true]
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:freedrive_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
    • 功能:从机器人的主端口(30001)获取机器人的运动学参数并打印。向机器人发送一个会触发运行时异常的脚本,捕获异常并打印。向机器人发送一个能正常运行的脚本,脚本功能是在机器人示教器“日志”栏打印“hello world”。
    • 运行:./primary_example <--robot-ip=ip>
    • 参数:
      • --robot-ip arg :机器人IP
    • 例子:./primary_example --robot-ip=192.168.1.200
    • 功能:连接机器人的RTSI服务,获取控制器版本信息并打印,设置标准数字IO 0为低电平,然后设置为高电平,并输出两次设置花费的时间。
    • 运行:./rtsi_example <--robot-ip=ip>
    • 参数:
      • --robot-ip arg :机器人IP
    • 例子:./rtsi_example --robot-ip=192.168.1.200
    • 功能:给机器人上电,释放抱闸,使用机器人的伺服透传功能让机器人在z轴上,向下沿直线运动约10cm后又向上沿直线运动约9cm。
    • 运行:./servoj_cartesian_example <--robot-ip=ip> [--local-ip=""] [--use-headless-mode=true]
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:./servoj_cartesian_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
    • 功能:给机器人上电,释放抱闸,使用机器人的伺服透传功能让机器人的第六关节旋转到 3 rad 后再旋转到 -3 rad。
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:./servoj_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
    • 功能:类似servoj_example.cpp,但旋转时增加了梯形波的速度规划。
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:./servoj_plan_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
  • 功能:给机器人上电,释放抱闸,使用机器人的speedj功能让末端关节以 -0.1 rad/s 的速度旋转约5秒,再以 0.1 rad/s 的速度旋转约5秒。
  • 参数:
    - --robot-ip arg :机器人IP
    - --local-ip arg:运行SDK电脑的IP(可选)
    - --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
  • 例子:./speedj_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
    • 功能:给机器人上电,释放抱闸,使用机器人的speedl功能让机器人在z轴方向,以 -0.02 rad/s 的速度运动约5秒,再以 0.02 rad/s 的速度运动约5秒。
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:./speedl_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode
    • 功能:给机器人上电,释放抱闸,让机器人以当前位姿为起点,运行一个三角形轨迹
    • 参数:
      • --robot-ip arg :机器人IP
      • --local-ip arg:运行SDK电脑的IP(可选)
      • --use-headless-mode=true:是否使用headless模式。(关于headless模式见5.1 常见问题
    • 例子:./trajectory_example --robot-ip=192.168.1.200 --local-ip=192.168.1.100 --use-headless-mode

5.1 运行示例常见问题

  • headless 模式,本意为无示教器模式,在这种模式下,不需要在机器人上运行“External Control”这个ELITECOs插件,程序会直接把EliteScript脚本发送给机器人执行。
  • 如果示教器出现报错:“socket_read_binary_integer:未连接服务器”,可以参考3.3.1 使用机器人脚本小节最后的“可能遇到的问题”。
  • 示教器出现“奇异点”的报警,大概率是运动开始时的位姿无法满足接下来要走的轨迹,可以手动将机器人移动到一个合适的位姿。

6. API 手册与用户指南

继续阅读下面的文档,可以帮助你详细了解CS机器人SDK的使用:
如果需要查看API的说明,可以查看下面的文档:
提交反馈