windows下使用FCL(Flexible-collision-library)

news2024/11/26 20:47:41

windows下使用FCL(The Flexible-collision-library)

   FCL做为一款开源的碰撞检测库,支持多种基础的几何体,及支持C++和python,在windows和linux平台均可以使用。是一款计算高效的碰撞检测工具。在机械臂规划控制框架moveit中做为基础的碰撞检测算法。
FCL支持的几何体类型:

  • box (长方体)
  • sphere(球)
  • ellipsoid(椭球)
  • capsule(胶囊体)
  • cone(锥体)
  • cylinder(圆柱)
  • convex(凸包)
  • half-space(半空间)
  • plane(平面)
  • mesh(面片)
  • octree (八叉树)

FCL库(The Flexible Collision Library)主要的功能有:
1、碰撞检测:检测两个模型是否重叠,以及(可选)所有重叠的三角形。
2、距离计算:计算一对模型之间的最小距离,即最近的一对点之间的距离。
3、公差验证:确定两个模型是否比公差距离更近或更远。
4、连续碰撞检测:检测两个运动模型在运动过程中是否重叠,以及可选的接触时间。
5、接触信息:对于碰撞检测和连续碰撞检测,可以选择返回接触信息(包括接触法线和接触点)。

源码下载及编译

FCL 源码github
  在windows环境下,使用VS studio直接编译FCL存在问题,需要将CMake设置成Release版本以及屏蔽掉测试程序。具体操作如下:

  1. 使用VS studio打开FCO源码工程,如图1所示。

图1
2. 通过改CMakeList.txt文件,屏蔽测试程序,如图2所示。

图2
3. 点击“项目”,再点击“fcl的CMake配置”,将编译设置成Release版本,如图3所示。

图3
4. 点击“生成”,再点击“全部重新生成”对FCL源码进行编译。

FCL碰撞测试demo

  测试程序如下所示:

//main.cpp
#include "fcl/math/constants.h"
#include "fcl/narrowphase/collision.h"
#include "fcl/narrowphase/collision_object.h"
#include "fcl/narrowphase/distance.h"

/**
 * @brief 两个相互碰撞的Box碰撞检测测试
 */
void test1() {
    std::shared_ptr<fcl::CollisionGeometry<double>> box1(
        new fcl::Box<double>(3, 3, 3));
    std::shared_ptr<fcl::CollisionGeometry<double>> box2(
        new fcl::Box<double>(1, 1, 1));

    fcl::Transform3d tf1 = fcl::Transform3d::Identity();
    fcl::CollisionObjectd obj1(box1, tf1);

    fcl::Transform3d tf2 = fcl::Transform3d::Identity();
    fcl::CollisionObjectd obj2(box2, tf2);

    fcl::CollisionRequestd request;
    fcl::CollisionResultd result;

    request.gjk_solver_type =
        fcl::GJKSolverType::GST_INDEP;  // specify solver type with the default
                                        // type is GST_LIBCCD

    fcl::collide(&obj1, &obj2, request, result);

    std::cout << "test1 collide result:" << result.isCollision() << std::endl;
}

/**
 * @brief 两个无碰撞的Box碰撞检测测试
 */
void test2() {
    std::shared_ptr<fcl::CollisionGeometry<double>> box1(
        new fcl::Box<double>(3, 3, 3));
    std::shared_ptr<fcl::CollisionGeometry<double>> box2(
        new fcl::Box<double>(1, 1, 1));

    fcl::Transform3d tf1 = fcl::Transform3d::Identity();
    fcl::CollisionObjectd obj1(box1, tf1);

    fcl::Transform3d tf2 = fcl::Transform3d::Identity();
    tf2.translation() = fcl::Vector3d{3, 0, 0};

    fcl::CollisionObjectd obj2(box2, tf2);

    fcl::CollisionRequestd request;
    fcl::CollisionResultd result;

    fcl::collide(&obj1, &obj2, request, result);

    std::cout << "test2 collide result:" << result.isCollision() << std::endl;
}

/**
 * @brief 两个无碰撞的Box碰撞检测测试,并计算最短距离
 */
