首页 > 编程语言 >碰撞检测:详解矩形AABB与OBB碰撞检测算法(附ROS C++可视化)

碰撞检测:详解矩形AABB与OBB碰撞检测算法(附ROS C++可视化)

时间:2024-09-16 18:27:25浏览次数:10  
标签:min max AABB OBB 碰撞检测 marker ROS

碰撞检测:详解矩形AABB与OBB碰撞检测算法(附ROS C++可视化)

引言

在机器人、游戏开发、计算机图形学等领域,碰撞检测是一个至关重要的任务。碰撞检测的目的是确定两个或多个物体是否发生了碰撞,以便采取相应的措施,如避免碰撞、触发事件等。在二维空间中,矩形是最常见的几何形状之一,而AABB(Axis-Aligned Bounding Box)和OBB(Oriented Bounding Box)是两种常用的矩形表示方法。本文将详细介绍AABB和OBB的碰撞检测算法,并结合ROS(Robot Operating System)和C++进行可视化展示。

1. AABB碰撞检测算法

1.1 AABB的基本概念

AABB是一种轴对齐的包围盒,即矩形的边与坐标轴平行。AABB通常用于表示物体的最小包围矩形,其优点是计算简单、效率高。AABB的表示方法通常为两个顶点坐标:最小顶点(x_min, y_min)和最大顶点(x_max, y_max)。

1.2 AABB碰撞检测原理

AABB的碰撞检测非常直观:两个AABB是否相交,取决于它们在x轴和y轴上的投影是否重叠。具体来说,如果两个AABB在x轴上的投影重叠,并且在y轴上的投影也重叠,则它们相交。

设两个AABB分别为A和B,其顶点坐标分别为:

  • A: (A_x_min, A_y_min), (A_x_max, A_y_max)
  • B: (B_x_min, B_y_min), (B_x_max, B_y_max)

则AABB碰撞检测的条件为:

(A_x_max >= B_x_min && A_x_min <= B_x_max) && (A_y_max >= B_y_min && A_y_min <= B_y_max)

1.3 AABB碰撞检测的C++实现

以下是一个简单的C++函数,用于检测两个AABB是否相交:

bool isAABBIntersect(float A_x_min, float A_y_min, float A_x_max, float A_y_max,
                     float B_x_min, float B_y_min, float B_x_max, float B_y_max) {
    return (A_x_max >= B_x_min && A_x_min <= B_x_max) &&
           (A_y_max >= B_y_min && A_y_min <= B_y_max);
}

1.4 ROS中的AABB碰撞检测可视化

在ROS中,可以使用visualization_msgs::Marker来可视化AABB。以下是一个简单的ROS节点,用于发布两个AABB,并在Rviz中显示它们的碰撞检测结果。

#include <ros/ros.h>
#include <visualization_msgs/Marker.h>

