Laser based suspension?

About advanced scenes, and the Thyme scripting language used in Algodoo.

Laser based suspension?

Postby royalblue » Sat Mar 06, 2010 10:59 pm

I was thinking maybe we could have a laser at the front end of the car that would read the distance from the car to the ground and then that distance would be input into the spring length box so it would create a smoother ride. how do you go about finding the distance of a laser between the laser and where it hits something? I know ive seen something about it before
royalblue
 
Posts: 14
Joined: Mon Aug 31, 2009 9:22 pm

Re: Laser based suspension?

Postby KarateBrot » Sun Mar 07, 2010 1:48 am

It's called an active suspension. I experimented with it last year in phun. I also saw a scene from Kilinich. He uploaded one to phunbox.
Image
User avatar
KarateBrot
 
Posts: 825
Joined: Mon Aug 31, 2009 7:32 pm
Location: Germany

Re: Laser based suspension?

Postby Dakta » Sun Mar 07, 2010 4:22 am

What you're talking about is exactly what karatebrot said, an active suspension system.

The method of using a laser to detect the distance is one used in most game engines. You have a raycast collider that sends out a ray and returns the distance and other info about what it hits. Then you have a visual representation of the wheel that you spin and move up and down according to the vehicle's world velocity. No physics involved, just code.

Using that method, you can tweak everything precisely and get the feel you want, and still run fast on slow computers. I have yet to encounter a 100% physics vehicle in a final release multiplayer game. They all have to use code to optimize.

There is one node and beam (basically points in space connected by springs) based 100% physics simulator out there, called Rigs of Rods. Free @ rigsofrods.com

This is all dependent on knowing the distance a laser goes before hitting anything, which I am not sure can be easily determined in Algodoo right now. I would stick to physical wheels and suspension for the time being :P

