# Lite3_MotionSDK **Repository Path**: wj-ouxiang/Lite3_MotionSDK ## Basic Information - **Project Name**: Lite3_MotionSDK - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: add_python - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-29 - **Last Updated**: 2025-07-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 绝影Lite3运动控制SDK [English](./README.md) ## 目录 [1 SDK更新记录](#1-SDK更新记录) [2 SDK简介](#2-sdk简介) [3 SDK下载及解压](#3-sdk下载及解压) [4 确定运动主机地址用户名和密码](#4-确定运动主机地址用户名和密码) [5 配置数据上报地址和型号参数](#5-配置数据上报地址和型号参数) [6 配置sdk数据下发地址](#6-配置sdk数据下发地址) [7 编译开发](#7-编译开发) [7.1 检查通讯](#71-检查通讯) [7.2 通讯问题排查](#72-通讯问题排查) [7.3 编译环境检查](#73-编译环境检查) [7.4 编译开发](#74-编译开发) [8 示例代码](#8-示例代码) [其他注意事项](#其他注意事项)   ## 1 SDK更新记录 ### V1.0(2023-03-31) **[新增]** 首次发布。 ### V1.1(2023-05-16) **[新增]** ***received.h***中添加`RegisterCallBack`回调函数:目前仅支持在机器人数据每次更新时调用回调函数,对应的函数参数值,即`std::function CallBack_`中的`int`值为`0x0906`。 **[修改]** ***main.cpp***中打印的数据,由原先的关节力矩,改为陀螺仪角加速度。 ### V1.2(2024-12-24) **[新增]** 添加***add_python***分支,支持使用Python进行编译开发。   ## 2 SDK简介 **MotionSDK** 提供了低速端(即**关节端**)的5个控制参数接口: $pos_{goal}$, $vel_{goal}$, $kp$, $kd$, $t_{ff}$。 当SDK有指令下发时,底层控制器会优先执行SDK的控制指令,将指令分发给机器狗的12个关节。底层关节根据5个控制参数可计算出最终关节目标力为: $$T=kp*(pos_{goal} - pos_{real})+kd*(vel_{goal} - vel_{real})+t_{ff}$$ 驱动器端会将最终的关节目标力转化成期望电流,并以20kHz的频率进行闭环控制。 当SDK没有指令下发时,经过1s的超时判断后,底层控制器会拿回控制权,进入阻尼保护模式一段时间后,清空关节指令。 **控制流程可以参考下图:** **控制参数使用举例:** 当做纯位控即位置控制时,电机的输出轴将会稳定在一个固定的位置。例如,如果我们希望电机输出端固定在3.14弧度的位置,下发数据格式示例: $$pos_{goal}=3.14, vel_{goal}=0, kp=30, kd=0, t_{ff} = 0$$ 当做速度控制时,下发数据格式示例: $$pos_{goal}=0, vel_{goal}=5, kp=0, kd=1, t_{ff} = 0$$ 当做阻尼控制时,下发数据格式示例: $$pos_{goal}=0, vel_{goal}=0, kp=0, kd=1, t_{ff} = 0$$ 当做力矩控制时,下发数据格式示例: $$pos_{goal}=0, vel_{goal}=0, kp=0, kd=0, t_{ff} = 3$$ 当做零力矩控制时,下发数据格式示例: $$pos_{goal}=0, vel_{goal}=0, kp=0, kd=0, t_{ff} = 0$$ 当做混合控制时,下发数据格式示例: $$pos_{goal}=3.14, vel_{goal}=0, kp=30, kd=1, t_{ff} = 1$$   ## 3 SDK下载及解压 - 下载 **Lite3_MotionSDK-main**,并解压。(CPP版本) - 下载 **Lite3_MotionSDK-add_python**,并解压。(Python版本)   ## 4 确定运动主机地址、用户名和密码 ### 4.1 确定运动主机地址 - 如果通过WiFi连接,请查看开发主机分配到的IP: - 如果网段为1,则运动主机地址为**192.168.1.120**。 - 如果网段为2,则运动主机地址为**192.168.2.1**。 - 如果通过背部网口连接,则运动主机地址为**192.168.1.120**。 ### 4.2 确定用户名和密码 绝影Lite3的运动主机有三组可能的用户名和密码: |用户名|密码| | :------- | :-------- | |`ysc`|`'`(英文单引号)| |`user`|`123456`| |`firefly`|`firefly`| 请分别使用上述三组用户名尝试ssh连接到运动主机,以确定与其匹配的用户名和密码。   ## 5 配置数据上报地址和型号参数 开发者可通过ssh远程连接到运动主机,以配置运动主机上报关节等运动数据的目标地址。 - 首先开发者可通过机器人WiFi或背部网口将开发主机连入机器人局域网,然后在终端中使用上一步确定的运动主机用户名和运动主机地址ssh登录到运动主机: ```Bash ssh XXXXXX@192.168.X.XXX # ssh @ ``` - ssh登录运动主机后,在终端中输入以下命令以打开网络配置文件: ```Bash cd ~/jy_exe/conf vim network.toml ``` - 配置文件 ***network.toml*** 内容如下: ```toml ip = '192.168.1.102' # Motion host will send data to this IP address target_port = 43897 local_port = 43893 ``` - 修改配置文件第一行中的IP地址,使得 **MotionSDK** 能够接收到机器狗数据(运动主机地址参考第4节): - 如果 **MotionSDK** 在机器人运动主机内运行,IP设置为连接到的运动主机IP:`192.168.1.120`或`192.168.2.1`; - 如果 **MotionSDK** 在开发者自己的开发主机中运行,设置为开发主机的静态IP:`192.168.1.XXX`或`192.168.2.xxx`。 - 网络配置完成后,进行型号配置,首先需要检查运动程序版本,打开一个新的终端,输入以下命令(密码请参照第4节): ```Bash cd ~/jy_exe/scripts ./stop.sh ./run.sh ``` - 随后终端中会出现版本信息(如上图所示),若用户名为`user`(用户名请参照第4节)且**Deeprcs Version**早于**1.4.24(97)**,或者用户名为`firefly`且**Deeprcs Version**早于**1.4.21(94)**,则需要检查配置文件***name.toml***: - 打开一个新的终端,输入以下命令: ```Bash cd ~/jy_exe/conf vim name.toml ``` - 配置文件***name.toml***内容如下: ```Bash name = standard_1 ``` - 将name值配置为standard_2。 - 若终端中出现的信息如下图所示,则无需更改配置文件***name.toml***,关闭当前终端。如需打印日志信息,可打开一个新的终端,输入以下命令(密码参照第4节): ```Bash cd ~/jy_exe/scripts ./show_log.sh ``` - 重启运动程序使配置生效: ```bash cd ~/jy_exe/scripts sudo ./stop.sh sudo ./restart.sh ```   ## 6 配置sdk数据下发地址 - C++版本:***main.cpp***中第39行代码创建了一个sdk向机器狗运动主机下发控制指令的发送线程: ```c++ Sender* send_cmd = new Sender("192.168.1.120",43893); ///< Create send thread ``` - Python版本:***/Lite3_MotionSDK-add_python/python/example.py***中第27行代码创建了一个sdk向机器狗运动主机下发控制指令的发送线程: ```python sender = dr.Sender('192.168.1.120', 43893) ``` 请根据第4节中确定的运动主机地址修改`Sender()`中的目标IP。   ## 7 编译开发 ***main.cpp***中提供了机器狗站立的简单demo,并在完成站立一段时间后将控制权归还给底层控制器,进入阻尼保护模式: **但为了确保SDK的安全使用,在*main.cpp*的原始代码中,第73行的下发指令代码是被注释掉的,因此机器狗默认只会回零但不会起立:** ```c++ //send_cmd->SendCmd(robot_joint_cmd); ``` > 注意:在取消注释前,开发者务必确保SDK与机器狗正常通讯(可参考“7.1 检查通讯”),并确保自己的下发控制指令正确,否则机器狗执行控制指令时可能会产生危险! ### 7.1 检查通讯 MotionSDK采用UDP与机器狗进行通讯。 针对数据上报,可以在SDK里打印关节数据或陀螺仪数据等信息,以此判断是否收到机器狗上报的SDK数据;或者观察SDK运行时,是否打印connection refused,以此判断是否收到机器狗上报的SDK数据。 针对指令下发,如果SDK运行后,机器狗做出回零动作,则证明SDK能成功下发指令到机器狗本体。 - 首先对未取消下发指令注释的代码进行编译。 > 注意:编译前可以取消注释***main.cpp***原始代码中的第75行 `cout << robot_data->imu.acc_x << endl`,使SDK打印imu数据,以此判断是否收到机器狗上报的数据。 - 进入解压得到的文件夹,在***CMakeLists.txt*** 的同级目录下新建 ***build*** 文件夹; ```bash cd xxxxxxxx # cd mkdir build ``` > 注意:开发者可在任何地方创建 ***build*** 文件夹,但在编译时,`cmake` 指令须指向 ***CMakeLists.txt*** 所在的路径。 - 打开 ***build*** 文件夹并编译; - 如果主机是x86架构,在终端中输入: ```bash cd build cmake .. -DBUILD_PLATFORM=x86 # cmake make -j ``` - 如果主机是ARM架构,在终端中输入: ```bash cd build cmake .. -DBUILD_PLATFORM=arm # cmake make -j ``` - 编译结束后,会在 ***build*** 目录下生成一个名为 ***Lite_motion*** 的可执行文件,此即为我们代码编译出来的结果; - 在终端中继续输入以下命令行以运行程序(运行前请确保开发主机已连入机器狗网络): ```bash ./Lite_motion ``` > 注意:为使机器狗能够顺利回零,请在运行程序前将机器狗调整到准备姿势。 - 观察程序运行过程中机器狗是否回零,以及终端中打印机器狗上报数据是否正常。 ### 7.2 通讯问题排查 如果SDK未接收到机器狗上报的数据,可按照下述步骤进行排查: - 首先检查开发主机是否与机器狗主机处于同一网段下(如果是在机器狗上运行SDK,此步骤可跳过):将开发主机连到接机器狗的WiFi网络或背部网口,然后在开发主机上ping运动主机(运动主机地址参考第4节),ping通之后ssh连接到机器狗运动主机内,在运动主机内ping开发主机的静态IP。如果无法ping通,请尝试手动设置自己开发主机的IP地址,并再次按照第5节对配置文件进行修改。 - 如果开发者的开发环境为虚拟机,建议把虚拟机网络连接方式改为桥接并手动设置虚拟机IP地址后重启虚拟机,并再次按照第5节对配置文件进行修改。 如果仍收不到机器狗上报数据,可在机器狗运动主机上抓包: - 如果 **MotionSDK** 在机器人运动主机内运行,I运行`sudo tcpdump -x port 43897 -i lo`; - 如果运动主机用户名为`user`(用户名请参照第4节),**MotionSDK** 在开发者的开发主机内运行,且开发主机通过WiFi与机器狗连接,运行`sudo tcpdump -x port 43897 -i p2p0`; - 如果运动主机用户名为`user`,**MotionSDK** 在开发者的开发主机内运行,且开发主机通过背部网口与机器狗连接,运行`sudo tcpdump -x port 43897 -i eth1`; - 如果运动主机用户名为`firefly`,且 **MotionSDK** 在开发者的开发主机内运行,运行`sudo tcpdump -x port 43897 -i eth0`。 执行抓包命令后等待2分钟,观察机器狗是否有原始数据上报。如果没有,输入top命令查看机器狗本体控制程序进程jy_exe是否正常运行,若jy_exe没有正常运行,参照以下指令重启运动程序: ```bash cd ~/jy_exe sudo ./stop.sh sudo ./restart.sh ``` ### 7.3 编译环境检查 在使用Python版本进行编译前,需要检查环境是否包含编译所需的包。参照以下步骤进行检查: ```bash python3 # 进入Python环境 help("modules") # 检查Python环境包含的包 ``` 若Python环境不包含编译所需的包,则需要将机器狗连接至公网,参照以下步骤进行: ```bash sudo nmcli dev wifi #列出机器狗检索到的WiFi sudo nmcli dev wifi connect "Your WiFi name" password "Your WiFi password" ifname wlan0 #将机器狗连接至公网,需要将引号中的Your WiFi name与Your WiFi password改为WiFi的名称与密码 ``` > 注意:若将机器狗连接至可访问公网的WiFi后,机器狗任然无法访问公网,请尝试删除`/etc/netplan/config.yaml`文件中的`gateway4`行,再检查机器狗是否能访问公网。 将机器狗成功连接至公网后,使用***apt***与***pip***安装所需的包,参照以下步骤进行: ```bash sudo apt-get install pip3 #使用apt-get下载安装pip3包 pip3 install numpy #使用pip3下载安装numpy ``` Python包含编译所需的包后,则可进行下一步的编译开发。 ### 7.4 编译开发 确保SDK与机器狗正常通讯,并确保自己的下发控制指令正确后,可以将 ***main.cpp***原始代码中第73行的下发指令代码`send_cmd->SendCmd(robot_joint_cmd)`取消注释,然后重新编译运行: #### 7.4.1 C++版本编译运行 - 删除之前生成的构建文件夹***build***: - 打开一个新的终端,新建一个空的 ***build*** 文件夹; ```bash cd xxxxxxxx # cd mkdir build ``` - 打开 ***build*** 文件夹并编译; - 如果主机是x86架构,在终端中输入: ```bash cd build cmake .. -DBUILD_PLATFORM=x86 # cmake make -j ``` - 如果主机是ARM架构,在终端中输入: ```bash cd build cmake .. -DBUILD_PLATFORM=arm # cmake make -j ``` - 编译结束后,会在 ***build*** 目录下生成一个名为 ***Lite_motion*** 的可执行文件,运行该文件时,机器狗将会执行下发的控制指令: ```bash ./Lite_motion ``` #### 7.4.2 Python版本编译运行 - 删除之前生成的构建文件夹***build***: - 打开一个新的终端,新建一个空的 ***build*** 文件夹; ```bash cd xxxxxxxx # cd mkdir build ``` - 打开 ***build*** 文件夹并编译; 在终端中输入: ```bash cd build cmake .. -DBUILD_PYTHON=ON make -j ``` - 正常情况下编译好的动态库文件会自动复制到 `/python/lib` 目录下,随后可以进入 `/Lite3_MotionSDK-add_python/python` 目录直接执行 ***example.py*** 文件: ```bash cd python/ python3 example.py ``` > 注意:用户在使用Lite3执行算法和实验的过程中,请与机器狗保持至少5米距离,并将机器狗悬挂在调试架上避免意外造成人员和设备损伤。若实验过程中,机器狗摔倒或者用户想搬动机器狗位置,需要靠近机器狗时,用户应当使得机器狗处于急停状态或者使用 `sudo ./stop.sh` 命令关闭运动程序。   ## 8 示例代码 本节对 ***main.cpp*** 进行说明。 定时器,用于设置算法周期,获得当前时间: ```cpp DRTimer set_timer; set_timer.TimeInit(int); ///< Timer initialization, input: cycle; unit: ms set_timer.GetCurrentTime(); ///< Obtain time for algorithm set_timer.TimerInterrupt() ///< Timer interrupt flag set_timer.GetIntervalTime(double); ///< Get the current time ``` SDK在绑定机器人的IP和端口后,获取控制权,发送关节控制指令: ```cpp Sender* send_cmd = new Sender("192.168.1.120",43893); ///< Create a sender thread send_cmd->RobotStateInit(); ///< Reset all joints to zero and gain control right send_cmd->SetSend(RobotCmd); ///< Send joint control command send_cmd->ControlGet(int); ///< Return the control right ``` SDK接收机器人下发的关节数据: ```cpp Receiver* robot_data_recv = new Receiver(); ///< Create a thread for receiving and parsing robot_data_recv->GetState(); ///< Receive data from 12 joints robot_data_recv->RegisterCallBack(CallBack); ///< Registering Callbacks ``` SDK接收到的关节数据将保存在`robot_data`中: ```cpp RobotData *robot_data = &robot_data_recv->GetState(); ///< Saving joint data to the robot_data ///< Left front leg:fl_leg[3], the sequence is FL_HipX, FL_HipY, FL_Knee ///< Right front leg:fr_leg[3], the sequence is FR_HipX, FR_HipY, FR_Knee ///< Left hind leg:hl_leg[3], the sequence is HL_HipX, HL_HipY, HL_Knee ///< Right hind leg:hr_leg[3], the sequence is HR_HipX, HR_HipY, HR_Knee ///< All joints:leg_force[12]/joint_data[12], the sequence is FL_HipX, FL_HipY, FL_Knee, FR_HipX, FR_HipY, FR_Knee, HL_HipX, HL_HipY, HL_Knee, HR_HipX, HR_HipY, HR_Knee robot_data->contact_force.fl_leg[] ///< Contact force on left front foot in X-axis, Y-axis and Z-axis robot_data->contact_force.fr_leg[] ///< Contact force on right front foot in X-axis, Y-axis and Z-axis robot_data->contact_force.hl_leg[] ///< Contact force on left hind foot in X-axis, Y-axis and Z-axis robot_data->contact_force.hr_leg[] ///< Contact force on right hind foot in X-axis, Y-axis and Z-axis robot_data->contact_force.leg_force[] ///< Contact force on all feet robot_data->tick ///< Cycle of operation robot_data->imu ///< IMU data robot_data->imu.acc_x ///< Acceleration on X-axis robot_data->imu.acc_y ///< Acceleration on Y-axis robot_data->imu.acc_z ///< Acceleration on Z-axis robot_data->imu.angle_pitch ///< Pitch angle robot_data->imu.angle_roll ///< Roll angle robot_data->imu.angle_yaw ///< Yaw angle robot_data->imu.angular_velocity_pitch ///< Pitch angular velocity robot_data->imu.angular_velocity_roll ///< Roll angular velocity robot_data->imu.angular_velocity_yaw ///< Yaw angular velocity robot_data->imu.buffer_byte ///< Buffer data robot_data->imu.buffer_float ///< Buffer data robot_data->imu.timestamp ///< Time when the data is obtained robot_data->joint_data ///< Motor status robot_data->joint_data.fl_leg[].position ///< Motor position of left front leg robot_data->joint_data.fl_leg[].temperature ///< Motor temperature of left front leg robot_data->joint_data.fl_leg[].torque ///< Motor torque of left front leg robot_data->joint_data.fl_leg[].velocity ///< Motor velocity of left front leg robot_data->joint_data.joint_data ///< All joint data ``` 机器人关节控制指令: ```cpp RobotCmd robot_joint_cmd; ///< Target data of each joint ///< Left front leg:fl_leg[3], the sequence is FL_HipX, FL_HipY, FL_Knee ///< Right front leg:fr_leg[3], the sequence is FR_HipX, FR_HipY, FR_Knee ///< Left hind leg:hl_leg[3], the sequence is HL_HipX, HL_HipY, HL_Knee ///< Right hind leg:hr_leg[3], the sequence is HR_HipX, HR_HipY, HR_Knee ///< All joints:leg_force[12]/joint_data[12], the sequence is FL_HipX, FL_HipY, FL_Knee, FR_HipX, FR_HipY, FR_Knee, HL_HipX, HL_HipY, HL_Knee, HR_HipX, HR_HipY, HR_Knee robot_joint_cmd.fl_leg[]->kd; ///< Kd of left front leg robot_joint_cmd.fl_leg[]->kp; ///< Kp of left front leg robot_joint_cmd.fl_leg[]->position; ///< Position of left front leg robot_joint_cmd.fl_leg[]->torque; ///< Torue of left front leg robot_joint_cmd.fl_leg[]->velocity; ///< Velocity of left front leg ``` 机器人站立的简单demo: 1. 将机器人腿收起来(回零),为站立做准备; 2. 记录下当前时间与关节数据; 3. 机器人起立。 ```cpp MotionExample robot_set_up_demo; ///< Demo for testing /// @brief Spend 1 sec drawing the robot's legs in and preparing to stand /// @param cmd Send control command /// @param time Current timestamp /// @param data_state Real-time status data of robot robot_set_up_demo.PreStandUp(robot_joint_cmd,now_time,*robot_data); /// @brief Only the current time and angle are recorded /// @param data Current joint data /// @param time Current timestamp robot_set_up_demo.GetInitData(robot_data->motor_state,now_time); /// @brief Spend 1.5 secs standing up /// @param cmd Send control command /// @param time Current timestamp /// @param data_state Real-time status data of robot robot_set_up_demo.StandUp(robot_joint_cmd,now_time,*robot_data); ```   ## 其他注意事项 1. Lite3运动主机是ARM架构的,如果开发者想在运动主机上运行自己的程序,需要注意。 2. WiFi通讯受网络环境干扰产生的通讯延迟波动,可能对控制频率在500Hz以上的控制器有一定的影响。