void test3() {
    std::shared_ptr<fcl::CollisionGeometry<double>> box1(
        new fcl::Box<double>(3, 3, 3));
    std::shared_ptr<fcl::CollisionGeometry<double>> box2(
        new fcl::Box<double>(1, 1, 1));

    fcl::Transform3d tf1 = fcl::Transform3d::Identity();
    fcl::CollisionObjectd obj1(box1, tf1);

    fcl::Transform3d tf2 = fcl::Transform3d::Identity();
    tf2.translation() = fcl::Vector3d{3, 0, 0};

    fcl::CollisionObjectd obj2(box2, tf2);

    fcl::CollisionRequestd request;
    fcl::CollisionResultd result;

    // fcl::collide(&obj1,&obj2,request,result);

    std::cout << "test3 collide result:" << result.isCollision() << std::endl;

    fcl::DistanceRequestd dist_request(true);
    dist_request.distance_tolerance = 1e-4;
    fcl::DistanceResultd dist_result;

    fcl::distance(&obj1, &obj2, dist_request, dist_result);

    std::cout << "test3 collide distance:" << dist_result.min_distance
              << std::endl;
    std::cout << "test3 collide point 0:" << dist_result.nearest_points[0]
              << std::endl;
    std::cout << "test3 collide point 1:" << dist_result.nearest_points[1]
              << std::endl;
}

/**
 * @brief 加载STL模型
 */
bool loadSTLFile(const std::string& filename,
                 std::vector<fcl::Triangle>& triangles) {
    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file) {
        std::cerr << "Failed to open STL file: " << filename << std::endl;
        return false;
    }
    file.seekg(0, std::ios::end);  /// 定位到流末尾的位置,0偏移
    std::streampos length = file.tellg();  /// 记录当前指针位置
    file.seekg(0, std::ios::beg);  /// 定位到流开头的位置,0偏移
    std::vector<char> buffer(length);
    file.read(&buffer[0], length);
    file.close();

    if (length < 84) {
        std::cerr << "Invalid STL file: " << filename << std::endl;
        return false;
    }
    unsigned int num_triangles = *(unsigned int*)&buffer[80];
    triangles.resize(num_triangles);
    unsigned int offset = 84;
    for (unsigned int i = 0; i < num_triangles; ++i) {
        for (unsigned int j = 0; j < 3; ++j) {
            // 3顶点构成三角形
            float* vertex = (float*)&buffer[offset + j * 12];
            triangles[i][j] = (vertex[0], vertex[1], vertex[2]);
        }
        offset += 50;
    }
    return true;
}

/**
 * @brief 在STL文件格式中,文件头部分包含80个字节的文件头信息和4个字节的三角形数量信息,因此文件总长度至少为84个字节。
因此,在loadSTLFile函数中我们首先检查文件长度是否小于84个字节,如果是则认为文件格式非法。
在STL文件中,每个三角形由12个浮点数和2个无用字节组成,因此每个三角形占用50个字节。
因此,在loadSTLFile函数中,我们通过一个循环遍历每个三角形,并从文件中读取对应的12个浮点数,最后将三角形的3个顶点存储在一个fcl::Triangle类型的变量中。
每次读取完一个三角形后,需要将读取指针向前移动50个字节,即offset += 50。由于文件头部分占用了前84个字节,因此,在开始循环前需要将读取指针初始化为offset= 84,从而跳过文件头部分,开始读取三角形信息。
 */
void test4() {
    std::vector<fcl::Triangle> triangles;  /// 创建三角片序列
    /// 加载模型
    if (!loadSTLFile("C:/test0.STL", triangles)) {
        std::cout << "Error:loadSTLFile failed!" << std::endl;

        return;
    }
    /// 创建mesh,并添加三角片到mesh
    ///
    std::shared_ptr<fcl::BVHModel<fcl::OBBRSSd>> mesh_geometry(
        new fcl::BVHModel<fcl::OBBRSSd>());
    mesh_geometry->beginModel();
    for (const auto& triangle : triangles) {
        Eigen::Vector3d p1(triangle[0]), p2(triangle[1]), p3(triangle[2]);
        mesh_geometry->addTriangle(p1, p2, p3);
    }
    mesh_geometry->endModel();

    /// 建立碰撞对象-stl ,并添加CollisionGeometry,坐标位置(0,0,0)
    fcl::CollisionObjectd obj(mesh_geometry);
    /// 建立碰撞对象-box ,坐标位置(0,0,20)
    std::shared_ptr<fcl::Boxd> box1 = std::make_shared<fcl::Boxd>(2.0, 2.0, 2.0);
    fcl::CollisionObjectd obj1(box1);
    obj1.setTranslation(Eigen::Vector3d(0, 0, 0));

    fcl::CollisionRequestd request;
    fcl::CollisionResultd result;

    /// 进行碰撞检测
    fcl::collide(&obj, &obj1, request, result);
    /// 输出碰撞结果
    if (result.isCollision()) {
        std::cout << "Collision detected!" << std::endl;
    } else {
        std::cout << "No collision detected." << std::endl;
    }
    /// 距离检测
    fcl::DistanceRequestd requestd;
    fcl::DistanceResultd resultd;
    fcl::distance(&obj, &obj1, requestd, resultd);
    std::cout << "min_distance:" << resultd.min_distance << std::endl;
}

