isaac sim 14 物理学习(车辆动力学)

文章内容均来自博客文章、官方文档手册等

参考内容

Nvidia Isaac Sim代码编程 入门教程 2024(7)_isaac sim franka-CSDN博客

Python Bindings API — omni_physics 106.1 documentation

Physics — Omniverse IsaacSim latest documentation

Vehicle Dynamics — Omniverse Extensions latest documentation

 

车辆动力学模型

        在Isaac Sim 的 Vehicle Dynamics 扩展中提供了用于创建车辆仿真的工具,其中包括轮胎、发动机、离合器、变速箱和悬架模型。

        车辆动力学示例场景:打开 Physics Demo Scenes: Window > Simulation > Demo Scenes。单击 Load scene (加载场景)

        如果您已将游戏手柄连接到 PC,并且想要使用它驾驶车辆,请单击 Viewport 窗口左上角的设置图标。然后,取消选中 Gamepad Camera Control 设置。这允许游戏手柄控制车辆,而不是相机。如果您希望使用键盘箭头键控制车辆,则可以跳过此步骤。

        

        如果启用了该扩展,则可以添加一个跟随车辆的特殊摄像头。在 Stage 窗口中选择 Vehicle 基元。右键单击 Vehicle ,将光标光标置于 Add 菜单上,然后将鼠标悬停在 Cameras 菜单上,然后选择 Follow Look 菜单项。(omni.physx.camera)

        

        摄像机将出现在 Viewport 中。要通过该摄像机查看场景,请单击 Viewport 窗口左上角的摄像机图标,单击 Cameras 按钮并选择 VehicleLookFollowCamera0。有关摄像头扩展以及如何调整所有摄像头设置的其他信息,请参阅 PhysX 摄像头文档。

        

        VehicleAudio.py:可以以交互的方式播放发动机和轮胎的声音。请确保您的 PC 音频未静音并设置为合理的音量。按下 Omniverse USD Composer 左侧的 Play 按钮开始模拟。

        如果使用的是游戏手柄,请使用右扳机加速,使用左扳机制动,使用左模拟操纵杆左右驾驶车辆。如果您使用的是键盘,请使用向上箭头键进行加速,使用向下箭头键进行制动,使用向左和向右箭头键进行车辆转向。按 Stop 按钮结束模拟。

使用 Vehicle Wizard 创建车辆

        Vehicle Wizard 和 Vehicle Demo 用原始的几何形状创建一辆车,一个盒子用于底盘,四个圆柱体用于车轮。然后,可以将用于渲染的车辆网格链接到这些变换并设置动画。

        Omniverse USD Composer 创建的物理表示和渲染的车辆网格应使用相同的坐标系和单位进行创作。这样就无需添加额外的旋转或缩放来使两种表示匹配。Vehicle Demo 是硬编码的,使用 Y 轴作为向上轴。但是,可以将 Vehicle Wizard 配置为匹配任何坐标系。在使用 Vehicle Wizard 之前,打开 Edit > Preferences 窗口,选择 Stage 并选择 Default Up Axis 以匹配用于创作渲染车辆的坐标系。创建一个新阶段 (File > New) 以确保更改的默认值生效。

         

