新松机械臂 2001端口服务的客户端例程

article/2025/7/31 19:39:08

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客

C#是我多年以来的业余爱好,新搞的东西能用C#的就用C#了。


        新松机械臂报告状态的端口是2001,每100毫秒报告一次状态,每次报告数据长度1468字节。

        这个端口只用来报告状态,控制则使用2000端口。

        获取状态非常简单,连接上去,读取数据,按照格式拆分数据即可。具体数据数据格式见开发手册。

目录

一、C++头文件

二、main函数

三、核心代码

四、运行


 

一、C++头文件

         只需要使用C++头文件DucoRobat.h即可。其实并不需要这个头文件,本例程中引入是因为借用了里面定义好的状态结构而已:

// 机器人相关信息
struct RobotStatusList
{std::vector<double>  jointExpectPosition;   // 目标关节位置std::vector<double>  jointExpectVelocity;   // 目标角速度std::vector<double>  jointExpectAccelera;   // 目标角加速度std::vector<double>  jointActualPosition;   // 实际关节位置std::vector<double>  jointActualVelocity;   // 实际角速度std::vector<double>  jointActualAccelera;   // 实际角加速度std::vector<double>  jointActualCurrent;    // 实际关节电流std::vector<double>  jointTemperature;      // 时间关节温度std::vector<double>  driverTemperature;     // 未使用std::vector<double>  cartExpectPosition;    // 目标末端位姿std::vector<double>  cartExpectVelocity;    // 目标末端速度std::vector<double>  cartExpectAccelera;    // 目标末端加速度std::vector<double>  cartActualPosition;    // 实际末端位姿std::vector<double>  cartActualVelocity;    // 实际末端速度std::vector<double>  cartActualAccelera;    // 实际末端加速度std::vector<bool>    slaveReady;            // 从站状态bool    collision;       // 是否发生碰撞int8_t  collisionAxis;   // 发生碰撞的关节bool    emcStopSignal;   // 未使用int8_t  robotState;      // 机器人状态int32_t robotError;      // 机器人错误码
};

二、main函数

int main(int argc, char** argv)
{if (!InitActiveApp("DOUCO", 1024 * 1024 * 10, argc, argv))return 1;thelog << "新松机器人 TCP及IP接口" << endi;WORD sockVersion = MAKEWORD(1, 1);WSADATA wsaData;if (WSAStartup(sockVersion, &wsaData) != 0){return 0;}bool bExitCmd = false;thread t(CMyDUCO::VirtualServer, &bExitCmd);//模拟服务SleepSeconds(1);CMyDUCO myduco;string ip = "127.0.0.1";//正式使用修改为设备实际IPthelog << "连接 " << ip << " ......"<< endi;if (!myduco.Recv(ip.c_str())){thelog << "连接到 " << ip << " 失败" << ende;}else{myduco.ProcessFrame();myduco.Print();myduco.Save();}while (true)SleepSeconds(5);bExitCmd = true;t.join();WSACleanup();return 0;
}

        这个代码默认访问自带的模拟服务,实际使用修改目标IP(代码中已标注)。

三、核心代码