int main(int argc, char** argv) {
    std::cout << "FCL test" << std::endl;

    test1();
    test2();
    test3();
    test4();

    std::cout << "end test" << std::endl;
    return 0;
}

CMakeList.txt文件如下所示:

cmake_minimum_required(VERSION 3.14)
find_package(Eigen3 REQUIRED)
find_package(FCL REQUIRED)
add_executable(use_fcl main.cpp)
target_link_libraries(use_fcl fcl Eigen3::Eigen)
target_include_directories(use_fcl PUBLIC ${EIGEN3_INCLUDE_DIRS} ${FCL_INCLUDE_DIRS})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1177595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Shopee买家通系统一款全自动操作虾皮买家号的软件

Shopee买家通系统可以全自动批量注册虾皮买家号&#xff0c;注册时可以自动调用手机号、自动接收短信验证、自动绑地址及支付卡&#xff0c;注册成功后还能自动绑定邮箱进行验证。 软件支持5个国家使用&#xff0c;越南、泰国、菲律宾、印度尼西亚、马来西亚。 内置防指纹技术 …

jenkins展示html报告样式需要注意的要点

一、jenkins展示html报告样式需要注意的要点 最后&#xff1a;

【Linux】vim

文章目录 一、vim是什么&#xff1f;二 、命令模式三、插入模式四、底行模式五、vim配置 一、vim是什么&#xff1f; Vim是一个强大的文本编辑器&#xff0c;它是Vi的增强版&#xff0c;支持多种语法高亮、插件扩展、多模式操作等功能。Vim有三种基本的工作模式&#xff1a;命…

操作系统——对文件的 基本操作(王道视频p65)

1.总体概述&#xff1a; 2.进程打开文件表 和 系统打开文件表&#xff1a;

产品经理日常工作流程汇总

产品经理在日常的团队工作过程中&#xff0c;承担着重要的衔接作用。由于工作性质的特殊性&#xff0c;产品经理日常工作内容特别繁杂&#xff0c;导致很多产品小白刚一上手&#xff0c;会无从下手&#xff0c;经常丢三落四。这时拥有一个好的工作流程&#xff0c;很大程度上就…

CAD圆锥齿轮画法

大端面的法向是大端模数的标准齿形&#xff0c;然后分度圆线按照45和中心线相交&#xff0c;然后齿顶圆齿根圆的母线和相交点连线。

硕鼠——视频下载利器

相信很多做自媒体、剪辑的同志们&#xff0c;经常会遇到一个棘手的问题&#xff1a;剪辑的素材从何而来。诸如很多高燃混剪的视频&#xff0c;往往需要多个影视作品中的原画来进行二次创作&#xff0c;可是这些视频素材从何而来呢&#xff1f; 有小伙伴们提出&#xff0c;通过录…

【基础IO⑨】:重定向实现原理 “Linux下一切皆文件“

【基础IO⑨】&#xff1a;重定向原理 与 "Linux下一切皆文件" 一.重定向1.实现原理2.输出重定向3.输入重定向4.补充&#xff1a;简易shell中实现重定向 二."Linux下一切皆文件"1.虚拟文件系统(VFS) 一.重定向 我们首先关闭2号文件描述符&#xff0c;然后再…

Apple :苹果将在明年年底推出自己的 AI,预计将随 iOS 18 一起推出

本心、输入输出、结果 文章目录 Apple &#xff1a;苹果将在明年年底推出自己的 AI&#xff0c;预计将随 iOS 18 一起推出前言三星声称库克相关图片弘扬爱国精神 Apple &#xff1a;苹果将在明年年底推出自己的 AI&#xff0c;预计将随 iOS 18 一起推出 编辑&#xff1a;简简单…

