View Full Version : Unicycle Robot

07 July 2007, 08:32 AM
I've created a robot that is essentially a unicycle for a lower half.

I've read through the forum, and found the techniques on creating an expression that is driven by the controler's Z translate value. Not very useful for this character because it can turn and move down the X value as well.

Can anyone point me in a more functional direction?

Maybe putting the robot on a path, though I'm not sure how I could rock the bot back and forth, pause, etc.

08 August 2007, 03:50 PM
Putting it on a path is a good way to go. To control the timing you can animate the .uValue of the motionPath node.

08 August 2007, 12:38 AM
I assume you want to automate the wheel rotation?

If so create an expression using the three-space distance formula found here:

That way you can turn your character around and not worry about what direction he's going in. Before rendering though you should bake out the rotation. Otherwise each render packet will start with a rotation of zero and you'll get jumping.

This also avoids all of the headaches associated with paths.

Hope this helps.


08 August 2007, 08:32 AM
Hello again John!
Coming to my rescue.

Both ideas sound good. I do like James idea as well. Seems like just the ticket. Since I already know how to write an expression that only works in the Z axis this one would probably be the better option.

So I visited the wiki link and well, I didn't do so good in geometry. Algebra I'm good but the triangle (delta) symbol loses me. I understand the rest of the formula: square root, second power, etc. Just that delta symbol trips me up. I looked it up further and understand it literally means triangle, as in the three sides. duh...

I thought art wasn't going to be so mathematical.

08 August 2007, 09:55 AM
A little triangle in a formula could also refer to 'delta', which is also used as a mathematical symbol.

Maybe that helps you out?

Δ often denotes a difference (; δ can represent a small change or amount
In elementary set theory and Boolean algebras, Δ usually denotes the symmetric difference (

08 August 2007, 12:35 AM
Yes, in this case Delta means "difference". So it's talking about a first position in XYZ and a second position in XYZ.

Here's one implementation of the distance formula. It's not ready for an expression in this form but I keep my real wheel expression on my work computer which I don't have access to right now.

global proc float jpDistance(float $start[], float $end[]) //asks for a start and end position
{ //as float arrays
float $deltaX = $start[0] - $end[0]; //Finds the difference for X
float $deltaY = $start[1] - $end[1]; // Y
float $deltaZ = $start[2] - $end[2]; // Z

float $powX = `pow $deltaX 2`; //Finds the square of delta X
float $powY = `pow $deltaY 2`; // Y
float $powZ = `pow $deltaZ 2`; // Z
float $powers = ($powX + $powY + $powZ); //Adds all the squares together
float $distance = `sqrt $powers`; //Takes the square root of all those powers
//and that's the distance between the start
//and end points

return $distance;
}//end proc

Basically the idea is to have a locator at your wheel hub and measure the distance that that locator moves for each frame. Then take that distance along with the circumference of your wheel (2 * pi * r) and rotate your wheel accordingly, so that the distance rotated on the circumference of your wheel matches the distance travelled at the hub. (yes I know that this method is inaccurate for high angle leaning turns, but it works for most situations and is easily modifable so the locator measured can be at the contact point) Make sense?

Personally I like to use a DistanceDimension node to measure the radius of my wheel so I can scale things and not have to change my expressions.

Hope this helps.

08 August 2007, 10:45 PM
OK, here's the final expression. Naturally your locator and driven group names will change. And I put a channel called "calcRot" on my locator just so I can see what my expression results are. It's not too different from the previously posted proc.

float $frame = `currentTime -q`;
float $lastFrame[] = `getAttr -t ($frame - 1) "front_left_posIndicator_LOC.translate"`;
float $thisFrame[] = `getAttr "front_left_posIndicator_LOC.translate"`;
float $deltaX = $thisFrame[0] - $lastFrame[0];
float $deltaY = $thisFrame[1] - $lastFrame[1];
float $deltaZ = $thisFrame[2] - $lastFrame[2];

float $powX = `pow $deltaX 2`;
float $powY = `pow $deltaY 2`;
float $powZ = `pow $deltaZ 2`;
float $powers = ($powX + $powY + $powZ);
float $distance = `sqrt $powers`;

float $pi = 3.1415;
float $wheelRad = front_left_tireRadius_DDShape.distance;

float $circumference = $wheelRad * 2 * $pi;
float $rotation = ($distance/$circumference) * 360;

front_left_posIndicator_LOC.calcRot = $rotation;
if($frame == 1)
front_left_drive_loRes_GRP.rotateX = 0;
front_left_drive_GRP.rotateX = 0;
front_left_drive_loRes_GRP.rotateX = (front_left_drive_loRes_GRP.rotateX + $rotation) % 360;
front_left_drive_GRP.rotateX = (front_left_drive_GRP.rotateX + $rotation) %360;

08 August 2007, 10:56 PM
Thank you thank you thank you!!!
and my hairline thanks you.

I've done simple expressions but never anything as complex as this. This clearly would have been beyond me.

And I'm sure future forum searchers will thank you as well. I'm certain this posting will be very handy to many.

CGTalk Moderation
08 August 2007, 10:56 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.