void publishAABBMarker(ros::Publisher& marker_pub, float x_min, float y_min, float x_max, float y_max, int id, int r, int g, int b) {
    visualization_msgs::Marker marker;
    marker.header.frame_id = "map";
    marker.header.stamp = ros::Time::now();
    marker.ns = "aabb";
    marker.id = id;
    marker.type = visualization_msgs::Marker::CUBE;
    marker.action = visualization_msgs::Marker::ADD;
    marker.pose.position.x = (x_min + x_max) / 2.0;
    marker.pose.position.y = (y_min + y_max) / 2.0;
    marker.pose.position.z = 0;
    marker.pose.orientation.w = 1.0;
    marker.scale.x = x_max - x_min;
    marker.scale.y = y_max - y_min;
    marker.scale.z = 0.1;
    marker.color.r = r / 255.0;
    marker.color.g = g / 255.0;
    marker.color.b = b / 255.0;
    marker.color.a = 0.5;
    marker_pub.publish(marker);
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "aabb_collision_detection");
    ros::NodeHandle nh;
    ros::Publisher marker_pub = nh.advertise<visualization_msgs::Marker>("visualization_marker", 1);

    float A_x_min = -1, A_y_min = -1, A_x_max = 1, A_y_max = 1;
    float B_x_min = 0, B_y_min = 0, B_x_max = 2, B_y_max = 2;

    ros::Rate loop_rate(1);
    while (ros::ok()) {
        publishAABBMarker(marker_pub, A_x_min, A_y_min, A_x_max, A_y_max, 0, 255, 0, 0);
        publishAABBMarker(marker_pub, B_x_min, B_y_min, B_x_max, B_y_max, 1, 0, 0, 255);

        if (isAABBIntersect(A_x_min, A_y_min, A_x_max, A_y_max, B_x_min, B_y_min, B_x_max, B_y_max)) {
            ROS_INFO("AABB collision detected!");
        } else {
            ROS_INFO("No collision detected.");
        }

        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

2. OBB碰撞检测算法

2.1 OBB的基本概念

OBB是一种方向包围盒,即矩形的边可以与坐标轴不平行。OBB通常用于表示物体的最小包围矩形,其优点是可以更好地贴合物体的形状,但计算复杂度较高。OBB的表示方法通常为矩形的中心点、旋转角度、宽度和高度。

2.2 OBB碰撞检测原理

OBB的碰撞检测比AABB复杂得多,因为OBB的边不与坐标轴平行。OBB碰撞检测的核心思想是分离轴定理(Separating Axis Theorem, SAT)。SAT指出,如果两个凸多边形在某个轴上的投影不重叠,则它们不相交。对于OBB,需要检查的轴包括两个OBB的各条边以及它们的法线。

2.3 OBB碰撞检测的C++实现

以下是一个简单的C++函数,用于检测两个OBB是否相交:

struct OBB {
    float center_x, center_y;
    float width, height;
    float angle;
};

bool isOBBIntersect(const OBB& A, const OBB& B) {
    // TODO: Implement OBB collision detection using SAT
    return false;
}

2.4 ROS中的OBB碰撞检测可视化

在ROS中,可以使用visualization_msgs::Marker来可视化OBB。以下是一个简单的ROS节点,用于发布两个OBB,并在Rviz中显示它们的碰撞检测结果。

#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <tf/transform_datatypes.h>

void publishOBBMarker(ros::Publisher& marker_pub, const OBB& obb, int id, int r, int g, int b) {
    visualization_msgs::Marker marker;
    marker.header.frame_id = "map";
    marker.header.stamp = ros::Time::now();
    marker.ns = "obb";
    marker.id = id;
    marker.type = visualization_msgs::Marker::CUBE;
    marker.action = visualization_msgs::Marker::ADD;
    marker.pose.position.x = obb.center_x;
    marker.pose.position.y = obb.center_y;
    marker.pose.position.z = 0;
    tf::Quaternion q;
    q.setRPY(0, 0, obb.angle);
    marker.pose.orientation.x = q.x();
    marker.pose.orientation.y = q.y();
    marker.pose.orientation.z = q.z();
    marker.pose.orientation.w = q.w();
    marker.scale.x = obb.width;
    marker.scale.y = obb.height;
    marker.scale.z = 0.1;
    marker.color.r = r / 255.0;
    marker.color.g = g / 255.0;
    marker.color.b = b / 255.0;
    marker.color.a = 0.5;
    marker_pub.publish(marker);
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "obb_collision_detection");
    ros::NodeHandle nh;
    ros::Publisher marker_pub = nh.advertise<visualization_msgs::Marker>("visualization_marker", 1);

    OBB A = {0, 0, 2, 1, 0};
    OBB B = {1, 1, 2, 1, 0};

    ros::Rate loop_rate(1);
    while (ros::ok()) {
        publishOBBMarker(marker_pub, A, 0, 255, 0, 0);
        publishOBBMarker(marker_pub, B, 1, 0, 0, 255);

        if (isOBBIntersect(A, B)) {
            ROS_INFO("OBB collision detected!");
        } else {
            ROS_INFO("No collision detected.");
        }

        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

3. 总结

本文详细介绍了AABB和OBB的碰撞检测算法,并结合ROS和C++进行了可视化展示。AABB碰撞检测简单高效,适用于轴对齐的矩形;而OBB碰撞检测虽然复杂,但可以更好地贴合物体的形状。在实际应用中,可以根据具体需求选择合适的碰撞检测算法。

通过ROS的可视化工具Rviz,我们可以直观地观察到碰撞检测的结果,这对于调试和验证算法非常有帮助。希望本文能为读者在碰撞检测领域的学习和应用提供一些参考。

标签:min,max,AABB,OBB,碰撞检测,marker,ROS
From: https://blog.51cto.com/u_17019724/12031759

相关文章

  • ROS的通讯机制(一):常用命令
        一、rosnode:操作节点        rosnode是用于获取节点信息的命令。相关命令:rosnodeping测试到节点的连接状态rosnodelist列出活动节点rosnodeinfo打印节点信息rosnodemachine列出指定设备上节点rosnodekill......
  • 小米SUV最新谍照曝光:动感设计,疑似对标法拉利Purosangue
    9月16日最新动态,知名汽车博主@电动星球小新今日分享了一组小米首款SUV车型的路试谍照。从公布的图片中可以看出,小米SUV呈现出强烈的运动风格,与奥迪A4Avant并列停放时,更能凸显其偏向年轻化和动感的设计理念,有网友戏称其颇有几分法拉利Purosangue的味道。车身设计与特征溜背......
  • ROS2图形化方式新建功能包工具- Turtle Nest
    提示:全文AI生成。链接:https://github.com/Jannkar/turtle_nest配置TurtleNest使用说明(中文版)一、TurtleNest简介正如海龟巢是幼海龟的诞生地,ROS2TurtleNest是ROS2包的诞生和成长之地。TurtleNest提供了一个易用的图形用户界面(GUI),简化了ROS2包的创建......
  • 推荐一个比较好用的工具Microsoft PowerToys
    MicrosoftPowerToys是一组实用工具,可帮助高级用户调整和简化其Windows体验,从而提高工作效率。虽然刚刚使用这个工具不久,但是已经能初步感受到它的强大,接下来我就对于我使用的几个功能进行简单介绍。屏幕截取这个功能在日常工作中应该是经常会用到,在学生时代,使用这个功能......
  • abc370D Cross Explosion
    一开始并查集写的,ga掉。set应用一道非常好的题目。```#include<bits/stdc++.h>#include<set>#definesiiset<int>::iteratorusingnamespacestd;inth,w,q,ans;set<int>s1[400007],s2[400007];voiddel(intx,inty){//printf("%d%d\n",x,......
  • 使用 Microsoft.Extensions.ServiceDiscovery 进行服务发现并调用
    简介在现代微服务架构中,服务发现(ServiceDiscovery)是一项关键功能。它允许微服务动态地找到彼此,而无需依赖硬编码的地址。以前如果你搜.NETServiceDiscovery,大概率会搜到一大堆Eureka,Consul等的文章。现在微软为我们带来了一个官方的包:Microsoft.Extensions.ServiceDiscovery......
  • macOS 中 Rosetta 模拟器打开,造成 MLX 框架的错误
    概述背景AppleSilicon(M1,M2芯片)是基于ARM架构的,而老的IntelMac是基于x86_64架构的。Rosetta2是macOS提供的工具,用于在AppleSilicon上模拟运行x86应用程序。某些应用程序(如终端)可能默认通过Rosetta运行为x86架构,而不是ARM原生运行。在安装及编......
  • 使用 `Roslyn` 分析器和修复器 对异步方法规范化返回Async结尾
    之前写过一篇使用修复器帮助添加头部注释文本的功能,今天使用Roslyn的代码修复器对异步返回方法规范化的功能实现分析器首先需要实现分析器,使用RegisterSyntaxNodeAction,分析所有SyntaxKind.MethodDeclaration的语法类型,[DiagnosticAnalyzer(LanguageNames.CSharp)]public......
  • ros 自定义消息(图像+标志位+位姿)python和c++发布和接受
      编译 脚本 v3_gaosi_img_pose_flag.sh#!/bin/bash#外部给与执行权限#sudochmod+xrun_ros_nodes.sh#定义ROS安装路径#安装时候添加到系统路径了不需要每次都sourceROS_SETUP="/opt/ros/noetic/setup.bash"#定义工作目录路径自己的工程没有加到系......
  • Ros2 - Moveit2 - Grasps(抓握)
    MoveItGrasps是一款用于抓取块或圆柱体等物体的抓取生成器,可用作MoveIt拾取和放置管道的替代品。MoveItGrasps提供基于可达性和接近、抬起和后退运动的笛卡尔规划来过滤抓取的功能。抓握生成算法基于简单的长方体形状,不考虑摩擦锥或其他抓握动力。MoveItGrasps可与平行......