车辆向导描述

        Vehicle Wizard 可以通过 Create > Physics > Vehicle 菜单命令打开。

        Vehicle Wizard 包含三个页面。第一个要求车辆的基本尺寸和配置,第二个设置轮胎的尺寸以及其他车轮和悬架相关设置。最后一页提供了完成无人机及其物理设置的可选后续步骤的检查列表。

        向导创建的车辆将根据 Create 的坐标系进行定向。如果选择了 Z 轴向上,则 X 轴或 Y 轴可以是向前方向。如果选择了 Y 轴向上,则 X 轴或 Z 轴可以向前移动。Vehicle Wizard 将创建一个应用了 PhysxVehicleContextAPI 的 PhysicsScene 基元,它将反映所选配置。但是,如果舞台中已经存在应用了 PhysxVehicleContextAPI 的物理场景基元,则其垂直轴和纵轴信息将用于确定新车辆的方向。

        

        Vehicle Prim 面板允许指定应用作车辆 prim 的 prim 的路径。车辆图元是车辆层次结构的根,其中包含随车辆移动的所有部分。如果有可用的车辆渲染资产,并且目标是直接将车辆相关属性应用于该资产的图元以将其转换为车辆模拟资产,则可以考虑此选项。必须注意,指定的车辆图元需要是 UsdGeomXform。此外,请参阅编写车辆的渲染网格,了解有关舞台设置以及如何排列资产图元的一些建议。如果未定义 Vehicle prim,向导将创建一个 prim (以及车轮等的子 prims)。Selected (选定) 和 Clear (清除) 按钮是允许分别拾取当前所选图元的路径或清除路径的辅助对象。

        在 Chassis Box 面板中,输入 Length, Width 和 Height ,其单位与 Omniverse USD Composer 中用于对世界进行建模的单位相同。这些维度将用于计算车辆的质量分布或惯性矩。此外,尺寸将影响车轮的放置位置(除非扫描车轮几何形状或明确指定车轮附件图元)。如果未定义 Vehicle Prim,则尺寸也将用于创建应包含大部分 Vehicle Mesh 几何体的碰撞盒。如果需要,可以删除向导创建的碰撞箱,并在以后将其替换为更形状拟合的表示。但是,计算车辆的基本质量属性仍然需要这些输入。

        如果要偏离自动计算的值,请在 Mass 编辑框中输入车辆的重量。使用与阶段中定义的相同的权重单位。

        可以从 纵向轴 下拉列表中选择车辆的前进 (纵向) 方向。如果舞台上存在应用了 PhysxVehicleContextAPI 的图元,则 Longitudinal Axis 下拉列表将被禁用,并显示 PhysxVehicleContextAPI 中指定的纵轴。如果之前未选择纵向,则将显示可用选项。

        通过从舞台中选择一组代表机箱的图元,然后按 Scan 按钮,可以使用自动填充大多数设置的选项。确保在运行扫描之前根据需要定义 Longitudinal Axis。Vehicle Wizard 将使轴对齐的边界框适合选定的图元,并填写尺寸设置。质量也会被调整,除非之前覆盖了该字段。边界框还将用于定义车辆位置(如果未指定车辆图元)和计算车辆的质心。图元具有描述其用途的用途,例如 render、guide、default 和 proxy。仅扫描 render 和 default prims。此外,只能使用几何网格和形状来拟合边界框。请注意,选择车辆图元和扫描底盘箱是分开的,因为车辆图元不必靠近底盘箱,并且并非车辆图元下的所有渲染网格或几何体都适合包含在底盘箱的边界框计算中。

        “驱动”面板要求使用以下三种方法之一来推动车辆:Standard(标准)、Basic(基本)或 None(无)。

        Number of Axles 编辑框用于设置车辆上的轮胎对数。轮胎设置将在下一页进行调整。

        按 Next 按钮访问这些设置。或者,可以按下 Create 按钮以使用 Axle Page 的默认设置来创建车辆。随时按 Reset 将向导设置重置为其默认值(这也将清除用户覆盖的字段并返回自动计算这些值)。

         

标准驱动器 

        标准驱动类型利用发动机和变速器将扭矩传递到驱动轮胎。使用此驱动类型时,请输入最大发动机马力、最大发动机转速和变速器中的齿轮数

车辆发动机将配置为遵循由以下参考点定义的马力与发动机 RPM 曲线:

        

        当发动机达到其最大 RPM 的三分之一时,此功率曲线输出峰值马力,并在发动机怠速和最大 RPM 时下降到 80%。这条曲线不是很现实,但它在怠速时产生更多动力,以获得更好的静止加速。

        Number of Gears (齿轮数) 指定变速器中的齿轮数。最高档位始终为 1:1,1 档传动比设置为与档位数相同的值,例如,在具有 5 个档位的变速器中为 5:1。其余档位均匀地降低 1 档和最高档之间的传动比。最终传动比设置为 4:1。

        齿轮在将发动机产生的扭矩施加到轮胎之前对其进行缩放。然而,传动比越高,变速器必须在发动机达到最大转速之前越早升至下一个档位。较重的车辆需要更高的传动比来产生更大的轮胎扭矩来加速,但需要额外的档位和更多的换档时间来补偿。

        车辆的最高速度将由 RPM 决定,并在一定程度上由 Horsepower 设置决定,而车辆的加速曲线将由 Number of Gears 和 Horsepower 设置控制。如果增加马力没有增加车辆加速度,则很可能是驱动轮胎打滑或烧坏。为了进一步提高车辆的加速度,需要增加轮胎的纵向刚度或摩擦力。

