“物理引擎”是指在一款仿真软件/平台中使用的模拟现实世界物理逻辑(如碰撞、各种有形变/无形变的力学等)的计算单元,例如在开源机器人仿真平台gazebo中,就支持如ODE、Bullets、SimBody等多种物理引擎。

在AirSim中,针对无人机MultiRotor的物理引擎是AirSim自己开发的FastPhysics,而针对车辆Car的物理引擎是Unreal自己的PhysX引擎。

我不知道AirSim团队进行这样设计的初衷是什么,我推测可能是FastPhysics是针对无人机开发的一款比较快速的物理引擎,毕竟可能无人机的物理模型比车辆要更复杂一点。但我不知道为什么他们不顺便把车辆的仿真模式中也用上自己的FastPhysics,我估计是因为Unreal的PhysX对车辆模拟来说已经足够好了,并且使用上也方便一些。

  • 有关PhysX的简要介绍:UE4物理系统浅析
  • FastPhysics的定义在/AirSim/AirLib/include/physics/FastPhysicsEngine.hpp中

但这样做会产生一个问题,那就是AirSim中的settings中的ClockSpeed参数只对无人机MultiRotor SimMode有效,在车辆Car SimMode下无法有效调节仿真速率,具体问题描述可以参见:微软开源仿真器AirSim ROS接口中的第2节。

在车辆模式应用物理引擎的/AirSim/Unreal/Plugins/AirSim/Source/Vehicles/Car/SimModeCar.cpp文件中,原本是这样写的:

#include "SimModeCar.h"
#include "UObject/ConstructorHelpers.h"#include "AirBlueprintLib.h"
#include "common/AirSimSettings.hpp"
#include "CarPawnSimApi.h"
#include "AirBlueprintLib.h"
#include "common/Common.hpp"
#include "common/EarthUtils.hpp"
#include "vehicles/car/api/CarRpcLibServer.hpp"extern CORE_API uint32 GFrameNumber;void ASimModeCar::BeginPlay()
{Super::BeginPlay();initializePauseState();
}void ASimModeCar::initializePauseState()
{pause_period_ = 0;pause_period_start_ = 0;pause(false);
}bool ASimModeCar::isPaused() const
{return current_clockspeed_ == 0;
}void ASimModeCar::pause(bool is_paused)
{if (is_paused)current_clockspeed_ = 0;elsecurrent_clockspeed_ = getSettings().clock_speed;UAirBlueprintLib::setUnrealClockSpeed(this, current_clockspeed_);
}void ASimModeCar::continueForTime(double seconds)
{pause_period_start_ = ClockFactory::get()->nowNanos();pause_period_ = seconds;pause(false);
}void ASimModeCar::continueForFrames(uint32_t frames)
{targetFrameNumber_ = GFrameNumber + frames;frame_countdown_enabled_ = true;pause(false);
}void ASimModeCar::setupClockSpeed()
{current_clockspeed_ = getSettings().clock_speed;//setup clock in PhysX//在这里我们可以看到,代码直接使用了UAirBlueprintLib的相关方法,也就是使用了Unreal的默认引擎PhysX(目前Unreal新增了Chaos引擎,不知道AirSim以后会不会向Chaos兼容)//值得注意的是,在这里的确是设定了clockspeed,但效果仅仅是使整个仿真在”人的感官“下产生了速度变化,//仿真输出的时间戳没有变化,不像FastPhysicsEngine那样,仿真输出的时间戳也会相应变化。UAirBlueprintLib::setUnrealClockSpeed(this, current_clockspeed_);UAirBlueprintLib::LogMessageString("Clock Speed: ", std::to_string(current_clockspeed_), LogDebugLevel::Informational);
}void ASimModeCar::Tick(float DeltaSeconds)
{Super::Tick(DeltaSeconds);if (pause_period_start_ > 0) {if (ClockFactory::get()->elapsedSince(pause_period_start_) >= pause_period_) {if (!isPaused())pause(true);pause_period_start_ = 0;}}if(frame_countdown_enabled_){if (targetFrameNumber_ <= GFrameNumber){if (! isPaused())pause(true);frame_countdown_enabled_ = false;}}
}//-------------------------------- overrides -----------------------------------------------//
//以下略。

代码中的

UAirBlueprintLib::setUnrealClockSpeed(this, current_clockspeed_);

目的是设置clockspeed,但是对Unreal的PhysX而言,仅仅是使仿真速度在“人的感官”下产生了变化,而仿真输出的信息的时间戳并没有随着ClockSpeed参数的设置而产生更“稀疏”或更“稠密”的变化。

