hybridPosePositioning
version 1.3.9 : 转子钢芯, 改进了料筐检测方法
This commit is contained in:
parent
737d741406
commit
bf8b449e48
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user