基本驱动器

        Basic 驱动类型的工作原理是简单地设置施加到驱动轮胎的最大扭矩。不会创建任何引擎或变速箱。扭矩由施加的节气门量成比例。输入设备还用于控制转向轮胎的转向角。此 Drive Type 可用于模拟电动汽车。最大扭矩是根据 Horsepower 设置计算的(以及选择此驱动类型时保持锁定的 RPM 值:Horsepower * 7120 / RPM)。

无驱动器 (无)

        当选择 None 驱动类型时,车辆不会将轮胎扭矩传递到轮胎。相反,轮胎扭矩和转向角是手动设置的。这允许用户独立地对每个轮胎进行自定义控制。这对于机器人应用非常有用,例如,轮胎可以沿相反方向旋转以使机器人就地旋转。

        

官方代码示例

WheelController.py

~/.local/share/ov/pkg/isaac-sim-4.1.0/extsPhysics/omni.physx.vehicle/omni/physxvehicle/scripts/samples/WheelController.py

直接控制车辆车轮,而不使用驱动模型

import mathfrom pxr import Gf, PhysxSchemafrom ..helpers import Factory
from .VehicleSampleBase import VehicleSampleBase
from . import Stepperimport omni.physxdemos as democlass WheelControllerDemo(VehicleSampleBase):title = "Wheel controller"category = demo.Categories.VEHICLESshort_description = "Usage of wheel controller"description = "Demo showing how to control wheels directly when not using a drive model."def create(self, stage):super().create(stage)create(stage)self.autofocus = True # autofocus on the scene at first updateself.autofocus_zoom = 0.28 # Get a bit closerclass WheelControllerScenario(Stepper.Scenario):def __init__(self, stage, vehiclePaths, wheelAttachmentPaths, wheelDriveTorques, wheelBrakeTorques, wheelSteerAngles,timeStepsPerSecond):secondsToRun = 6.0super().__init__(secondsToRun, 1.0 / timeStepsPerSecond)self._stage = stageself._vehicleCount = len(vehiclePaths)self._vehiclePaths = vehiclePathsself._wheelAttachmentPaths = wheelAttachmentPathsself._wheelControllers = []for i in range(self._vehicleCount):self._wheelControllers.append([])for j in range(len(self._wheelAttachmentPaths[i])):prim = self._stage.GetPrimAtPath(self._wheelAttachmentPaths[i][j])self._wheelControllers[i].append(PhysxSchema.PhysxVehicleWheelControllerAPI(prim))self._wheelDriveTorques = wheelDriveTorquesself._wheelBrakeTorques = wheelBrakeTorquesself._wheelSteerAngles = wheelSteerAnglesself._steerStop = 0.3 * secondsToRunself._accelStop = 0.5 * secondsToRunself._brakeStart = self._accelStopdef on_start(self):for i in range(self._vehicleCount):for j in range(len(self._wheelAttachmentPaths[i])):self._wheelControllers[i][j].GetBrakeTorqueAttr().Set(0)self._wheelControllers[i][j].GetSteerAngleAttr().Set(0)self._wheelControllers[i][Factory.WHEEL_FRONT_LEFT].GetDriveTorqueAttr().Set(self._wheelDriveTorques[i])self._wheelControllers[i][Factory.WHEEL_FRONT_RIGHT].GetDriveTorqueAttr().Set(self._wheelDriveTorques[i])def on_end(self):returndef on_step(self, deltaTime, totalTime):if totalTime < self._steerStop:for i in range(self._vehicleCount):steerAngle = (totalTime / self._steerStop) * self._wheelSteerAngles[i]self._wheelControllers[i][Factory.WHEEL_FRONT_LEFT].GetSteerAngleAttr().Set(steerAngle)self._wheelControllers[i][Factory.WHEEL_FRONT_RIGHT].GetSteerAngleAttr().Set(steerAngle)elif (totalTime - self._steerStop) <= deltaTime:for i in range(self._vehicleCount):self._wheelControllers[i][Factory.WHEEL_FRONT_LEFT].GetSteerAngleAttr().Set(0)self._wheelControllers[i][Factory.WHEEL_FRONT_RIGHT].GetSteerAngleAttr().Set(0)if (totalTime > self._accelStop) and ((totalTime - self._accelStop) <= deltaTime):for i in range(self._vehicleCount):self._wheelControllers[i][Factory.WHEEL_FRONT_LEFT].GetDriveTorqueAttr().Set(0)self._wheelControllers[i][Factory.WHEEL_FRONT_RIGHT].GetDriveTorqueAttr().Set(0)if (totalTime >= self._brakeStart) and ((totalTime - self._brakeStart) <= deltaTime):for i in range(self._vehicleCount):self._wheelControllers[i][Factory.WHEEL_REAR_LEFT].GetBrakeTorqueAttr().Set(self._wheelBrakeTorques[i])self._wheelControllers[i][Factory.WHEEL_REAR_RIGHT].GetBrakeTorqueAttr().Set(self._wheelBrakeTorques[i])def create(stage):vehicleCount = 3vehiclePaths = []wheelAttachmentPaths = []timeStepsPerSec = 60Factory.create4WheeledCarsScenario(stage,1.0,vehicleCount,createCollisionShapesForWheels=True,driveMode=Factory.DRIVE_NONE,vehiclePathsOut=vehiclePaths,wheelAttachmentPathsOut=wheelAttachmentPaths,vehicleDelta=[-3, 0, 0],timeStepsPerSecond = timeStepsPerSec)wheelDriveTorques = [300, 600, 900]wheelBrakeTorques = [500, 1000, 2000]wheelSteerAngles = [(45 * math.pi) / 180, (30 * math.pi) / 180, (10 * math.pi) / 180]scenario = WheelControllerScenario(stage, vehiclePaths, wheelAttachmentPaths, wheelDriveTorques, wheelBrakeTorques, wheelSteerAngles,timeStepsPerSec)Stepper.run_scenario(scenario)

