hybridPosePositioning

version 1.3.9 : 转子钢芯, 改进了料筐检测方法
This commit is contained in:
jerryzeng 2026-08-25 23:41:55 +08:00
parent 737d741406
commit bf8b449e48
3 changed files with 286 additions and 40 deletions

View File

@ -674,6 +674,7 @@ void _outputRGBDResult_XYZ_RGBD_workpieceInfo(
char* fileName, char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines, std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<WD_workpieceInfo>& poseInfo, std::vector<WD_workpieceInfo>& poseInfo,
WD_HRM_BinInfo* binInfo,
double dirLen) double dirLen)
{ {
int objNumber = 0; int objNumber = 0;
@ -793,6 +794,55 @@ void _outputRGBDResult_XYZ_RGBD_workpieceInfo(
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl; 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(); sw.close();
@ -1651,6 +1701,7 @@ void _XOYprojection_workpieceInfo(
cv::Mat& img, cv::Mat& img,
std::vector<std::vector< SVzNL3DPosition>>& dataLines, std::vector<std::vector< SVzNL3DPosition>>& dataLines,
std::vector<WD_workpieceInfo>& workpieceInfo, std::vector<WD_workpieceInfo>& workpieceInfo,
std::vector<SVzNL3DPoint>& binRectVertex,
const double scale, const double scale,
const int sideWidth, const int sideWidth,
const SVzNLRangeD x_range, const SVzNLRangeD x_range,
@ -1719,6 +1770,24 @@ void _XOYprojection_workpieceInfo(
cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), 2); cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), 2);
} }
} }
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 }; //y轴用绿色
cv::line(img, cv::Point(px1, py1), cv::Point(px2, py2), cv::Scalar(rgb[2], rgb[1], rgb[0]), 2);
}
}
} }
void _genXOYProjectionImage_workpieceInfo( void _genXOYProjectionImage_workpieceInfo(
@ -1726,6 +1795,7 @@ void _genXOYProjectionImage_workpieceInfo(
std::vector<std::vector< SVzNL3DPosition>>& scanLines, std::vector<std::vector< SVzNL3DPosition>>& scanLines,
const double scale, const double scale,
std::vector<WD_workpieceInfo>& workpieceInfo, std::vector<WD_workpieceInfo>& workpieceInfo,
WD_HRM_BinInfo* binInfo,
const double rpy[3], const double dirLen) const double rpy[3], const double dirLen)
{ {
//旋转视角显示 //旋转视角显示
@ -1749,7 +1819,40 @@ void _genXOYProjectionImage_workpieceInfo(
SVzNLRangeD rx_range, ry_range; SVzNLRangeD rx_range, ry_range;
_rotateCloudPts(scanLines, matrix3d, rotateLines, rx_range, ry_range); _rotateCloudPts(scanLines, matrix3d, rotateLines, rx_range, ry_range);
//统计X和Y的范围 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;
}
}
}
int x_cols = (int)((rx_range.max - rx_range.min) / scale) + 1; int x_cols = (int)((rx_range.max - rx_range.min) / scale) + 1;
if (x_cols % 2 == 1) if (x_cols % 2 == 1)
x_cols += 1; x_cols += 1;
@ -1763,7 +1866,7 @@ void _genXOYProjectionImage_workpieceInfo(
cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3); cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3);
//计算投影比例 //计算投影比例
_XOYprojection_workpieceInfo(img, rotateLines, rotatedWorkpiece, scale, sideWidth, rx_range, ry_range, dirLen); _XOYprojection_workpieceInfo(img, rotateLines, rotatedWorkpiece, binRectVertex, scale, sideWidth, rx_range, ry_range, dirLen);
cv::imwrite(fileName, img); cv::imwrite(fileName, img);
return; return;
} }
@ -2145,17 +2248,18 @@ void HaiRuiMa_groundCalib_test(void)
} }
//拓普发工件孔定位(工件定位) //拓普发工件孔定位(工件定位)
#define HRM_RotorCore_TEST_GROUP 2 #define HRM_RotorCore_TEST_GROUP 3
void HaiRuiMa_rotorCorePositioning_test(void) void HaiRuiMa_rotorCorePositioning_test(void)
{ {
const char* dataPath[HRM_RotorCore_TEST_GROUP] = { const char* dataPath[HRM_RotorCore_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/宁波海瑞马/转子钢芯/数据2D3D/", //0 "F:/ShangGu/项目/冠钦项目/宁波海瑞马/转子钢芯/数据2D3D/", //0
"F:/ShangGu/项目/冠钦项目/宁波海瑞马/转子钢芯/WorkpieceRotor/", //1 "F:/ShangGu/项目/冠钦项目/宁波海瑞马/转子钢芯/WorkpieceRotor/", //1
"F:/ShangGu/项目/冠钦项目/宁波海瑞马/转子钢芯/现场数据/"
}; };
SVzNLRange fileIdx[HRM_RotorCore_TEST_GROUP] = { SVzNLRange fileIdx[HRM_RotorCore_TEST_GROUP] = {
{1,10}, {3,70} {1,10}, {3,70},{1,1}
}; };
const char* ver = wd_hybridPositioningVersion(); const char* ver = wd_hybridPositioningVersion();
@ -2183,7 +2287,7 @@ void HaiRuiMa_rotorCorePositioning_test(void)
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{ {
//fidx = 26; //fidx = 50;
char _scan_file[256]; char _scan_file[256];
sprintf_s(_scan_file, "%s%d_cloud.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%s%d_cloud.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNLPositionD>> scanLines; std::vector<std::vector< SVzNLPositionD>> scanLines;
@ -2199,6 +2303,7 @@ void HaiRuiMa_rotorCorePositioning_test(void)
#endif #endif
WD_HRM_BinInfo binInfo; WD_HRM_BinInfo binInfo;
#if 0
if (grp == 1) if (grp == 1)
{ {
std::vector< std::vector<SVzNL3DPosition>> scanData; std::vector< std::vector<SVzNL3DPosition>> scanData;
@ -2217,13 +2322,13 @@ void HaiRuiMa_rotorCorePositioning_test(void)
double zSliceRange = 50.0; //取料筐最上边沿的Z切片范围 double zSliceRange = 50.0; //取料筐最上边沿的Z切片范围
binInfo = wd_HRM_getBinSize(scanData, groundCalibPara, binHeight, zSliceRange, &rCode); binInfo = wd_HRM_getBinSize(scanData, groundCalibPara, binHeight, zSliceRange, &rCode);
} }
else else if(grp == 0)
{ {
//读取料筐参数 //读取料筐参数
sprintf_s(calibFile, "%sbin_info.txt", dataPath[grp]); sprintf_s(calibFile, "%sbin_info.txt", dataPath[grp]);
binInfo = _readBinInfo(calibFile); binInfo = _readBinInfo(calibFile);
} }
#endif
sprintf_s(_scan_file, "%s%d_result.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%s%d_result.txt", dataPath[grp], fidx);
std::vector<WD_objArea2D> objROIs; std::vector<WD_objArea2D> objROIs;
if( (grp == 0) && (fidx <= 9)) if( (grp == 0) && (fidx <= 9))
@ -2235,6 +2340,7 @@ void HaiRuiMa_rotorCorePositioning_test(void)
workpieceParam.radius = 45.0; workpieceParam.radius = 45.0;
workpieceParam.height = 20.0; workpieceParam.height = 20.0;
double groundRemoveOffset = 200; //料筐地面去除的Z偏置,实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
long t1 = (long)GetTickCount64();//统计时间 long t1 = (long)GetTickCount64();//统计时间
int errCode = 0; int errCode = 0;
@ -2243,10 +2349,11 @@ void HaiRuiMa_rotorCorePositioning_test(void)
wd_HRM_RotorCorePositioning( wd_HRM_RotorCorePositioning(
scanLines, scanLines,
objROIs, objROIs,
binInfo,
groundCalibPara, groundCalibPara,
workpieceParam, workpieceParam,
groundRemoveOffset,
workpiecePositions, workpiecePositions,
binInfo,
#ifdef _OUTPUT_DEBUG_DATA #ifdef _OUTPUT_DEBUG_DATA
debugScanLines, debugScanLines,
#endif #endif
@ -2277,14 +2384,14 @@ void HaiRuiMa_rotorCorePositioning_test(void)
workpiecePositions[i].x_dir = rpt; workpiecePositions[i].x_dir = rpt;
} }
sprintf_s(_scan_file, "%sresult/result_%d.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%sresult/result_%d.txt", dataPath[grp], fidx);
_outputRGBDResult_XYZ_RGBD_workpieceInfo(_scan_file, debugScanLines, workpiecePositions, 50); _outputRGBDResult_XYZ_RGBD_workpieceInfo(_scan_file, debugScanLines, workpiecePositions, &binInfo, 50);
#if 1 #if 1
sprintf_s(calibFile, "%sresult/result_%d_projection.png", dataPath[grp], fidx); sprintf_s(calibFile, "%sresult/result_%d_projection.png", dataPath[grp], fidx);
double rpy[3] = { 0, 0, 0 }; //{ 0,-45, 0 }; // double rpy[3] = { 0, 0, 0 }; //{ 0,-45, 0 }; //
double angleDrawLen = 15; double angleDrawLen = 15;
double displayScale = 0.3; double displayScale = 0.3;
cv::String imgName(calibFile); cv::String imgName(calibFile);
_genXOYProjectionImage_workpieceInfo(imgName, debugScanLines, displayScale, workpiecePositions, rpy, angleDrawLen); _genXOYProjectionImage_workpieceInfo(imgName, debugScanLines, displayScale, workpiecePositions, &binInfo, rpy, angleDrawLen);
#endif #endif
printf("done\n"); printf("done\n");
} }
@ -2487,7 +2594,7 @@ void HaiRuiMa_workpieceSizeCompute_test(void)
a_pose.value = workpieceInfo.workpieceRadius; a_pose.value = workpieceInfo.workpieceRadius;
a_pose.z_dir = { 0, 0, 1.0 }; a_pose.z_dir = { 0, 0, 1.0 };
poseInfo.push_back(a_pose); poseInfo.push_back(a_pose);
_outputRGBDResult_XYZ_RGBD_workpieceInfo(_scan_file, scanLines, poseInfo, 500); _outputRGBDResult_XYZ_RGBD_workpieceInfo(_scan_file, scanLines, poseInfo, NULL, 500);
sprintf_s(_scan_file, "%sresult/%d_workpiece_info.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%sresult/%d_workpiece_info.txt", dataPath[grp], fidx);
_outputWorkpieceInfo(_scan_file, workpieceInfo); _outputWorkpieceInfo(_scan_file, workpieceInfo);
@ -2496,7 +2603,7 @@ void HaiRuiMa_workpieceSizeCompute_test(void)
double angleDrawLen = 500; double angleDrawLen = 500;
double displayScale = 1.0; double displayScale = 1.0;
cv::String imgName(calibFile); cv::String imgName(calibFile);
_genXOYProjectionImage_workpieceInfo(imgName, scanLines, displayScale, poseInfo, rpy, angleDrawLen); _genXOYProjectionImage_workpieceInfo(imgName, scanLines, displayScale, poseInfo, NULL, rpy, angleDrawLen);
printf("done\n"); printf("done\n");
} }
} }

