{"id":156,"date":"2025-06-19T16:19:44","date_gmt":"2025-06-19T08:19:44","guid":{"rendered":"https:\/\/mcfrys.cn\/?p=156"},"modified":"2025-06-19T17:38:11","modified_gmt":"2025-06-19T09:38:11","slug":"%e4%b8%89%e7%bb%b4%e6%89%ab%e6%8f%8f%e8%ae%be%e5%a4%87-%e6%af%95%e4%b8%9a%e8%ae%be%e8%ae%a1%e5%88%9b%e6%96%b0%e7%82%b9%e8%ae%b0%e5%bd%95","status":"publish","type":"post","link":"https:\/\/web.mcfrys.cn\/index.php\/2025\/06\/19\/%e4%b8%89%e7%bb%b4%e6%89%ab%e6%8f%8f%e8%ae%be%e5%a4%87-%e6%af%95%e4%b8%9a%e8%ae%be%e8%ae%a1%e5%88%9b%e6%96%b0%e7%82%b9%e8%ae%b0%e5%bd%95\/","title":{"rendered":"\u4e09\u7ef4\u626b\u63cf\u8bbe\u5907-\u6bd5\u4e1a\u8bbe\u8ba1(\u521b\u65b0\u70b9\u8bb0\u5f55)"},"content":{"rendered":"\n<p>1.\u6dfb\u52a0\u8def\u5f84\u89c4\u5212\u529f\u80fd<\/p>\n\n\n\n<p>\u5c06\u4e09\u7ef4\u6d4b\u91cf\u70b9\u6295\u5f71\u5230\u4e00\u4e2a\u5e73\u9762\u4e0a\uff0c\u63a8\u6d4b\u4e00\u4e2a\u5242\u91cf\u503c\uff0c\u7136\u540e\u5e73\u9762\u8def\u5f84\u89c4\u5212 \u4e4b\u540e\u518d\u628a\u8def\u5f84\u663e\u793a\u5230\u4e09\u7ef4\u4e2d<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.&nbsp;<strong class=\"\">\u6295\u5f71\u65b9\u5f0f<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u76f4\u63a5\u6295\u5f71\u5230\u57fa\u5e73\u9762\uff08\u5982 XY \u5e73\u9762\uff09<\/strong>\uff1a\n<ul class=\"wp-block-list\">\n<li>\u5ffd\u7565 Z \u5750\u6807\uff0c\u5c06\u6240\u6709\u4e09\u7ef4\u70b9\u6295\u5f71\u5230 XY \u5e73\u9762\u4e0a\u3002<\/li>\n\n\n\n<li>\u8fd9\u662f\u6700\u7b80\u5355\u7684\u65b9\u5f0f\uff0c\u9002\u7528\u4e8e\u9ad8\u5ea6\u53d8\u5316\u4e0d\u5927\u6216\u9ad8\u5ea6\u4fe1\u606f\u4e0d\u91cd\u8981\u7684\u573a\u666f\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u6295\u5f71\u5230\u7279\u5b9a\u9ad8\u5ea6\u5e73\u9762<\/strong>\uff1a\n<ul class=\"wp-block-list\">\n<li>\u9009\u62e9\u4e00\u4e2a\u7279\u5b9a\u7684\u9ad8\u5ea6\uff08\u5982\u5730\u9762\u9ad8\u5ea6\uff09\uff0c\u5c06\u6240\u6709\u4e09\u7ef4\u70b9\u6295\u5f71\u5230\u8be5\u5e73\u9762\u4e0a\u3002<\/li>\n\n\n\n<li>\u9002\u7528\u4e8e\u9700\u8981\u5173\u6ce8\u7279\u5b9a\u9ad8\u5ea6\uff08\u5982\u5730\u9762\uff09\u7684\u573a\u666f\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2.&nbsp;<strong class=\"\">\u6570\u636e\u805a\u5408\u65b9\u6cd5<\/strong><\/h3>\n\n\n\n<p>\u5728\u5c06\u4e09\u7ef4\u6570\u636e\u6295\u5f71\u5230\u4e8c\u7ef4\u5e73\u9762\u540e\uff0c\u9700\u8981\u5bf9\u6bcf\u4e2a\u4e8c\u7ef4\u7f51\u683c\u5185\u7684\u6570\u636e\u8fdb\u884c\u805a\u5408\u3002\u4ee5\u4e0b\u662f\u51e0\u79cd\u5e38\u89c1\u7684\u805a\u5408\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">(1)&nbsp;<strong class=\"\">\u53d6\u6700\u5927\u503c<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u65b9\u6cd5<\/strong>\uff1a\u5728\u6bcf\u4e2a\u4e8c\u7ef4\u7f51\u683c\u5185\uff0c\u53d6\u6240\u6709\u6295\u5f71\u70b9\u4e2d\u7684\u6700\u5927\u5242\u91cf\u503c\u3002<\/li>\n\n\n\n<li><strong>\u9002\u7528\u573a\u666f<\/strong>\uff1a\n<ul class=\"wp-block-list\">\n<li>\u5f53\u9700\u8981\u89c4\u907f\u9ad8\u5242\u91cf\u533a\u57df\u65f6\uff0c\u53d6\u6700\u5927\u503c\u53ef\u4ee5\u786e\u4fdd\u8def\u5f84\u89c4\u5212\u907f\u5f00\u6700\u5371\u9669\u7684\u533a\u57df\u3002<\/li>\n\n\n\n<li>\u9002\u7528\u4e8e\u5bf9\u9ad8\u5242\u91cf\u533a\u57df\u654f\u611f\u7684\u5e94\u7528\uff08\u5982\u8f90\u5c04\u9632\u62a4\uff09\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code><code>\n<\/code>#include &lt;iostream>\n#include &lt;QApplication>\n#include &lt;QMainWindow>\n#include &lt;QFileDialog>\n#include &lt;QPushButton>\n#include &lt;QVBoxLayout>\n#include &lt;QSlider>\n#include &lt;QLabel>\n\n\/\/ Point Cloud Library\n#include &lt;pcl\/io\/pcd_io.h>\n#include &lt;pcl\/point_cloud.h>\n#include &lt;pcl\/point_types.h>\n#include &lt;pcl\/visualization\/pcl_visualizer.h>\n\n\/\/ VTK\n#include &lt;vtkGenericOpenGLRenderWindow.h>\n#include &lt;vtkSmartPointer.h>\n#include &lt;vtkRenderer.h>\n#include &lt;QVTKWidget.h>\t\n\n<code>typedef pcl::PointXYZRGBA PointT;\ntypedef pcl::PointCloud&lt;PointT> PointCloudT;<\/code><code>\nclass MainWindow : public QMainWindow\n{\n    Q_OBJECT\n\npublic:\n    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent), ui(new Ui::MainWindow)\n    {\n        ui->setupUi(this);\n\n        <em>\/\/ \u521d\u59cb\u5316\u70b9\u4e91<\/em>\n        cloud.reset(new PointCloudT);\n\n        <em>\/\/ \u8bbe\u7f6e\u7a97\u53e3\u6807\u9898<\/em>\n        this->setWindowTitle(\"3D Point Cloud Viewer with Path Planning\");\n\n        <em>\/\/ \u521b\u5efa\u7528\u4e8e\u663e\u793a\u70b9\u4e91\u7684\u7a97\u53e3\u90e8\u4ef6<\/em>\n        vtkSmartPointer&lt;vtkRenderer> renderer = vtkSmartPointer&lt;vtkRenderer>::New();\n        renderWindow = vtkSmartPointer&lt;vtkGenericOpenGLRenderWindow>::New();\n        renderWindow->AddRenderer(renderer);\n        viewer.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, \"viewer\", false));\n\n        <em>\/\/ \u521b\u5efa QVTKWidget \u5e76\u8bbe\u7f6e\u5230\u4e3b\u7a97\u53e3<\/em>\n        vtkWidget = new QVTKWidget(this);\n        vtkWidget->SetRenderWindow(viewer->getRenderWindow());\n        viewer->setupInteractor(vtkWidget->GetInteractor(), vtkWidget->GetRenderWindow());\n\n        <em>\/\/ \u8bbe\u7f6e\u5e03\u5c40<\/em>\n        QWidget *centralWidget = new QWidget(this);\n        QVBoxLayout *layout = new QVBoxLayout(centralWidget);\n        layout->addWidget(vtkWidget);\n        this->setCentralWidget(centralWidget);\n\n        <em>\/\/ \u52a0\u8f7d\u70b9\u4e91\u6309\u94ae<\/em>\n        loadButton = new QPushButton(\"Load Point Cloud\", this);\n        layout->addWidget(loadButton);\n\n        <em>\/\/ \u76ee\u6807\u70b9\u6309\u94ae<\/em>\n        targetButton = new QPushButton(\"Set Target Point\", this);\n        layout->addWidget(targetButton);\n\n        <em>\/\/ \u8fde\u63a5\u6309\u94ae\u4fe1\u53f7\u4e0e\u69fd<\/em>\n        connect(loadButton, &amp;QPushButton::clicked, this, &amp;MainWindow::loadPointCloud);\n        connect(targetButton, &amp;QPushButton::clicked, this, &amp;MainWindow::setTargetPoint);\n\n        <em>\/\/ \u521d\u59cb\u5316\u8def\u5f84\u89c4\u5212\u5668<\/em>\n        planner = nullptr;\n    }\n\n    ~MainWindow()\n    {\n        delete ui;\n    }\n\npublic Q_SLOTS:\n    void loadPointCloud()\n    {\n        QString fileName = QFileDialog::getOpenFileName(this, \"Open PCD File\", \"\", \"PCD Files (*.pcd)\");\n        if (!fileName.isEmpty()) {\n            if (pcl::io::loadPCDFile&lt;pcl::PointXYZRGBA>(fileName.toStdString(), *cloud) == -1) {\n                PCL_ERROR(\"Couldn't read file %s \\n\", fileName.toStdString().c_str());\n                return;\n            }\n            <em>\/\/ \u663e\u793a\u70b9\u4e91<\/em>\n            viewer->addPointCloud&lt;pcl::PointXYZRGBA>(cloud, \"cloud\");\n            viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, \"cloud\");\n            viewer->resetCamera();\n            viewer->spinOnce();\n        }\n    }\n\n    void setTargetPoint()\n    {\n        <em>\/\/ \u8fd9\u91cc\u4f60\u53ef\u4ee5\u5b9e\u73b0\u9009\u62e9\u76ee\u6807\u70b9\u7684\u903b\u8f91\uff0c\u4f8b\u5982\u901a\u8fc7\u9f20\u6807\u70b9\u51fb\u9009\u62e9\u70b9\u4e91\u4e2d\u7684\u4e00\u4e2a\u70b9<\/em>\n        <em>\/\/ \u7136\u540e\u8c03\u7528\u8def\u5f84\u89c4\u5212\u5668\u6765\u89c4\u5212\u8def\u5f84<\/em>\n        std::cout &lt;&lt; \"Setting target point...\" &lt;&lt; std::endl;\n\n        <em>\/\/ \u793a\u4f8b\uff1a\u5047\u8bbe\u9009\u62e9\u70b9\u4e91\u7684\u6700\u540e\u4e00\u4e2a\u70b9\u4f5c\u4e3a\u76ee\u6807\u70b9<\/em>\n        if (!cloud->points.empty()) {\n            int index = cloud->points.size() - 1;\n            pcl::PointXYZRGBA targetPoint = cloud->points&#91;index];\n\n            <em>\/\/ \u521b\u5efa\u8def\u5f84\u89c4\u5212\u5668\u5e76\u89c4\u5212\u8def\u5f84\u5230\u76ee\u6807\u70b9<\/em>\n            if (planner == nullptr) {\n                planner = new PathPlanner(cloud); <em>\/\/ \u5047\u8bbe\u4f60\u7684\u8def\u5f84\u89c4\u5212\u5668\u7c7b\u6709\u4e00\u4e2a\u6784\u9020\u51fd\u6570\u63a5\u53d7\u70b9\u4e91<\/em>\n            }\n            std::vector&lt;pcl::PointXYZ> path = planner->planPath(cloud->points&#91;0], targetPoint);\n\n            <em>\/\/ \u663e\u793a\u8def\u5f84\uff08\u793a\u4f8b\uff1a\u5c06\u8def\u5f84\u70b9\u4fdd\u5b58\u5230\u4e00\u4e2a\u6587\u4ef6\uff09<\/em>\n            if (!path.empty()) {\n                std::cout &lt;&lt; \"Path planned with \" &lt;&lt; path.size() &lt;&lt; \" points.\" &lt;&lt; std::endl;\n                <em>\/\/ \u5728\u8fd9\u91cc\u4f60\u53ef\u4ee5\u6dfb\u52a0\u4ee3\u7801\u6765\u53ef\u89c6\u5316\u8def\u5f84\u6216\u4fdd\u5b58\u8def\u5f84\u5230\u6587\u4ef6<\/em>\n            }\n        }\n    }\n\nprivate:\n    Ui::MainWindow *ui;\n    QVTKWidget *vtkWidget;\n    vtkSmartPointer&lt;vtkGenericOpenGLRenderWindow> renderWindow;\n    pcl::visualization::PCLVisualizer::Ptr viewer;\n    PointCloudT::Ptr cloud;\n    QPushButton *loadButton;\n    QPushButton *targetButton;\n    PathPlanner *planner; <em>\/\/ \u5047\u8bbe\u4f60\u7684\u8def\u5f84\u89c4\u5212\u5668\u7c7b\u540d\u4e3a PathPlanner<\/em>\n};\n\n<em>\/\/ PathPlanner \u7c7b\u7684\u7b80\u5355\u5b9e\u73b0\u793a\u4f8b\uff08\u9700\u8981\u6839\u636e\u4f60\u7684\u5177\u4f53\u9700\u6c42\u8c03\u6574\uff09<\/em>\nclass PathPlanner {\npublic:\n    PathPlanner(PointCloudT::Ptr cloud) : cloud(cloud) {}\n    std::vector&lt;pcl::PointXYZ> planPath(const pcl::PointXYZ &amp;start, const pcl::PointXYZ &amp;goal) {\n        <em>\/\/ \u8fd9\u91cc\u662f\u8def\u5f84\u89c4\u5212\u7684\u903b\u8f91<\/em>\n        <em>\/\/ \u5728\u5b9e\u9645\u5e94\u7528\u4e2d\uff0c\u4f60\u9700\u8981\u6839\u636e\u4f60\u7684\u5177\u4f53\u7b97\u6cd5\uff08\u5982 A*\uff09\u6765\u5b9e\u73b0<\/em>\n        std::vector&lt;pcl::PointXYZ> path;\n        <em>\/\/ \u793a\u4f8b\uff1a\u6dfb\u52a0\u8d77\u70b9\u548c\u76ee\u6807\u70b9\u5230\u8def\u5f84<\/em>\n        path.push_back(start);\n        path.push_back(goal);\n        return path;\n    }\nprivate:\n    PointCloudT::Ptr cloud;\n};<\/code><\/code><\/pre>\n\n\n\n<p>2.\u626b\u63cf\u5b9e\u65f6\u83b7\u53d6\u56fe-\u7f51\u683c\u5316\uff08\u4f18\u5316\u6027\u80fd\uff09<\/p>\n\n\n\n<p>\u5177\u4f53\u5b9e\u73b0 \u4f53\u7d20\u6ee4\u6ce2\u964d\u91c7\u6837\u540e\u51cf\u5c11\u70b9\u4e91\u4e2a\u6570 \u7136\u540e\u518d\u5c06\u5269\u4e0b\u7684\u70b9\u4e91\u653e\u5927\u5373\u53ef<\/p>\n\n\n\n<p>3.\u5242\u91cf\u7b97\u6cd5\u4f18\u5316\uff08\u4f4e\u5242\u91cf\u533a\u57df\u91c7\u7528\u80fd\u8c31\u63a2\u6d4b\u5668G(E)\u51fd\u6570\u8f6c\u6362)<\/p>\n\n\n\n<p>4.\u53cd\u6295\u5f71\u7b97\u6cd5\u4f18\u5316(\u770b\u662f\u5426\u80fd\u6dfb\u52a0\u65b9\u5411\u56e0\u5b50)<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1.\u6dfb\u52a0\u8def\u5f84\u89c4\u5212\u529f\u80fd \u5c06\u4e09\u7ef4\u6d4b\u91cf\u70b9\u6295\u5f71\u5230\u4e00\u4e2a\u5e73\u9762\u4e0a\uff0c\u63a8\u6d4b\u4e00\u4e2a\u5242\u91cf\u503c\uff0c\u7136\u540e\u5e73\u9762\u8def\u5f84\u89c4\u5212 \u4e4b\u540e\u518d\u628a\u8def\u5f84\u663e\u793a\u5230\u4e09\u7ef4\u4e2d [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-156","post","type-post","status-publish","format-standard","hentry","category-learn"],"_links":{"self":[{"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/posts\/156","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/comments?post=156"}],"version-history":[{"count":6,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/posts\/156\/revisions"}],"predecessor-version":[{"id":164,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/posts\/156\/revisions\/164"}],"wp:attachment":[{"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/media?parent=156"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/categories?post=156"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/web.mcfrys.cn\/index.php\/wp-json\/wp\/v2\/tags?post=156"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}