物理学——车辆碰撞检测

车辆碰撞检测

借助于前面的代码,我们已经知道如何检测汽车与护栏的碰撞。只需创建两个碰撞平面,每个护栏一个,然后检查四个轮子与这两个平面的碰撞。因为赛车不仅是一个球体,因此无法像小行星那样做简单的处理,四个面都必须检测,但只检测四轮的位置(或至少是赛车的最外层)仍能实现基本碰撞检测(见图13-15)。

1
Figure 13-15

碰撞检测的代码在CarPhysics类的ApplyGravityAndCheckForCollisions方法中。此代码遍历了赛车的四个角并检测是否与平面碰撞(见图13-15中的道路旁边的两条线)。在实际车长和宽的基础上可计算赛车的四个角:

// Check all 4 corner points of our car.
Vector3 carRight = Vector3.Cross(carDir, carUp);
Vector3 carLeft = -carRight;
// Car dimensions are 2.6m (width) x 5.6m (length) x 1.8m (height)
// Note: This could be improved by using more points or using
// the actual car geometry.
// Note: We ignore the height, this way the collision is simpler.
// We then check the height above the road to see if we are flying
// above the guard rails out into the landscape.
Vector3[] carCorners = new Vector3[]
{
  // Top left
  pos + carDir * 5.6f/2.0f - carRight * 2.6f/2.0f,
  // Top right
  pos + carDir * 5.6f/2.0f + carRight * 2.6f/2.0f,
  // Bottom right
  pos - carDir * 5.6f/2.0f + carRight * 2.6f/2.0f,
  // Bottom left
  pos - carDir * 5.6f/2.0f - carRight * 2.6f/2.0f,
};

借助于在此方法前计算过的辅助值,碰撞检测现在相对简单了:

// Check for each corner if we collide with the guard rail
for (int num = 0; num < carCorners.Length; num++)
{
  // Hit any guardrail?
  float leftDist = Vector3Helper.DistanceToLine(
    carCorners[num], guardrailLeft, nextGuardrailLeft);
  float rightDist = Vector3Helper.DistanceToLine(
    carCorners[num], guardrailRight, nextGuardrailRight);

  // If we are closer than 0.1f, thats a collision!
  if (leftDist < 0.1f ||
    // Also include the case where we are farther away from rightDist
    // than the road is wide.
    rightDist > roadWidth)
  {
    // Handle collision with left guard rail here
  } // if (leftDist < 0.1f)

  if (rightDist < 0.1f ||
    // Also include the case where we are farther away from leftDist
    // than the road is wide.
    leftDist > roadWidth)
  {
    // Handle collision with right guard rail here
  } // if (rightDist < 0.1f)
} // for (num)

碰撞处理的最后部分是碰撞事件的反应。但在此之前,你需要在单元测试中设置一些字段来显示碰撞检测代码是否正常工作。或只在“if”代码块中设置断点,看看是否已进入条件。

现在,所有要做的就是播放碰撞音效并根据车的哪个角碰撞选择车辆。汽车将减速,相机摇晃告知玩家他刚刚碰撞了。如果直行时碰撞(0~45度对墙),车将完全停住并播放完全碰撞的音效:

// Force car back on the road, for that calculate impulse and
// collision direction (same stuff as in Rocket Commander).
Vector3 collisionDir =
  Vector3.Reflect(carDir, guardrailRightNormal);

float collisionAngle =
  Vector3Helper.GetAngleBetweenVectors(
    carLeft, guardrailRightNormal);

// Flip at 180 degrees (if driving in wrong direction)
if (collisionAngle > MathHelper.Pi / 2)
  collisionAngle -= MathHelper.Pi;

// Just correct rotation if collison happened at 0-45 degrees (slowly)
if (Math.Abs(collisionAngle) < MathHelper.Pi / 4.0f)
{
  // Play crash sound
  Sound.PlayCrashSound(false);

  // For front wheels to full collision rotation, for back half!
  if (num < 2)
  {
    rotateCarAfterCollision = +collisionAngle / 1.5f;
    speed *= 0.935f;//0.85f;
    if (viewDistance > 0.75f)
      viewDistance -= 0.1f;//0.15f;
  } // if (num)
  else
  {
    rotateCarAfterCollision = +collisionAngle / 2.5f;
    //slowdownCarAfterCollision = 0.8f;
    speed *= 0.96f;//0.9f;
    if (viewDistance > 0.75f)
      viewDistance -= 0.05f;//0.1f;
  } // else
  // Shake camera
  ChaseCamera.SetCameraWobbel(0.00075f * speed);
} // if (collisionAngle)