小车加音效。利用物理引擎数据(如车辆速度、轮胎滑移、引擎转速等)生成动态音效

VehicleAudio.py

/home/lxy/.local/share/ov/pkg/isaac-sim-4.1.0/extsPhysics/omni.physx.vehicle/omni/physxvehicle/scripts/samples/VehicleAudio.py

import enum
import math
import osimport pxr.OmniAudioSchema as AudioSchema
from pxr import Gf, PhysxSchema, Usd, UsdPhysicsimport omni.kit.app
import omni.physxdemos as demo
import omni.timeline
import omni.usd
from omni.physx.bindings._physx import (VEHICLE_DRIVE_STATE_ENGINE_ROTATION_SPEED,VEHICLE_WHEEL_STATE_ROTATION_SPEED, VEHICLE_WHEEL_STATE_TIRE_LATERAL_SLIP,VEHICLE_WHEEL_STATE_TIRE_LONGITUDINAL_SLIP)from . import BasicSetup
from .VehicleSampleBase import VehicleSampleBaseCMPS_TO_MPH = 0.0223694
RPS_TO_RPM = 30.0 / 3.1415NOTE0 = 13.6
NOTE1 = 0.0066
NOTE2 = -2.95e-7GAUSSIAN_A = 0.8
GAUSSIAN_B = 0.0
GAUSSIAN_C = 666.0class VehicleSoundDemo(VehicleSampleBase):title = "Vehicle sounds"category = demo.Categories.VEHICLESshort_description = "Usage of vehicle telemetry to emit sounds"description = ("Demo of engine, tire roll and skidding audio and how to connect it to the vehicle telemetry. The arrow keys can be used to steer, accelerate and brake. ""To use a gamepad for controlling the vehicle, make sure to disable Gamepad Camera Control in the Viewport Settings.")def create(self, stage):super().create(stage)self._physxInterface = omni.physx.get_physx_interface()BasicSetup.create(stage, True)create(stage, self._physxInterface)self.autofocus = True # autofocus on the scene at first updateself.autofocus_zoom = 0.28 # Get a bit closerdef on_shutdown(self):self._physxInterface = Noneclass SoundType(enum.Enum):engine = 1tire = 2skid = 3class VehicleSound:def __init__(self, vehiclePrim, soundPrim, soundType, lowLoad, rpm, speed):self._vehicle = vehiclePrimself._sound = soundPrimself._soundType = soundTypeself._lowLoad = lowLoadself._rpm = rpmself._speed = speedclass LowPassFilter:def __init__(self):self._timeConstant = 1.0self._oneOverTimeConstant = 0.0self._value = 0.0def setTimeConstant(self, timeConstant):if (timeConstant > 0.0):self._timeConstant = timeConstantself._oneOverTimeConstant = 1.0 / timeConstantdef getValue(self):return self._valuedef filter(self, value, timeStep):if (timeStep < self._timeConstant):k = timeStep * self._oneOverTimeConstantself._value = k * value + (1.0 - k) * self._valueelse:self._value = valuereturn self._valuedef Lerp(x0, y0, x1, y1, x):t = (x - x0) / (x1 - x0)t = min(max(t, 0.0), 1.0)return y0 + t * (y1 - y0)def gaussian(a, b, c, x):numerator = -(x - b) * (x - b)denominator = 2.0 * c * cgauss = a * math.exp(numerator / denominator)return gaussclass VehicleAudioSample:def __init__(self, stage, physxInterface):self._physxInterface = physxInterfaceself._stage = stage# the update loop callback seems to get triggered before the vehicle update and thus the vehicles have not# been set up yet. Unfortunately, there seems no way to describe depenencies on other tasks to enforce# an order. Hence, just wait for one update to pass before starting.#self._firstUpdatePassed = Falseself._slipFilter = LowPassFilter()self._slipFilter.setTimeConstant(0.1)self._soundList = []self._timeline = omni.timeline.get_timeline_interface()self._appUpdate = omni.kit.app.get_app().get_update_event_stream().create_subscription_to_pop(self.update, name="omni.physx.vehicle update")self._usd_context = omni.usd.get_context()self._stageEventSubscription = self._usd_context.get_stage_event_stream().create_subscription_to_pop(self.on_stage_event)vehiclePrim = Noneself._maxRPM = 0self._minRPM = 99999for prim in self._stage.Traverse():# print(dir(prim))if (prim.HasAPI(PhysxSchema.PhysxVehicleAPI)):vehiclePrim = primelif (prim.IsA(AudioSchema.Sound)):# Initialize all of the sounds.# Silent and looping.prim.GetAttribute("timeScale").Set(1.0)prim.GetAttribute("gain").Set(0.0)prim.GetAttribute("loopCount").Set(-1)primPath = str(prim.GetPath())rpm = 0speed = 0lowLoad = FalselowLoadIndex = primPath.find("loww")highLoadIndex = primPath.find("high")tireIndex = primPath.find("driveon")skidIndex = primPath.find("tireslip")if (lowLoadIndex != -1):soundType = SoundType.enginelowLoad = Truerpm = int(primPath[lowLoadIndex + 4:])self._maxRPM = max(self._maxRPM, rpm)self._minRPM = min(self._minRPM, rpm)elif (highLoadIndex != -1):soundType = SoundType.enginerpm = int(primPath[highLoadIndex + 4:])elif (tireIndex != -1):soundType = SoundType.tirespeed = int(primPath[tireIndex + 7:])elif (skidIndex != -1):soundType = SoundType.skidnewSound = VehicleSound(vehiclePrim, prim, soundType, lowLoad, rpm, speed)self._soundList.append(newSound)def on_stage_event(self, event):if (event.type == int(omni.usd.StageEventType.CLOSING)):self.shutdown()def shutdown(self):self._slipFilter = Noneself._soundList = Noneself._appUpdate = Noneself._stageEventSubscription = Nonedef update(self, e):if (self._timeline.is_playing()):if (self._firstUpdatePassed):deltaTime = e.payload["dt"]vehiclePrim = Nonethrottle = NonewheelState = NonetireRadius = 35.0for vehicleSound in self._soundList:gain = 0.0timeScale = 1.0if (vehiclePrim != vehicleSound._vehicle):vehiclePrim = vehicleSound._vehiclethrottle = vehiclePrim.GetAttribute("physxVehicleController:accelerator").Get()rearLeftWheelPath = vehiclePrim.GetPath().pathString + "/RearLeftWheel"wheelState = self._physxInterface.get_wheel_state(rearLeftWheelPath)driveState = self._physxInterface.get_vehicle_drive_state(vehiclePrim.GetPath().pathString)longitudinalSlip = math.fabs(wheelState[VEHICLE_WHEEL_STATE_TIRE_LONGITUDINAL_SLIP])lateralSlip = math.fabs(wheelState[VEHICLE_WHEEL_STATE_TIRE_LATERAL_SLIP])slip = max(longitudinalSlip, lateralSlip)slip = min(max(slip, 0.0), 1.0)wheelRotationSpeed = wheelState[VEHICLE_WHEEL_STATE_ROTATION_SPEED]wheelSpeedMPH = tireRadius * math.fabs(wheelRotationSpeed) * CMPS_TO_MPHspeedMPH = wheelSpeedMPHrpm = driveState[VEHICLE_DRIVE_STATE_ENGINE_ROTATION_SPEED] * RPS_TO_RPMrpm = min(max(rpm, self._minRPM), self._maxRPM)currentNote = rpm * rpm * NOTE2 + rpm * NOTE1 + NOTE0if (vehicleSound._soundType == SoundType.engine):# Engine soundsloadGain = throttleif (vehicleSound._lowLoad):loadGain = 1 - throttledeltaRPM = rpm - vehicleSound._rpmrpmGain = gaussian(GAUSSIAN_A, GAUSSIAN_B, GAUSSIAN_C, deltaRPM)gain = loadGain * rpmGainsoundNote = vehicleSound._rpm * vehicleSound._rpm * NOTE2 + vehicleSound._rpm * NOTE1 + NOTE0semitoneDelta = currentNote - soundNotetimeScale = math.pow(2.0, semitoneDelta / 12.0)elif (vehicleSound._soundType == SoundType.tire):# Tire rolling soundsif (vehicleSound._speed == 10.0):if (speedMPH < 10.0):gain = Lerp(0.0, 0.0, 10.0, 0.7, speedMPH)semitoneDelta = Lerp(0.0, -2.0, 10.0, 0.0, speedMPH)else:gain = Lerp(10.0, 0.7, 20.0, 0.3, speedMPH)semitoneDelta = Lerp(10.0, 0.0, 20.0, 2.0, speedMPH)elif (vehicleSound._speed == 20.0):if (speedMPH < 20.0):gain = Lerp(10.0, 0.0, 20.0, 0.7, speedMPH)semitoneDelta = Lerp(10.0, -2.0, 20.0, 0.0, speedMPH)else:gain = Lerp(20.0, 0.7, 60.0, 0.35, speedMPH)semitoneDelta = Lerp(20.0, 0.0, 60.0, 3.0, speedMPH)elif (vehicleSound._speed == 60.0):gain = Lerp(0.0, 0.0, 30.0, 1.0, speedMPH)if (speedMPH < 60.0):semitoneDelta = Lerp(10.0, -2.0, 60.0, 0.0, speedMPH)else:semitoneDelta = Lerp(60.0, 0.0, 150.0, 2.0, speedMPH)timeScale = math.pow(2.0, semitoneDelta / 12.0)elif (vehicleSound._soundType == SoundType.skid):# Tire skidding soundsgain = self._slipFilter.filter(slip, deltaTime)vehicleSound._sound.GetAttribute("gain").Set(gain)vehicleSound._sound.GetAttribute("timeScale").Set(timeScale)else:self._firstUpdatePassed = Trueelse:self._firstUpdatePassed = Falsedef _create_audio_prim(stage, audioFolder, rootPath, filename):sound = AudioSchema.Sound.Define(stage, rootPath + "/Vehicle/Audio/" + filename)sound.CreateFilePathAttr().Set(audioFolder + "/" + filename + ".wav")def create(stage, physxInterface):# print(dir(AudioSchema.Sound))data_path = "../../../../../data/audio"audio_folder = os.path.abspath(os.path.normpath(os.path.join(__file__, data_path)))audio_folder = audio_folder.replace("\\", "/")# print(audio_folder)rootPath = str(stage.GetDefaultPrim().GetPath())# Engine sounds_create_audio_prim(stage, audio_folder, rootPath, "loww1000")_create_audio_prim(stage, audio_folder, rootPath, "loww1500")_create_audio_prim(stage, audio_folder, rootPath, "loww2000")_create_audio_prim(stage, audio_folder, rootPath, "loww2500")_create_audio_prim(stage, audio_folder, rootPath, "loww3000")_create_audio_prim(stage, audio_folder, rootPath, "loww3500")_create_audio_prim(stage, audio_folder, rootPath, "loww4000")_create_audio_prim(stage, audio_folder, rootPath, "loww4500")_create_audio_prim(stage, audio_folder, rootPath, "loww5000")_create_audio_prim(stage, audio_folder, rootPath, "loww5500")_create_audio_prim(stage, audio_folder, rootPath, "loww6000")_create_audio_prim(stage, audio_folder, rootPath, "loww6500")_create_audio_prim(stage, audio_folder, rootPath, "high1000")_create_audio_prim(stage, audio_folder, rootPath, "high1500")_create_audio_prim(stage, audio_folder, rootPath, "high2000")_create_audio_prim(stage, audio_folder, rootPath, "high2500")_create_audio_prim(stage, audio_folder, rootPath, "high3000")_create_audio_prim(stage, audio_folder, rootPath, "high3500")_create_audio_prim(stage, audio_folder, rootPath, "high4000")_create_audio_prim(stage, audio_folder, rootPath, "high4500")_create_audio_prim(stage, audio_folder, rootPath, "high5000")_create_audio_prim(stage, audio_folder, rootPath, "high5500")_create_audio_prim(stage, audio_folder, rootPath, "high6000")_create_audio_prim(stage, audio_folder, rootPath, "high6500")# Skid sounds_create_audio_prim(stage, audio_folder, rootPath, "tireslip")# Drive on sounds_create_audio_prim(stage, audio_folder, rootPath, "driveon10")_create_audio_prim(stage, audio_folder, rootPath, "driveon20")_create_audio_prim(stage, audio_folder, rootPath, "driveon60")vehicleAudio = VehicleAudioSample(stage, physxInterface)

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

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

