Page's Personal Website

Physx vehicle启动慢的问题

2020-06-14

@[toc] 把PhysX vehicle接到我们miniclient中,发现按w键,车子要好半天才启动起来~

经历

1.各种修改数据,阻尼,弹簧啥的

参考[1]

结果:无果

2.跟源代码,查看数据

跟踪的一些数据表明,确定引擎是有动力的=

小结:

(1) 从轮子的旋转上看就发现miniclient中车子一开始轮子旋转几乎是0,看四元素的x分量。因为车子是z方向,轮子也是,所以是绕x轴旋转

	# computeWheelLocalPoses() 这里代码很好理解,就是根据旋转的角度算这个轮子新的四元数,然后x、y和z分别算的
	  //Compute the transform of the wheel shapes. 
	  const PxVec3 pos=cmOffset+wheelsSimData.getWheelCentreOffset(i)-wheelsSimData.getSuspTravelDirection(i)*jounce;
	  const PxQuat quat(wheelQueryResults[i].steerAngle, gUp);
	  const PxQuat quat2(camberAngle, quat.rotate(forward));
	  const PxQuat quat3=quat2*quat;
	  const PxQuat quat4(rotAngles[i],quat3.rotate(gRight));
	  const PxTransform t(pos,quat4*quat3);

(2)可以看出来miniclient按键后一段时间forwardSpeed还是接近0,就等于没动

	# processSuspTireWheels()
    //Now compute the speeds along each of the tire axes.
    const PxF32 tireLongSpeed=wheelBottomVel.dot(tireLongDir);
    const PxF32 tireLatSpeed=wheelBottomVel.dot(tireLatDir);

    //Store the forward speed (having a local copy avoids lhs).
    forwardSpeeds[i]=tireLongSpeed;

	# integrateWheelRotationAngles() 这里的wheelSpeed就是forwardSpeed
  	PxF32 wheelOmega=wheelSpeeds[j];
  	if(jounces[j] > -vehSuspWheelTire4SimData.getSuspensionData(j).mMaxDroop &&	//(i) wheel touching ground
	   false==isBrakeApplied[j] &&	//(ii) no brake applied
	   0.0f==diffTorqueRatios[j]*KG*engineDriveTorque &&	//(iii) no drive torque applied
	   PxAbs(forwardSpeeds[j])<gThresholdForwardSpeedForWheelAngleIntegration)	//(iv) low speed
 	 {
	   const PxF32 recipWheelRadius=vehSuspWheelTire4SimData.getWheelData(j).getRecipRadius();
	   const PxF32 alpha=PxAbs(forwardSpeeds[j])*gRecipThresholdForwardSpeedForWheelAngleIntegration;
	   wheelOmega = (forwardSpeeds[j]*recipWheelRadius)*(1.0f-alpha) + wheelOmega*alpha;
	  }

	  PxF32 newRotAngle=wheelRotationAngles[j]+wheelOmega*timestep;
	  //Clamp the wheel rotation angle to a range (-10*pi,10*pi) to stop it getting crazily big.
  newRotAngle=physx::intrinsics::fsel(newRotAngle-10*PxPi, newRotAngle-10*PxPi, physx::intrinsics::fsel(-newRotAngle-10*PxPi, newRotAngle + 10*PxPi, newRotAngle));
	  wheelRotationAngles[j]=newRotAngle;

(3)可以看到影响forwardSpeed的carChassisLinVel 一开始传进来的就是0 (4)但是调试代码发现carChassisLinVel是会影响的,结果值是正常的

	# integrateBody()
	PX_INLINE void integrateBody
