// gasFillingPortPosition_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include #include #include #include #include #include "direct.h" #include #include "bagThreadPositioning_Export.h" #include #include #include 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; void vzReadLaserScanPointFromFile_encodePlyTxt( const char* fileName, double lineStep, double baseZ, std::vector>& scanData) { std::ifstream inputFile(fileName); std::string linedata; if (inputFile.is_open() == false) return; std::vector< SVzNL3DPosition> linePoints; linePoints.clear(); int startIdx = -1; int ptIdx = 0; double pre_y = DBL_MAX; while (std::getline(inputFile, linedata)) { if (linedata.empty()) continue; int X; double Y, Z, tmp; sscanf_s(linedata.c_str(), "%d,%lf,%lf", &X, &Y, &Z); if (startIdx < 0) startIdx = X; SVzNL3DPosition a_pt; a_pt.nPointIdx = ptIdx; ptIdx++; a_pt.pt3D.x = (double)(X - startIdx) * lineStep; a_pt.pt3D.y = Y; a_pt.pt3D.z = baseZ - Z; if (Z < -9990.0) { a_pt.pt3D = { 0, 0, 0 }; } if (Y < pre_y) { //新行 if(linePoints.size() > 0) scanData.push_back(linePoints); linePoints.clear(); ptIdx = 0; } linePoints.push_back(a_pt); pre_y = Y; } if(linePoints.size() > 0) scanData.push_back(linePoints); return; } bool checkGridFormat(std::vector>& scanData) { if (scanData.size() == 0) return false; int linePtNum = (int)scanData[0].size(); for (int i = 1; i < (int)scanData.size(); i++) { if (linePtNum != (int)scanData[i].size()) return false; } return true; } void wdReadLaserScanPointFromFile_XYZ_vector(const char* fileName, std::vector>& 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>& scanData, SVzNLRangeD roi_y, std::vector>& 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>& 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 _outputChanneltInfo(char* fileName, std::vector& threadInfo) { std::ofstream sw(fileName); char dataStr[250]; int objNum = (int)threadInfo.size(); for (int i = 0; i < objNum; i++) { sprintf_s(dataStr, 250, "线头_%d: 位置( %g, %g, %g ), 下刀位置_( %g, %g, %g ), 角度_%g", i + 1, threadInfo[i].threadPos.x, threadInfo[i].threadPos.y, threadInfo[i].threadPos.z, threadInfo[i].operatePos.x, threadInfo[i].operatePos.y, threadInfo[i].operatePos.z, threadInfo[i].rotateAngle); sw << dataStr << std::endl; } sw.close(); } void _outputRGBDScan_RGBD( char* fileName, std::vector>& scanLines, std::vector& threadInfo ) { int lineNum = (int)scanLines.size(); std::ofstream sw(fileName); int realLines = lineNum; int objNum = (int)threadInfo.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 == 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*2) << std::endl; size = 8; for (int i = 0; i < objNum; i++) { rgb = { 250, 0, 0 }; float x = (float)threadInfo[i].threadPos.x; float y = (float)threadInfo[i].threadPos.y; float z = (float)threadInfo[i].threadPos.z; sw << "{" << x << "," << y << "," << z << "}-"; sw << "{0,0}-{0,0}-"; sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; rgb = { 250, 250, 0 }; x = (float)threadInfo[i].operatePos.x; y = (float)threadInfo[i].operatePos.y; z = (float)threadInfo[i].operatePos.z; sw << "{" << x << "," << y << "," << z << "}-"; sw << "{0,0}-{0,0}-"; sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; } //多输出一个,修正显示工具bug rgb = { 250, 0, 0 }; float x = (float)threadInfo[0].threadPos.x; float y = (float)threadInfo[0].threadPos.y; float z = (float)threadInfo[0].threadPos.z; sw << "{" << x << "," << y << "," << z << "}-"; sw << "{0,0}-{0,0}-"; sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; //输出法向 size = 1; double len = 60; lineIdx = 0; for (int i = 0; i < objNum; i++) { SVzNL3DPoint pt0 = threadInfo[i].threadPos; SVzNL3DPoint pt1 = threadInfo[i].operatePos; //显示法向量 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++; } //多输出一个,修正显示工具bug SVzNL3DPoint pt0 = threadInfo[0].threadPos; SVzNL3DPoint pt1 = threadInfo[0].operatePos; //显示法向量 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(); } #define CONVERT_TO_GRID 0 #define BAG_THREAD_POSITIONING 1 #define TEST_GROUP 1 int main() { const char* dataPath[TEST_GROUP] = { "F:/ShangGu/项目/吕宁项目/袋子拆线/模拟数据/", //0 }; SVzNLRange fileIdx[TEST_GROUP] = { {1,13}, }; const char* ver = wd_bagThreadPositioningVersion(); printf("ver:%s\n", ver); #if CONVERT_TO_GRID int convertGrp = 0; for (int fidx = fileIdx[convertGrp].nMin; fidx <= fileIdx[convertGrp].nMax; fidx++) { char _scan_file[256]; sprintf_s(_scan_file, "%s袋子_%d.txt", dataPath[convertGrp], fidx); std::vector> scanData; double lineStep = 0.096; double baseZ = 350.0; vzReadLaserScanPointFromFile_encodePlyTxt(_scan_file, lineStep, baseZ, scanData); bool isGridData = checkGridFormat(scanData); int gridFormat = (true == isGridData) ? 1 : 0; printf("%s: 栅格格式=%d\n", _scan_file, gridFormat); //将数据恢复为按扫描线存储格式 sprintf_s(_scan_file, "%s袋子_grid_%d.txt", dataPath[convertGrp], fidx); _outputScanDataFile(_scan_file, scanData,0, 0, 0); printf("%s: done.\n", _scan_file); } #endif #if BAG_THREAD_POSITIONING for (int grp = 0; grp < TEST_GROUP; grp++) { for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) { char _scan_file[256]; sprintf_s(_scan_file, "%s袋子_grid_%d.txt", dataPath[grp], fidx); std::vector> scanLines; wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines); long t1 = (long)GetTickCount64();//统计时间 SSG_cornerParam cornerParam; cornerParam.cornerTh = 70; cornerParam.scale = 1.5; //袋子缝的尺度1.5mm比较合适 cornerParam.minEndingGap = 1.0; // cornerParam.minEndingGap_z = 1.0; cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平 cornerParam.jumpCornerTh_2 = 60; SSG_raisedFeatureParam raisedFeatureParam; raisedFeatureParam.minJumpZ = 1.5; raisedFeatureParam.minK = 2.0; //对应63度 raisedFeatureParam.widthRange.min = 1.0; raisedFeatureParam.widthRange.max = 4.0; SSG_outlierFilterParam filterParam; filterParam.continuityTh = 3.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声 filterParam.outlierTh = 2; SSG_treeGrowParam growParam; growParam.maxLineSkipNum = -1; //对于轮廓仪,线间隔很小,使用扫描线数的物理意义不清晰,使用maxSkipDistance growParam.maxSkipDistance = 5.0; growParam.yDeviation_max = 5.0; growParam.zDeviation_max = 5.0;// growParam.minLTypeTreeLen = 10; //mm, growParam.minVTypeTreeLen = 10; //mm bool isHorizonScan = false; //true:激光线平行线缝;false:激光线垂直线缝 int errCode = 0; std::vector bagThreadInfo; wd_bagThreadPositioning( scanLines, isHorizonScan, //true:激光线平行线缝;false:激光线垂直线缝 filterParam, //噪点过滤参数 cornerParam, //V型特征参数 raisedFeatureParam,//线尾凸起参数 growParam, //特征生长参数 bagThreadInfo, &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(_scan_file, scanLines, bagThreadInfo); sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx); _outputChanneltInfo(_scan_file, bagThreadInfo); } } #endif } // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 // 调试程序: F5 或调试 >“开始调试”菜单 // 入门使用技巧: // 1. 使用解决方案资源管理器窗口添加/管理文件 // 2. 使用团队资源管理器窗口连接到源代码管理 // 3. 使用输出窗口查看生成输出和其他消息 // 4. 使用错误列表窗口查看错误 // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件