algoLib/rodAndBarDetection_test/rodAndBarDetection_test.cpp
jerryzeng 6674c32adc rodAndBarDetection
version 1.6.0 : 矩森棒材抓取算法改进:添加了料筐信息提取和对边缘工件的判断
2026-08-30 09:43:29 +08:00

2199 lines
69 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// gasFillingPortPosition_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <VZNL_Types.h>
#include "direct.h"
#include <string>
#include "rodAndBarDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <Windows.h>
#include <limits>
#include <SG_baseAlgo_Export.h>
#include <cmath>
typedef struct
{
int r;
int g;
int b;
}SG_color;
typedef struct
{
int nPointIdx;
double x;
double y;
double z;
float r;
float g;
float b;
} SPointXYZRGB;
bool fileExists(const char* path) {
FILE* f = fopen(path, "r");
if (f != NULL) {
fclose(f);
return true;
}
return false;
}
// 点乘 dot
double _dotMultiply(const SVzNL3DPoint& a, const SVzNL3DPoint& b)
{
return (a.x * b.x + a.y * b.y + a.z * b.z);
}
// 模长
double _length(const SVzNL3DPoint& a)
{
return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
}
// 计算两个向量夹角(返回 角度)
float _computeVecAngle(const SVzNL3DPoint& a, const SVzNL3DPoint& b)
{
float l = _length(a) * _length(b);
if (l < 1e-6f)
return 0.0f; // 避免除零
float cosTheta = _dotMultiply(a, b) / l;
cosTheta = cosTheta > 1.0 ? 1.0 : cosTheta;
cosTheta = cosTheta < -1.0 ? -1.0 : cosTheta;
float rad = acosf(cosTheta);
float degree = rad * 180.0f / (float)M_PI;
return degree;
}
void _outputCalibPara(char* fileName, SSG_planeCalibPara calibPara)
{
std::ofstream sw(fileName);
char dataStr[250];
//调平矩阵
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[0], calibPara.planeCalib[1], calibPara.planeCalib[2]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[3], calibPara.planeCalib[4], calibPara.planeCalib[5]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[6], calibPara.planeCalib[7], calibPara.planeCalib[8]);
sw << dataStr << std::endl;
//地面高度
sprintf_s(dataStr, 250, "%g", calibPara.planeHeight);
sw << dataStr << std::endl;
//反向旋转矩阵
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[0], calibPara.invRMatrix[1], calibPara.invRMatrix[2]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[3], calibPara.invRMatrix[4], calibPara.invRMatrix[5]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[6], calibPara.invRMatrix[7], calibPara.invRMatrix[8]);
sw << dataStr << std::endl;
sw.close();
}
SSG_planeCalibPara _readCalibPara(char* fileName)
{
//设置初始结果
double initCalib[9] = {
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 };
SSG_planeCalibPara planePara;
for (int i = 0; i < 9; i++)
planePara.planeCalib[i] = initCalib[i];
planePara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
planePara.invRMatrix[i] = initCalib[i];
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return planePara;
//调平矩阵
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[0], &planePara.planeCalib[1], &planePara.planeCalib[2]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[3], &planePara.planeCalib[4], &planePara.planeCalib[5]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[6], &planePara.planeCalib[7], &planePara.planeCalib[8]);
//地面高度
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf", &planePara.planeHeight);
//反向旋转矩阵
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[0], &planePara.invRMatrix[1], &planePara.invRMatrix[2]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[3], &planePara.invRMatrix[4], &planePara.invRMatrix[5]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[6], &planePara.invRMatrix[7], &planePara.invRMatrix[8]);
inputFile.close();
return planePara;
}
void wdReadLaserScanPointFromFile_XYZ_vector(const char* fileName, std::vector<std::vector< SVzNL3DPosition>>& scanData)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return;
std::vector< SVzNL3DPosition> a_line;
int ptIdx = 0;
while (getline(inputFile, linedata))
{
if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int ptSize = (int)a_line.size();
if (ptSize > 0)
{
scanData.push_back(a_line);
}
a_line.clear();
ptIdx = 0;
}
else if (0 == strncmp("{", linedata.c_str(), 1))
{
float X, Y, Z;
int imageY = 0;
float leftX, leftY;
float rightX, rightY;
sscanf_s(linedata.c_str(), "{%f,%f,%f}-{%f,%f}-{%f,%f}", &X, &Y, &Z, &leftX, &leftY, &rightX, &rightY);
SVzNL3DPosition a_pt;
a_pt.pt3D.x = X;
a_pt.pt3D.y = Y;
a_pt.pt3D.z = Z;
a_pt.nPointIdx = ptIdx;
ptIdx++;
a_line.push_back(a_pt);
}
}
//last line
int ptSize = (int)a_line.size();
if (ptSize > 0)
{
scanData.push_back(a_line);
a_line.clear();
}
inputFile.close();
return;
}
void wd_gridScan_GetROIData(std::vector<std::vector< SVzNL3DPosition>>& scanData, SVzNLRangeD roi_y, std::vector<std::vector< SVzNL3DPosition>>& roiData)
{
int lineNum = (int)scanData.size();
int linePtNum = (int)scanData[0].size();
int globalPtStart = INT_MAX;
int globalPtEnd = 0;
int lineStart = INT_MAX;
int lineEnd = 0;
for (int line = 0; line < lineNum; line++)
{
std::vector< SVzNL3DPosition >& lineData = scanData[line];
int ptSize = (int)lineData.size();
int vldNum = 0;
int ptStart = INT_MAX;
int ptEnd = 0;
for (int i = 0; i < ptSize; i++)
{
if (lineData[i].pt3D.z > 1e-4)
{
if ((lineData[i].pt3D.y < roi_y.min) || (lineData[i].pt3D.y > roi_y.max))
lineData[i].pt3D = { 0.0, 0.0, 0.0 };
}
if (lineData[i].pt3D.z > 1e-4)
{
if (ptStart > i)
ptStart = i;
ptEnd = i;
vldNum++;
}
}
if (vldNum > 0)
{
if (globalPtStart > ptStart)
globalPtStart = ptStart;
if (globalPtEnd < ptEnd)
globalPtEnd = ptEnd;
if (lineStart > line)
lineStart = line;
lineEnd = line;
}
}
int vldLineNum = lineEnd - lineStart + 1;
int vldPtNum = globalPtEnd - globalPtStart + 1;
roiData.resize(vldLineNum);
for (int line = 0; line < vldLineNum; line++)
{
roiData[line].resize(vldPtNum);
for (int i = 0; i < vldPtNum; i++)
roiData[line][i] = scanData[line + lineStart][i + globalPtStart];
}
return;
}
void _outputScanDataFile(char* fileName, std::vector<std::vector< SVzNL3DPosition>>& scanData,
float lineV, int maxTimeStamp, int clockPerSecond)
{
std::ofstream sw(fileName);
int lineNum = (int)scanData.size();
sw << "LineNum:" << lineNum << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed:" << lineV << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp:" << maxTimeStamp << "_" << clockPerSecond << std::endl;
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanData[line].size();
sw << "Line_" << line << "_0_" << nPositionCnt << std::endl;
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition& pt3D = scanData[line][i];
float x = (float)pt3D.pt3D.x;
float y = (float)pt3D.pt3D.y;
float z = (float)pt3D.pt3D.z;
sw << "{ " << x << "," << y << "," << z << " }-";
sw << "{0,0}-{0,0}" << std::endl;
}
}
sw.close();
}
void _readRodParas(char* fileName, std::vector<SSX_rodParam>& rodParas)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return;
std::vector<int> indices;
int maxIdx = 0;
std::vector< SSX_rodParam> paras;
while (getline(inputFile, linedata))
{
int idx;
float len, dia;
sscanf_s(linedata.c_str(), "%d_L_%f_D_%f", &idx, &len, &dia);
SSX_rodParam a_para = { dia , len };
indices.push_back(idx);
paras.push_back(a_para);
maxIdx = maxIdx < idx ? idx : maxIdx;
}
if (maxIdx == 0)
return;
rodParas.resize(maxIdx + 1);
for (int i = 0; i < (int)indices.size(); i++)
{
int idx = indices[i];
rodParas[idx] = paras[i];
}
return;
}
void _outputChanneltInfo(char* fileName, std::vector<SSX_rodPoseInfo>& screwInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)screwInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_( %g, %g, %g )",
i + 1, screwInfo[i].center.x, screwInfo[i].center.y, screwInfo[i].center.z,
screwInfo[i].axialDir.x, screwInfo[i].axialDir.y, screwInfo[i].axialDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputPlatePiseInfo(char* fileName, SSX_platePoseInfo& centerInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
sprintf_s(dataStr, 250, "定位盘: \n");
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " holeLT_(% g, % g, % g)\n", centerInfo.holeLT.x, centerInfo.holeLT.y, centerInfo.holeLT.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " holeRB_(% g, % g, % g)\n", centerInfo.holeRB.x, centerInfo.holeRB.y, centerInfo.holeRB.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " center_(% g, % g, % g)\n", centerInfo.center.x, centerInfo.center.y, centerInfo.center.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " normalDir_(% g, % g, % g)\n", centerInfo.normalDir.x, centerInfo.normalDir.y, centerInfo.normalDir.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " xDir_(% g, % g, % g)\n", centerInfo.xDir.x, centerInfo.xDir.y, centerInfo.xDir.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " yDir_(% g, % g, % g)\n", centerInfo.yDir.x, centerInfo.yDir.y, centerInfo.yDir.z);
sw << dataStr << std::endl;
sw.close();
}
void _outputRodtInfo(char* fileName, std::vector<SSX_rodPositionInfo>& rodInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)rodInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_axia( %g, %g, %g ), dir_normal_( %g, %g, %g )",
i + 1, rodInfo[i].center.x, rodInfo[i].center.y, rodInfo[i].center.z,
rodInfo[i].axialDir.x, rodInfo[i].axialDir.y, rodInfo[i].axialDir.z,
rodInfo[i].normalDir.x, rodInfo[i].normalDir.y, rodInfo[i].normalDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputWeldSeamInfo(char* fileName, std::vector<SSX_weldSeamInfo>& weldSeamInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)weldSeamInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_normal_( %g, %g, %g ), x_dir_(",
i + 1, weldSeamInfo[i].center.x, weldSeamInfo[i].center.y, weldSeamInfo[i].center.z,
weldSeamInfo[i].normalDir.x, weldSeamInfo[i].normalDir.y, weldSeamInfo[i].normalDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputRGBDScan_RGBD(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_rodPoseInfo>& screwInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)screwInfo.size();
if (objNum > 0)
realLines += 1;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int maxLineIndex = 0;
int max_stamp = 0;
SG_color rgb = { 0, 0, 0 };
SG_color objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
int lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->nPointIdx == 1)
{
rgb = objColor[pt3D->nPointIdx];
size = 3;
}
else if (pt3D->nPointIdx == 2)
{
rgb = { 250, 0, 0 };
size = 3;
}
else if (pt3D->nPointIdx == 4)
{
rgb = { 250, 250, 0 };
size = 6;
}
else //if (pt3D->nPointIdx == 0)
{
rgb = { 200, 200, 200 };
size = 1;
}
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
if (objNum > 0)
{
sw << "Line_" << lineIdx << "_0_" << objNum << std::endl;
rgb = { 250, 0, 0 };
size = 8;
for (int i = 0; i < objNum; i++)
{
float x = (float)screwInfo[i].center.x;
float y = (float)screwInfo[i].center.y;
float z = (float)screwInfo[i].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
//多输出一个,修正显示工具bug
float x = (float)screwInfo[0].center.x;
float y = (float)screwInfo[0].center.y;
float z = (float)screwInfo[0].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
//输出法向
rgb = { 250, 255, 0 };
size = 1;
double len1 = 30;
double len2 = 300;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
SVzNL3DPoint pt0 = { screwInfo[i].center.x - len1 * screwInfo[i].axialDir.x,
screwInfo[i].center.y - len1 * screwInfo[i].axialDir.y,
screwInfo[i].center.z - len1 * screwInfo[i].axialDir.z };
SVzNL3DPoint pt1 = { screwInfo[i].center.x + len2 * screwInfo[i].axialDir.x,
screwInfo[i].center.y + len2 * screwInfo[i].axialDir.y,
screwInfo[i].center.z + len2 * screwInfo[i].axialDir.z };
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
}
sw.close();
}
void _outputRGBDScan_RGBD_centerPose(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
SSX_platePoseInfo& poseInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
realLines += 1;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int maxLineIndex = 0;
int max_stamp = 0;
SG_color rgb = { 0, 0, 0 };
SG_color objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
int lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->nPointIdx == 2)
{
rgb = { 135,206,235 };
size = 5;
}
else if (pt3D->nPointIdx == 3)
{
rgb = { 250, 0, 0 };
size = 5;
}
else //if (pt3D->nPointIdx == 0)
{
rgb = { 200, 200, 200 };
size = 1;
}
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
{
sw << "Line_" << lineIdx << "_0_3" << std::endl;
rgb = { 250, 0, 0 };
size = 8;
float x = (float)poseInfo.center.x;
float y = (float)poseInfo.center.y;
float z = (float)poseInfo.center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
x = (float)poseInfo.holeLT.x;
y = (float)poseInfo.holeLT.y;
z = (float)poseInfo.holeLT.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
x = (float)poseInfo.holeRB.x;
y = (float)poseInfo.holeRB.y;
z = (float)poseInfo.holeRB.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
//输出法向
size = 1;
double len = 110;
lineIdx = 0;
{
SVzNL3DPoint pt0 = { poseInfo.center.x, // - len * poseInfo.normalDir.x,
poseInfo.center.y, // - len * poseInfo.normalDir.y,
poseInfo.center.z }; // - len * poseInfo.normalDir.z };
SVzNL3DPoint pt1 = { poseInfo.center.x + len * poseInfo.normalDir.x,
poseInfo.center.y + len * poseInfo.normalDir.y,
poseInfo.center.z + len * poseInfo.normalDir.z };
SVzNL3DPoint basePt = poseInfo.center;
SVzNL3DPoint pt2 = { poseInfo.center.x + len * poseInfo.xDir.x,
poseInfo.center.y + len * poseInfo.xDir.y,
poseInfo.center.z + len * poseInfo.xDir.z };
SVzNL3DPoint pt3 = { poseInfo.center.x + len * poseInfo.yDir.x,
poseInfo.center.y + len * poseInfo.yDir.y,
poseInfo.center.z + len * poseInfo.yDir.z };
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 250, 0 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 0, 250 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt3.x << "," << pt3.y << "," << pt3.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 250, 0 };
basePt = { poseInfo.holeLT.x - len * poseInfo.xDir.x,
poseInfo.holeLT.y - len * poseInfo.xDir.y,
poseInfo.holeLT.z - len * poseInfo.xDir.z };
pt2 = { poseInfo.holeLT.x + len * poseInfo.xDir.x,
poseInfo.holeLT.y + len * poseInfo.xDir.y,
poseInfo.holeLT.z + len * poseInfo.xDir.z };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
basePt = { poseInfo.holeRB.x - len * poseInfo.xDir.x,
poseInfo.holeRB.y - len * poseInfo.xDir.y,
poseInfo.holeRB.z - len * poseInfo.xDir.z };
pt2 = { poseInfo.holeRB.x + len * poseInfo.xDir.x,
poseInfo.holeRB.y + len * poseInfo.xDir.y,
poseInfo.holeRB.z + len * poseInfo.xDir.z };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
}
sw.close();
}
void _outputRGBDScan_RGBD_rodInfo(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_rodPositionInfo>& rodInfo,
SWD_BinInfo* binInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)rodInfo.size();
if (objNum > 0)
realLines += 1;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int maxLineIndex = 0;
int max_stamp = 0;
SG_color rgb = { 0, 0, 0 };
SG_color objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
int lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
pt3D->pt3D = { 0.0, 0.0, 0.0 };
if (pt3D->nPointIdx > 0)
{
int centerFlag = pt3D->nPointIdx >> 4;
if (centerFlag > 0)
{
rgb = { 180, 0, 0 };
size = 2;
}
else if(pt3D->nPointIdx < 3)
{
rgb = objColor[pt3D->nPointIdx % 8];
size = 2;
}
else //料筐
{
rgb = { 0, 200,200 };
size = 2;
}
}
else //if (pt3D->nPointIdx == 0)
{
rgb = { 200, 200, 200 };
size = 1;
}
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
if (objNum > 0)
{
int lastLineNum = objNum;
if (objNum < (int)scanLines[0].size())
lastLineNum = (int)scanLines[0].size();
sw << "Line_" << lineIdx << "_0_" << lastLineNum << std::endl;
size = 25;
for (int i = 0; i < objNum; i++)
{
if (i == 0)
rgb = { 250, 250, 0 };
else if (rodInfo[i].workpieceType > 0) //边上目标
rgb = { 0, 250, 250 };
else
rgb = { 250, 0, 0 };
float x = (float)rodInfo[i].center.x;
float y = (float)rodInfo[i].center.y;
float z = (float)rodInfo[i].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
for (int i = objNum; i < (int)scanLines[0].size(); i++)
{
sw << "{0,0,0}-{0,0}-{0,0}-{0,0,0,1 }" << std::endl;
}
//输出法向
size = 8;
double len = 60;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
if (i == 0)
rgb = { 250, 255, 0 };
else
rgb = { 250, 0, 0 };
SVzNL3DPoint pt0 = { rodInfo[i].center.x, rodInfo[i].center.y, rodInfo[i].center.z };
SVzNL3DPoint pt1 = { rodInfo[i].center.x + len * rodInfo[i].axialDir.x,
rodInfo[i].center.y + len * rodInfo[i].axialDir.y,
rodInfo[i].center.z + len * rodInfo[i].axialDir.z };
SVzNL3DPoint pt2 = { rodInfo[i].center.x + len * rodInfo[i].normalDir.x,
rodInfo[i].center.y + len * rodInfo[i].normalDir.y,
rodInfo[i].center.z + len * rodInfo[i].normalDir.z };
//显示轴向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)rodInfo[i].startPt.x << "," << (float)rodInfo[i].startPt.y << "," << (float)rodInfo[i].startPt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)rodInfo[i].endPt.x << "," << (float)rodInfo[i].endPt.y << "," << (float)rodInfo[i].endPt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt2.x << "," << (float)pt2.y << "," << (float)pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
lineIdx++;
if (binInfo)
{
rgb = { 0, 0, 250 };
//输出外接矩形
SVzNL3DPoint dirPt1 = binInfo->minRectVertex[0];
SVzNL3DPoint dirPt2 = binInfo->minRectVertex[1];
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << dirPt1.x << "," << dirPt1.y << "," << dirPt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << dirPt2.x << "," << dirPt2.y << "," << dirPt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
dirPt1 = binInfo->minRectVertex[1];
dirPt2 = binInfo->minRectVertex[2];
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << dirPt1.x << "," << dirPt1.y << "," << dirPt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << dirPt2.x << "," << dirPt2.y << "," << dirPt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
dirPt1 = binInfo->minRectVertex[2];
dirPt2 = binInfo->minRectVertex[3];
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << dirPt1.x << "," << dirPt1.y << "," << dirPt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << dirPt2.x << "," << dirPt2.y << "," << dirPt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
dirPt1 = binInfo->minRectVertex[3];
dirPt2 = binInfo->minRectVertex[0];
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << dirPt1.x << "," << dirPt1.y << "," << dirPt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << dirPt2.x << "," << dirPt2.y << "," << dirPt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
}
sw.close();
}
void _outputRGBDScan_RGBD_weldSeam(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_weldSeamInfo>& weldSeamInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)weldSeamInfo.size();
if (objNum > 0)
realLines += 1;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int maxLineIndex = 0;
int max_stamp = 0;
SG_color rgb = { 0, 0, 0 };
SG_color objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
int lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->nPointIdx > 0)
{
int centerFlag = pt3D->nPointIdx >> 4;
if (centerFlag > 0)
{
if (centerFlag <= 2)
{
rgb = { 180, 0, 0 };
size = 2;
}
else if(centerFlag == 4)
{
rgb = { 0, 250, 0 };
size = 4;
}
}
else
{
rgb = objColor[pt3D->nPointIdx % 8];
size = 2;
}
}
else //if (pt3D->nPointIdx == 0)
{
rgb = { 200, 200, 200 };
size = 1;
}
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
if (objNum > 0)
{
std::vector<SVzNL3DPoint> weldPoints;
for (int i = 0; i < objNum; i++)
{
if (weldSeamInfo[i].weldType == KeWD_WELD_POINT)
weldPoints.push_back(weldSeamInfo[i].center);
else
{
weldPoints.push_back(weldSeamInfo[i].startPt);
weldPoints.push_back(weldSeamInfo[i].center);
weldPoints.push_back(weldSeamInfo[i].endPt);
}
}
sw << "Line_" << lineIdx << "_0_" << (int)weldPoints.size() << std::endl;
size = 15;
for (int i = 0; i < (int)weldPoints.size(); i++)
{
rgb = { 250, 0, 0 };
float x = (float)weldPoints[i].x;
float y = (float)weldPoints[i].y;
float z = (float)weldPoints[i].z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
//输出法向
size = 4;
double len1 = 20;
double len2 = 20;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
SVzNL3DPoint pt0, pt1;
if (weldSeamInfo[i].weldType == KeWD_WELD_POINT)
{
pt0 = weldSeamInfo[i].center;
pt1 = { weldSeamInfo[i].center.x + len1 * weldSeamInfo[i].axialDir.x,
weldSeamInfo[i].center.y + len1 * weldSeamInfo[i].axialDir.y,
weldSeamInfo[i].center.z + len1 * weldSeamInfo[i].axialDir.z };
}
else
{
pt0 = weldSeamInfo[i].startPt;
pt1 = weldSeamInfo[i].endPt;
}
SVzNL3DPoint pt2 = { weldSeamInfo[i].center.x, weldSeamInfo[i].center.y, weldSeamInfo[i].center.z };
SVzNL3DPoint pt3 = { weldSeamInfo[i].center.x + len2 * weldSeamInfo[i].normalDir.x,
weldSeamInfo[i].center.y + len2 * weldSeamInfo[i].normalDir.y,
weldSeamInfo[i].center.z + len2 * weldSeamInfo[i].normalDir.z };
//显示轴向量
rgb = { 0, 0, 250 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt1.x << "," << (float)pt1.y << "," << (float)pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
//显示法向量
rgb = { 250, 0, 0 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt2.x << "," << (float)pt2.y << "," << (float)pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt3.x << "," << (float)pt3.y << "," << (float)pt3.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
lineIdx++;
}
sw.close();
}
#define SCREW_TEST_GROUP 12
void screwTest(void)
{
const char* dataPath[SCREW_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/数据/模拟数据/", //0
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云2/上方两根/", //1
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云3/", //2
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云4/位置1/", //3
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云4/位置2/", //4
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云4/位置2未动螺杆拧进去100mm左右/", //5
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云4/位置2向前100mm螺杆拧进去100mm左右/", //6
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云20260621/另一根螺杆/", //7
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云20260621/拍照点1/", //8
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/螺杆点云20260621/拍照点1xyz移动10mm/", //9
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/异常点云0615/", //10
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/异常点云0618/", //11
};
SVzNLRange fileIdx[SCREW_TEST_GROUP] = {
{1,4},{1,30},{1,11},
{1,20}, {1,20}, {1,5}, {1,21},
{1,10}, {1,10}, {1,10},
{1,9},{1,30}
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 11; grp <= 11; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =2;
char _scan_file[256];
if(0 == grp)
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
else if( (grp>= 7)&&(grp <= 9))
sprintf_s(_scan_file, "%sLaserline_%d.txt", dataPath[grp], fidx);
else if(10 == grp)
sprintf_s(_scan_file, "%s%d_LaserData.txt", dataPath[grp], fidx);
else
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C299.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
double rodDiameter;
if (grp == 0)
rodDiameter = 10.0;
else
rodDiameter = 32.0; //现场螺杆直径28mm
//double rodDiameter = 10.0;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 30; //45度角
cornerParam.scale = rodDiameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 20.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声
filterParam.outlierTh = 5;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 30;
growParam.yDeviation_max = 5.0;
growParam.maxSkipDistance = 30.0;
growParam.zDeviation_max = 50;//
growParam.minLTypeTreeLen = 50; //mm, 螺杆长度
growParam.minVTypeTreeLen = 50; //mm
bool isHorizonScan = true; //true:激光线平行槽道;false:激光线垂直槽道
int errCode = 0;
std::vector<SSX_rodPoseInfo> screwInfo;
sx_hexHeadScrewMeasure_PCA(
scanLines,
//isHorizonScan, //true:激光线平行槽道;false:激光线垂直槽道
cornerParam,
filterParam,
growParam,
rodDiameter,
screwInfo,
&errCode);
long t2 = (long)GetTickCount64();
//输出测试结果
char _out_file[256];
sprintf_s(_out_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD(_out_file, scanLines, screwInfo);
sprintf_s(_out_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputChanneltInfo(_out_file, screwInfo);
if (screwInfo.size() > 0)
{
SVzNL3DPoint zAxis = { 0, 0, 1.0 };
float angle = _computeVecAngle(screwInfo[0].axialDir, zAxis);
printf("%s: %d(ms), errCode=%d, {%f, %f, %f}, 与Z轴夹角=%f \n", _scan_file, (int)(t2 - t1), errCode,
(float)screwInfo[0].center.x, (float)screwInfo[0].center.y, (float)screwInfo[0].center.z, angle);
}
else
printf("%s: %d(ms), errCode=%d\n", _scan_file, (int)(t2 - t1), errCode);
}
}
}
#define LOCATING_PALTE_TEST_GROUP 1
void locatingPlateTest(void)
{
const char* dataPath[LOCATING_PALTE_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/定位盘点云/", //0
};
SVzNLRange fileIdx[LOCATING_PALTE_TEST_GROUP] = {
{1,17},
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 0; grp < LOCATING_PALTE_TEST_GROUP; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =2;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
double rodDiameter = 10.0;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 60; //45度角
cornerParam.scale = rodDiameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
int errCode = 0;
SSX_platePoseInfo centerPose = sx_getLocationPlatePose(
scanLines,
cornerParam,
& errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_centerPose(_scan_file, scanLines, centerPose);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputPlatePiseInfo(_scan_file, centerPose);
}
}
}
#define NEW_LOCATING_PALTE_TEST_GROUP 2
void newLocatingPlateTest(void)
{
const char* dataPath[NEW_LOCATING_PALTE_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/定位盘点云20260521/", //0
"F:/ShangGu/项目/冠钦项目/配天螺杆测量/配天现场点云/定位盘点云20260603/", //1
};
SVzNLRange fileIdx[NEW_LOCATING_PALTE_TEST_GROUP] = {
{12,13}, {1,52}
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 1; grp < NEW_LOCATING_PALTE_TEST_GROUP; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =16;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 45; //45度角
cornerParam.scale = 5.0; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
int errCode = 0;
SSX_platePoseInfo centerPose = sx_getLocationPlatePose_new(
scanLines,
cornerParam,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms),errCode=%d\n", _scan_file, (int)(t2 - t1), errCode);
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_centerPose(_scan_file, scanLines, centerPose);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputPlatePiseInfo(_scan_file, centerPose);
}
}
}
;
void _removeNullData(std::vector<std::vector< SVzNL3DPosition>>& scanLines, double _F, std::vector<std::vector< SVzNLPointXYZRGBA>>& scanData)
{
std::vector< SVzNLPointXYZRGBA> validPoints;
for (int line = 0; line < (int)scanLines.size(); line++)
{
for (int j = 0; j < (int)scanLines[line].size(); j++)
{
if (scanLines[line][j].pt3D.z > 1e-4)
{
SVzNLPointXYZRGBA a_pt;
double v = _F * scanLines[line][j].pt3D.y / scanLines[line][j].pt3D.z + 2000;
a_pt.nRGB = (int)(v + 0.5);
a_pt.x = scanLines[line][j].pt3D.x;
a_pt.y = scanLines[line][j].pt3D.y;
a_pt.z = scanLines[line][j].pt3D.z;
validPoints.push_back(a_pt);
}
}
}
std::vector< SVzNLPointXYZRGBA> a_line;
SVzNLPointXYZRGBA pre_pt;
pre_pt.x = 0;
pre_pt.y = 0;
pre_pt.z = 0;
pre_pt.nRGB = -1;
for (int i = 0; i < validPoints.size(); i++)
{
if (validPoints[i].nRGB < (pre_pt.nRGB - 10))
{
if (a_line.size() > 0)
scanData.push_back(a_line);
a_line.clear();
}
a_line.push_back(validPoints[i]);
pre_pt = validPoints[i];
}
if(a_line.size() > 0)
scanData.push_back(a_line);
return;
}
void _convertToGridData_XYZRGB(std::vector<std::vector< SVzNLPointXYZRGBA>>& scanData, double _F, std::vector<std::vector< SVzNL3DPosition>>& gridData)
{
int lineNum = (int)scanData.size();
int min_y = 100000000;
int max_y = -10000000;
int validStartLine = -1;
int validEndLine = -1;
for (int line = 0; line < lineNum; line++)
{
if (scanData[line].size() > 0)
{
if (validStartLine < 0)
{
validStartLine = line;
validEndLine = line;
}
else
validEndLine = line;
}
for (int i = 0; i < (int)scanData[line].size(); i++)
{
SVzNLPointXYZRGBA& a_pt = scanData[line][i];
if (a_pt.z > 1e-4)
{
double v = _F * a_pt.y / a_pt.z + 2000;
a_pt.nRGB = (int)(v + 0.5);
max_y = max_y < (int)a_pt.nRGB ? (int)a_pt.nRGB : max_y;
min_y = min_y > (int)a_pt.nRGB ? (int)a_pt.nRGB : min_y;
}
}
}
if (min_y == 100000000)
return;
int vldLineNum = validEndLine - validStartLine + 1;
gridData.resize(vldLineNum);
int pt_counter = max_y - min_y + 1;
for (int i = 0; i < vldLineNum; i++)
{
gridData[i].resize(pt_counter);
for (int j = 0; j < pt_counter; j++)
{
gridData[i][j].nPointIdx = j;
gridData[i][j].pt3D.x = 0;
gridData[i][j].pt3D.y = 0;
gridData[i][j].pt3D.z = 0;
}
}
for (int line = validStartLine; line <= validEndLine; line++)
{
int gridLine = line - validStartLine;
for (int i = 0; i < (int)scanData[line].size(); i++)
{
SVzNLPointXYZRGBA& a_pt = scanData[line][i];
if (a_pt.z > 1e-4)
{
int pt_id = a_pt.nRGB - min_y;
gridData[gridLine][pt_id].pt3D.x = a_pt.x;
gridData[gridLine][pt_id].pt3D.y = a_pt.y;
gridData[gridLine][pt_id].pt3D.z = a_pt.z;
}
}
}
return;
}
void rotationMatrixToEulerZYX1(const double R[9], double rpy[3]) {
// 计算俯仰角(pitch)θ
double pitch = asin(-R[6]); // asin返回弧度
double yaw, roll;
// 检查万向节锁(cosθ接近0)
const double epsilon = 1e-6;
if (abs(cos(pitch)) > epsilon) {
// 无万向节锁,正常计算yaw和roll
yaw = atan2(R[3], R[0]);
roll = atan2(R[7], R[8]);
}
else {
// 万向节锁,约定roll=0,计算yaw
roll = 0.0;
yaw = atan2(-R[1], R[4]);
}
// 将弧度转换为角度
const double rad2deg = 180.0 / M_PI;
rpy[2] = yaw* rad2deg;
rpy[1] = pitch* rad2deg;
rpy[0] = roll* rad2deg;
return;
}
void EulerRpyToRotation1(const double rpy[3], double matrix3d[9]) {
double cos0 = cos(rpy[0] * PI / 180);
double sin0 = sin(rpy[0] * PI / 180);
double cos1 = cos(rpy[1] * PI / 180);
double sin1 = sin(rpy[1] * PI / 180);
double cos2 = cos(rpy[2] * PI / 180);
double sin2 = sin(rpy[2] * PI / 180);
matrix3d[0] = cos2 * cos1;
matrix3d[1] = cos2 * sin1 * sin0 - sin2 * cos0;
matrix3d[2] = cos2 * sin1 * cos0 + sin2 * sin0;
matrix3d[3] = sin2 * cos1;
matrix3d[4] = sin2 * sin1 * sin0 + cos2 * cos0;
matrix3d[5] = sin2 * sin1 * cos0 - cos2 * sin0;
matrix3d[6] = -sin1;
matrix3d[7] = cos1 * sin0;
matrix3d[8] = cos1 * cos0;
return;
}
SVzNL3DPoint _ptRotate(SVzNL3DPoint pt3D, double matrix3d[9])
{
SVzNL3DPoint _r_pt;
_r_pt.x = pt3D.x * matrix3d[0] + pt3D.y * matrix3d[1] + pt3D.z * matrix3d[2];
_r_pt.y = pt3D.x * matrix3d[3] + pt3D.y * matrix3d[4] + pt3D.z * matrix3d[5];
_r_pt.z = pt3D.x * matrix3d[6] + pt3D.y * matrix3d[7] + pt3D.z * matrix3d[8];
return _r_pt;
}
void _rotateCloudPts(
std::vector<std::vector< SVzNL3DPosition>>& scanLines,
double matrix3d[9],
std::vector<std::vector< SVzNL3DPosition>>& rotateLines,
SVzNLRangeD& rx_range, SVzNLRangeD& ry_range)
{
int lineNum = (int)scanLines.size();
rotateLines.resize(lineNum);
rx_range.min = 0;
rx_range.max = -1;
ry_range.min = 0;
ry_range.max = -1;
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < (int)scanLines[line].size(); i++)
{
SVzNL3DPosition& pt3D = scanLines[line][i];
if (pt3D.pt3D.z < 1e-4)
continue;
SVzNL3DPosition r_pt;
r_pt.pt3D = _ptRotate(pt3D.pt3D, matrix3d);
r_pt.nPointIdx = pt3D.nPointIdx;
rotateLines[line].push_back(r_pt);
if (rx_range.max < rx_range.min)
{
rx_range.min = r_pt.pt3D.x;
rx_range.max = r_pt.pt3D.x;
}
else
{
if (rx_range.min > r_pt.pt3D.x)
rx_range.min = r_pt.pt3D.x;
if (rx_range.max < r_pt.pt3D.x)
rx_range.max = r_pt.pt3D.x;
}
if (ry_range.max < ry_range.min)
{
ry_range.min = r_pt.pt3D.y;
ry_range.max = r_pt.pt3D.y;
}
else
{
if (ry_range.min > r_pt.pt3D.y)
ry_range.min = r_pt.pt3D.y;
if (ry_range.max < r_pt.pt3D.y)
ry_range.max = r_pt.pt3D.y;
}
}
}
}
void _XOYprojection_rodInfo(
cv::Mat& img,
std::vector<std::vector< SVzNL3DPosition>>& dataLines,
std::vector<SSX_rodPositionInfo>& rodInfo,
std::vector<SVzNL3DPoint>& binRectVertex,
const double scale,
const int sideWidth,
const SVzNLRangeD x_range,
const SVzNLRangeD y_range,
const double dirAngleLen)
{
cv::Vec3b rgb = cv::Vec3b(0, 0, 0);
cv::Vec3b objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
for (int line = 0; line < dataLines.size(); line++)
{
std::vector< SVzNL3DPosition>& a_line = dataLines[line];
for (int i = 0; i < a_line.size(); i++)
{
SVzNL3DPosition& pt3D = a_line[i];
if (pt3D.pt3D.z < 1e-4)
continue;
if (pt3D.nPointIdx > 0)
{
int centerFlag = pt3D.nPointIdx >> 4;
if (centerFlag > 0)
{
rgb = { 180, 0, 0 };
size = 2;
}
else if(pt3D.nPointIdx < 3)
{
rgb = objColor[pt3D.nPointIdx % 8];
size = 2;
}
else //料筐
{
rgb = { 0, 200, 200 };
size = 2;
}
}
else //if (pt3D->nPointIdx == 0)
{
rgb = { 250, 250, 250 };
size = 1;
}
double x = pt3D.pt3D.x;
double y = pt3D.pt3D.y;
int px = (int)((x - x_range.min) / scale + sideWidth);
int py = (int)((y - y_range.min) / scale + sideWidth);
if (size == 1)
img.at<cv::Vec3b>(py, px) = cv::Vec3b(rgb[2], rgb[1], rgb[0]);
else
cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1);
}
}
if (rodInfo.size() > 0)
{
for (int i = 0; i < (int)rodInfo.size(); i++)
{
if (i == 0)
rgb = { 255, 255, 0 };
else if (rodInfo[i].workpieceType > 0) //边上目标
rgb = { 0, 250, 250 };
else
rgb = { 255, 0, 0 };
size = int(10.0 / scale);
int px = (int)((rodInfo[i].center.x - x_range.min) / scale + sideWidth);
int py = (int)((rodInfo[i].center.y - y_range.min) / scale + sideWidth);
cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1);
//画圆
int px1 = (int)((rodInfo[i].startPt.x - x_range.min) / scale + sideWidth);
int py1 = (int)((rodInfo[i].startPt.y - y_range.min) / scale + sideWidth);
int px2 = (int)((rodInfo[i].endPt.x - x_range.min) / scale + sideWidth);
int py2 = (int)((rodInfo[i].endPt.y - y_range.min) / scale + sideWidth);
size = int(5.0 / scale);
if (size == 0)
size = 1;
cv::line(img, cv::Point(px1, py1), cv::Point(px2, py2), cv::Scalar(rgb[2], rgb[1], rgb[0]), size);
}
}
if (binRectVertex.size() == 4)
{
for (int i = 0; i < 4; i++)
{
int idx_0 = i;
int idx_1 = (i + 1) % 4;
double x1 = binRectVertex[idx_0].x;
double y1 = binRectVertex[idx_0].y;
int px1 = (int)((x1 - x_range.min) / scale + sideWidth);
int py1 = (int)((y1 - y_range.min) / scale + sideWidth);
double x2 = binRectVertex[idx_1].x;
double y2 = binRectVertex[idx_1].y;
int px2 = (int)((x2 - x_range.min) / scale + sideWidth);
int py2 = (int)((y2 - y_range.min) / scale + sideWidth);
rgb = { 0, 0, 255 };
cv::line(img, cv::Point(px1, py1), cv::Point(px2, py2), cv::Scalar(rgb[2], rgb[1], rgb[0]), 2);
}
}
}
void _genXOYProjectionImage_rodInfo(
cv::String& fileName,
std::vector<std::vector< SVzNL3DPosition>>& scanLines,
const double scale,
std::vector<SSX_rodPositionInfo>& rodInfo,
SWD_BinInfo* binInfo,
const double rpy[3], const double dirLen)
{
//旋转视角显示
double matrix3d[9];
EulerRpyToRotation1(rpy, matrix3d);
std::vector<SSX_rodPositionInfo> rotatedRod;
for (int i = 0; i < (int)rodInfo.size(); i++)
{
SSX_rodPositionInfo rotateObj;
rotateObj.id = rodInfo[i].id;
rotateObj.workpieceType = rodInfo[i].workpieceType;
rotateObj.center = _ptRotate(rodInfo[i].center, matrix3d);
rotateObj.axialDir = _ptRotate(rodInfo[i].axialDir, matrix3d);
rotateObj.normalDir = _ptRotate(rodInfo[i].normalDir, matrix3d);
rotateObj.startPt = _ptRotate(rodInfo[i].startPt, matrix3d);
rotateObj.endPt = _ptRotate(rodInfo[i].endPt, matrix3d);
rotatedRod.push_back(rotateObj);
}
std::vector<std::vector< SVzNL3DPosition>> rotateLines;
SVzNLRangeD rx_range, ry_range;
_rotateCloudPts(scanLines, matrix3d, rotateLines, rx_range, ry_range);
std::vector<SVzNL3DPoint> binRectVertex;//最小外接矩形顶点
if (binInfo)
{
binRectVertex.resize(4);
for (int i = 0; i < 4; i++)
{
binRectVertex[i] = _ptRotate(binInfo->minRectVertex[i], matrix3d);
if (rx_range.max < rx_range.min)
{
rx_range.min = binRectVertex[i].x;
rx_range.max = binRectVertex[i].x;
}
else
{
if (rx_range.min > binRectVertex[i].x)
rx_range.min = binRectVertex[i].x;
if (rx_range.max < binRectVertex[i].x)
rx_range.max = binRectVertex[i].x;
}
if (ry_range.max < ry_range.min)
{
ry_range.min = binRectVertex[i].y;
ry_range.max = binRectVertex[i].y;
}
else
{
if (ry_range.min > binRectVertex[i].y)
ry_range.min = binRectVertex[i].y;
if (ry_range.max < binRectVertex[i].y)
ry_range.max = binRectVertex[i].y;
}
}
}
//统计X和Y的范围
int x_cols = (int)((rx_range.max - rx_range.min) / scale) + 1;
if (x_cols % 2 == 1)
x_cols += 1;
int y_rows = (int)((ry_range.max - ry_range.min) / scale) + 1;
if (y_rows % 2 == 1)
y_rows += 1;
int sideWidth = 32;
int imgCols = x_cols + sideWidth * 2;
int imgRows = y_rows + sideWidth * 2;
cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3);
//计算投影比例
_XOYprojection_rodInfo(img, rotateLines, rotatedRod, binRectVertex, scale, sideWidth, rx_range, ry_range, dirLen);
cv::imwrite(fileName, img);
return;
}
#define ROD_POSITION_TEST_GROUP 8
#define TEST_CONVERT_TO_GRID 0
#define TEST_COMPUTE_CALIB_PARA 0
#define TEST_COMPUTE_ROD_POSITION 1
void rodPositionTest(void)
{
#if TEST_CONVERT_TO_GRID
//将数据转换成栅格格式格式
char _scan_dir[256];
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
sprintf_s(_scan_dir, "F:/ShangGu/项目/冠钦项目/矩森棒材抓取/空料框及内剩一根棒材/");
char _scan_src_file[256];
double _F = 1219.15; //f
for (int i = 1; i <= 3; i++)
{
//read ply txt
sprintf_s(_scan_src_file, "%sLaserDataRAW_%d.txt", _scan_dir, i);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_src_file, scanLines);
std::vector<std::vector< SVzNLPointXYZRGBA>> scanData;
_removeNullData(scanLines, _F, scanData);
std::vector<std::vector< SVzNL3DPosition>> gridData;
_convertToGridData_XYZRGB(scanData, _F, gridData);
char _out_file[256];
sprintf_s(_out_file, "%sLaserData_%d.txt", _scan_dir, i);
_outputScanDataFile(_out_file, gridData, 0.0f, 0, 0);
printf("%s: convert done!\n", _scan_src_file);
}
printf("all converted done!\n", _scan_src_file);
#endif
#if TEST_COMPUTE_CALIB_PARA
const char* calibDataPath = "F:/ShangGu/项目/冠钦项目/矩森棒材抓取/异常点云/";
char _calib_datafile[256];
sprintf_s(_calib_datafile, "%sGroundData_1.txt", calibDataPath);
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
std::vector<std::vector< SVzNL3DPosition>> scanData;
wdReadLaserScanPointFromFile_XYZ_vector(_calib_datafile, scanData);
lineNum = (int)scanData.size();
if (scanData.size() > 0)
{
SSG_planeCalibPara calibPara = sx_rodPosition_getBaseCalibPara(scanData);
//结果进行验证
for (int i = 0; i < lineNum; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sx_rodPosition_lineDataR(scanData[i], calibPara.planeCalib, -1);
}
//
char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", calibDataPath);
_outputCalibPara(calibFile, calibPara);
char _out_file[256];
sprintf_s(_out_file, "%sGroundData_1_calib_verify.txt", calibDataPath);
_outputScanDataFile(_out_file, scanData, lineV, maxTimeStamp, clockPerSecond);
#if 0
for (int fidx = fileIdx[cvtGrp].nMin; fidx <= fileIdx[cvtGrp].nMax; fidx++)
{
//fidx =4;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[cvtGrp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
if (scanLines.size() == 0)
continue;
lineNum = (int)scanLines.size();
for (int i = 0; i < lineNum; i++)
{
//调平,去除地面
wd_lineDataR(scanLines[i], calibPara.planeCalib, -1);
}
sprintf_s(_scan_file, "%sLaserData_%d_calib_verify.txt", dataPath[cvtGrp], fidx);
int headNullLines = 0;
_outputScanDataFile_vector(_scan_file, scanLines, false, &headNullLines);
}
#endif
printf("%s: calib done!\n", _calib_datafile);
}
#endif
#if TEST_COMPUTE_ROD_POSITION
const char* dataPath[ROD_POSITION_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/测试数据/", //0
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/空料框及内剩一根棒材/", //1
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/其它尺寸棒材点云/", //2
"F:/ShangGu/项目/冠钦项目/胶布圆棒抓取/模拟测试数据/", //3
"F:/ShangGu/项目/冠钦项目/胶布圆棒抓取/模拟测试数据2/", //4
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/异常点云/", //5
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/异常点云2/", //6
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/异常点云3/", //7
};
SVzNLRange fileIdx[ROD_POSITION_TEST_GROUP] = {
{1,8}, {1,3}, {1,31},
{1,5},{1,11},{1,26},{1,41}, {1, 23}
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 7; grp <= 7; grp++)
{
SSG_planeCalibPara poseCalibPara;
//初始化成单位阵
poseCalibPara.planeCalib[0] = 1.0;
poseCalibPara.planeCalib[1] = 0.0;
poseCalibPara.planeCalib[2] = 0.0;
poseCalibPara.planeCalib[3] = 0.0;
poseCalibPara.planeCalib[4] = 1.0;
poseCalibPara.planeCalib[5] = 0.0;
poseCalibPara.planeCalib[6] = 0.0;
poseCalibPara.planeCalib[7] = 0.0;
poseCalibPara.planeCalib[8] = 1.0;
poseCalibPara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
poseCalibPara.invRMatrix[i] = poseCalibPara.planeCalib[i];
char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
poseCalibPara = _readCalibPara(calibFile);
sprintf_s(calibFile, "%sparameter.txt", dataPath[grp]);
std::vector<SSX_rodParam> rodParas;
if (grp <= 2)
_readRodParas(calibFile, rodParas);
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =10;
char _scan_file[256];
if( (3 == grp) ||(4 == grp))
sprintf_s(_scan_file, "%s%d_LaserData_Hi229156.txt", dataPath[grp], fidx);
else if(5 == grp)
sprintf_s(_scan_file, "%s%d_LaserData_Ik256066.txt", dataPath[grp], fidx);
else if (6 == grp)
sprintf_s(_scan_file, "%s%d_LaserData_Ik256066.txt", dataPath[grp], fidx);
else if(7 == grp)
sprintf_s(_scan_file, "%s%d_cloud.txt", dataPath[grp], fidx);
else
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
SSX_rodParam rodParam;
if (grp <= 2)
{
rodParam = rodParas[fidx];
}
else if (grp == 5)
{
rodParam.diameter = 96.0; //圆棒直径
rodParam.len = 440;
}
else if ( (grp == 6) ||(grp ==7))
{
rodParam.diameter = 62.0; //圆棒直径
rodParam.len = 380;
}
else
{
rodParam.diameter = 68.0; //圆棒直径
rodParam.len = 187;
}
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 30; //45度角
cornerParam.scale = rodParam.diameter / 6; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 5.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声
filterParam.outlierTh = 5;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 15;
growParam.yDeviation_max = 20.0;
growParam.maxSkipDistance = 25.0;
growParam.zDeviation_max = 10.0;//
growParam.minLTypeTreeLen = rodParam.len * 0.75; //mm, 螺杆长度
growParam.minVTypeTreeLen = rodParam.len * 0.75; //mm
const double distToSideRatio = 1.1; //边距系数,边距门限=边距系数*工件直径;当工件距边的距离大于边距门限时,判断为边上的工件
double groundRemoveOffset = 100; //料筐地面去除的Z偏置,实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
double clusterNDist; //料筐聚类尺度, 当两点距离小于此尺度时, 被聚为一类。此参数和点云密度相关,用于滤除料筐周围的干扰。
if ( grp == 5)
clusterNDist = 10.0;// 10.0;
else if (grp == 6)
clusterNDist = 15.0;
else if (grp == 7)
clusterNDist = 15.0;
int errCode = 0;
std::vector<SSX_rodPositionInfo> rodInfo;
SWD_BinInfo binInfo;
sx_rodPositioning(
scanLines,
poseCalibPara,
cornerParam,
filterParam,
growParam,
rodParam,
distToSideRatio,
groundRemoveOffset,
clusterNDist,
rodInfo,
binInfo,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms),errCode=%d\n", _scan_file, (int)(t2 - t1),errCode);
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_rodInfo(_scan_file, scanLines, rodInfo, &binInfo);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputRodtInfo(_scan_file, rodInfo);
#if 1
sprintf_s(_scan_file, "%sresult/%d_result_projection.png", dataPath[grp], fidx);
double rpy[3] = { -60, 0, 10 }; //{ 0,-45, 0 }; //
double angleDrawLen = 15;
double displayScale = 1.0;
cv::String imgName(_scan_file);
_genXOYProjectionImage_rodInfo(imgName, scanLines, displayScale, rodInfo, &binInfo, rpy, angleDrawLen);
//正投影
sprintf_s(_scan_file, "%sresult/%d_result_projection_2.png", dataPath[grp], fidx);
rotationMatrixToEulerZYX1(poseCalibPara.planeCalib, rpy);
cv::String imgName2(_scan_file);
_genXOYProjectionImage_rodInfo(imgName2, scanLines, displayScale, rodInfo, &binInfo, rpy, angleDrawLen);
#endif
}
}
#endif
}
int counterValidPts(std::vector<SVzNL3DPosition>& lineData)
{
int num = 0;
for (int i = 0; i < (int)lineData.size(); i++)
{
if (lineData[i].pt3D.z > 1e-4)
num++;
else
{
lineData[i].pt3D = { 0, 0, 0 };
}
}
return num;
}
#define WELD_SEAM_TEST_GROUP 4
void rodWeldSeamPosition_test(void)
{
const char* dataPath[WELD_SEAM_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/视觉照片1/", //0
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/视觉照片2/", //1
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/数据3/特征点1/", //2
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/数据3/特征点2/", //3
};
SVzNLRange fileIdx[WELD_SEAM_TEST_GROUP] = {
{1,20},{1,20},{1,27}, { 1,21 },
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 2; grp < WELD_SEAM_TEST_GROUP; grp++)
{
SSG_planeCalibPara poseCalibPara;
//初始化成单位阵
poseCalibPara.planeCalib[0] = 1.0;
poseCalibPara.planeCalib[1] = 0.0;
poseCalibPara.planeCalib[2] = 0.0;
poseCalibPara.planeCalib[3] = 0.0;
poseCalibPara.planeCalib[4] = 1.0;
poseCalibPara.planeCalib[5] = 0.0;
poseCalibPara.planeCalib[6] = 0.0;
poseCalibPara.planeCalib[7] = 0.0;
poseCalibPara.planeCalib[8] = 1.0;
poseCalibPara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
poseCalibPara.invRMatrix[i] = poseCalibPara.planeCalib[i];
//char calibFile[250];
//sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
//poseCalibPara = _readCalibPara(calibFile);
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =1;
char _scan_file[256];
sprintf_s(_scan_file, "%s%d_LaserData_groundAdjusted.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
if ((grp == 2) || (grp == 3)) //计算调平矩阵
{
#if 0
std::vector<cv::Point3f> validPts;
std::vector<std::vector< SVzNL3DPosition>> copy_scanLines;
copy_scanLines.resize(scanLines.size());
for (int line = 0; line < (int)scanLines.size(); line++)
{
std::vector< SVzNL3DPosition>& a_line = scanLines[line];
copy_scanLines[line].resize(a_line.size());
for (int j = 0; j < (int)a_line.size(); j++)
{
copy_scanLines[line][j] = a_line[j];
if (a_line[j].pt3D.z > 1e-4)
{
cv::Point3f a_pt = cv::Point3f((float)a_line[j].pt3D.x, (float)a_line[j].pt3D.y, (float)a_line[j].pt3D.z);
validPts.push_back(a_pt);
}
}
}
std::vector<cv::Point3f> out_inliers;
Plane res = ransacFitPlane(validPts, out_inliers);
if (res.C < 0)
{
res.A = -res.A;
res.B = -res.B;
res.C = -res.C;
res.D = -res.D;
}
float meanH = 0;
int counter = 0;
for (int i = 0; i < (int)out_inliers.size(); i++)
{
meanH += out_inliers[i].z;
counter++;
}
//计算投影向量
SVzNL3DPoint vec_1 = { res.A, res.B, res.C };
SVzNL3DPoint vec_2 = { 0, 0, 1.0 };
SSG_planeCalibPara calibPara = wd_computeRTMatrix(vec_1, vec_2);
for (int m = 0; m < 9; m++)
{
poseCalibPara.planeCalib[m] = calibPara.planeCalib[m];
poseCalibPara.invRMatrix[m] = calibPara.invRMatrix[m];
}
poseCalibPara.planeHeight = meanH / counter;
char _out_file[256];
sprintf_s(_out_file, "%s%d_calib_para.txt", dataPath[grp], fidx);
_outputCalibPara(_out_file, poseCalibPara);
sprintf_s(_out_file, "%s%d_LaserData_groundAdjusted.txt", dataPath[grp], fidx);
//if (false == fileExists(_out_file))
{
//输出调平效果
int firstValidLine = -1;
int lastValidLine = -1;
for (int line = 0; line < (int)copy_scanLines.size(); line++)
{
//行处理
//调平,去除地面
double cuttingZ = poseCalibPara.planeHeight - 100;
sx_rodPosition_lineDataR(copy_scanLines[line], poseCalibPara.planeCalib, cuttingZ);
int ptsNum = counterValidPts(copy_scanLines[line]);
if (ptsNum > 10)
{
if (firstValidLine < 0)
firstValidLine = line;
lastValidLine = line;
}
}
if ((lastValidLine > 0) && (lastValidLine < copy_scanLines.size() - 1))
{
copy_scanLines.erase(copy_scanLines.begin() + lastValidLine + 1, copy_scanLines.end());
}
if(firstValidLine > 1)
{
copy_scanLines.erase(copy_scanLines.begin(), copy_scanLines.begin() + firstValidLine - 1);
}
_outputScanDataFile(_out_file, copy_scanLines, 0.0f, 0, 0);
}
#endif
}
long t1 = (long)GetTickCount64();//统计时间
SSX_rodParam rodParam;
rodParam.diameter = 16.0; //钢筋直径
rodParam.len = 50;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 60; //45度角
cornerParam.scale = rodParam.diameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 4.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声
filterParam.outlierTh = 4;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 5;
growParam.yDeviation_max = 5.0;
growParam.maxSkipDistance = 20.0;
growParam.zDeviation_max = 5.0;//
growParam.minLTypeTreeLen = 50; //mm, 螺杆长度
growParam.minVTypeTreeLen = 50; //mm
bool isHorizonScan = true; //true:激光线平行槽道;false:激光线垂直槽道
SVzNLRangeD weldSeamRange;//焊缝距钢筋交叉点的范围
if ((grp == 0) || (grp == 1))
{
weldSeamRange.min = rodParam.diameter / 2;
weldSeamRange.max = 100;
}
else
{
weldSeamRange.min = 0;
weldSeamRange.max = 80;
}
EWD_weldingCategory weldCategory;
if ((grp == 0) || (grp == 1))
weldCategory = KeWD_WELD_CATEGPRY_I;
else
weldCategory = KeWD_WELD_CATEGPRY_II;
int errCode = 0;
std::vector<SSX_weldSeamInfo> weldSeamInfo;
sx_rebarWeldSeamPositioning(
scanLines,
poseCalibPara,
cornerParam,
filterParam,
growParam,
rodParam,
weldSeamRange,
weldCategory,
weldSeamInfo,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
if (errCode == 0)
{
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_weldSeam(_scan_file, scanLines, weldSeamInfo);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputWeldSeamInfo(_scan_file, weldSeamInfo);
}
}
}
}
typedef enum
{
keSG_测试_配天螺杆定位 = 0,
keSG_测试_配天定位盘定位,
keSG_测试_配天新定位盘定位,
keSG_测试_矩森棒材抓取,
keSG_测试_筑裕钢筋焊缝定位,
} ESG_testMode;
int main()
{
//ESG_testMode testMode = keSG_测试_配天螺杆定位;
//ESG_testMode testMode = keSG_测试_配天定位盘定位;
//ESG_testMode testMode = keSG_测试_配天新定位盘定位;
ESG_testMode testMode = keSG_测试_矩森棒材抓取;
//ESG_testMode testMode = keSG_测试_筑裕钢筋焊缝定位;
if(keSG_测试_配天螺杆定位 == testMode)
screwTest();
else if(keSG_测试_配天定位盘定位 == testMode)
locatingPlateTest();
else if (keSG_测试_配天新定位盘定位 == testMode)
newLocatingPlateTest();
else if(keSG_测试_矩森棒材抓取 == testMode)
rodPositionTest();
else if(keSG_测试_筑裕钢筋焊缝定位 == testMode)
rodWeldSeamPosition_test();
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件