Caster like wheel

mcimolin

23-07-2010 19:24:52

I'm trying to make caster like wheels for a vehicle I'm building and was wondering how I'd go about it.
I know that I need to attach a joint between the caster style wheel and the body of the vehicle, but am
not quite sure how to do this, or which type of caster would be needed for the wheel to be able to swivel.
I'm using the vehicle code from my other post http://www.ogre3d.org/addonforums/viewtopic.php?f=6&t=12890
as a base, and am not sure how to add joints when the actor is being created from an array of shapes.

Any help would be appretiated.

betajaen

23-07-2010 20:30:26

Hmm. A caster would require three bodies/actor. The main part, connected to a hinge joint that would swivel which is connected to the "metal bracket" which contains the wheel, which that is joined via another hinge joint acting as the axle for the capsule/convex shape wheel.

What about a sphere with a spherical joint connected to your main part of your Body. You'd have to have a "pretend" caster in the visualisation part and just point it in the direction that the spherical joint is. You'd only have two bodies then (or one per wheel plus chassis), and it would go in any direction as intended.

If you want some pseudo code on this idea, please ask.

mcimolin

23-07-2010 20:52:13

I was hoping to use the NxOgre::Wheel instead of using a sphere or capsule. I'm working off of the vehicle code
you'd writen in an earlier tutorial.

Here is the code I have:
#include "WheelChairVehicle.h"

/*
Create and Register the Vehicle
*/
WheelChairVehicle::WheelChairVehicle(const NxOgre::Vec3& position, NxOgre::Scene* scene, OGRE3DRenderSystem* renderSystem, Ogre::SceneManager* _mSceneManager, int selectedChair)
{
Machine();
mScene = scene;
mRenderSystem = renderSystem;
mSceneManager = _mSceneManager;
mSelectedChair = selectedChair;

NxOgre::RigidBodyDescription description;

description.mMass = 40; // Make it heavy.
description.mWakeUpCounter = 1E30; // Never go to sleep.

maxBrakeTorque = 275.0f;
maxDriveTorque = 200.0f;
maxReverseTorque = -200.0f;
maxSteerTorque = 200.0f;
maxSteerAngle = 60.0f;
maxSpeed = 0;

wheelBrakeTorque = 0;
leftDriveTorque = 0;
rightDriveTorque = 0;

NxOgre::Shapes shapes;

shapes = buildChair(shapes);

mActor = mScene->createActor(shapes, position, description);
mActor->setCMassOffsetLocalPosition(NxOgre::Vec3(0.12792f,0.286539f,-0.0324331f));

mWheelChairNode = mSceneManager->getRootSceneNode()->createChildSceneNode("WheelChairNode");

mCameraNode = mWheelChairNode->createChildSceneNode("WheelChairCameraNode", Ogre::Vector3(0.1f,1.2f,-0.25f));
mCameraNode->yaw(Ogre::Radian(Ogre::Degree(180)), Ogre::Node::TS_LOCAL);

mWheelChairNode->setPosition((mActor->getGlobalPosition()).as<Ogre::Vector3>());
mWheelChairNode->setOrientation(mActor->getGlobalOrientationQuat().as<Ogre::Quaternion>());

switch(mSelectedChair){
case 0: mPointRenderable = mRenderSystem->createPointRenderable("mWheelChair.mesh"); break;
case 1: mPointRenderable = mRenderSystem->createPointRenderable("rWheelChair.mesh"); break;
case 2: mPointRenderable = mRenderSystem->createPointRenderable("mtWheelChair.mesh"); break;
case 3: mPointRenderable = mRenderSystem->createPointRenderable("rtWheelChair.mesh"); break;
}

mActor->getNxActor()->setGroup(1);
mScene->registerMachine(this);

}


/*
Destructor
*/
WheelChairVehicle::~WheelChairVehicle()
{
mSceneManager->getRootSceneNode()->removeAndDestroyChild("WheelChairNode");
delete mChassisShape;
mChassisShape = NULL;
mActor = NULL;
delete mPointRenderable;
mScene->unregisterMachine(this);
}