View File

@ -19,7 +19,8 @@
//version 1.3.6 : 在1.3.5版本的基础上根据现场数据修正了转子钢芯定位算法中的bug //version 1.3.6 : 在1.3.5版本的基础上根据现场数据修正了转子钢芯定位算法中的bug
//version 1.3.7 : 在1.3.6版本的基础上添加了ID, 与2D结果保持一致 //version 1.3.7 : 在1.3.6版本的基础上添加了ID, 与2D结果保持一致
//version 1.3.8 : 添加了输入栅格格式检查, 调整边缘目标为目标距料筐外廓边的距离在直径的1.1倍以内 //version 1.3.8 : 添加了输入栅格格式检查, 调整边缘目标为目标距料筐外廓边的距离在直径的1.1倍以内
std::string m_strVersion = "HybridPositioning 1.3.8"; //version 1.3.9 : 转子钢芯, 改进了料筐检测方法
std::string m_strVersion = "HybridPositioning 1.3.9";
const char* wd_hybridPositioningVersion(void) const char* wd_hybridPositioningVersion(void)
{ {
return m_strVersion.c_str(); return m_strVersion.c_str();
@ -937,13 +938,160 @@ void _getYTopLine(
return; return;
} }
double _getListMeanZ(std::vector< SVzNL3DPosition>& listData, SVzNLRangeD& zRange)
{
if (listData.size() == 0)
return 0;
double meanZ = 0;
zRange.max = -1;
zRange.min = 0;
for (int i = 0; i < (int)listData.size(); i++)
{
meanZ += listData[i].pt3D.z;
if (zRange.max < 0)
{
zRange.max = listData[i].pt3D.z;
zRange.min = listData[i].pt3D.z;
}
else
{
zRange.max = zRange.max < listData[i].pt3D.z ? listData[i].pt3D.z : zRange.max;
zRange.min = zRange.min > listData[i].pt3D.z ? listData[i].pt3D.z : zRange.min;
}
}
meanZ = meanZ / (double)listData.size();
return meanZ;
}
//检测料筐边缘,以中心点为基准进行规划
WD_HRM_BinInfo wd_HRM_getBinSize_2(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const SVzNLRangeD zSliceRange)
{
WD_HRM_BinInfo resultPose;
memset(&resultPose, 0, sizeof(WD_HRM_BinInfo));
int lineNum = (int)scanLines.size();
int linePtNum = (int)scanLines[0].size();
//Z层切
std::vector<SVzNL3DPosition> zBinSliceData;
for (int line = 0; line < lineNum; line++)
{
for (int j = 0; j < linePtNum; j++)
{
scanLines[line][j].nPointIdx = 0;
if ((scanLines[line][j].pt3D.z > zSliceRange.min) && (scanLines[line][j].pt3D.z < zSliceRange.max))
{
SVzNL3DPosition a_pt;
a_pt.nPointIdx = (line << 16) | (j & 0xffff);
a_pt.pt3D = scanLines[line][j].pt3D;
zBinSliceData.push_back(a_pt);
scanLines[line][j].nPointIdx = 1; //标注
}
}
}
//聚类
int clusterCheckWin = 5;
double clusterDist = 10.0;
int distType = 1; //0 - 2d distance; 1- 3d distance
std::vector<std::vector< SVzNL3DPosition>> objClusters;
wd_pointClustering_speedUp(zBinSliceData, lineNum, linePtNum, clusterCheckWin, clusterDist, distType, objClusters);
if(objClusters.size() == 0)
return resultPose;
int bestIdx = 0;
for (int i = 1; i < (int)objClusters.size(); i++)
{
if (objClusters[bestIdx].size() < objClusters[i].size())
bestIdx = i;
}
std::vector<SVzNL3DPosition>& zSliceData = objClusters[bestIdx];
SVzNLRangeD dataZRange;
double zSliceZ = _getListMeanZ(zSliceData, dataZRange);
//计算轮廓
// 最小外接矩形
std::vector<cv::Point2f> points;
for (int i = 0; i < (int)zSliceData.size(); i++)
{
cv::Point2f a_pt = cv::Point2f(zSliceData[i].pt3D.x, zSliceData[i].pt3D.y);
points.push_back(a_pt);
}
if (points.size() == 0)
{
return resultPose;
}
cv::RotatedRect rect = minAreaRect(points);
cv::Point2f vertices[4];
rect.points(vertices);
double width = rect.size.width; //投影的宽和高
double height = rect.size.height;
if (width < height)
{
double tmp = height;
height = width;
width = tmp;
}
//计算姿态角vertices[0]是旋转点
double dist_v0v3 = sqrt(pow(vertices[0].x - vertices[3].x, 2) + pow(vertices[0].y - vertices[3].y, 2));
double width_diff = abs(dist_v0v3 - width);
double pose_yaw;
if (CV_VERSION == "3.2.0")
{
if (width_diff < 10.0)//width方向
{
pose_yaw = -rect.angle;
}
else //长度方向
{
pose_yaw = -rect.angle - 90;
if (pose_yaw < -90)
pose_yaw = 180 + pose_yaw;
}
}
else //if (CV_VERSION == "4.8.0")
{
if (width_diff < 10.0) //width方向
{
pose_yaw = -rect.angle;
}
else//长度方向
{
pose_yaw = -rect.angle + 90;
if (pose_yaw > 90)
pose_yaw = pose_yaw - 180;
}
}
//生成料筐信息
double binZ = zSliceRange.min;
double sinTheta = sin(-PI * pose_yaw / 180);
double cosTheta = cos(-PI * pose_yaw / 180);
resultPose.center = { rect.center.x, rect.center.y, binZ };
resultPose.bottomNormal = { 0.0, 0.0, 1.0 };
resultPose.x_dir = { cosTheta , sinTheta , 0.0 };
resultPose.y_dir = vec3_cross(resultPose.bottomNormal, resultPose.x_dir); //叉乘出y_dir
resultPose.length = width;
resultPose.width = height;
resultPose.binTopZ = zSliceZ;
resultPose.minRectVertex[0] = { vertices[0].x, vertices[0].y, binZ };
resultPose.minRectVertex[1] = { vertices[1].x, vertices[1].y, binZ };
resultPose.minRectVertex[2] = { vertices[2].x, vertices[2].y, binZ };
resultPose.minRectVertex[3] = { vertices[3].x, vertices[3].y, binZ };
return resultPose;
}
void wd_HRM_RotorCorePositioning( void wd_HRM_RotorCorePositioning(
std::vector< std::vector<SVzNLPositionD>>& scanLinesInput, std::vector< std::vector<SVzNLPositionD>>& scanLinesInput,
std::vector<WD_objArea2D>& objROIs, std::vector<WD_objArea2D>& objROIs,
const WD_HRM_BinInfo binInfo,
const SSG_planeCalibPara groundCalibPara, const SSG_planeCalibPara groundCalibPara,
const SWD_Cylinder workpieceParam, //圆柱形工件的标称半径和高度 const SWD_Cylinder workpieceParam, //圆柱形工件的标称半径和高度
const double groundRemoveOffset, //料筐地面去除的Z偏置,实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
std::vector< WD_workpieceInfo>& workpiecePositions, std::vector< WD_workpieceInfo>& workpiecePositions,
WD_HRM_BinInfo& binInfo, //输出Bin信息,用于debug,确认料筐信息检测正确
#ifdef _OUTPUT_DEBUG_DATA #ifdef _OUTPUT_DEBUG_DATA
std::vector<std::vector<SVzNL3DPosition>>& debugScanLines, std::vector<std::vector<SVzNL3DPosition>>& debugScanLines,
#endif #endif
@ -1025,6 +1173,14 @@ void wd_HRM_RotorCorePositioning(
wd_lineDataR(scanLines[i], groundCalibPara.planeCalib, -1); wd_lineDataR(scanLines[i], groundCalibPara.planeCalib, -1);
} }
//生成数据副本,用于Bin信息检测
std::vector<std::vector<SVzNL3DPosition>> dataCopy;
dataCopy.resize(scanLines.size());
for (int i = 0; i < lineNum; i++)
{
dataCopy[i].insert(dataCopy[i].end(), scanLines[i].begin(), scanLines[i].end());
}
//产生水平扫描数据 //产生水平扫描数据
std::vector< std::vector<SVzNL3DPosition>> scanLines_h; std::vector< std::vector<SVzNL3DPosition>> scanLines_h;
scanLines_h.resize(linePtNum); scanLines_h.resize(linePtNum);
@ -1294,6 +1450,13 @@ void wd_HRM_RotorCorePositioning(
double highest_z = allWorkpiece[0].center.z; double highest_z = allWorkpiece[0].center.z;
for (int i = 1; i < (int)allWorkpiece.size(); i++) for (int i = 1; i < (int)allWorkpiece.size(); i++)
highest_z = highest_z > allWorkpiece[i].center.z ? allWorkpiece[i].center.z : highest_z; highest_z = highest_z > allWorkpiece[i].center.z ? allWorkpiece[i].center.z : highest_z;
//计算料筐信息
SVzNLRangeD zSliceRange;
zSliceRange.min = highest_z - workpieceParam.height;
zSliceRange.max = groundCalibPara.planeHeight - groundRemoveOffset;
binInfo = wd_HRM_getBinSize_2(dataCopy, zSliceRange);
//z方向排序 //z方向排序
std::vector< WD_workpieceInfo> zSortWorkpiece; std::vector< WD_workpieceInfo> zSortWorkpiece;
double topLayerTh = highest_z + workpieceParam.height * 0.75; double topLayerTh = highest_z + workpieceParam.height * 0.75;
@ -1747,31 +1910,6 @@ SSG_ROIRectD _getListROI(std::vector< SVzNL3DPosition>& listData)
return roi; return roi;
} }
double _getListMeanZ(std::vector< SVzNL3DPosition>& listData, SVzNLRangeD& zRange)
{
if (listData.size() == 0)
return 0;
double meanZ = 0;
zRange.max = -1;
zRange.min = 0;
for (int i = 0; i < (int)listData.size(); i++)
{
meanZ += listData[i].pt3D.z;
if (zRange.max < 0)
{
zRange.max = listData[i].pt3D.z;
zRange.min = listData[i].pt3D.z;
}
else
{
zRange.max = zRange.max < listData[i].pt3D.z ? listData[i].pt3D.z : zRange.max;
zRange.min = zRange.min > listData[i].pt3D.z ? listData[i].pt3D.z : zRange.min;
}
}
meanZ = meanZ / (double)listData.size();
return meanZ;
}
//逆时针旋转时 θ > 0 ;顺时针旋转时 θ < 0 //逆时针旋转时 θ > 0 ;顺时针旋转时 θ < 0
cv::Point2f _rotate2D(cv::Point2f pt, double sinTheta, double cosTheta) cv::Point2f _rotate2D(cv::Point2f pt, double sinTheta, double cosTheta)
{ {

View File

@ -61,10 +61,11 @@ SG_APISHARED_EXPORT void wd_lineDataR(
SG_APISHARED_EXPORT void wd_HRM_RotorCorePositioning( SG_APISHARED_EXPORT void wd_HRM_RotorCorePositioning(
std::vector< std::vector<SVzNLPositionD>>& scanLinesInput, std::vector< std::vector<SVzNLPositionD>>& scanLinesInput,
std::vector<WD_objArea2D>& objROIs, std::vector<WD_objArea2D>& objROIs,
const WD_HRM_BinInfo binInfo,
const SSG_planeCalibPara groundCalibPara, const SSG_planeCalibPara groundCalibPara,
const SWD_Cylinder workpieceParam, //圆柱形工件的标称半径和高度 const SWD_Cylinder workpieceParam, //圆柱形工件的标称半径和高度
const double groundRemoveOffset, //料筐地面去除的Z偏置,实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
std::vector< WD_workpieceInfo>& workpiecePositions, std::vector< WD_workpieceInfo>& workpiecePositions,
WD_HRM_BinInfo& binInfo, //输出Bin信息,用于debug,确认料筐信息检测正确
#ifdef _OUTPUT_DEBUG_DATA #ifdef _OUTPUT_DEBUG_DATA
std::vector<std::vector<SVzNL3DPosition>>& debugScanLines, std::vector<std::vector<SVzNL3DPosition>>& debugScanLines,
#endif #endif