// If 90-45 degrees (in either direction), make frontal crash
// + stop car + wobble camera
else if (Math.Abs(collisionAngle) < MathHelper.Pi * 3.0f / 4.0f)
{
  // Also rotate car if less than 60 degrees
  if (Math.Abs(collisionAngle) < MathHelper.Pi / 3.0f)
    rotateCarAfterCollision = +collisionAngle / 3.0f;
  // Play crash sound
  Sound.PlayCrashSound(true);

  // Shake camera
  ChaseCamera.SetCameraWobbel(0.005f * speed);

  // Just stop car!
  speed = 0;
} // if (collisionAngle)

// For all collisions, kill the current car force
carForce = Vector3.Zero;

// Always make sure we are OUTSIDE of the collision range for
// the next frame. But first find out how much we have to move.
float speedDistanceToGuardrails =
  speed * Math.Abs(Vector3.Dot(carDir, guardrailLeftNormal));

if (rightDist > 0)
{
  float correctCarPosValue = (rightDist + 0.01f +//0.11f +
    0.1f * speedDistanceToGuardrails * moveFactor);
  carPos += correctCarPosValue * guardrailRightNormal;
} // if (rightDist)

有了这些代码,现在你可以进行TestCarPhysicsOnPlaneWithGuardRails单元测试并调整与护栏的碰撞。该代码有点复杂,但规则相同,所有的碰撞代码和物理计算与单元测试中使用的的完全一样。

转载于:https://www.cnblogs.com/AlexCheng/archive/2010/10/16/2120190.html

### 车辆检测仿真工具及相关教程 在自动驾驶和机器人领域,车辆检测仿真是验证算法性能的重要环节之一。通过仿真环境可以模拟真实场景中的各种情况,从而测试感知模块、路径规划以及避障等功能。 #### ROS Rviz 插件与 Gazebo 的结合 ROS (Robot Operating System) 提供了一个强大的框架用于开发和测试机器人应用。Rviz 是 ROS 中的一个可视化工具,能够显示传感器数据、轨迹以及其他信息。为了实现更复杂的碰撞检测功能,可以通过编写自定义插件扩展其能力[^1]。此外,Gazebo 是一个物理引擎驱动的仿真器,支持动态物体交互并提供逼真的渲染效果。两者配合使用可创建高度真实的驾驶场景。 对于多边形碰撞检测而言,可以在 RViz 或 Gazebo 中加载包含障碍物的地图文件(如 .yaml),并通过编程接口设置这些对象为不可穿透区域。例如: ```python from gazebo_msgs.srv import SpawnModel, DeleteModel import rospy rospy.init_node('spawn_model') model_name = 'obstacle' model_xml = open('/path/to/your/model.sdf', 'r').read() robot_namespace = '' initial_pose = Pose(position=Point(x=-4.0, y=-3.0, z=0)) reference_frame = '' try: spawn_sbrv = rospy.ServiceProxy('/gazebo/spawn_sdf_model', SpawnModel) resp = spawn_sbrv(model_name, model_xml, robot_namespace, initial_pose, reference_frame) except Exception as e: print(f"Error spawning model {e}") ``` 此脚本展示了如何利用服务调用来向 Gazebo 场景中添加新实体——这里假设该实体代表某种类型的静态或移动障碍物。 #### CARLA 自动驾驶仿真平台介绍 CARLA(https://carla.org/)是一个开源的城市驾驶模拟器,专为研究自主驾驶而设计。它不仅提供了丰富的API访问权限以便集成不同的AI模型,还内置了多种天气条件下的高清城市地图模板。更重要的是,CARLA 支持 Python API 和 Unreal Engine 图形界面操作,允许开发者轻松配置实验参数并记录结果。 以下是启动简单客户端连接到服务器端运行默认城镇的一段代码片段: ```python import carla client = carla.Client('localhost', 2000) world = client.get_world() settings = world.get_settings() settings.fixed_delta_seconds = 0.05 settings.no_rendering_mode = False world.apply_settings(settings) blueprint_library = world.get_blueprint_library() vehicle_bp = blueprint_library.find('vehicle.tesla.model3') transform = random.choice(world.get_map().get_spawn_points()) ego_vehicle = world.spawn_actor(vehicle_bp, transform) ``` 以上实例说明了怎样选取一辆特定品牌型号的小轿车放置于随机起点位置处作为主角车参与后续动作序列执行过程的一部分内容描述而已并非完整程序清单列表形式呈现出来供大家参考学习之用罢了! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值