Jump to content

Motorcycle wheelie


Isobeast
 Share

You are about to reply to a thread that has been inactive for 1163 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello!

I am trying to add a wheelie to a motorcycle script. Here is my control section. However, the bike takes off into the air if I ride on the rear wheel. How to fix it?

Thanks a bunch for any help!

    control(key name, integer level, integer edge)
    {
        vector linear;
        vector angular;

        ...

        if (level & CONTROL_UP)
        {
            angular.y = 25.0; // wheelie up
        }
        if (level & CONTROL_DOWN)
        {
            angular.y = -25.00; // wheelie down
        }

        if (linear) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, linear);
        if (angular) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular);
    }

 

Link to comment
Share on other sites

My best guess is you don't want to alter the angular velocity to give any vertical component, but instead rotate  the vehicle appropriately? Maintain the velocity as a forward one (unless you're building a Scot-Squirrel or SunBeam/Indian in which case they did actually have the ability to reverse).

  • Like 1
Link to comment
Share on other sites

56 minutes ago, Profaitchikenz Haiku said:

My best guess is you don't want to alter the angular velocity to give any vertical component, but instead rotate  the vehicle appropriately? Maintain the velocity as a forward one (unless you're building a Scot-Squirrel or SunBeam/Indian in which case they did actually have the ability to reverse).

Yes, the script does have reverse and gear/throttle shifting. This is how it looks like:

        if (level & CONTROL_FWD)
        {
            if (edge & CONTROL_FWD)
            {
                if (throttle < 100) throttle += 10;
                throttlePress = 0;
            }
            else if (++throttlePress == 10)
            {
                throttlePress = 0;
                if (throttle < 100) throttle += 10;
            }
        }
        if (level & CONTROL_BACK)
        {
            if (edge & CONTROL_BACK)
            {
                if (throttle > -30) throttle -= 10;
                throttlePress = 0;
            }
            else if (++throttlePress == 10)
            {
                throttlePress = 0;
                if (throttle > -30) throttle -= 10;
            }
        }

 

Link to comment
Share on other sites

2 hours ago, Profaitchikenz Haiku said:

Maintain the velocity as a forward one

I did as you recommended and it looks very good. This is my first motorcycle, and I am not sure "to shift, or not to shift" gears/throttle. Another problem is that the speed of rotation of the wheels depends on the throttle valve. And if I remove the throttling, how then to calculate the speed of rotation of the wheels, depending on what?

        if (throttle)
        {
            llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, < fwd * (throttle * 0.01), 0, 0 > );
            llSetLinkPrimitiveParamsFast(WHEEL_PRIM, [PRIM_OMEGA, WHEEL_AXIS, throttle * 0.2, 1, PRIM_LINK_TARGET, WHEEL_PRIM_2, PRIM_OMEGA, WHEEL_AXIS, throttle * 0.2, 1]);
        }

New wheelie:

        if (level & CONTROL_UP)
        {
            linear.x = 20.0;
            angular.y = 25.0;
        }
        if (level & CONTROL_DOWN)
        {
            linear.x = -1.00;
            angular.y = -25.00;
        }

 

Addition:  I tried to adjust the rotation of the wheels depending on the speed, but when reversing, the wheels continue to rotate forward.

float speed = llVecMag(llGetVel());

llSetLinkPrimitiveParamsFast(PROP_PRIM, [PRIM_OMEGA, PROP_AXIS, speed, 1, PRIM_LINK_TARGET, PROP_PRIM_2, PRIM_OMEGA, PROP_AXIS, speed, 1]);

 

Edited by Isobeast
Link to comment
Share on other sites

llVecMag will remove any negative quantities in the velocity vector. (* There is a better way of putting this)

You will have to find a way of working out if you are going in reverse and use the sign of that in the PRIM_OMEGA speed value.

i.e integer direction = 1; but if you are going backwards direction = -1, and so use direction * speed as the value for prim_omega

 

* One, some, or all of my proof readers will be along once the market place crash has stopped drawing them all to look and goggle, and hopefully give you a more accurate answer than I can.

Edited by Profaitchikenz Haiku
  • Like 1
Link to comment
Share on other sites

8 minutes ago, Profaitchikenz Haiku said:

llVecMag will remove any negative quantities in the velocity vector. (* There is a better way of putting this)

You will have to find a way of working out if you are going in reverse and use the sign of that in the PRIM_OMEGA speed value.

i.e integer direction = 1; but if you are going backwards direction = -1, and so use direction * speed as the value for prim_omega

 

* One, some, or all of my proof readers will be along once the market place crash has stopped drawing them all to look and goggle, and hopefully give you a more accurate answer than I can.

Thank you! ;)

Wondering how to determine the direction +/- ... and is it possible to keep the throttle here and does it make any sense?

Link to comment
Share on other sites

 

9 minutes ago, Isobeast said:

Wondering how to determine the direction +/-

llGetLocalRot(backside) is your friend.

Quite seriously though, you will usually be going forwards so direction is 1 by default, you will only be going backwards if you have either

