How to control the speed of a rotation

Hi !

I’m currently trying to control the rotation speed of an svg image. For the moment I wrote this :

rotation = ofGetElapsedTimef()*100*rotationSpeed;

Where rotation is my angle and rotationSpeed is a midi knob which return a value between 0 and 1.
So basically, it should not rotate the svg when set to 0 and make it rotates faster and faster when I turn it.

My svg is well rotated, but when I turn the knob it becomes Glitchy, values are skipping.

I guess I need to introduce a vector like

rotation = oldRotation + delta*(newRotation-oldRotation); 

or something like this, but I can’t figure it out.

Thank in advance for the help :blush:

Cyril

How are you rendering the image? Are you using ofRotate?

Actually I use the SVG to send into an ilda Laser so the code is :

ildaFrame.getPolys().clear();
polylines.clear();
ofPolyline p;
while (svgLoader.hasNextPolyline()){
    p.clear();
    p = svgLoader.getPolyline();
    // size and rot
    for (int i=0; i<p.size(); i++) {
        ofVec2f pt = p[i];
        pt.x *= 2.;
        pt.x -= 1.;
        pt.y *= 2.;
        pt.y -= 1.;
        
        pt *= size;
        pt.rotate(whichRot);
     
        p[i] = pos+pt;
    }
    polylines.push_back(p);
 svgLoader.update();
}

and the rotation :

 whichRot=rotation; 
 rotation = ofGetElapsedTimef()*100*rotationSpeed;

Cyril

So what’s your value range for those rotationSpeed midi input values, [0, 127] integers?

Also, you seem to be using only whichRotation in the animation code, why do you assign the old value of rotation to it, you actually introduce a frame of latency by doing that, if real-time responsiveness is an issue for you.

What is the unit of measurement which you expect whichRot to have? ofVec2f.rotate() seems to be expecting degrees. Write the values of rotationSpeed, rotation, whichRot to console and check if that’s what you expect.

If you render at a framerate of 60Hz, and want to have a rotation of lets say 360deg per second, whichRot/rotation should have a value around 360/60 == 6 deg/frame (modulo jitter), check the specific values against your assumptions.

Hi, thank for the reply,

I mapped the value from 0-127 to 0-1.
I use WhichRotation because I made another rotation that is trigged by a drum.

I don’t really care about the Deg/second, I just need to accelerate the rotation or decelerate it, then It’s a visual performance, so I’ll ajust the final speed.

Cyril

I just meant that you check if your values are in some reasonable range. What do you mean exactly by ‘values are skipping’?

Here is a video :

When I turn the knob, the rotation jump,

Cyril

Looking at the original line of code you posted, if you suddenly set the rotation speed to 0, the rotation of the object is going to also snap to zero - whereas what you want is for it to stop at it’s current rotation.

Rotation speed is the change in angle per unit of time. Therefore it’s something that you want to add to the angle with each iteration. So you probably want something link this:

float rotationSpeed = ofGetElapsedTimef() * rotationSpeedControl * rotationSpeedMax;
rotation += rotationSpeed;

Where rotationSpeedControl is your 0 - 1 value you pass in from the midi controller, and rotationSpeedMax is a variable you use to set the maximum speed when the controller value = 1. (edit … previously said max speed was when controller = 0!)

1 Like

Thank @superartificial !

It’s what I was looking for, and it works perfectly :smiley:

Cyril

Actually I’ve realised you probably don’t want to be multiplying by ofGetElapsedTimef() … that number is going to keep getting bigger as your application runs meaning rotation is going to get faster and faster. Just taking that out should give you a steady enough rotation as long as your frame rate is fairly constant.

If you wanted a reliable rotation rate per sec you could incorporate ofGetLastFrameTime into the equation.

Hi, same problem, the incrementation is still getting faster and faster…

Cyril

@Cyril even when you take out the reference to ofGetElapsedTimef(), so using something like this?

float rotationSpeed = rotationSpeedControl * rotationSpeedMax;
rotation += rotationSpeed;

That should give a constant rotationSpeed value, assuming the control doesn’t change…

Yep :

Is it actually getting faster and faster with time though, or just going really really fast?

It looks like you’re multiplying the slider value by 1000 which would mean you’re rotating by up to 1000 degrees or nearly three revolutions each frame, which is going to effectively result in it just bouncing around all different angles instead of any rotation effect.

Because the rotation speed is the amount you’re changing the rotation each frame you’ll want this to be a fairly small value … e.g. say you’re running at around 60fps, a rotation speed of 1 is going to mean it takes 360 / 60 = 6 seconds per rotation. So if you multiply your input control value by 18 you’d have a range from 0 - 3 rotations per second (or probably higher depending on your fps).

The value that you are writing to the log output is the amount it has rotated, and this should be always be increasing unless your input control is set to 0. It’s the rotationSpeed value that shouldn’t be changing for a steady rotation when the input value hasn’t been changed.