相关文章

理解Laravel中的pipeline

pipeline在laravel的启动过程中出现次数很多&#xff0c;要了解laravel的启动过程和生命周期&#xff0c;理解pipeline就是其中的一个关键点。网上对pipeline的讲解很少&#xff0c;所以我自己写一写吧。 首先还是来看看调用栈&#xff0c;也就是从一个请求开始到返回响应&…

基于uniapp和java的电动车智能充电系统软件平台的设计

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 对电动车智能充电系统进行设计和开发。通过使用本系统可有效地减少运营成本&#xff0c;提高管理效率。 根据近年来社会…

使用css和html制作导航栏

代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}#m{background-color: antiquewhite;width: 100%;height: 50px;}#i{float: left;width: 100px;height: 50px;li…

怎样使用pycharm的服务?

‌在PyCharm中使用服务器的步骤如下‌&#xff1a; ‌打开PyCharm&#xff0c;选择“File”->“Settings”‌。‌选择左侧工具栏中的“Project:…”‌&#xff0c;然后选择“Python Interpreter”。‌点击右上角的“Add Interpreter”‌&#xff0c;选择“On SSH”。‌如果…

CI_CD

什么是CI/CD 在前端开发中&#xff0c;CI/CD 是 Continuous Integration&#xff08;持续集成&#xff09;和 Continuous Deployment/Continuous Delivery&#xff08;持续部署/持续交付&#xff09;的简称。它是一种软件开发实践&#xff0c;自动化了应用的构建、测试和发布过…