a) selected reverse gear - in which case you explicity set it to -1

b) have ridden into and are rebounding from an obstacle. I'd not bother rotating the wheels in this case

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

I have a script in each wheel which manages its rotation, depending on the velocity in the local frame. But you don't have to.

speed is how fast you're going. > 0 is forward. rate is how fast the wheel should turn at that speed.

 
 
vector vehdir = <1.0,0.0,0.0>*llGetRootRotation(); // global direction of vehicle
float speed = vehdir*llGetVel(); // speed in fwd direction
//  Convert to wheel rotation rate in radians/sec
float rate = speed / (WheelDiameter*PI);

You need to put in a WheelDiameter of your own.

Useful hints:

  • On each update cycle, send a new omega to the wheel only if it's changed by 10% or more, or it's stopped. Otherwise you send too many updates to the viewer and the changes may not look good.
  • Limit rate to 10 or so. Turning faster than that, it doesn't look good given the frame rates SL can achieve.
  • Check for near 0 and set to 0 rate. Slowly turning wheels while stopped look silly.

The problem of rotating both the front forks and the wheel is left as an exercise for the student.

  • Thanks 1
Link to comment
Share on other sites

2 hours ago, animats said:
 
 

The problem of rotating both the front forks and the wheel is left as an exercise for the student.

Thanks a lot! 😊

Now both wheels are turning correctly!

            float WheelDiameter = 0.71403;
            
            vector vehdir = <1.0,0.0,0.0> * llGetRootRotation(); // Global direction of vehicle
            float speed = vehdir * llGetVel(); // Speed in fwd direction
            // Convert to wheel rotation rate in radians/sec
            float rate = speed / (WheelDiameter * PI);
            
            llSetLinkPrimitiveParamsFast(PROP_PRIM, [PRIM_OMEGA, PROP_AXIS, rate * 5, 1, PRIM_LINK_TARGET, PROP_PRIM_2, PRIM_OMEGA, PROP_AXIS, rate * 5, 1]);

Only it is not clear how to limit this part by 10%? 🤔

2 hours ago, animats said:
 
 

On each update cycle, send a new omega to the wheel only if it's changed by 10% or more, or it's stopped. Otherwise you send too many updates to the viewer and the changes may not look good.

 

Edited by Isobeast
Link to comment
Share on other sites

9 hours ago, Isobeast said:

Thanks a lot! 😊

Now both wheels are turning correctly!


            float WheelDiameter = 0.71403;
            
            vector vehdir = <1.0,0.0,0.0> * llGetRootRotation(); // Global direction of vehicle
            float speed = vehdir * llGetVel(); // Speed in fwd direction
            // Convert to wheel rotation rate in radians/sec
            float rate = speed / (WheelDiameter * PI);
            
            llSetLinkPrimitiveParamsFast(PROP_PRIM, [PRIM_OMEGA, PROP_AXIS, rate * 5, 1, PRIM_LINK_TARGET, PROP_PRIM_2, PRIM_OMEGA, PROP_AXIS, rate * 5, 1]);

Only it is not clear how to limit this part by 10%? 🤔

 

Save the last value you set. If the new value is within 10% of the old, and is not zero, don't change the speed of the wheel.

  • Like 1
Link to comment
Share on other sites

6 hours ago, animats said:

Save the last value you set. If the new value is within 10% of the old, and is not zero, don't change the speed of the wheel.

Thanks again!

But I'm sure that I'm doing everything wrong ...

rate++

if (rate >= rate / 10)

{

    llSetLinkPrimitiveParamsFast(PROP_PRIM, [PRIM_OMEGA, PROP_AXIS, rate * 5, 1, PRIM_LINK_TARGET, PROP_PRIM_2, PRIM_OMEGA, PROP_AXIS, rate * 5, 1]);

}

 

Link to comment
Share on other sites

6 hours ago, Profaitchikenz Haiku said:

Try



if ( llFabs(rate - oldRate) > rate / 10)

You will obviously have to assign values to oldRate prior to this test

Thanks a lot! ;)

And how to assign these values? Will I need to make a list?

Edited by Isobeast
Link to comment
Share on other sites

Look for where rate is declared and declare oldRate just below it, as the same type. 

Where you see rate being assigned a value, such as

rate++;

or

rate = 0.0;

 immediately before that line, add

oldRate = rate;

Instead of rate++, I suggest you determine a minimum speed increase and use that to increment or decrement rate

ie

instead of rate++ use rate += 0.5

or instead of rate-- use rate -= 0.5

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

In passing, don't forget that in the expression 

2 hours ago, Isobeast said:

if ( llFabs(rate - oldRate) > rate / 10)

rate is being used as a divisor, so in the special case where you have come to a stop, don't try testing to see if the change is 10%, just do it. 

Similarly, when starting from standstill, don't bother with the test, just apply the rate

This then leads you to the combined expression

if( rate == 0.0 || oldRate == 0.0 || (llFabs(rate - oldRate) > rate / 10.0) ) // do it
else // ignore it