所以我对此文件进行了改写,使车辆模式的仿真也可以使用MultiRotor的FastPhysicsEngine,直接上代码:

#include "SimModeCar.h"
#include "UObject/ConstructorHelpers.h"
#include "Logging/MessageLog.h"
#include "Engine/World.h"
#include "GameFramework/PlayerController.h"
#include <exception>
#include "AirBlueprintLib.h"
#include "common/AirSimSettings.hpp"
#include "CarPawnSimApi.h"
#include "physics/PhysicsBody.hpp"
#include "common/ClockFactory.hpp"
#include "common/EarthUtils.hpp"
#include "common/Common.hpp"
#include <memory>
#include "vehicles/car/api/CarRpcLibServer.hpp"void ASimModeCar::BeginPlay()
{Super::BeginPlay();//let base class setup physics worldinitializeForPlay();
}
void ASimModeCar::initializeForPlay()
{std::vector<msr::airlib::UpdatableObject*> vehicles;for (auto& api : getApiProvider()->getVehicleSimApis())vehicles.push_back(api);//TODO: directly accept getVehicleSimApis() using generic containerstd::unique_ptr<PhysicsEngineBase> physics_engine = createPhysicsEngine();physics_engine_ = physics_engine.get();physics_world_.reset(new msr::airlib::PhysicsWorld(std::move(physics_engine),vehicles, getPhysicsLoopPeriod()));
}
void ASimModeCar::EndPlay(const EEndPlayReason::Type EndPlayReason)
{//remove everything that we created in BeginPlayphysics_world_.reset();//stop physics thread before we dismantle//stopAsyncUpdator();Super::EndPlay(EndPlayReason);
}
void ASimModeCar::startAsyncUpdator()
{physics_world_->startAsyncUpdator();
}void ASimModeCar::stopAsyncUpdator()
{physics_world_->stopAsyncUpdator();
}long long ASimModeCar::getPhysicsLoopPeriod() const //nanoseconds
{return physics_loop_period_;
}
void ASimModeCar::setPhysicsLoopPeriod(long long  period)
{physics_loop_period_ = period;
}
std::unique_ptr<ASimModeCar::PhysicsEngineBase> ASimModeCar::createPhysicsEngine()
{std::unique_ptr<PhysicsEngineBase> physics_engine;std::string physics_engine_name = getSettings().physics_engine_name;//选择使用的物理引擎:if (physics_engine_name == "")physics_engine.reset(); //no physics engineelse if (physics_engine_name == "FastPhysicsEngine") {msr::airlib::Settings fast_phys_settings;if (msr::airlib::Settings::singleton().getChild("FastPhysicsEngine", fast_phys_settings)) {physics_engine.reset(new msr::airlib::FastPhysicsEngine(fast_phys_settings.getBool("EnableGroundLock", true)));}else {physics_engine.reset(new msr::airlib::FastPhysicsEngine());}}else {physics_engine.reset();UAirBlueprintLib::LogMessageString("Unrecognized physics engine name: ",  physics_engine_name, LogDebugLevel::Failure);}return physics_engine;
}bool ASimModeCar::isPaused() const
{return physics_world_->isPaused();
}void ASimModeCar::pause(bool is_paused)
{physics_world_->pause(is_paused);UGameplayStatics::SetGamePaused(this->GetWorld(), is_paused);pause_physx(true);
}
void ASimModeCar::pause_physx(bool is_paused)
{float current_clockspeed_;if (is_paused)current_clockspeed_ = 0;elsecurrent_clockspeed_ = getSettings().clock_speed;UE_LOG(LogTemp,Display,TEXT("*******check point pause:"));UAirBlueprintLib::setUnrealClockSpeed(this, current_clockspeed_);
}
void ASimModeCar::continueForTime(double seconds)
{if(physics_world_->isPaused()){physics_world_->pause(false);UGameplayStatics::SetGamePaused(this->GetWorld(), false);        pause_physx(false);}physics_world_->continueForTime(seconds);while(!physics_world_->isPaused()){continue; }UGameplayStatics::SetGamePaused(this->GetWorld(), true);
}void ASimModeCar::updateDebugReport(msr::airlib::StateReporterWrapper& debug_reporter)
{unused(debug_reporter);//we use custom debug reporting for this class
}void ASimModeCar::Tick(float DeltaSeconds)
{{ //keep this lock as short as possiblephysics_world_->lock();physics_world_->enableStateReport(EnableReport);physics_world_->updateStateReport();for (auto& api : getApiProvider()->getVehicleSimApis())api->updateRenderedState(DeltaSeconds);physics_world_->unlock();}//perform any expensive rendering update outside of lock regionfor (auto& api : getApiProvider()->getVehicleSimApis())api->updateRendering(DeltaSeconds);Super::Tick(DeltaSeconds);
}void ASimModeCar::reset()
{UAirBlueprintLib::RunCommandOnGameThread([this]() {physics_world_->reset();}, true);//no need to call base reset because of our custom implementation
}std::string ASimModeCar::getDebugReport()
{return physics_world_->getDebugReport();
}
void ASimModeCar::setupClockSpeed()
{typedef msr::airlib::ClockFactory ClockFactory;float clock_speed = getSettings().clock_speed;float printout = getSettings().clock_speed;//setup clock in PhysX UAirBlueprintLib::setUnrealClockSpeed(this, clock_speed);UAirBlueprintLib::LogMessageString("Clock Speed: ", std::to_string(clock_speed), LogDebugLevel::Informational);UE_LOG(LogTemp,Display,TEXT("*******check point 3: %f"),printout);//setup clock in ClockFactorystd::string clock_type = getSettings().clock_type;//在此设定了时间步长:if (clock_type == "ScalableClock") {//scalable clock returns interval same as wall clock but multiplied by a scale factorClockFactory::get(std::make_shared<msr::airlib::ScalableClock>(clock_speed == 1 ? 1 : 1 / clock_speed));UE_LOG(LogTemp,Display,TEXT("*******check point 3_1: %f"),clock_speed);}else if (clock_type == "SteppableClock") {//steppable clock returns interval that is a constant number irrespective of wall clock//we can either multiply this fixed interval by scale factor to speed up/down the clock//but that would cause vehicles like quadrotors to become unstable//so alternative we use here is instead to scale control loop frequency. The downside is that//depending on compute power available, we will max out control loop frequency and therefore can no longer//get increase in clock speed//Approach 1: scale clock period, no longer used now due to quadrotor instability//ClockFactory::get(std::make_shared<msr::airlib::SteppableClock>(//static_cast<msr::airlib::TTimeDelta>(getPhysicsLoopPeriod() * 1E-9 * clock_speed)));//Approach 2: scale control loop frequency if clock is speeded upUE_LOG(LogTemp,Display,TEXT("*******check point 3_2: %f"),clock_speed);if (clock_speed >= 1) {ClockFactory::get(std::make_shared<msr::airlib::SteppableClock>(static_cast<msr::airlib::TTimeDelta>(getPhysicsLoopPeriod() * 1E-9))); //no clock_speed multipliersetPhysicsLoopPeriod(getPhysicsLoopPeriod() / static_cast<long long>(clock_speed));}else {//for slowing down, this don't generate instabilityClockFactory::get(std::make_shared<msr::airlib::SteppableClock>(static_cast<msr::airlib::TTimeDelta>(getPhysicsLoopPeriod() * 1E-9 * clock_speed)));}}elsethrow std::invalid_argument(common_utils::Utils::stringf("clock_type %s is not recognized", clock_type.c_str()));
}//-------------------------------- overrides -----------------------------------------------//
//以下略

显然对应的hpp也需要修改,全部改动后的代码在:GimpelZhang/AirSim

AirSim中的物理引擎相关推荐

  1. 【Unity】FPS游戏中的物理引擎——角色控制器(CharacterController)和刚体(Rigidbody)初解

    今天会谈到角色控制器和刚体主要是为了做一个游戏人物的控制器,角色控制器和刚体各有各的优点. 首先说一下刚体吧,刚体这个组件可以说是做一些真是物理游戏的开发者的福音,只要你给物体加上刚体基本可以算是给它 ...

  2. 《Unity 4 3D开发实战详解》一6.7 物理引擎综合案例

    本节书摘来异步社区<Unity 4 3D开发实战详解>一书中的第6章,第6.7节,作者: 吴亚峰 , 杜化美 , 张月霞 , 索依娜 责编: 张涛,更多章节内容可以访问云栖社区" ...

  3. U3d之物理引擎(上)

    如果对你有帮助,请做一棵蒲公英,让知识随风飘荡留在人的心里. 1. 人机交互 为什么说物理引擎要说起人机交互呢?假如我们在玩游戏的时候,要控制的可能是人物,飞机,汽车等游戏对象,我们需要跟电脑进行交互 ...

  4. 【UE4】物理引擎(蓝图)

    文章目录 虚幻物理系统 1.物理引擎 2.物理交互 产生物理交互的必备条件 3.物理碰撞 静态网格编辑器 简单碰撞 添加简单形状碰撞 添加K-DOP简单凸包碰撞 添加自动凸包碰撞 添加复杂碰撞 4.碰 ...

  5. PhysX 物理引擎研究(一)源码编译

    前言 Unity 3D 中的物理引擎分为 2D 引擎和 3D 引擎两部分,其中 2D 引擎使用的 Erin Catto 写的是 Box2D,而 3D 引擎使用的的 NVIDIA 的 PhysX,在 U ...

  6. 七巧板平台html5游戏开发之初识物理引擎

    七巧板平台html5游戏开发之初识物理引擎 七巧板平台是用于Web App.中轻度HTML5游戏及富媒体类应用开发,集开发.运营于一体的平台.它基于HTML5技术开发,具有进入门槛极低.开发极简单.跨 ...

  7. Unity 3D 物理引擎简介 || Unity 3D 物理材质|| Unity 3D 力(AddForce)

    Unity 3D 物理引擎简介 早期的游戏并没有强调物理引擎的应用,当时无论是哪一种游戏,都是用极为简单的计算方式做出相应的运算就算完成物理表现,如超级玛丽和音速小子等游戏. 较为常见的物理处理是在跳 ...

  8. Ophone平台2D游戏引擎实现——物理引擎(一)(二)

    http://dev.10086.cn/cmdn/wiki/index.php?doc-view-4271.html http://dev.10086.cn/cmdn/wiki/index.php?d ...

  9. 【Canvas】HTML5游戏开发的基本流程+P2.js物理引擎实战开发

    <HTML5游戏开发的基本流程> * 1. HTML5的简述 * 2. HTML5游戏开发所需的环境与工具 * 2.1. 开发环境 * 2.1.1. 浏览器 * 2.1.2. 开发语言 * ...

  10. (九)flax Engine 游戏引擎物理引擎joints(关节)

    2021SC@SDUSC 前八次文章我们分析了flax Engine 游戏引擎中物理引擎的Actors(角色)包下的相关的源码的分析,从本次开始我们将针对flax Engine 游戏引擎中的物理引擎中 ...

最新文章

  1. sonar检测java vue项目_Jenkins集成SonarQube 实现构建项目同时审查代码
  2. 电机调速制动matlab,基于Matlab的三相异步电动机起动、调速和制动特性仿真
  3. .NET对象克隆的深究(转)
  4. 北电PBX资料_LD 24 進線直撥功能設定
  5. Java面试题(亲身经历)
  6. 对称加密算法-DES以及DESede算法
  7. 优化 Hive ETL 任务(参数篇)
  8. 在webstorm中配置sass的自动编译,并且可以指定编译后的css的目录.
  9. 【codevs1039】01年noip TG--数的划分满分dp+愚蠢深搜+pas的奇怪做法
  10. android 按钮点击声音,如何在Android中单击按钮时播放声音?
  11. p6s与onvif_大华的录像机添加海康摄像头,使用了onvif协议,为啥也添加不进去?...
  12. txt文本保存操作(新建文件夹以及保存txt文本)
  13. Flutter报setState() or markNeedsBuild() called during build.错误解决办法
  14. 博客起航:为什么应该写博客
  15. android设置wifi蓝牙共享文件,无需互联网或蓝牙即可通过WiFi通过android共享文件...
  16. 全球及中国婴儿奶瓶架行业发展趋势预测及投资前景展望报告2022-2028年
  17. iOS自学-混合编程
  18. 日历控件CalendarView
  19. [Angular实战网易云]——15、歌词渲染
  20. 生成EAN13条码(C语言实现)

热门文章

  1. 轻轻松松学会Python入门一:初识Python
  2. matlab 距平,[转载]基于Matlab软件进行EOF分解、回归趋势分析,并
  3. ZEGO 自研客户端配置管理系统 —— 云控
  4. 网络分析系列之十三 Wireshark显示过滤器
  5. 网络操作系统和分布式系统区别简介
  6. MFC操作Access数据库
  7. Android包体优化总结
  8. php李炎辉,李炎恢PHP视频教程第一季资源分享
  9. crackme005
  10. android 教学ppt下载 百度云,百度云盘使用教程ppt课件.ppt