// DUCO.h : 新松机器人 TCP及IP接口
//#include <iostream>
//#include "DucoCobot.h"
//using namespace DucoRPC;
using namespace std;
#include "env/myUtil.h"
#include "function/htmldoc.h"
#include "function/mysocket.h"
using namespace ns_my_std;#pragma comment(lib,"ws2_32.lib")
// 机器人相关信息
struct RobotStatusList
{std::vector<double>  jointExpectPosition;   // 目标关节位置std::vector<double>  jointExpectVelocity;   // 目标角速度std::vector<double>  jointExpectAccelera;   // 目标角加速度std::vector<double>  jointActualPosition;   // 实际关节位置std::vector<double>  jointActualVelocity;   // 实际角速度std::vector<double>  jointActualAccelera;   // 实际角加速度std::vector<double>  jointActualCurrent;    // 实际关节电流std::vector<double>  jointTemperature;      // 时间关节温度std::vector<double>  driverTemperature;     // 未使用std::vector<double>  cartExpectPosition;    // 目标末端位姿std::vector<double>  cartExpectVelocity;    // 目标末端速度std::vector<double>  cartExpectAccelera;    // 目标末端加速度std::vector<double>  cartActualPosition;    // 实际末端位姿std::vector<double>  cartActualVelocity;    // 实际末端速度std::vector<double>  cartActualAccelera;    // 实际末端加速度std::vector<bool>    slaveReady;            // 从站状态bool    collision;       // 是否发生碰撞int8_t  collisionAxis;   // 发生碰撞的关节bool    emcStopSignal;   // 未使用int8_t  robotState;      // 机器人状态int32_t robotError;      // 机器人错误码
};constexpr int frame_size = 1468;
class CMyDUCO
{
private:int32_t _getUInt(int byte_pos){if (4 != sizeof(int32_t))throw "4 != sizeof(int32_t)";int32_t tmp;memcpy(&tmp, frame + byte_pos, sizeof(int32_t));return tmp;}float _getFloat(int byte_pos){if (4 != sizeof(float))throw "4 != sizeof(float)";float tmp;memcpy(&tmp, frame + byte_pos, sizeof(float));return tmp;}void _FloatX(vector<double>& vd7, int count, int byte_pos){vd7.clear();for (int i = 0; i < count; ++i){vd7.push_back(_getFloat(byte_pos + i * 4));}}union{char frame[frame_size];float _;}m_frame;char* frame = m_frame.frame;RobotStatusList m_RobotStatusList;
public:bool Save(){CEasyFile file;for (int i = 0; i < 100; ++i){char buf[256];sprintf(buf, "data%03d.dat", i);if (file.IsFileExist(buf))continue;return file.WriteFile(buf, frame, frame_size);}thelog << "已经存在的文件太多" << ende;return false;}void ProcessFrame(){// 目标关节位置_FloatX(m_RobotStatusList.jointExpectPosition, 7, 112);// 目标角速度_FloatX(m_RobotStatusList.jointExpectVelocity, 7, 140);// 目标角加速度_FloatX(m_RobotStatusList.jointExpectAccelera, 7, 168);// 实际关节位置_FloatX(m_RobotStatusList.jointActualPosition, 7, 0);// 实际角速度_FloatX(m_RobotStatusList.jointActualVelocity, 7, 28);// 实际角加速度_FloatX(m_RobotStatusList.jointActualAccelera, 7, 56);// 实际关节电流_FloatX(m_RobotStatusList.jointActualCurrent, 7, 252);// 实际关节温度_FloatX(m_RobotStatusList.jointTemperature, 7, 224);// 目标末端位姿_FloatX(m_RobotStatusList.cartExpectPosition, 6, 464);// 目标末端速度_FloatX(m_RobotStatusList.cartExpectVelocity, 6, 488);// 目标末端加速度_FloatX(m_RobotStatusList.cartExpectAccelera, 6, 512);// 实际末端位姿_FloatX(m_RobotStatusList.cartActualPosition, 6, 368);// 实际末端速度_FloatX(m_RobotStatusList.cartActualVelocity, 6, 392);// 实际末端加速度_FloatX(m_RobotStatusList.cartActualAccelera, 6, 416);// 是否发生碰撞m_RobotStatusList.collision = (1 == frame[1452]);// 发生碰撞的关节m_RobotStatusList.collisionAxis = frame[1453];// 机器人状态m_RobotStatusList.robotState = frame[1449];// 机器人错误码m_RobotStatusList.robotError = _getUInt(1456);}void Random(){static int base = 0;float* p = &m_frame._;for (int i = 0; i < frame_size / 4; ++i){p[i] = base+i;}++base;// 是否发生碰撞frame[1452] = 1;// 发生碰撞的关节frame[1453] = 6;// 机器人状态frame[1449] = 9;// 机器人错误码*(int32_t*)&frame[1456] = 10;}void _PrintV(CHtmlDoc::CHtmlTable2 &table,vector<double> & vectorD, char const* title){table.AddLine();table.AddData(title);for (auto v : vectorD){table.AddData(v, 2);}}void Print(){CHtmlDoc::CHtmlTable2 table;table.AddCol("名称");for (int i = 0; i < 7; ++i){char buf[32];sprintf(buf, "关节%d", i + 1);table.AddCol(buf, CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);}_PrintV(table, m_RobotStatusList.jointExpectPosition, "目标关节位置");_PrintV(table, m_RobotStatusList.jointExpectVelocity, "目标角速度");_PrintV(table, m_RobotStatusList.jointExpectAccelera, "目标角加速度");_PrintV(table, m_RobotStatusList.jointActualPosition, "实际关节位置");_PrintV(table, m_RobotStatusList.jointActualVelocity, "实际角速度");_PrintV(table, m_RobotStatusList.jointActualAccelera, "实际角加速度");_PrintV(table, m_RobotStatusList.jointActualCurrent, "实际关节电流");_PrintV(table, m_RobotStatusList.jointTemperature, "时间关节温度");_PrintV(table, m_RobotStatusList.driverTemperature, "未使用");_PrintV(table, m_RobotStatusList.cartExpectPosition, "目标末端位姿");_PrintV(table, m_RobotStatusList.cartExpectVelocity, "目标末端速度");_PrintV(table, m_RobotStatusList.cartExpectAccelera, "目标末端加速度");_PrintV(table, m_RobotStatusList.cartActualPosition, "实际末端位姿");_PrintV(table, m_RobotStatusList.cartActualVelocity, "实际末端速度");_PrintV(table, m_RobotStatusList.cartActualAccelera, "实际末端加速度");theLog << table.MakeTextTable() << endi;theLog << endl << m_RobotStatusList.collision << " 是否发生碰撞" << endl;theLog << (int)m_RobotStatusList.collisionAxis << " 发生碰撞的关节" << endl;theLog << (int)m_RobotStatusList.robotState << " 机器人状态" << endl;theLog << m_RobotStatusList.robotError << " 机器人错误码" << endi;}//接收数据bool Recv(char const * ip){CMySocket s;if (!s.Connect(ip, 2001)){thelog << "连接失败 "<<ip << ende;return false;}thelog << "连接成功 " << ip << endi;int count = 0;while (count != frame_size){long readCount = 0;if (!s.Recv(frame + count, frame_size - count, &readCount)){thelog << "接收失败 " << ip << ende;s.Close();return false;}thelog << readCount<<" 收到数据 " << count << endi;count += readCount;}thelog << "收到数据 " << count << endi;s.Close();return count == frame_size;}//虚拟服务static void VirtualServer(bool * pExitCmd){thelog.SetSource("TEST SERVER");CMySocket s;if (!s.Listen(2001)){thelog << "监听端口2001失败" << ende;exit(1);}thelog << "服务已创建" << endi;while (!*pExitCmd){bool tmp_bool;if (!s.IsSocketReadReady(1, tmp_bool)){thelog << "IsSocketReadReady失败" << ende;exit(1);}if (!tmp_bool)continue;CMySocket client_socket = s.Accept();if (!client_socket.IsConnected()){thelog << "Accept失败" << ende;exit(1);}thelog << "Accept成功" << endi;CMyDUCO myDUCO;myDUCO.Random();client_socket.Send(myDUCO.frame, frame_size);client_socket.Close();}s.Close();thelog << "服务结束" << endi;}
};