MySQL——Centos7下环境安装

目录 0.说明 1. 检查环境&#xff08;systemctl start/stop/restart&#xff09; 2. 检查系统安装包&#xff08;rpm -qa&#xff09; 3. 卸载这些默认安装包&#xff08;yum remove、xargs&#xff09; 4. 获取mysql官方yum源 5. 安装mysql yum源&#xff0c;对比前后yu…

【网络】五中IO模型介绍 + 多路转接中select和poll服务器的简单编写

高级IO 前言正式开始前面的IO函数简单过一遍什么叫做低效的IO钓鱼的例子同步IO和异步IO五种IO模型阻塞IO非阻塞IO信号驱动多路转接异步IO 小结 代码演示非阻塞IO多路转接select介绍简易select服务器timeout 为 nullptrtimeout 为 {0, 0}timeout 为 {5, 0}调用accept select编写…

已经不做程序媛4年半了,后悔么?不好说...但再次看到之前写的博客,真的感慨万分。

四年半前&#xff0c;我还在大四实习&#xff0c;做了一年Java开发。四年半后&#xff0c;我是地理信息行业的一名销售经理。 今天&#xff0c;突然点开了CSDN&#xff0c;看到自己的博客有很多人看过&#xff0c;霎时间感慨万千…因为上一次这么认真的对待自己&#xff0c;竟…

网络运维Day06

文章目录 磁盘空间管理一块硬盘的“艺术”之旅识别磁盘分区规划分区模式MBR(主启动记录模式)GPT分区 使用GPT分区方案分区 格式化与挂载使用格式化挂载使用 实现开机自动挂载实验 光盘挂载交换空间 总结 磁盘空间管理 磁盘空间管理 扇区默认512字节 一块硬盘的“艺术”之旅 …

【Spring】spring中存储Bean(对象)的相关注解及相关用法

五大注解&#xff1a;Controller&#xff0c;Service&#xff0c;Repository&#xff0c;Component&#xff0c;Configuration 1、controller 控制器&#xff08;注入服务&#xff09; 控制层,接收请求,对请求进⾏处理,并进⾏响应。用于标注控制层&#xff0c;相当于struts中的…

【mmcv报错】ModuleNotFoundError: No module named ‘mmcv.runner

跑一个代码需要用到mmcv和mmseg 其中有两行代码&#xff1a; from mmcv.runner import load_checkpoint from mmseg.utils import get_root_logger我先是按照官方推荐的安装方法去安装了mmcv和mmseg pip install -U openmim mim install mmcv它会自动帮你安装mmengine 我的cu…

关于Vue使用props传值遇到的一些问题

一、The data property “tableData” is already declared as a prop. Use prop default value instead. 翻译过来&#xff1a;数据属性“tableData”已声明为prop。请改prop默认值。 将父组件的prop传过去变量改一下 二、prop传值&#xff0c;子组件比父组件先渲染&#…

内存取证 worldskills3.vmem与gs02.jpg题目WP

worldskills3.vmem 题目信息 获取admin用户密码是多少&#xff1f; 获取ip和主机名是什么&#xff1f; 获取桌面上的flag.txt文件的内容是什么&#xff1f; 服务器存在一个挖矿病毒&#xff0c;矿池地址是&#xff1f; 恶意代码在系统中注册了服务&#xff0c;服务名是什么&a…

pytest 的使用===谨记

发现用例的规则 a) 文件test_.py开头和_test.py结尾 b) Test开头的类中test开头的方法&#xff08;测试类不能带有__init__方法&#xff09; c) 模块中test开头的函数&#xff08;可以不在class中&#xff09; 注意点&#xff1a; pytest是以方法为单位发现用例的&#xff0c;你…

单通道低压 H 桥电机驱动芯片AT9110H 兼容L9110 马达驱动芯片

H桥直流电机驱动电路是一种用于控制直流电机运转的电路&#xff0c;其主要特点是可以实现正反转控制&#xff0c;控制电机转速和方向&#xff0c;同时也具有过流保护功能。 H桥电路由四个功率晶体管和一些辅助电路组成&#xff0c;其中两个晶体管用于控制电机正转&#xff0c;…