设置JAVA以适配华为2288HV2服务器的KVM控制台

华为2288HV2服务器比较老旧了&#xff0c;其管理控制台登录java配置比较麻烦&#xff0c;华为的ibmc_kvm_client_windows客户端测试了几个版本&#xff0c;连接控制台也有问题&#xff0c;最终安装JDK解决。 一、测试环境 主机为WindowsServer2012R2,64位系统 二、Java软件包…

机器学习—构建一个神经网络

如何在Tensorflow中构建神经网络&#xff1f; 回到之前的例子&#xff0c;如果你想做钱进支柱&#xff0c;初始化数据x创建第一层&#xff0c;如下图所示计算一个1&#xff0c;然后创建第二层并计算一个2&#xff0c;所以这是一种明确的向前推进的方式。 事实证明&#xff0c;…

基于51单片机的步进电机定时控制proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1_F5bfyS_e_eKSblnja7RqA 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

【云原生开发】如何通过client-go来操作K8S集群

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

idea 配置自动导入设置

配置自动导入设置&#xff1a; 通过访问 Settings→Editor→General→Auto Import&#xff0c;勾选 Add unambiguous imports on the fly 和 Optimize imports on the fly 选项&#xff0c;可以实现自动添加明确的导入和快速优化导入&#xff0c;即自动删除无用的导入

