Ok, I’m very confused, so, please, help me with this code:
Wheel:
class Wheel(entity.Entity):
def __init__(self, *args, **kwargs):
entity.Entity.__init__(self, *args, **kwargs)
# Mesh 3D.
self.m3d = loader.loadModel(kwargs['filename'])
self.m3d.reparentTo(kwargs['root'])
min, max = self.m3d.getTightBounds()
size = Point3(max - min)
self.radius = size.getZ() * 0.5
# Physics.
self.phys_body = OdeBody(kwargs['phys_world'])
mass = OdeMass()
mass.setSphere(100, self.radius)
self.phys_body.setMass(mass)
self.phys_geometry = OdeSphereGeom(kwargs['phys_space'], self.radius)
self.phys_geometry.setBody(self.phys_body)
self.accept('physics_world.simulation.step', self.__on_simulation_step)
def __on_simulation_step(self):
pos = Point3(self.phys_body.getPosition())
quat = Quat(self.phys_body.getQuaternion())
self.m3d.setPosQuat(render, pos, quat)
Where entity.Entity is for now only a subclass of direct.DirectObject.
This is the generic wheeled vehicle code:
class WheeledVehicle(entity.Entity):
def __init__(self, *args, **kwargs):
entity.Entity.__init__(self, *args, **kwargs)
self.__phys_world = kwargs['phys_world']
self.__wheels = []
self.__joints = []
self.__throttle = 0.0
self.__brake = 0.0
self.__steer = 0.0
self.__engine_fmax = 475
self.__brake_fmax = 1000
self.__steer_fmax = 100
self.__air_friction_coefficient = 0.3
self.__gear_box_efficiency = 0.7
self.__diff_ratio = 3.42
self.__gear_ratios = [2.66, -1.78, 1.30]
self.__gear = 0
# Car body AABB size.
self.__size = kwargs['vehicle_size']
# Physics.
self.phys_body = OdeBody(self.__phys_world)
mass = OdeMass()
mass.setBox(10, self.__size)
self.phys_body.setMass(mass)
self.phys_geometry = OdeBoxGeom(kwargs['phys_space'], self.__size)
self.phys_geometry.setCollideBits(BitMask32(0x00000002))
self.phys_geometry.setCategoryBits(BitMask32(0x00000001))
self.phys_geometry.setBody(self.phys_body)
taskMgr.add(self.__on_update_simulation, "Wheeled Vehicle Physics Simulation")
self.accept('physics_world.simulation.step', self.__on_simulation_step)
def add_wheel(self, wheel, traction=False, steer_limits=Vec2.zero(), susp_softness=0.001, susp_damping=0.1):
if wheel in self.__wheels:
id = self.__wheels.index_of(wheel)
self.__wheels.remove(id)
del self.__joints[id]
final_pos = self.phys_body.getPosition() + wheel.phys_body.getPosition()
wheel.phys_body.setPosition(final_pos)
# Suspension joint.
susp = OdeHinge2Joint(self.__phys_world)
susp.attach(self.phys_body, wheel.phys_body)
susp.setAnchor(final_pos)
susp.setAxis1(Vec3(0, 0, 1))
susp.setAxis2(Vec3(1, 0, 0))
susp.setParamFMax(0, self.__steer_fmax)
susp.setParamLoStop(0, steer_limits.getY())
susp.setParamHiStop(0, steer_limits.getX())
susp.setParamSuspensionCFM(0, susp_softness)
susp.setParamSuspensionERP(0, susp_damping)
if traction:
susp.setParamFMax(1, self.__engine_fmax)
susp.setParamFudgeFactor(1, 0.1)
self.__joints.append((susp, traction))
self.__wheels.append(wheel)
def __on_update_simulation(self, task):
engine_torque = self.__throttle * self.__engine_fmax
area = self.__size.getX() * self.__size.getY()
speed = self.phys_body.getLinearVel().length()
air_force = speed * speed * 0.5 * self.__air_friction_coefficient * area * 1.29
brake_force = self.__brake * self.__brake_fmax
ratio = self.__gear_ratios[self.__gear] * self.__diff_ratio * self.__gear_box_efficiency
k = engine_torque * ratio
sign = -1
if k < 0:
sign = 1
for n, (j, t) in enumerate(self.__joints):
if t is True:
wheel = self.__wheels[n]
drive_torque = k / wheel.radius
wheel_torque = drive_torque
if wheel_torque != 0:
wheel_torque += sign * (brake_force + air_force)
j.setParamVel(1, wheel_torque)
wheel_angle = j.getAngle1()
wheel_steer = self.__steer - wheel_angle
j.setParamVel(0, wheel_steer)
return task.cont
def accelerate(self, delta):
self.__throttle = delta
def brake(self, delta):
self.__brake = delta
def steer(self, delta):
self.__steer = delta
def prev_gear(self):
if self.__gear > 0:
self.__gear -= 1
def next_gear(self):
if self.__gear < (len(self.__gear_ratios)-1):
self.__gear += 1
def __on_simulation_step(self):
pos = Point3(self.phys_body.getPosition())
quat = Quat(self.phys_body.getQuaternion())
self.m3d.setPosQuat(render, pos, quat)
The simulation is very unstable and i don’t understand why…Besides i don’t know how i can implement a realistic wheel turn simulation, something more accurate than:
wheel_angle = j.getAngle1()
wheel_steer = self.__steer - wheel_angle
j.setParamVel(0, wheel_steer)
Thanks!