        这个代码已经把所需的结构直接放进来了,不需要包含DucoRobat.h。

        代码主要功能:

  • Save 保存到当前目录
  • ProcessFrame 解析收到的数据
  • Random 用于模拟服务生成数据,其实并不是随机,而是递增
  • Print 输出表格
  • Recv 接收数据
  • VirtualServer 内置模拟服务

四、运行

        运行起来结果如下:

[05-30 11:13:55][应用][信息][C:\working\IoT\DUCO\main_t.cpp:  12(main)][  0.00]新松机器人 TCP及IP接口
[05-30 11:13:55][TEST SERVER][12824- 1][信息][C:\working\IoT\DUCO\myDUCO.h: 230(VirtualServer)][  0.02]服务已创建
[05-30 11:13:56][应用][12824][信息][C:\working\IoT\DUCO\main_t.cpp:  27(main)][  1.01]连接 127.0.0.1 ......
[05-30 11:13:56][应用][12824][信息][C:\working\IoT\DUCO\myDUCO.h: 199(Recv)][  1.01]连接成功 127.0.0.1
[05-30 11:13:56][TEST SERVER][12824- 1][信息][C:\working\IoT\DUCO\myDUCO.h: 247(VirtualServer)][  1.01]Accept成功
[05-30 11:13:56][应用][12824][信息][C:\working\IoT\DUCO\myDUCO.h: 211(Recv)][  1.01]1468 收到数据 0
[05-30 11:13:56][应用][12824][信息][C:\working\IoT\DUCO\myDUCO.h: 215(Recv)][  1.01]收到数据 1468
[05-30 11:13:56][应用][12824][信息]
名称            关节1  关节2  关节3  关节4  关节5  关节6 关节7
-------------- ------ ------ ------ ------ ------ ------ -----
目标关节位置    28.00  29.00  30.00  31.00  32.00  33.00 34.00
目标角速度      35.00  36.00  37.00  38.00  39.00  40.00 41.00
目标角加速度    42.00  43.00  44.00  45.00  46.00  47.00 48.00
实际关节位置     0.00   1.00   2.00   3.00   4.00   5.00  6.00
实际角速度       7.00   8.00   9.00  10.00  11.00  12.00 13.00
实际角加速度    14.00  15.00  16.00  17.00  18.00  19.00 20.00
实际关节电流    63.00  64.00  65.00  66.00  67.00  68.00 69.00
时间关节温度    56.00  57.00  58.00  59.00  60.00  61.00 62.00
未使用
目标末端位姿   116.00 117.00 118.00 119.00 120.00 121.00
目标末端速度   122.00 123.00 124.00 125.00 126.00 127.00
目标末端加速度 128.00 129.00 130.00 131.00 132.00 133.00
实际末端位姿    92.00  93.00  94.00  95.00  96.00  97.00
实际末端速度    98.00  99.00 100.00 101.00 102.00 103.00
实际末端加速度 104.00 105.00 106.00 107.00 108.00 109.00
-------------- ------ ------ ------ ------ ------ ------ -----[05-30 11:13:56][应用][12824][信息]
1 是否发生碰撞
6 发生碰撞的关节
9 机器人状态
10 机器人错误码