The order in which those individual tests are made ensures that the division won't occur if rate is zero, because the test for zero is made first of all, and the logical OR || ensures a true result at that point, no further evaluation of the expression should occur.

  • Thanks 1
  • Confused 1
Link to comment
Share on other sites

7 hours ago, Quistessa said:

maybe I'm just tired, but shouldn't it only matter if 0 is a divisor?

I thought so at first, but then I realised the two special cases of the vehicle either stopping or else starting from rest were both instances where you would want to start or stop a rotation regardless of the amount it had changed by, so came up with a one-liner.

  • Like 1
Link to comment
Share on other sites

15 hours ago, Profaitchikenz Haiku said:

The order in which those individual tests are made ensures that the division won't occur if rate is zero, because the test for zero is made first of all, and the logical OR || ensures a true result at that point, no further evaluation of the expression should occur.

Unfortunately I just remembered :

Quote

Note: Unlike most other languages that use the C-style && and || operators, both operands are always evaluated. For example,


if (TRUE || 1/0) llSay(PUBLIC_CHANNEL, "Aha!");
will cause a Math Error rather than say "Aha!"

 

http://wiki.secondlife.com/wiki/LSL_Operators

I think this means it's reasonable practice to use nested if statements for &&. || is a bit more tricky, but you could probably do something similar to 'most other languages' if you really needed to with some clever jumps.

Edited by Quistessa
  • Like 1
Link to comment
Share on other sites

15 hours ago, Profaitchikenz Haiku said:

In passing, don't forget that in the expression 

rate is being used as a divisor, so in the special case where you have come to a stop, don't try testing to see if the change is 10%, just do it. 

Similarly, when starting from standstill, don't bother with the test, just apply the rate

This then leads you to the combined expression


if( rate == 0.0 || oldRate == 0.0 || (llFabs(rate - oldRate) > rate / 10.0) ) // do it
else // ignore it

The order in which those individual tests are made ensures that the division won't occur if rate is zero, because the test for zero is made first of all, and the logical OR || ensures a true result at that point, no further evaluation of the expression should occur.

Perfect! Thanks for not leaving me alone with my problem!! 🚲👍🏻👍🏻👍🏻

( I hope I did everything right. One more question. How to display the value of the rate in the chat? I wanted to know how it changes and tried llOwnerSay(rate); but it turns out "Function call .." )

That's what I got ..  may be useful to someone

            float WheelDiameter = 0.71403;
            
            vector vehdir = <1.0,0.0,0.0> * llGetRootRotation(); // Global direction of vehicle
            float speed = vehdir * llGetVel(); // Speed in fwd direction
            // Convert to wheel rotation rate in radians/sec
            float rate = speed / (WheelDiameter * PI);
            float oldRate = speed / (WheelDiameter * PI);
            
            oldRate = rate;
            
            rate += 0.5;
            
            if( rate == 0.0 || oldRate == 0.0 || (llFabs(rate - oldRate) > rate / 10.0) )
            {
                llSetLinkPrimitiveParamsFast(PROP_PRIM, [PRIM_OMEGA, PROP_AXIS, rate * 5, 1, PRIM_LINK_TARGET, PROP_PRIM_2, PRIM_OMEGA, PROP_AXIS, rate * 5, 1]);
            }

 

Link to comment
Share on other sites

4 hours ago, Quistessa said:

 

Yes, you're right on both counts, there wasn't the risk of division by zero in my initial lines, I guess the tiredness is contagious.

I played around with that operator example you pointed to because I was quite flabbergasted I had a) never known that about LSL, and b) never yet got tripped up by it. Maybe I need to get out more. I'm going to retire from answering request for help on this forum until I've worked out if I really am on the way downhill or if this is just a bad-luck-streak-in-dancing-school thing.

Edited by Profaitchikenz Haiku
  • Like 1
Link to comment
Share on other sites

1 hour ago, Profaitchikenz Haiku said:

I'm going to retire from answering request for help on this forum until I've worked out if I really am on the way downhill or if this is just a bad-luck-streak-in-dancing-school thing.

Please do not! 😭

  • Like 2
Link to comment
Share on other sites

Back to the main topic, is there any other way to make the wheelie without changing linear/angular, for example, rotating the root prim and the entire linkset?

Maybe I can use llApplyImpulse for this?

Edited by Isobeast
Link to comment
Share on other sites

8 hours ago, Isobeast said:

Back to the main topic, is there any other way to make the wheelie without changing linear/angular, for example, rotating the root prim and the entire linkset?

Maybe I can use llApplyImpulse for this?

is not a good idea to mix them up

doing wheelies with angular motor can be done fairly easily.  In your OP script you are applying way to much direct power. The better way is to apply some multiple of the current motor

the original Linden motorcycle script is a good source to look at how linear and angular motors can work quite well together

a modified version of this script is here.

the mods are more about showing what happens on region crossings. But the basics of the Linden motorcycle engine are preserved

  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1163 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...