(const PxF32 inverseMass, const PxVec3& invInertia, const PxVec3& force, const PxVec3& torque, const PxF32 dt,
 PxVec3& v, PxVec3& w, PxTransform& t)
	{
	 //Integrate linear velocity.
	 v+=force*(inverseMass*dt);

可以看到carChassisLinVel(也就是函数中的v向量),是受force,inverseMass和dt三个影响的,结果这三个是正常的,算出来的值也是正确的,然后设置到actor中

(5)问题出在了这个值参与计算的时候是从开始取的,然后这个值就是很小的一个值

# updateDrive4W()
carChassisLinVel = vehActor->getLinearVelocity();

后面数据断点问题大概是PhysX的线程中会改vehActor->setLinearVelocity改的。不是很好看,感觉是simulate然后fetchResult之后更改的

# syncState()
 if ((bufferFlags & Buf::BF_LinearVelocity) == 0)
  mBufferedLinVelocity = mBodyCore.getLinearVelocity();
  • 时序图记录一下
sequenceDiagram
# 
Note Over physx: PxVehicleUpdates
physx->>PxVehicleUpdate: 
Note Over PxVehicleUpdate: update
Note Over PxVehicleUpdate: updateDrive4W
Note Over physx: processSuspTireWheels
Note Over physx: integrateWheelRotationAngles
Note Over physx: integrateBody

说明:

  • PxVehicleUpdate::updateDrive4W一开始就取了carChassisLinVel
    carChassisLinVel = vehActor->getLinearVelocity();
    
  • processSuspTireWheels根据carChassisLinVel算出来forwardSpeed
    //Now compute the speeds along each of the tire axes.
    const PxF32 tireLongSpeed=wheelBottomVel.dot(tireLongDir);
    const PxF32 tireLatSpeed=wheelBottomVel.dot(tireLatDir);

    //Store the forward speed (having a local copy avoids lhs).
    forwardSpeeds[i]=tireLongSpeed;
  • integrateWheelRotationAngles根据forwardSpeed算出来每个轮子的旋转角度(按x轴的)
  PxF32 wheelOmega=wheelSpeeds[j];
  if(jounces[j] > -vehSuspWheelTire4SimData.getSuspensionData(j).mMaxDroop &&	//(i) wheel touching ground
   false==isBrakeApplied[j] &&	//(ii) no brake applied
   0.0f==diffTorqueRatios[j]*KG*engineDriveTorque &&	//(iii) no drive torque applied
   PxAbs(forwardSpeeds[j])<gThresholdForwardSpeedForWheelAngleIntegration)	//(iv) low speed
  {
   const PxF32 recipWheelRadius=vehSuspWheelTire4SimData.getWheelData(j).getRecipRadius();
   const PxF32 alpha=PxAbs(forwardSpeeds[j])*gRecipThresholdForwardSpeedForWheelAngleIntegration;
   wheelOmega = (forwardSpeeds[j]*recipWheelRadius)*(1.0f-alpha) + wheelOmega*alpha;
  }

  PxF32 newRotAngle=wheelRotationAngles[j]+wheelOmega*timestep;
  //Clamp the wheel rotation angle to a range (-10*pi,10*pi) to stop it getting crazily big.
  newRotAngle=physx::intrinsics::fsel(newRotAngle-10*PxPi, newRotAngle-10*PxPi, physx::intrinsics::fsel(-newRotAngle-10*PxPi, newRotAngle + 10*PxPi, newRotAngle));
  wheelRotationAngles[j]=newRotAngle;
  correctedWheelSpeeds[j]=wheelOmega;
  • integrateBody重新计算carChassisLinVel
 //Integrate linear velocity.
 v+=force*(inverseMass*dt);

然而并没有卵用

3.和代码库里面sample例子对比一下代码

跟底层代码太深了,还是不能断定哪里出了问题,感觉载具引擎那边数据没啥问题~。所以,就再回头对比下啊Sample的代码,发现问题出在了档位上面

解决

看Sample里面有一段代码,会把车子初始设置为1档

   //Set the car back to its rest state.
   vehDrive4W->setToRestState();
   //Set the car to first gear.
   vehDrive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);

我这边加了下就可以了,可以了,以了,了~

总结

  • PhysX vehicle默认是空挡,但是自动挡的时候从空挡到1档会很慢,不知道是不是还有哪里设置的不对

参考

[1]官方文档


Similar Posts

Comments