Also, for raycast colliders, that is what they use to simulate guns. They send a raycast out of the barrel and apply damage and force to what it hits, and right as that happens, since the raycast is instantaneous, they send out an object with a trail renderer (pen) and particle emitter attached and stuff, then instantiate particles at the barrel and the hit point. <-- Not all in that order :D
.. ,__,_____
. / __.==--" - - - - - - - - ""
./#(-'
.`-' From http://www.ascii-art.de/. Modded by me to work in Arial. Image
a Mammoth wrote:be boring and interesting.

Mystery wrote:If you were jailbreaker you shouldn't have when't up the 3.1.3
I didn't know you could go up 3.1.3! Thanks Mystery person!
User avatar
Dakta
 
Posts: 417
Joined: Sat Sep 12, 2009 4:36 pm

Re: Laser based suspension?

Postby Mr_Stabby » Sun Mar 07, 2010 1:47 pm

reading the surface is easy, determining the best suspension configuration from that however is not. adjusting wheels simply based on the distance a laser is currently reading is just reacting which is pretty much what a regular suspension does. What you need is planning that considers vehicle position, different forces acting on it and most importanly atleast a little knowledge of the road ahead meaning recognition of different road nuances (naturally you react differently to for example driving uphill and a speedbump but for the laser they look exactly the same at some point), from all that you can derive a continous suspension configuration that you can optimize for either a smooth ride/maximum climbing ability/maximum speed or whatever you like. Even tho thyme isnt really suited for programming it still has all the necessary tools for creating what i described above and it wouldnt actually be very difficult with highschool physics knowledge because algodoo pretty much serves you all the required variables on a plate
Mr_Stabby
 
Posts: 155
Joined: Wed Dec 16, 2009 12:16 am

Re: Laser based suspension?

Postby Dakta » Sun Mar 07, 2010 11:01 pm

Stabby is right. This would be a bit of work, especially given Thyme's limitations, but it could be done.

Actually, I've got some javascript written for the UnityEngine for a raycast collider car, if anyone's interested.

The Car:
Code: Select all
var wheelFL : Transform;
var wheelFR : Transform;
var wheelBL : Transform;
var wheelBR : Transform;

var frontWheelSteering = false;
var rearWheelSteering = false;

var frontWheelDrive = false;
var rearWheelDrive = false;

var minSteeringAngle = 0.00;
var maxSteeringAngle = 0.00;
var highSpeed = 0.00;

var motorMass = 1.00;
var motorDrag = 0.00;
var maxAcceleration = 0.00;
var maxMotorSpeed = 0.00;
var minTorque = 0.00;
var maxTorque = 0.00;

var centerOfMass : Vector3;
rigidbody.centerOfMass = centerOfMass;

private var scriptWheelFL : Wheel;
private var scriptWheelFR : Wheel;
private var scriptWheelBL : Wheel;
private var scriptWheelBR : Wheel;
scriptWheelFL = wheelFL.GetComponent(Wheel);
scriptWheelFR = wheelFR.GetComponent(Wheel);
scriptWheelBL = wheelBL.GetComponent(Wheel);
scriptWheelBR = wheelBR.GetComponent(Wheel);
scriptWheelFL.car = this;
scriptWheelFR.car = this;
scriptWheelBL.car = this;
scriptWheelBR.car = this;

var steeringInput = 0.00;
var motorInput = 0.00;

var motorTorque = 0.00;
var motorAccel = 0.00;
var motorSpeed = 0.00;
var steeringAngle = 0.00;

if(frontWheelDrive) scriptWheelFL.driven = scriptWheelFR.driven = true;
if(rearWheelDrive) scriptWheelBL.driven = scriptWheelBR.driven = true;

function FixedUpdate ()
{
   steeringInput = Input.GetAxis("Horizontal");
   motorInput = Input.GetAxis("Vertical");
   
   if(frontWheelSteering) wheelFL.localRotation = wheelFR.localRotation = Quaternion.LookRotation(Vector3(steeringInput * (steeringAngle / 90), 0, 1 + (-1 * Mathf.Abs(steeringInput * (steeringAngle / 90))) ));
   if(rearWheelSteering) wheelBL.localRotation = wheelBR.localRotation = Quaternion.LookRotation(Vector3(-steeringInput * (steeringAngle / 90), 0, 1 + (-1 * Mathf.Abs(steeringInput * (steeringAngle / 90))) ));
   
   if(frontWheelDrive || rearWheelDrive)
   {
      motorTorque = Mathf.Lerp(maxTorque / 30, minTorque / 30, motorSpeed / maxMotorSpeed) * Mathf.Abs(motorInput);
      if(motorTorque < 1) motorTorque = 1;
      motorAccel = Mathf.Lerp(maxAcceleration, 0, motorSpeed / maxMotorSpeed);
      steeringAngle = Mathf.Lerp(maxSteeringAngle, minSteeringAngle, rigidbody.velocity.magnitude / highSpeed);

      motorSpeed += motorInput * motorAccel / motorMass * Time.fixedDeltaTime;
      
      if(frontWheelDrive)
      {
         scriptWheelFL.speed = scriptWheelFR.speed = motorSpeed;
      }
      
      if(rearWheelDrive)
      {
         scriptWheelBL.speed = scriptWheelBR.speed = motorSpeed;
      }
      
      motorSpeed += -motorSpeed * motorDrag / motorTorque * Time.fixedDeltaTime;
   }
}

function AddForceOnMotor (force : float)
{
   motorSpeed += force / motorTorque;
}



The wheel:
Code: Select all
var mass = 1.00;
var wheelRadius = 0.00;
var suspensionRange = 0.00;
var suspensionForce = 0.00;
var suspensionDamp = 0.00;
var compressionFrictionFactor = 0.00;

var sidewaysFriction = 0.00;
var sidewaysDamp = 0.00;
var sidewaysSlipVelocity = 0.00;
var sidewaysSlipForce = 0.00;
var sidewaysSlipFriction = 0.00;
var sidewaysStiffnessFactor = 0.00;

var forwardFriction = 0.00;
var forwardSlipVelocity = 0.00;
var forwardSlipForce = 0.00;
var forwardSlipFriction = 0.00;
var forwardStiffnessFactor = 0.00;

var frictionSmoothing = 1.00;

private var hit : RaycastHit;

private var parent : Rigidbody;
parent = transform.root.rigidbody;

private var graphic : Transform;
graphic = transform.FindChild("Graphic");

private var wheelCircumference = 0.00;
wheelCircumference = wheelRadius * Mathf.PI * 2;

private var usedSideFriction = 0.00;
private var usedForwardFriction = 0.00;
private var sideSlip = 0.00;
private var forwardSlip = 0.00;

var car : Car;
var driven = false;

var speed = 0.00;

var brake = false;
var skidbrake = false;

function FixedUpdate ()
{
   down = transform.TransformDirection(Vector3.down);
   if(Physics.Raycast (transform.position, down, hit, suspensionRange + wheelRadius) && hit.collider.transform.root != transform.root)
   {
      velocityAtTouch = parent.GetPointVelocity(hit.point);
      
      compression = hit.distance / (suspensionRange + wheelRadius);
      compression = -compression + 1;
      force = -down * compression * suspensionForce;
      
      t = transform.InverseTransformDirection(velocityAtTouch);
      t.z = t.x = 0;
      shockDrag = transform.TransformDirection(t) * -suspensionDamp;
      
      forwardDifference = transform.InverseTransformDirection(velocityAtTouch).z - speed;
      newForwardFriction = Mathf.Lerp(forwardFriction, forwardSlipFriction, forwardSlip * forwardSlip);
      newForwardFriction = Mathf.Lerp(newForwardFriction, newForwardFriction * compression * 1, compressionFrictionFactor);
      if(frictionSmoothing > 0)
         usedForwardFriction = Mathf.Lerp(usedForwardFriction, newForwardFriction, Time.fixedDeltaTime / frictionSmoothing);
      else
         usedForwardFriction = newForwardFriction;
      forwardForce = transform.TransformDirection(Vector3(0, 0, -forwardDifference)) * usedForwardFriction;
      forwardSlip = Mathf.Lerp(forwardForce.magnitude / forwardSlipForce, forwardDifference / forwardSlipVelocity, forwardStiffnessFactor);
      
      sidewaysDifference = transform.InverseTransformDirection(velocityAtTouch).x;
      newSideFriction = Mathf.Lerp(sidewaysFriction, sidewaysSlipFriction, sideSlip * sideSlip);
      newSideFriction = Mathf.Lerp(newSideFriction, newSideFriction * compression * 1, compressionFrictionFactor);
      if(frictionSmoothing > 0)
         usedSideFriction = Mathf.Lerp(usedSideFriction, newSideFriction, Time.fixedDeltaTime / frictionSmoothing);
      else
         usedSideFriction = newSideFriction;
      sideForce = transform.TransformDirection(Vector3(-sidewaysDifference, 0, 0)) * usedSideFriction;
      sideSlip = Mathf.Lerp(sideForce.magnitude / sidewaysSlipForce, sidewaysDifference / sidewaysSlipVelocity, sidewaysStiffnessFactor);
      
      t = transform.InverseTransformDirection(velocityAtTouch);
      t.z = t.y = 0;
      sideDrag = transform.TransformDirection(t) * -sidewaysDamp;
      
      parent.AddForceAtPosition(force + shockDrag + forwardForce + sideForce + sideDrag, hit.point);

      if(driven)
         car.AddForceOnMotor (forwardDifference * usedForwardFriction * Time.fixedDeltaTime);
      else
         speed += forwardDifference;   

      graphic.position = transform.position + (down * (hit.distance - wheelRadius));
   }
   else
   {
      graphic.position = transform.position + (down * suspensionRange);
   }
   
   graphic.transform.Rotate(360 * (speed / wheelCircumference) * Time.fixedDeltaTime, 0, 0);
}



There's a lot of code and variables in there that you probably don't need (this is for 3d), and you'll probably need to check the unity3d.com reference manual and scripting reference. (http://unity3d.com/support/documentation/)
.. ,__,_____
. / __.==--" - - - - - - - - ""
./#(-'
.`-' From http://www.ascii-art.de/. Modded by me to work in Arial. Image
a Mammoth wrote:be boring and interesting.

Mystery wrote:If you were jailbreaker you shouldn't have when't up the 3.1.3
I didn't know you could go up 3.1.3! Thanks Mystery person!
User avatar
Dakta
 
Posts: 417
Joined: Sat Sep 12, 2009 4:36 pm


Return to Thyme scripting

Who is online

Users browsing this forum: No registered users and 26 guests

cron