        其实相当简单。


(这里是文档结束)


http://www.hkcw.cn/article/GSvtQRWmQK.shtml

相关文章

HarmonyOS-ArkUI固定样式弹窗(1)

固定样式弹窗指的就是ArkUI中为我们提供的一些具备界面模板性质的弹窗。样式是固定的,我们可以决定在这些模板里输入什么样的内容。常见的有,警告弹窗, 列表选择弹窗, 选择器弹窗,对话框,操作菜单。 下图是本文中要讲到的基类固定样式弹窗,其中选择器弹窗没有包含在内,…

Dify运行本地和在线模型

1、运行本地模型 1.1、下载Ollama 官网下载&#xff1a;Ollama 1.2、安装LLM大模型 Ollama官网搜索模型&#xff0c;复制命令&#xff1a; 在终端中粘贴下载&#xff0c;下载完成后可以输入对话&#xff0c;表示安装成功。 使用命令&#xff1a;ollama list 可以列出已经安装…

manus对比ChatGPT-Deep reaserch进行研究类论文数据分析!谁更胜一筹?

目录 没有账号&#xff0c;只能挑选一个案例 1、manus的效果 Step-1&#xff1a;直接看结果 Step-2&#xff1a;看看其他文件的细节 Step-3&#xff1a;看最终报告 2、Deep reaserch 3、Deep reaserch进行行业分析 总结一下&#xff1a; 大家好这里是学术Anan&#xff…

2025年大一ACM训练-尺取

2025年大一ACM训练-尺取 ​​尺取法&#xff08;Sliding Window&#xff09;&#xff1a; ​​1. 基本概念​​   尺取法&#xff08;又称滑动窗口法&#xff09;是一种​​通过维护窗口的左右边界来高效解决子区间问题​​的算法技巧&#xff0c;常用于&#xff1a;   1…

第十二章 MQTT会话

系列文章目录 第一章 总体概述 第二章 在实体机上安装ubuntu 第三章 Windows远程连接ubuntu 第四章 使用Docker安装和运行EMQX 第五章 Docker卸载EMQX 第六章 EMQX客户端MQTTX Desktop的安装与使用 第七章 EMQX客户端MQTTX CLI的安装与使用 第八章 Wireshark工具的安装与使用 …

【C++】C++入门基础

本文是小编巩固自身而作&#xff0c;如有错误&#xff0c;欢迎指出&#xff01; 1.C的第一个程序 C兼容C语⾔绝⼤多数的语法&#xff0c;所以C语⾔实现的hello world依旧可以运⾏&#xff0c;C中需要把定义⽂件 代码后缀改为.cpp&#xff0c;vs编译器看到是.cpp就会调⽤C编译…

iEKF的二维应用实例

如果熟悉 EKF 与卡尔曼的推导的话&#xff0c;iEKF 就比较容易理解&#xff0c;关于卡尔曼滤波的推导以及EKF&#xff0c;可以参考以前的文章&#xff1a; 卡尔曼滤波原理&#xff1a;https://blog.csdn.net/a_xiaoning/article/details/130564473?spm1001.2014.3001.5502 E…

[IMX] 10.串行外围设备接口 - SPI

代码链接&#xff1a;GitHub - maoxiaoxian/imx 参考资料&#xff1a; https://zhuanlan.zhihu.com/p/290620901 SPI协议详解 - bujidao1128 - 博客园 SPI总线协议及SPI时序图详解 - Ady Lee - 博客园 目录 1.SPI 简介 2.I.MX6U ECSPI 简介 2.1.控制寄存器 1 - ECSPIx_CO…

评论功能开发全解析:从数据库设计到多语言实现-优雅草卓伊凡

评论功能开发全解析&#xff1a;从数据库设计到多语言实现-优雅草卓伊凡 一、评论功能的核心架构设计 评论功能看似简单&#xff0c;实则涉及复杂的业务逻辑和技术考量。一个完整的评论系统需要支持&#xff1a;内容评论、回复评论、评论点赞、评论排序、敏感词过滤等功能。 …

计算机视觉入门:OpenCV与YOLO目标检测

计算机视觉入门&#xff1a;OpenCV与YOLO目标检测 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 计算机视觉入门&#xff1a;OpenCV与YOLO目标检测摘要引言技术原理对比1. OpenCV&#xff1a;传统图像处理与机器学…

C语言进阶--自定义类型详解(结构体、枚举、联合)

1.结构体 1.1结构体的声明 1.1.1结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.1.2结构的声明 struct tag {member-list; }variable-list;struct Stu {//学生的属性char name[20];int age; };struct Stu {…

asio之async_result

简介 async_result用来表示异步处理返回类型 async_result 是类模板 type&#xff1a;为类模板中声明的类型&#xff0c;对于不同的类型&#xff0c;可以使用类模板特例化&#xff0c;比如针对use_future

Hash 的工程优势: port range 匹配

昨天和朋友聊到 “如何匹配一个 port range”&#xff0c;觉得挺有意思&#xff0c;简单写篇散文。 回想起十多年前&#xff0c;我移植并优化了 nf-HiPAC&#xff0c;当时还看不上 ipset hash&#xff0c;后来大约七八年前&#xff0c;我又舔 nftables&#xff0c;因为用它可直…

力扣HOT100之动态规划:198. 打家劫舍

这道题之前刷代码随想录的时候做过&#xff0c;这一次直接一遍过了&#xff0c;还是按照动规五部曲&#xff1a; 1.确定dp[i]的含义:将下标为0 ~ i的房子纳入考虑范围时所能取到的最大收益 2.确定递推公式:dp[i] max(dp[i - 2] nums[i], dp[i - 1]); 3.dp数组初始化:dp[0] n…

基于VU37P的高性能采集板卡

基于VU37P的高性能采集板卡是一款最大可提供20路ADC接收通道的高性能采集板卡。每路A/D通道支持1GS/s的采样率&#xff0c;分辨率为14bit&#xff0c;模拟输入带宽可达500MHz&#xff0c;交流耦合&#xff0c;输入阻抗50欧姆。 产品简介 可提供20路ADC接收通道的高性能采集板…

使用ssh-audit扫描ssh过期加密算法配置

使用ssh-audit扫描ssh过期加密算法配置 安装检查ssh的加密算法配置修改ssh的加密算法配置 安装 # pip3安装ssh-audit pip3 instal ssh-audit检查ssh的加密算法配置 # 检查ssh的配置 ssh-audit 192.168.50.149修改ssh的加密算法配置 # 查看ssh加密配置文件是否存在 ls /etc/c…

身份证信息OCR识别提取

要实现Python中的身份证OCR识别&#xff0c;可以采用以下步骤和工具&#xff08;结合开源库和API服务&#xff09;&#xff0c;以下是两种主流方案&#xff1a; 方案1&#xff1a;使用第三方OCR API&#xff08;推荐百度/腾讯云&#xff09; 百度OCR API 示例 注册并获取API …

C++之string的模拟实现

string 手写C字符串类类的基本结构与成员变量一、构造函数与析构函数二、赋值运算符重载三、迭代器支持四、内存管理与扩容机制五、字符串操作函数六、运算符重载总结 手写C字符串类 从零实现一个简易版std::string 类的基本结构与成员变量 namespace zzh { class string { …

Linux的调试器--gbd/cgbd

1.引入 #include <stdio.h> int Sum(int s, int e) {int result 0;for(int i s; i < e; i){result i;}return result; } int main() {int start 1;int end 100;printf("I will begin\n");int n Sum(start, end);printf("running done, result i…

云原生 Cloud Native Build (CNB)使用初体验

云原生 Cloud Native Build&#xff08;CNB&#xff09;使用初体验 引言 当“一切皆可云”成为趋势&#xff0c;传统开发环境正被云原生工具重塑。腾讯云CNB&#xff08;Cloud Native Build&#xff09;作为一站式开发平台&#xff0c;试图解决多环境协作难题。 本文将分享c…