4:QT联合HALCON编程—机器人二次程序抓取开发(九点标定)
判断文件是否存在
//判断文件在不在
int HandEyeCalib::AnsysFileExists(QString FileAddr)
{QFile File1(FileAddr);if(!File1.exists()){QMessageBox::warning(this,QString::fromLocal8Bit("提示"),FileAddr+QString::fromLocal8Bit("文件不存在"));return -1;}else{return 0;}
}
图像九点坐标的获取与显示
1.首先进行九点标定
在UI界面上添加九点标定QT设计师类
在主程序中声明此类头文件,并添加此界面
.h文件
private:
//手眼标定类HandEyeCalib *m_PHandEyeCalib=NULL;
.cpp文件
m_PHandEyeCalib=new HandEyeCalib();ui->MainTab->addTab(m_PHandEyeCalib,QString::fromLocal8Bit("标定"));if(m_PHandEyeCalib!=NULL){delete m_PHandEyeCalib;m_PHandEyeCalib=NULL;}
第一步应该是打开一张拍摄好的九点图像,或者是打开相机现场采集。
则读图操作为:
//读图
void HandEyeCalib::on_pB_OpenImage_clicked()
{//调取 不同的图像 在这里完成测试//传入路径QString path = QFileDialog::getOpenFileName(this,"选择图片","","JPG文件(*.jpg;*.bmp)");if(path == "") return;//read imageHTuple file2=HTuple(path.toStdString().c_str());ReadImage(&halconImage,file2);//2592 1544SetPart(WindowHandle, 0, 0, 1544, 2592);DispObj(halconImage,WindowHandle);
}
绘制像素坐标点或者圆
可以现在HALCON中编写程序,如何导出C++添加到QT中
//绘制点
void MainWindow::on_action_triggered()
{HObject Cross;DrawPoint(WindowHandle, &Row, &Column);GenCrossContourXld(&Cross, Row, Column, 116, 0.785398);DispObj(Cross, WindowHandle);
}
由于绘制的点,在九点标定类中需要用到,所以要把得到的XY坐标点声明在全局变量中
HTuple Row, Column; //绘制点
然后在九点标定类的上面引用这两个变量(这是个通用方法,如果两个类都需要用到同一个变量,则可以使用此方法;也可以利用信号与槽机制)
extern HTuple Row, Column; //画点 -
在得到像素点之后,则可以显示加载在界面上
//加载显示像素点
void HandEyeCalib::on_pB_LoadPixelCoord_clicked()
{// Row 的长度为0// try catch ----HTuple Length;TupleLength(Row, &Length);if(Length[0].D()==0){QMessageBox::warning(this,"warning",QString::fromLocal8Bit("数据异常"));return;}//点1if(ui->spinBox_PointNum2->value()==1){//界面的点1 的 xy 更新为 row columnui->x_17->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_17->setValue(Column[0].D());}//点2if(ui->spinBox_PointNum2->value()==2){//界面的点1 的 xy 更新为 row columnui->x_18->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_18->setValue(Column[0].D());}//点3if(ui->spinBox_PointNum2->value()==3){//界面的点1 的 xy 更新为 row columnui->x_19->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_19->setValue(Column[0].D());}//点4if(ui->spinBox_PointNum2->value()==4){//界面的点1 的 xy 更新为 row columnui->x_20->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_20->setValue(Column[0].D());}//点5if(ui->spinBox_PointNum2->value()==5){//界面的点1 的 xy 更新为 row columnui->x_21->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_21->setValue(Column[0].D());}//点6if(ui->spinBox_PointNum2->value()==6){//界面的点1 的 xy 更新为 row columnui->x_22->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_22->setValue(Column[0].D());}//点7if(ui->spinBox_PointNum2->value()==7){//界面的点1 的 xy 更新为 row columnui->x_23->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_23->setValue(Column[0].D());}//点8if(ui->spinBox_PointNum2->value()==8){//界面的点1 的 xy 更新为 row columnui->x_24->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_24->setValue(Column[0].D());}//点9if(ui->spinBox_PointNum2->value()==9){//界面的点1 的 xy 更新为 row columnui->x_25->setValue(Row[0].D()); //HTUPLE 转换为 doubleui->y_25->setValue(Column[0].D());}}
机械臂坐标的获取与显示
包含库目录
include文件
lib文件
realse文件
.pro目录
INCLUDEPATH += $$PWD/include/libfairinoLIBS += -L$$PWD/lib/FairinoLib/ -lfairino
LIBS += -L$$PWD/lib/FairinoLib/ -lfairinod
头文件声明
#include <QWidget>
#include "robot.h"
#ifdef WINDOWS_OPTION
#include <string.h>
#include <windows.h>
#elif LINUX_OPTION
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <unistd.h>
#endif#include <chrono>
#include <thread>
添加机械臂的UI类,并在主函数中声明添加界面
.h文件
//法奥机器人类FairinoRobtics *m_pFairinoRobtics=NULL;
.cpp文件
//机器人UI类的实例化m_pFairinoRobtics= new FairinoRobtics();ui->MainTab->addTab(m_pFairinoRobtics,QString::fromLocal8Bit("法奥机器人"));if(m_pFairinoRobtics!=NULL){delete m_pFairinoRobtics;m_pFairinoRobtics=NULL;}
获取坐标
在机械臂类中,实例化具体的对象 —名字叫:robot
FRRobot robot;//声明机器人对象
连接机械臂
void FairinoRobtics::on_pushButton_2_clicked()
{robot.RPC("192.168.1.2");
}
获取当前坐标点
void FairinoRobtics::on_ptn_ModifyA_clicked()
{GetTargetTCPPose(nowPos);//获取坐标函数RobX=nowPos.tran.x;RobY=nowPos.tran.y;}//获取坐标定义
void FairinoRobtics::GetTargetTCPPose(DescPose &nowPos)
{int ret=robot.GetActualTCPPose(0,&nowPos);ui->Dx->setValue(nowPos.tran.x);ui->Dy->setValue(nowPos.tran.y);ui->Dz->setValue(nowPos.tran.z);ui->Drx->setValue(nowPos.rpy.rx);ui->Dry->setValue(nowPos.rpy.ry);ui->Drz->setValue(nowPos.rpy.rz);}
机械臂走点
void FairinoRobtics::on_pushButton_clicked()
{DescPose desc_pos;//创建一个笛卡尔空间位置数据memset(&desc_pos, 0, sizeof(DescPose));//初始化笛卡尔空间位置数据double x = ui->Dx->value();//取得ui空间的值(doubleSpinBox)double y = ui->Dy->value();//取得ui空间的值(doubleSpinBox)double z = ui->Dz->value();//取得ui空间的值(doubleSpinBox)double rx = ui->Drx->value();//取得ui空间的值(doubleSpinBox)double ry = ui->Dry->value();//取得ui空间的值(doubleSpinBox)double rz = ui->Drz->value();//取得ui空间的值(doubleSpinBox)desc_pos.tran.x = x; //为desc_pos赋值desc_pos.tran.y = y;desc_pos.tran.z = z;desc_pos.rpy.rx = rx;desc_pos.rpy.ry = ry;desc_pos.rpy.rz = rz;int tool = ui->sTool->value();int user = ui->sUser->value();double vel = 100;double acc = 100;double ovl = 100;double blendT = -1;double config = -1;robot.MoveCart(&desc_pos,tool,user,vel,acc,ovl,blendT,config);
}
在获取到坐标之后,需要把前两个参数传给九点标定的类中,所以需要把下面这两个坐标声明为全局变量
double RobX=1.5;
double RobY=1.6;
然后在九点标定类中引用这两个点
extern double RobX;
extern double RobY;
加载显示机械臂的点
void HandEyeCalib::on_pB_LoadRobCoord_clicked()
{if(ui->spinBox_PointNum1->value()==1) //value 获取值{ui->x_1->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_1->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==2) //value 获取值{ui->x_2->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_2->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点3if(ui->spinBox_PointNum1->value()==3) //value 获取值{ui->x_3->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_3->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==4) //value 获取值{ui->x_4->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_4->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==5) //value 获取值{ui->x_5->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_5->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==6) //value 获取值{ui->x_6->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_6->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==7) //value 获取值{ui->x_7->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_7->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==8) //value 获取值{ui->x_8->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_8->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}//点2if(ui->spinBox_PointNum1->value()==9) //value 获取值{ui->x_9->setValue(RobX); //机器人类的变量 extern 引用,赋值 设置值ui->y_9->setValue(RobY); //机器人类的变量 extern 引用,赋值 设置值}
}
上面已经完整对像素和机械臂的坐标加载显示;为了方便需要保存这些点
//保存所有点
void HandEyeCalib::on_pB_SaveParamters_clicked()
{//机器人坐标 ---QSeting ,htuple WriteTuple//像素坐标 PixelX,PixelYHTuple RobX,RobY,PixelX,PixelY;RobX = HTuple();RobX[0]=ui->x_1->value();RobX[1]=ui->x_2->value();RobX[2]=ui->x_3->value();RobX[3]=ui->x_4->value();RobX[4]=ui->x_5->value();RobX[5]=ui->x_6->value();RobX[6]=ui->x_7->value();RobX[7]=ui->x_8->value();RobX[8]=ui->x_9->value();RobY = HTuple();RobY[0]=ui->y_1->value();RobY[1]=ui->y_2->value();RobY[2]=ui->y_3->value();RobY[3]=ui->y_4->value();RobY[4]=ui->y_5->value();RobY[5]=ui->y_6->value();RobY[6]=ui->y_7->value();RobY[7]=ui->y_8->value();RobY[8]=ui->y_9->value();PixelX=HTuple();PixelX[0]=ui->x_17->value();PixelX[1]=ui->x_18->value();PixelX[2]=ui->x_19->value();PixelX[3]=ui->x_20->value();PixelX[4]=ui->x_21->value();PixelX[5]=ui->x_22->value();PixelX[6]=ui->x_23->value();PixelX[7]=ui->x_24->value();PixelX[8]=ui->x_25->value();PixelY = HTuple();PixelY[0]=ui->y_17->value();PixelY[1]=ui->y_18->value();PixelY[2]=ui->y_19->value();PixelY[3]=ui->y_20->value();PixelY[4]=ui->y_21->value();PixelY[5]=ui->y_22->value();PixelY[6]=ui->y_23->value();PixelY[7]=ui->y_24->value();PixelY[8]=ui->y_25->value();//判断文件夹是否存在QString FileAddr="./data/Param";QFile File1(FileAddr);if(File1.exists()){WriteTuple(RobX, "./data/Param/robX.tup");WriteTuple(RobY, "./data/Param/robY.tup");WriteTuple(PixelX, "./data/Param/RowS.tup");WriteTuple(PixelY, "./data/Param/ColumnS.tup");ui->textBrowser->append(QString::fromLocal8Bit("保存成功"));}else{ui->textBrowser->append(FileAddr+QString::fromLocal8Bit("文件不存在,无法保存"));}}
重新读图保存的坐标
void HandEyeCalib::on_pB_LoadParameters_clicked()
{HTuple RobX,RobY;QString FileAddr="./data/Param";QFile File1(FileAddr);try{if(File1.exists()){ReadTuple("./data/Param/robX.tup", &RobX);ReadTuple("./data/Param/robY.tup", &RobY);ui->textBrowser->append(QString::fromLocal8Bit("读取成功"));ui->x_1->setValue(RobX[0].D());ui->x_2->setValue(RobX[1].D());ui->x_3->setValue(RobX[2].D());ui->x_4->setValue(RobX[3].D());ui->x_5->setValue(RobX[4].D());ui->x_6->setValue(RobX[5].D());ui->x_7->setValue(RobX[6].D());ui->x_8->setValue(RobX[7].D());ui->x_9->setValue(RobX[8].D());ui->y_1->setValue(RobY[0].D());ui->y_2->setValue(RobY[1].D());ui->y_3->setValue(RobY[2].D());ui->y_4->setValue(RobY[3].D());ui->y_5->setValue(RobY[4].D());ui->y_6->setValue(RobY[5].D());ui->y_7->setValue(RobY[6].D());ui->y_8->setValue(RobY[7].D());ui->y_9->setValue(RobY[8].D());}else{ui->textBrowser->append(FileAddr+QString::fromLocal8Bit("文件不存在,无法保存"));}}catch(...){ui->textBrowser->append(FileAddr+QString::fromLocal8Bit("文件缺失"));}}
因为保存点和重新读图点,都是数组点;可以现在HALCON软件中写好程序,然后导出更方便
最终生成标定文件
void HandEyeCalib::on_pB_GenCalibResult_clicked()
{HTuple RowS, ColumnS, RobX, RobY;HTuple HomMat2D;//1.获取 4---9个点的 像素坐标系RowS = HTuple();ColumnS = HTuple();RobX = HTuple();RobY = HTuple();QString FileAddr;FileAddr="./data/Param/robX.tup";//判断文件在不在int ret=AnsysFileExists( FileAddr);if(ret==-1){return;}FileAddr="./data/Param/robY.tup";ret=AnsysFileExists( FileAddr);if(ret==-1){return;}FileAddr="./data/Param/RowS.tup";ret=AnsysFileExists( FileAddr);if(ret==-1){return;}FileAddr="./data/Param/ColumnS.tup";ret=AnsysFileExists( FileAddr);if(ret==-1){return;}try{ReadTuple("./data/Param/robX.tup", &RobX);ReadTuple("./data/Param/robY.tup", &RobY);ReadTuple("./data/Param/RowS.tup", &RowS);ReadTuple("./data/Param/ColumnS.tup", &ColumnS);//生成一个矩阵 HomMat2DVectorToHomMat2d(RowS, ColumnS, RobX, RobY, &HomMat2D);WriteTuple(HomMat2D, "./data/Param/HomMat2D.tup"); //标定文件QMessageBox::warning(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("创建标定矩阵成功"));return;}catch(...){QMessageBox::warning(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("创建标定矩阵失败"));return;}}
HALCON程序附录
保存、读图数组、绘制点、绘制圆
九点标定
*1.获取 4---9个点的 像素坐标系RowS:=[]ColumnS:=[]RobX:=[]RobY:=[]dev_open_window(0, 0, 512, 512, 'black', WindowHandle)* read_image(Image, '标定')
* draw_circle(WindowHandle, Row, Column, Radius)
* CenterCoord:=[Row, Column]Pose:=[253.871, 342.389]write_tuple(Pose,'./像素/Pose0.dat')Pose:=[253.487, 591.21]write_tuple(Pose,'./像素/Pose1.dat')Pose:=[251.388, 849.435]write_tuple(Pose,'./像素/Pose2.dat')Pose:=[496.451, 340.278]write_tuple(Pose,'./像素/Pose3.dat')Pose:=[499.304, 590.602]write_tuple(Pose,'./像素/Pose4.dat')Pose:=[502.83, 851.243]write_tuple(Pose,'./像素/Pose5.dat')Pose:=[707.115, 339.089]write_tuple(Pose,'./像素/Pose6.dat')Pose:=[700.256, 591.442]write_tuple(Pose,'./像素/Pose7.dat')Pose:=[694.649, 853.365]write_tuple(Pose,'./像素/Pose8.dat')*获取9个点的像素点for I := 0 to 8 by 1FileName:='./像素/Pose'+I+'.dat'read_tuple(FileName, Pose)RowS[I]:=Pose[0]ColumnS[I]:=Pose[1]endfor*获取9个点的机械手坐标*2获取4---9个点 机械手 坐标! (mm)for I := 11 to 19 by 1FileName:='./坐标/Pose'+I$'01d'+'.dat'read_pose(FileName, Pose)RobX[I-11]:=Pose[0]RobY[I-11]:=Pose[1]endfor*两者进行仿射变换 ,就可以得到 像素坐标和 机械手坐标的变换 。 *相机固定位置 , 机械手 定点拍照 都可以使用 *如果机械手移动拍照 , + 机械手 和标定 时刻拍照间的差值 !*生成一个矩阵 HomMat2Dvector_to_hom_mat2d(RowS ,ColumnS,RobX,RobY, HomMat2D)write_tuple(HomMat2D, 'HomMat2D')**识别图像的坐标 假如是RowS[0] ,ColumnS[0]*根据 这个矩阵 能否求出机械手坐标!Row1:=512Column1:= 640affine_trans_point_2d(HomMat2D,253.871, 342.389,Qx, Qy)
TCP标定
1.法兰盘姿态换算到工具姿态
*法兰盘坐标 换算到 工具末端坐标*X219.108Y579.008Z364.915RX-179.026RY0.549RZ-64.079,2*法兰盘 坐标 记录pose1:=[219.108,579.008,364.915,-179.026,0.549,-64.079,2]*坐标换算 旋转轴2 换算到旋转轴0convert_pose_type(pose1, 'Rp+T', 'gba', 'point', Pose11)*标定的 工具与法兰盘的 位置 tcptcpPose:=[-5.593,7.166,249.3040,0,0,0,0]*法兰盘 换算到 工具坐标系pose_compose( Pose11,tcpPose, PoseCompose1)*工具坐表 旋转 状态变换convert_pose_type(PoseCompose1, 'Rp+T', 'abg', 'point', Pose22)if(Pose22[3]>180)Pose22[3]:=Pose22[3]-360 endifif(Pose22[4]>180)Pose22[4]:=Pose22[4]-360 endifif(Pose22[5]>180)Pose22[5]:=Pose22[5]-360 endif*Pose22 就是最终的姿态结果*[212.986, 584.908, 115.59, 180.92, 0.636037, 64.0786,2]
2.工具姿态换算到法兰盘姿态
* 工具末端坐标换算到法兰盘坐标 *X212.988Y584.915Z115.59RX-179.026RY0.549RZ-64.079Pose22:=[212.986, 584.908, 115.59, -179.026, 0.549, -64.079, 2]*坐标换算 旋转轴2 换算到旋转轴0convert_pose_type(Pose22, 'Rp+T', 'gba', 'point', Pose2)*标定的 工具与法兰盘的 位置 tcptcpPose:=[-5.593,7.166,249.3040,0,0,0,0]*对标定结果进行逆变换pose_invert(tcpPose, PoseInvert1)pose_compose( Pose2, PoseInvert1, Pose11)*工具坐表 旋转 状态变换convert_pose_type(Pose11, 'Rp+T', 'abg', 'point', Pose1)if(Pose1[3]>180)Pose1[3]:=Pose1[3]-360 endifif(Pose1[4]>180)Pose1[4]:=Pose1[4]-360 endifif(Pose1[5]>180)Pose1[5]:=Pose1[5]-360 endif*Pose1 就是最终的姿态结果*[219.108, 579.008, 364.915, -179.026, 0.549, -64.079, 2]*法兰盘 坐标 记录*pose1:=[219.108,579.008,364.915,-179.026,0.549,-64.079,2]
相关文章:
4:QT联合HALCON编程—机器人二次程序抓取开发(九点标定)
判断文件是否存在 //判断文件在不在 int HandEyeCalib::AnsysFileExists(QString FileAddr) {QFile File1(FileAddr);if(!File1.exists()){QMessageBox::warning(this,QString::fromLocal8Bit("提示"),FileAddrQString::fromLocal8Bit("文件不存在"));retu…...
C语言之操作符
目录 1. 操作符的分类 2. 移位操作符 2.1 左移操作符 << 2.2 右移操作符 >> 3. 位操作符 3.1 按位与 & 3.2 按位或 | 3.3 按位异或 ^ 3.4 按位取反 ~ 3.5 例题 3.5.1 按位异或 ^ 拓展公式 3.5.2 不能创建临时变量(第三个变量ÿ…...
【优选算法 | 前缀和】前缀和算法:高效解决区间求和问题的关键
算法相关知识点可以通过点击以下链接进行学习一起加油!双指针滑动窗口二分查找 在本篇文章中,我们将深入解析前缀和算法的原理。从基础概念到实际应用,带你了解如何通过前缀和高效解决数组求和、区间查询等问题。无论你是刚接触算法的新手&am…...
『深夜_MySQL』详解数据库 探索数据库是如何存储的
1. 数据库基础 1.1 什么是数据库 存储数据用文件就可以了,那为什么还要弄个数据库? 一般的文件缺失提供了数据的存储功能,但是文件并没有提供非常好的数据管理能力(用户角度,内容方面) 文件保存数据有以…...
Microsoft Entra ID 免费版管理云资源详解
Microsoft Entra ID(原 Azure AD)免费版为企业提供了基础的身份管理功能,适合小型团队或预算有限的组织。以下从功能解析到实战配置,全面展示如何利用免费版高效管理云资源。 1. 免费版核心功能与限制 1.1 功能概览 功能免费版支持情况基础用户与组管理✔️ 支持创建、删除…...
k8s -hpa
hpa定义弹性自动伸缩 1、横向伸缩,当定义的cpu、mem指标达到hpa值时,会触发pods伸展 2、安装metrics-server 收集pods的cpu。mem信息供hpa参照 安装helm curl -fsSl -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 用helm安装metr…...
Web应用开发指南
一、引言 随着互联网的迅猛发展,Web应用已深度融入日常生活的各个方面。为满足用户对性能、交互与可维护性的日益增长的需求,开发者需要一整套高效、系统化的解决方案。在此背景下,前端框架应运而生。不同于仅提供UI组件的工具库,…...
Vue3 + TypeScript 实现 PC 端鼠标横向拖动滚动
功能说明 拖动功能: 鼠标按下时记录初始位置和滚动位置拖动过程中计算移动距离并更新滚动位置松开鼠标后根据速度实现惯性滚动 滚动控制: 支持鼠标滚轮横向滚动(通过 wheel 事件)自动边界检测防止滚动超出内容…...
MyBatis的SQL映射文件中,`#`和`$`符号的区别
在MyBatis的SQL映射文件中,#和$符号用于处理SQL语句中的参数替换,但它们的工作方式和使用场景有所不同。 #{} 符号 预编译参数:#{} 被用来作为预编译SQL语句的占位符。这意味着MyBatis会将你传入的参数设置为PreparedStatement的参数,从而防止SQL注入攻击,并允许MyBatis对…...
Python----卷积神经网络(池化为什么能增强特征)
一、什么是池化 池化(Pooling)是卷积神经网络(CNN)中的一种关键操作,通常位于卷积层之后,用于对特征图(Feature Map)进行下采样(Downsampling)。其核心目的是…...
React Native 从零开始完整教程(环境配置 → 国内镜像加速 → 运行项目)
React Native 从零开始完整教程(环境配置 → 国内镜像加速 → 运行项目) 本教程将从 环境配置 开始,到 国内镜像加速,最后成功运行 React Native 项目(Android/iOS),适合新手和遇到网络问题的开…...
SNR8016语音模块详解(STM32)
目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 三、程序设计 main文件 usart.h文件 usart.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 SNR8016语音模块是智纳捷科技生产的一种离线语音识别模块,设计适合用于DIY领域,开放用户设…...
驱动开发系列54 - Linux Graphics QXL显卡驱动代码分析(一)设备初始化
一:概述 QXL 是QEMU支持的一种虚拟显卡,用于虚拟化环境中的图形加速,旨在提高虚拟机的图形显示和远程桌面的用户体验;QEMU 也称 Quick Emulator,快速仿真器,是一个开源通用的仿真和虚拟化工具,可…...
通过IP计算分析归属地
在产品中可能存在不同客户端,请求同一个服务端接口的场景。 例如小程序和App或者浏览器中,如果需要对请求的归属地进行分析,前提是需要先获取请求所在的国家或城市,这种定位通常需要主动授权,而用户一般是不愿意提供的…...
【网络原理】从零开始深入理解HTTP的报文格式(二)
本篇博客给大家带来的是网络HTTP协议的知识点, 续上篇文章,接着介绍HTTP的报文格式. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅…...
【前缀和】二维前缀和(模板题)
DP35 【模板】二维前缀和 DP35 【模板】二维前缀和 给你一个 n 行 m 列的矩阵 A ,下标从 1 开始,接下来有 q 次查询,每次查询输入 4 个参数 x1 , y1 , x2 , y2。 请输出以 (x1, y1) 为左上角,(x2,y2) 为右下角的子矩阵的和。 输入描述: 第一行包含三个整数 …...
【开源工具】Python打造智能IP监控系统:邮件告警+可视化界面+配置持久化
🌐【开源工具】Python打造智能IP监控系统:邮件告警可视化界面配置持久化 🌈 个人主页:创客白泽 - CSDN博客 🔥 系列专栏:🐍《Python开源项目实战》 💡 热爱不止于代码,热…...
kotlin 过滤 filter 函数的作用和使用场景
1. filter 函数的作用 filter 是 Kotlin 集合操作中的一个高阶函数,用于根据指定条件从集合中筛选出符合条件的元素。 作用:遍历集合中的每个元素,并通过给定的 lambda 表达式判断是否保留该元素。返回值:一个新的集合ÿ…...
Java泛型(补档)
核心概念 Java 泛型是 Java SE 1.5 引入的一项重要特性,它的核心思想是 参数化类型(Parameterized Types),即通过将数据类型作为参数传递给类、接口或方法,使代码能够灵活地处理多种类型,同时保证类型安全性…...
C语言发展史:从Unix起源到现代标准演进
C语言发展史:从Unix起源到现代标准演进 C语言的诞生与早期发展 C语言的起源可以追溯到上世纪70年代初期,但其真正的萌芽始于1969年的夏天。在计算机发展史上,这是一个具有划时代意义的时刻。 当时,Ken Thompson和Dennis Ritchi…...
nginx 代理时怎么更改 Remote Address 请求头
今天工作中遇到用 localhost 访问网站能访问后台 api,但是用本机IP地址后就拒绝访问,我怀疑是后台获取 Remote Address 然后设置白名单了只能 localhost 访问。 想用 nginx 更改 Remote Address server {listen 8058;server_name localhost;loca…...
解决STM32待机模式无法下载程序问题的深度探讨
在现代嵌入式系统开发中,STM32系列微控制器因其高性能、低功耗和丰富的外设资源而广受欢迎。然而,开发者在使用STM32时可能会遇到一个问题:当微控制器进入待机模式后,无法通过调试接口(如SWD或JTAG)下载程序…...
进程、线程、进程间通信Unix Domain Sockets (UDS)
进程、线程、UDS 进程和线程进程间通信Unix Domain Sockets (UDS)UDS的核心适用场景和用途配置UDS的几种主要方式socketpair() 基本配置流程socketpair() 进阶——传递文件描述符 补充socketpair() 函数struct msghdr 结构体struct iovecstruct cmsghdrstruct iovec 、struct m…...
大数据平台与数据仓库的核心差异是什么?
随着数据量呈指数级增长,企业面临着如何有效管理、存储和分析这些数据的挑战。 大数据平台和 数据仓库作为两种主流的数据管理工具,常常让企业在选型时感到困惑,它们之间的界限似乎越来越模糊,功能也有所重叠。本文旨在厘清这两种…...
Hadoop虚拟机中配置hosts
( 一)修改虚拟机的主机名 默认情况下,本机的名称叫:localhost。 我们进入linux系统之后,显示出来的就是[rootlocalhost ~]# 。为了方便后面我们更加便捷地访问这台主机,而不是通过ip地址,我们要…...
a-upload组件实现文件的上传——.pdf,.ppt,.pptx,.doc,.docx,.xls,.xlsx,.txt
实现下面的上传/下载/删除功能:要求支持:【.pdf,.ppt,.pptx,.doc,.docx,.xls,.xlsx,.txt】 分析上面的效果图,分为【上传】按钮和【文件列表】功能: 解决步骤1:上传按钮 直接上代码: <a-uploadmultip…...
QCefView应用和网页的交互
一、demo的主要项目文件 结合QCefView自带的demo代码 main.cpp #include #include <QCefContext.h> #include “MainWindow.h” int main(int argc, char* argv[]) { QApplication a(argc, argv); // build QCefConfig QCefConfig config; config.setUserAgent(“QCef…...
C++,设计模式,【建造者模式】
文章目录 通俗易懂的建造者模式:手把手教你造电脑一、现实中的建造者困境二、建造者模式核心思想三、代码实战:组装电脑1. 产品类 - 电脑2. 抽象建造者 - 装机师傅3. 具体建造者 - 电竞主机版4. 具体建造者 - 办公主机版5. 指挥官 - 装机总控6. 客户端使…...
Axure疑难杂症:中继器制作下拉菜单(多级中继器高级交互)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 本文视频课程记录于上述地址第五章中继器专题第11节 课程主题:中继器制作下拉菜单 主要内容:创建条件选区、多级中继器…...
科研 | 光子技术为人工智能注入新动力
译《Nature》25.4.9 发表文章《A photonic processing boost for AI》 ▶ 基于人工智能(artificial intelligence, AI)的系统正被越来越广泛地应用于从基因数据解码到自动驾驶的各类任务。但随着AI模型的规模和应用的扩大,性能天花板与能耗壁…...
SQL语句练习 自学SQL网 多表查询
目录 Day 6 用JOINs进行多表联合查询 Day 7 外连接 OUTER JOINs Day 8 外连接 特殊关键字 NULLs Day 6 用JOINs进行多表联合查询 SELECT * FROM Boxoffice INNER JOIN movies ON movies.idboxoffice.Movie_id;SELECT * FROM Boxoffice INNER JOIN moviesON movies.idboxoffi…...
北京亦庄机器人马拉松:人机共跑背后的技术突破与产业启示
2025年4月19日,北京亦庄举办了一场具有里程碑意义的科技赛事——全球首个人形机器人半程马拉松。这场人类与20支机器人战队共同参与的21.0975公里竞速,不仅创造了人形机器人连续运动的最长纪录,更成为中国智能制造领域的综合性技术验证平台。…...
大连理工大学选修课——机器学习笔记(6):决策树
决策树 决策树概述 决策树——非参数机器学习方法 参数方法: 参数估计是定义在整个空间的模型 所有训练数据参与估算 所有的检验输入都用相同的模型和参数 非参数方法: 非参数估计采用局部模型 输入空间被分裂为一系列可以用距离度量的局部空间…...
现代前端工具链深度解析:从包管理到构建工具的完整指南
前言 在当今快速发展的前端生态中,高效的工具链已经成为开发者的必备利器。一个优秀的前端工具链可以显著提升开发效率、优化项目性能并改善团队协作体验。本文将深入探讨现代前端开发中最核心的两大工具类别:包管理工具(npm/yarn)和构建工具(Webpack/V…...
[C语言]猜数字游戏
文章目录 一、游戏思路揭秘二、随机数生成大法1、初探随机数:rand函数的魔力2、随机数种子:时间的魔法3、抓住时间的精髓:time函数 三、完善程序四、游戏成果1、游戏效果2、源代码 一、游戏思路揭秘 猜数字游戏,这个听起来就让人…...
【Linux】g++安装教程
Linux上安装g教程 实现c语言在Linux上编译运行 1. 更新软件包列表 打开终端,先更新软件包列表以确保获取最新版本信息: sudo apt update2. 安装 build-essential 工具包 build-essential 包含 g、gcc、make 和其他编译所需的工具: sudo…...
MQTT - Android MQTT 编码实战(MQTT 客户端创建、MQTT 客户端事件、MQTT 客户端连接配置、MQTT 客户端主题)
Android MQTT 编码实战 1、Settting 在项目级 build.gradle 目录下导入 MQTT 客户端依赖 implementation org.eclipse.paho:org.eclipse.paho.mqttv5.client:1.2.5 implementation org.eclipse.paho:org.eclipse.paho.android.service:1.1.1AndroidManifest.xml,…...
Redis分布式锁使用以及对接支付宝,paypal,strip跨境支付
本章重点在于如何使用redis的分布式锁来锁定库存。减少超卖,同时也对接了支付宝,paypal,strip跨境支付 第一步先建立一个商品表 CREATE TABLE sys_product (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键,code varchar(60) DEFAUL…...
沙箱逃逸(Python沙盒逃逸深度解析)
沙箱逃逸(Python沙盒逃逸深度解析) 一、沙盒逃逸的核心目标 执行系统命令 通过调用os.system、subprocess.Popen等函数执行Shell命令,例如读取文件或反弹Shell。 文件操作 读取敏感文件(如/etc/passwd)、写入后门文件…...
k8s-Pod生命周期
初始化容器 初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征: 1. 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成 2. 初…...
基于Springboot + vue实现的中医院问诊系统
项目描述 本系统包含管理员、医生、用户三个角色。 管理员角色: 用户管理:管理系统中所有用户的信息,包括添加、删除和修改用户。 配置管理:管理系统配置参数,如上传图片的路径等。 权限管理:分配和管理…...
computed计算值为什么还可以依赖另外一个computed计算值?
在 Vue(或类似的响应式框架)中,computed 计算属性之所以可以依赖另一个 computed 属性,是因为: ✅ 本质上 computed 是响应式依赖的“派生值” 每个 computed 本质上就是一个 基于其他响应式数据计算出来的值。 当你在…...
近期实践总结
一、计算机二级考试到底教会了我们什么? 1、概况 根据本人复习、考试的经验,不难发现里面的试题或多或少有些死板(甚至可以说落后于时代),当今时代已经不是二十年前什么都需要手搓的时代了,引擎、集成类软…...
Arduion 第一天,变量的详细解析
Arduino变量详解与嵌入式开发扩展 一、变量基础篇 1.1 变量声明与初始化 <ARDUINO>int ledPin 13; // 声明并初始化float sensorValue; // 先声明后赋值unsigned long startTime; // 无符号长整型void setup() {sensorValue analogRead(A0) *…...
【每日八股】复习 MySQL Day3:锁
文章目录 昨日内容复习MySQL 使用 B 树作为索引的优势是什么?索引有哪几种?什么是最左匹配原则?索引区分度?联合索引如何排序?使用索引有哪些缺陷?什么时候需要建立索引,什么时候不需要…...
2025年KBS新算法 SCI1区TOP:长颖燕麦优化算法AOO,深度解析+性能实测
目录 1.摘要2.算法原理3.结果展示4.参考文献5.文章&代码获取 1.摘要 本文提出了一种新颖的元启发式算法——长颖燕麦优化算法(AOO),该算法灵感来自动画燕麦在环境中的自然行为。AOO模拟了长颖燕麦的三种独特行为:(i) 通过自然…...
1.4 点云数据获取方式——结构光相机
图1-4-1结构光相机 结构光相机作为获取三维点云数据的关键设备,其工作原理基于主动式测量技术。通过投射已知图案,如条纹、点阵、格雷码等,至物体表面,这些图案会因物体表面的高度变化而发生变形。与此同时,利用相机从特定...
2025.4.29总结
工作:最近手头活变得多起来了,毕竟要测两个版本,有时候觉得很奇怪,活少的时候,又想让别人多分点活,活多的时候,又会有些许不自然。这种反差往往伴随着项目的节奏,伴随着两个极端。所…...
初探RAG
源码 核心工作流程 读取文件的内容将内容保存在向量数据库检索向量数据库用户的问题用户问题 上下文【向量数据】 > LLM 读取文件内容【pdf为例】 from pdfminer.high_level import extract_pages from pdfminer.layout import LTTextContainerclass PDFFileLoader():d…...
AIGC(生成式AI)技术全景图:从文本到图像的革命
AIGC(生成式AI)技术全景图:从文本到图像的革命 前言 生成式人工智能(AIGC)正以惊人的速度重塑数字内容的生产方式。从GPT系列模型的文本生成,到Stable Diffusion的图像创作,再到Sora的视频合成…...