/*
Builds the correct handling wheelchair based on selectedChair,
and returns the NxOgre::Shapes containing the wheelchair parts.
*/
NxOgre::Shapes WheelChairVehicle::buildChair(NxOgre::Shapes shapes){

//Load Resources
NxOgre::ResourceSystem::getSingleton()->openArchive("media", "file:media/");

//Convert to standard string
std::string mMesh;

switch(mSelectedChair){
case 0: mMesh = "media:midWheelChair.mesh.nxs"; break;
case 1: mMesh = "media:rearWheelChair.mesh.nxs"; break;
case 2: mMesh = "media:midWheelChair.mesh.nxs"; break;
case 3: mMesh = "media:rearWheelChair.mesh.nxs"; break;
}

const char* cMesh = mMesh.c_str();

NxOgre::Resource* rMesh = NxOgre::ResourceSystem::getSingleton()->open(cMesh, NxOgre::Enums::ResourceAccess_ReadOnly);

NxOgre::Mesh* convexMesh = NxOgre::MeshManager::getSingleton()->load(rMesh);

mChassisShape = new NxOgre::Convex(convexMesh);

shapes.insert(mChassisShape);

if(mSelectedChair == 0 || mSelectedChair == 2){
addWheel(0.5f, NxOgre::Vec3(-0.105f, 0.2f, 0.49f), false, false, false, true, false);
addWheel(0.5f, NxOgre::Vec3(0.375f, 0.2f, 0.49f), false, false, false, true, true);
addWheel(1.0f, NxOgre::Vec3(-0.105f, 0.1f, -0.422f), false, true, false, true, false);
addWheel(1.0f, NxOgre::Vec3(0.375f, 0.1f, -0.422f), false, true, false, true, true);
addWheel(1.0f, NxOgre::Vec3(-0.155f, 0.1f, 0.24f), true, true, true, false, false);
addWheel(1.0f, NxOgre::Vec3(0.425f, 0.1f, 0.24f), true, true, true, false, true);
}

else{
addWheel(1.0f, NxOgre::Vec3(-0.105f, 0.1f, 0.35f), false, true, false, true, false);
addWheel(1.0f, NxOgre::Vec3(0.375f, 0.1f, 0.35f), false, true, false, true, true);
addWheel(0.5f, NxOgre::Vec3(-0.105f, 0.05f, -0.6f), false, false, false, true, false);
addWheel(0.5f, NxOgre::Vec3(0.375f, 0.05f, -0.6f), false, false, false, true, true);
addWheel(2.0f, NxOgre::Vec3(-0.155f, 0.2f, -0.3f), true, true, true, false, false);
addWheel(2.0f, NxOgre::Vec3(0.425f, 0.2f, -0.3f), true, true, true, false, true);
}

for (unsigned int i=0; i < mWheels.size(); i++)
shapes.insert(mWheels[i].mWheel);

NxOgre::ResourceSystem::getSingleton()->close(rMesh);

return shapes;
}


/*
Creates and adds wheels to the vehicle
*/
void WheelChairVehicle::addWheel(float radius, const NxOgre::Vec3& position, bool driving, bool steering, bool braking, bool suspension, bool left)
{
CarWheel w;

// Create the physics wheel, which our rules and point renderable will represent and work with.
NxOgre::WheelBlueprint* blueprint = new NxOgre::WheelBlueprint();
blueprint->mRadius = 0.433f * 0.25f * radius;
blueprint->mLocalPose.set(position);
blueprint->mInverseWheelMass = 1.0f;
w.mWheel = new NxOgre::Wheel(blueprint);

// Create our rules about this wheel.
w.mDriving = driving;
w.mSteering = steering;
w.mBraking = braking;
w.mLeft = left;

mWheels.insert(w);

// Then create the machine part of that wheel, so rules can be applied to it, and it can be rendered.
createWheelMachinePart(w.mWheel, mRenderSystem->createPointRenderable("wheel.mesh"));
}