【文本情感分析识别】Python+SVM算法+模型训练+文本分类+文本情感分析

一、介绍 使用Python作为开发语言&#xff0c;基于文本数据集&#xff08;一个积极的xls文本格式和一个消极的xls文本格式文件&#xff09;&#xff0c;使用Word2vec对文本进行处理。通过支持向量机SVM算法训练情绪分类模型。实现对文本消极情感和文本积极情感的识别。并基于D…

iptables面试题

1、详述iptales工作流程以及规则过滤顺序&#xff1f; iptables过滤的规则顺序是由上至下&#xff0c;若出现相同的匹配规则则遵循由上至下的顺序 2、iptables的几个表以及每个表对应链的作用&#xff1f; Iptables有四表五链 Filter表 : Filter表是iptables中使用的默认表…

【青牛科技】GC2803:白色家电与安防领域中 ULN2803 的卓越替代者

在当今科技飞速发展的时代&#xff0c;电子元器件在各个领域都扮演着至关重要的角色。在白色家电和安防等产品的电路设计中&#xff0c;驱动芯片的选择尤为关键。传统的 ULN2803 曾是广泛应用的一款芯片&#xff0c;但如今&#xff0c;芯麦 GC2803 的出现为这些领域带来了新的选…

变脸、看完毒液3,我把自己的脸变毒液了,视频有点惊悚!请谨慎观看

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 AI工具集1&#xff1a;大厂AI工具【共23款…