/*
Applies a driving(forward) torque to the wheels, up to the
max torque
*/
void WheelChairVehicle::drive(float torque, bool steering, bool left)
{
mActor->wakeUp(1E30);

if(this->bNeedsBrake){
this->bNeedsBrake = false;
}

wheelBrakeTorque = 0;

/*if(steering){
if(left){
if(torque > 0){
if(rightDriveTorque > maxSteerTorque)
rightDriveTorque = maxSteerTorque;
else
rightDriveTorque = rightDriveTorque + torque;

if(leftDriveTorque < -maxSteerTorque)
leftDriveTorque = -maxSteerTorque;
else
leftDriveTorque = leftDriveTorque - torque;

}
else if(torque < 0){
if(rightDriveTorque < -maxSteerTorque)
rightDriveTorque = -maxSteerTorque;
else
rightDriveTorque = rightDriveTorque + torque;

if(leftDriveTorque > maxSteerTorque)
leftDriveTorque = maxSteerTorque;
else
leftDriveTorque = leftDriveTorque - torque;
}
}
else{
if(torque > 0){
if(rightDriveTorque < -maxSteerTorque)
rightDriveTorque = -maxSteerTorque;
else
rightDriveTorque = rightDriveTorque - torque;

if(leftDriveTorque > maxSteerTorque)
leftDriveTorque = maxSteerTorque;
else
leftDriveTorque = leftDriveTorque + torque;

}
else if(torque < 0){
if(rightDriveTorque > maxSteerTorque)
rightDriveTorque = maxSteerTorque;
else
rightDriveTorque = rightDriveTorque - torque;

if(leftDriveTorque < -maxSteerTorque)
leftDriveTorque = -maxSteerTorque;
else
leftDriveTorque = leftDriveTorque + torque;
}
}
}
else{*/
if(rightDriveTorque > maxDriveTorque)
rightDriveTorque = maxDriveTorque;
else if(rightDriveTorque < maxReverseTorque)
rightDriveTorque = maxReverseTorque;
else
rightDriveTorque = rightDriveTorque + torque;

if(leftDriveTorque > maxDriveTorque)
leftDriveTorque = maxDriveTorque;
else if(leftDriveTorque < maxReverseTorque)
leftDriveTorque = maxReverseTorque;
else
leftDriveTorque = leftDriveTorque + torque;
//}

for (unsigned int i=0;i < mWheels.size();i++){
if (mWheels[i].mDriving){
if(mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(this->leftDriveTorque);
if(!mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(this->rightDriveTorque);
}
}
//}
}


/*
Applies a stopping(reverse) torque to the wheels, down
to 0, then applies a brakeing torque.
*/
void WheelChairVehicle::slow(float torque)
{
if(this->leftDriveTorque > 75)
this->leftDriveTorque = this->leftDriveTorque - torque;
else if(this->leftDriveTorque < -75)
this->leftDriveTorque = this->leftDriveTorque + torque;
else{
this->leftDriveTorque = 0;
this->wheelBrakeTorque = this->maxBrakeTorque;
}

if(this->rightDriveTorque > 75)
this->rightDriveTorque = this->rightDriveTorque - torque;
else if(this->rightDriveTorque < -75)
this->rightDriveTorque = this->rightDriveTorque + torque;
else{
this->rightDriveTorque = 0;
this->wheelBrakeTorque = this->maxBrakeTorque;
}

for (unsigned int i=0;i < mWheels.size();i++){
if (mWheels[i].mBraking)
mWheels[i].mWheel->setBrakeTorque(this->wheelBrakeTorque);

if (mWheels[i].mDriving){
if(mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(this->leftDriveTorque);
if(!mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(this->rightDriveTorque);
}
}

this->bNeedsBrake = true;

float velocity = mActor->getLinearVelocity().x * mActor->getLinearVelocity().z;
if(velocity < (1E-3) && velocity > (-1E-3))
mActor->putToSleep();

}


/*
Applies a brakeing torque to the wheels.
*/
void WheelChairVehicle::brake(float torque)
{
mActor->wakeUp(1E30);

this->wheelBrakeTorque = this->wheelBrakeTorque + torque;
this->leftDriveTorque = 0;
this->rightDriveTorque = 0;

if(this->wheelBrakeTorque > maxBrakeTorque)
this->wheelBrakeTorque = maxBrakeTorque;

for (unsigned int i=0;i < mWheels.size();i++){
if (mWheels[i].mBraking)
mWheels[i].mWheel->setBrakeTorque(this->wheelBrakeTorque);

if (mWheels[i].mDriving)
mWheels[i].mWheel->setMotorTorque(0);
}
}


/*
Sets the steering angle of the wheels, between
the maximum and -maximum values.
*/
void WheelChairVehicle::steer(float angle)//float torque, bool left, bool drive)
{
mActor->wakeUp(1E30);

if(this->bNeedsBrake){
this->bNeedsBrake = false;
}
if(steerAngle > maxSteerAngle)
steerAngle = maxSteerAngle;
else if(steerAngle < -maxSteerAngle)
steerAngle = -maxSteerAngle;
else
steerAngle = steerAngle + angle;

for (unsigned int i=0;i < mWheels.size();i++){
if (mWheels[i].mSteering){
mWheels[i].mWheel->setSteeringAngle(Ogre::Degree(steerAngle).valueRadians());
}
}

/*
this->wheelBrakeTorque = 0;

if(drive){
if(left){
if(rightDriveTorque >= maxSteerTorque)
rightDriveTorque = maxSteerTorque;
else
rightDriveTorque = rightDriveTorque + torque;

if(leftDriveTorque <= -maxSteerTorque)
leftDriveTorque = -maxSteerTorque;
else
leftDriveTorque = leftDriveTorque - torque;

for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(leftDriveTorque);
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && !mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(rightDriveTorque);
}

if(!left){
if(rightDriveTorque <= -maxSteerTorque)
rightDriveTorque = -maxSteerTorque;
else
rightDriveTorque = rightDriveTorque - torque;

if(leftDriveTorque >= maxSteerTorque)
leftDriveTorque = maxSteerTorque;
else
leftDriveTorque = leftDriveTorque + torque;

for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(leftDriveTorque);
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && !mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(rightDriveTorque);
}
}
else{
if(left){
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && mWheels[i].mLeft){
mWheels[i].mWheel->setMotorTorque(-maxSteerTorque);
}
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && !mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(maxSteerTorque);
}

if(!left){
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(maxSteerTorque);
for (unsigned int i=0;i < mWheels.size();i++)
if (mWheels[i].mSteering && !mWheels[i].mLeft)
mWheels[i].mWheel->setMotorTorque(-maxSteerTorque);
}
}*/
}

/*
This function adjusts the maximum speed of the chair
*/
void WheelChairVehicle::setMaxSpeed(float forwardSpeed){

for (unsigned int i=0;i < mWheels.size();i++){
if(forwardSpeed <=2)
mWheels[i].mWheel->setInverseWheelMass(forwardSpeed/12);
else
mWheels[i].mWheel->setInverseWheelMass(forwardSpeed/16.6);
}

maxSpeed = forwardSpeed;
}

/*
This function adjusts the reverse speed of the chair
*/
void WheelChairVehicle::setReverseSpeed(float reverseSpeed){
maxReverseTorque = -(maxDriveTorque * (reverseSpeed/maxSpeed));
}


/*
This function adjusts the turning speed of the chair
*/
void WheelChairVehicle::setTurningSpeed(float turnSpeed){
maxSteerTorque = (maxDriveTorque * (turnSpeed/maxSpeed));
}

/*
This function sets the damping of the wheelchair.
*/
void WheelChairVehicle::applyDamping(int damping){
mActor->setLinearDamping(damping);
}


/*
Sets the position and orientation of the Vehicle
*/
void WheelChairVehicle::setPositionAndOrientation(NxOgre::Vec3 position, Ogre::Quaternion orientation){

mActor->setGlobalPosition(position);
mActor->setGlobalOrientationQuat(orientation);
mActor->putToSleep();
}


I was hoping to connect 2 of the wheels created with the addWheel method to the convexBody using joints, but I'm not sure how I'd
do that as the mActor is being created from the shapes array. Can I add joints to the shapes array? or is there another way to
build the actor? or can I just leave the actor as is, and directly attach the wheels to the convex body with joints?

betajaen

23-07-2010 21:40:27

Wheels are shapes like boxes or convexes. To connect them you simply attach them to your Actor/Body usually when you first create the body.

But you want a caster effect, the wheel shape doesn't allow the steering angle to change based on direction - which is what you would want if you want a caster. Which is why I suggested a sphere/sphericaljoint.

mcimolin

23-07-2010 22:11:24

Alright, so the only way to change the angles of a wheel would be with the steering angle function then. There's no way to
attach the wheel with a joint. If I'm understanding that correctly then I'd love some psuedo code for the sphere/sperical
joint solution you offered. I believe that should work.

The visualization isn't a problem as you can never actually see the wheels of the vehicle as the only camera is a first
person view from the position of someone sitting in the vehicle.