数据分析:微生物功能差异分析之Maaslin2

文章目录 介绍加载R包数据链接导入数据数据预处理Maaslin2检验输出结果画图系统信息介绍 Maaslin2(Microbiome Multivariable Associations with Linear Models)是一种用于微生物组学数据的多变量关联分析工具。它的原理和特点如下: 多变量关联分析: Maaslin2旨在高效确定…

电脑软件:推荐四款非常好用的电脑磁盘分析工具

一、WizTree WizTree 是一款Windows下磁盘空间分析工具。它可以快速扫描并分析你的电脑硬盘驱动器中文件和文件夹&#xff0c;并以可视化块状的方式展示哪些文件和文件夹使用的磁盘空间最多。这样你就可以很方便找到占用磁盘空间大的文件。 WizTree的特点 ● 磁盘空间利…

6. STM32之TIM实验--编码器接口()--(实验5:PWM驱动直流电机)

这篇文章是通用定时器的最后一章节&#xff0c;也就是编码器接口&#xff0c;主要是用来进行对精确测量旋转角度或速度的负载进行精确控制。 STM32 编码器模式详解-CSDN博客 STM32——编码器测速原理及STM32编码器模式_龙邱512编码器stm32历程-CSDN博客 代码可根据这个进行编…

如何批量创建文件夹并命名?6个一键批量创建的方法

如何批量创建文件夹并命名&#xff1f;在快节奏的现代工作环境中&#xff0c;时间成为了最宝贵的资源。面对海量的数据与文件&#xff0c;如何高效地组织与管理&#xff0c;成为了提升工作效率的关键。为了节省时间&#xff0c;批量创建文件夹并命名&#xff0c;成为了一项至关…

人工智能之人脸识别(face_recognition)

文章目录 face_recognition 介绍主要功能**与opencv联系联系检测人脸切割人脸提取人物关键特征计算人脸的欧几里得距离计算人脸匹配程度总结 face_recognition 介绍 face_recognition 介绍 face_recognition 是一个非常流行的 Python 库&#xff0c;专门用于人脸识别任务。它基…

Java学习路线:JUL日志系统(二)使用Properties配置文件

目录 认识properties 使用properties编写日志配置文件 认识properties 之前的学习中&#xff0c;我们学习了使用XML配置文件&#xff0c;但是XML的读取实在有些麻烦。那有没有更简单的方式来配置文件呢&#xff1f; 答案是&#xff1a;使用Properties配置文件 在这里了解pro…