4
$\begingroup$

A bit of context first. I'm trying to model an RC plane, using blender as a kind of CAD software: plane

In the process, I try to model the actuators, i.e. rudder, elevator and ailerons. I did manage to rig the tail unit using some IK chains, but I am stuck with the ailerons control.

The rig

The idea is to have the servo arm command the ailerons movement. The mechanical system has three components:

  • a servo arm (blue)
  • a crank (brown)
  • two symetrical aileron command rods (silver)

mechanism

First, the servo arm rotates (1), pushes the crank through a rigid link (2), forcing it to rotate too (3).
This part is easily rigged with a couple of bones.

Second, each aileron command rod slides into its crank slot (4), thus being forced to rotate along its only free axis (5). dynamics

Key constraints

  • a typical servo has a +-45° course, while the ailerons might have another (+20°/-15° in my case, if I want to mimic the real plane). Since aerodynamic constraints do no scale well, I would rather make provisions for other values.
  • aileron movement is asymetrical, i.e. the deflection is greater upwards than downwards. Having a limited downward course helps preventing adverse yaw.
  • aileron hinge direction is dictated by wing geometry, and is not aligned with any global axis. The difference is about 6° on Y and 4° on Z.
  • the aim of the rig is to provide me with the key locations needed to design the crank: main axis, aileron rod slots and servo linkage hole.

In real builds, most of the time, you can approximate this movement by a simple rotation (assuming the contact point between the crank and the rod is stationary, which would require it to travel on a plane/cone intersection, i.e. an arc of hyperbola approximated by a circle). Small mechanical adjustments will take place to compensate (the structure or rods will move or warp slightly, at the cost of more strain on the servo and a small loss of precision).
I could live happily with that, but I find it interesting to see how blender would allow to produce a more accurate solution.

Design parameters

The crank/aileron rod movement is rather complex, being a composition of rotation and translation that depends on the relative positions of the crank and the rod (which, again, are not aligned in any way).

I figure the key is the contact zone between the crank and the rod. If I could get an empty to follow it as the crank rotates, the rest would be easy.

As far as geometry is concerned, this zone can be approximated (neglecting thicknesses) as the point of intersection between the crank slot (whose shape can be chosen arbitrarily within certain limits, though assuming it's a fixed point is bound to produce some degree of approximation) and the cone swept by the rod end as it rotates around its axis.

Servo position is likely to change, mainly on the Y axis, to balance the plane's CG

Aileron command rods geometry is highly constrained. The only parameters you can play with is the hinge length (as long as it fits within the fuselage) and the angle/length of the upwards end.

The crank is the main variable part.

  • It can be placed at any height and should be as large as possible (larger means more precision), so I bet the sweet spot is near the height where the fuselage is broadest.
  • The link with the servo must be symetrical, so that both ailerons have a proper opposed motion. Playing on the distance from the axis allows to change the rotation course of the crank.
  • The slots guiding the aileron rods can have an arbitrary shape, though a straight line is preffered (the part is quite small considering the plane scale and is supposed to be cut out of thin plywood by hand, so a complicated shape would be difficult to reproduce precisely).
  • Their lateral offset from the crank's axis will define the proportion of upward/downward motion. This can be calculated approximately with a couple of arccosine, but I'll be happy to tune it manually by trial and error.

Any idea how to tackle this problem?

EDIT:

some contributor posted an interesting answer in another thread I posted trying to come up with a more general problem, though it did not fully answer this question (here I need a cone-line intersection, but having a practical means of intersecting two lines would get me closer to the solution). The answer is still useful as an elegant approximation.

The trick is, the contact "point" between rod and crank (neglecting thicknesses) is neither stationary relative to the rod nor the crank, so any solution using a fixed empty parented to the rod or the crank is bound to be inexact. It will either position the rod outside the slot or deform/displace it at some point of the trajectory.

EDIT 2:
the suggestion of letting the rod slide along its axis and somehow compensate for it might be worth a try. Still, the problem is, the rod main axis (i.e. the aileron hinge) has no alignment with the crank axis : it is rotated about Y by wing dihedral and about global Z by the slanted wing shape, so any trigonometry would have to consider some vector cross product, not just an angle along some global axis. Same goes for the rod end, which can have an arbitrary orientation relative to the hinge.

$\endgroup$
  • $\begingroup$ You could allow your horizontal rod @ '5' to slide horizontally, and calculate the horizontal movement by the cosine(rotation angle of '3') - the distance gained from the slide along the sloped part of the rod. $\endgroup$ – Rick Riggs Mar 2 '16 at 8:58
  • $\begingroup$ I'm not sure why these two questions are split? Link to Other Question & Answer $\endgroup$ – Rick Riggs Mar 2 '16 at 9:02
  • $\begingroup$ well the other question is more general, and actually does not solve my particular problem, It would allow to design a better approximation of the actual cone-line intersection though. I think a practical answer to it (i.e. not requiring to mess with PyDrivers) might be useful to people not interested in differential aileron rigging :). I would rather see your answer move to this thread. As for an analytic solution to the problem, I had given up on it, but your suggestion of letting the rod slide and compensate for it is interesting. $\endgroup$ – kuroi neko Mar 2 '16 at 9:14
  • $\begingroup$ Looking back at it closer after your comments, The math is correct to follow the empty. How often blender updates the information is causing a delayed update issue. The only thing that technically needs to change is the hole/slot shape to allow for the elliptical changes along the rotation. Fun problem thanks for putting it out there. $\endgroup$ – Rick Riggs Mar 2 '16 at 9:30
  • $\begingroup$ Well thanks to you for your help. Still, as I added in the question, the aileron hinge is not aligned to any global axis, while the crank has to be at least aligned with X and Z (since it will eventually drive both ailerons symetrically), and rotating it about Y would not really make the problem simpler as far as I see it. $\endgroup$ – kuroi neko Mar 2 '16 at 9:45
4
$\begingroup$

I would set this up using constraints. Starting with the servo arm I have added a Limit Rotation constraint so that it can only rotate from -15 to 15 on the z axis. This just makes it a little easier to use as you can start rotating from anywhere and it will only rotate on the set axis and within the limits.

servo limit rotation

The conrod between the servo and the rear arm is only for appearance but I have setup a Transformation Constraint for visual consistency and completeness. The transformation constraint can get confusing, in this config I have the z-rotation of the servo arm translated to x-location of the conrod. When the source and destination axis varies you need to set what axes are linked in the Source to Destination Mappping in the centre of the panel.

In this example, when the servo arm rotates from -15 to 15 the conrod moves -0.6 to 0.6 on the x axis.

conrod-ServoToRearArm settings

For the rear arm I also have a transformation constraint. While a Copy Rotation Constraint can be used for direct rotation mapping, I chose to also use a tranformation constraint so that adjustments can be made. For example you could set the source rotation to be from -15 to 15 while the destination is from -30 to 30 - when using that configuration the rear arm would rotate twice as much as the servo arm.

For the conrod from the rear arm to the aileron I also setup a transformation constraint, in this one I have set -20 to 20 in the source z-rotation maps to -20 to 20 x-rotation on the conrod.

conrod-RearArmToAilron

This provides the following animation. (could use a little more fine tuning)

Servo animation

You can have a closer look here

$\endgroup$
  • $\begingroup$ I agree the first link can be simulated with a transform constraint, though I find it easier to use an IK chain, so that moving the anchor points recomputes the rotation automatically. This can be done with trigonometry, but if the anchor point is not aligned with the transversal axis it becomes complicated. For the crank-rod link, the resulting movement is highly non-linear, so a proportional driver will not do the trick. As long as the aileron hinge is not too misaligned with the crank, it will be hardly noticeable, but at the extremities you can see the rod moving out of the slot. $\endgroup$ – kuroi neko Mar 3 '16 at 0:04
  • $\begingroup$ That's were I mean it needs some fine tuning, I set using 20 and 20 as a quick demonstration but it may need to be 20 on the source to 22 on the destination, the pieces will need to be positioned at the right distances to get the right transformation settings. $\endgroup$ – sambler Mar 3 '16 at 8:12
  • $\begingroup$ Given the positions of items in my example changing the destination rotation of the aileron conrod to -16.9 and 17.6 gives a good tracking over the keyed motion. As shown here $\endgroup$ – sambler Mar 3 '16 at 8:51
  • $\begingroup$ Anyway a F curve would allow to compensate for non-linearities. The only problem I see here is that you start with a geometry and tweak the parameters to make it work, while I would rather fid a sound rig relatively easy to modify, so that I can try different shapes and positions for the rods and crank and have the rig follow. $\endgroup$ – kuroi neko Mar 3 '16 at 18:24
  • $\begingroup$ The constraints can also be applied to bones. I tend to think of constraints as pre-made drivers with a gui control. $\endgroup$ – sambler Mar 4 '16 at 2:24
1
$\begingroup$

Here is what I came up with. For one thing, it works. On the other hand, it's not especially simple. it's alive!!!

The blender file is rather a mess, but it might help following the explanations.

Problem analysis

My goal was to manage to get an empty to follow the point of contact between a rod and its slot.
To manage that, I figured I had to find a set of constraints simple enough to be handled by blender without resorting to python code.

After much trial and error, I came up with a way of constraining an object to follow the intersection of a segment and a plane.

This was the eureka moment, since the course of this contact point can indeed be described as a plane/segment intersection.

If you look at the aileron command rod, its end sweeps a cone as it rotates around the aileron hinge. However, if we orient this end at a right angle with the hinge, the cone degenerates into a disc: rod end sweep

The disc itself is located on a plane that can be described with a normal vector and a reference point. Here the vector is the hinge direction and the reference point is where the hinge and the end meet. Note that even though the rod rotates, this point remains stationary.

Now we can define (arbitrarily) the slot geometry as a segment running parallel with the crank axis, and define an empty that will follow the intersection of the slot and the rod trajectory.

Slot geometry choice is guided by simplicity, but efficiency too: this orientation will exert maximal force on the rods when close to neutral position, and become somewhat less efficient at the end of the course.

Rigging the rod/crank contact point

First thing is to reorient the command rods with a local vector (X in this case) aligned with the hinge, and put their origin on the hinge/end junction. That defines the reference planes I need.
The other two local vectors do not really matter, though having one aligned with the end can be convenient to reposition the rod tip.
rod orientation and origin

Now for the slots. They are simple X-aligned two-point paths parented to the crank.

Lastly, an empty representing the famous contact point is created for each aileron.

This shot shows the left aileron command rod, slot and contact point (the crank itself is hidden) : contact point rig

Here is the constraint stack on the contact point: contact point constraints

Getting the "Floor" constraint to work as intended (i.e. make the empty stick to the plane) was tricky.

  • I had to move the empty rest position (i.e. when constraints are disabled) far back along the slot to make the constraint work during the whole course of the crank. I suppose whatever intermediate position blender computes for the "clamp to" operation has to be located on the positive X side of the plane, and if the rest position is too close from it, it eventually crosses the plane and makes the "Floor" constraint fail.
  • The rig seems to work better when the empty is parented to the slot. This makes its local vector X point directly along the slot direction, possibly increasing the "clamp to" constraint efficiency.

Now that I have my contact point, the rest is easy.

Rigging the servo/crank link

The servo arm is the commanding element (actually I rigged it to an empty allowing to rotate ailerons, rudder and elevator, but it's the start of the ailerons command chain anyway).

servo/crank IK chain

An empty is positionned over one of the linkage holes and can be easily moved to change linkage amplitude.

An IK chain uses this empty as a target to produce the crank axis rotation. servo IK target

All 3 bones are unstretching. The "rod" rotates freely, the "crank" is immobile and the "axis" can only rotate along, well, the crank's axis.

Finally, the crank itself has a "Transformation" constraint on the "axis" bone to copy its rotation directly (the "Transformation" constraint is only needed to switch from Y to Z axis).

crank rotation

This makes repositioning the servo or changing the linkage points rather easy. All you have to do is edit the IK chain and move a couple of bone heads/tails around.

Of course the crank rotation could be computed with some trigonometry and programmed with a "Transformation" constraint based on the servo arm, but I would rather fiddle with a few bones than with arctangents and proportional coefficients.
This IK chain allows to work on the actual geometry without takig measurements. For instance the maximal crank width is constrained by the space available inside the fuselage, and I find it more convenient to reposition the control points and check the effect visually.

Rigging the crank/rod link

Here again I set up an IK chain for each aileron.

The target is naturally this famous contact point, and the chain goes back to the aileron hinge to determine its rotation. enter image description here

Only two bones are used. The "hinge" is unstretching and can only rotate, well, around the hinge. The "arm" is not allowed to rotate, but stretches toward the contact point. This represents the rod as a rigid body only allowed to rotate around the hinge.

Same as before, the whole aileron (including the rod itself) has a "Transformation" constraint to copy the rotation around the hinge.

How come this thing works?

To sum it up:

  • someone rotates the servo arm
  • the first IK chain rotates the crank (including the rod slots and contact point)
  • the constraints on the contact point do their magic and move it where it should be
  • the second IK chain follows this contact point and finally rotates the aileron (including the command rod)

There is actually a kind of circular reference here: the contact point depends on the rod rotation and vice versa.
I suppose what makes the thing work is that the plane defined by the rod is invariant through rotation (the rotation does not change the reference point and vector needed by the "Floor" constraint that positions the contact point).

As a matter of fact, you can see the rig having difficulties to follow the chain. Fiddling with the servo arm angle (adding/substracting one degree or so) seems enough to get the rig to position properly.

Tuning the rig

The crank height and width is chosen to fit it in the broadest section of the fuselage, with a few mm of leeway. This maximizes its size, and hopefully minimizes the errors due to imperfect manufacturing of the part.

Once the crank is roughly positioned, the neutral position is setup. This is easily achieved by moving the slots along the Y axis until the ailerons become flush with the wings.

Now the Y position of the crank is chosen to achieve a desired ratio of upward/downward deflection. The further the slots are away from the crank axis, the greates the difference between up and down course. This can be approximated by a couple of arccosine, but I confess I simply did fiddle with the rig until I reached the proper ratio.

Moving the crank without spoiling the neutral position is a bit tedious, but manageable.

  • unparent the slots from the crank
  • move the crank as you see fit
  • edit the servo/rank IK chain and move the two last bones the same distance as the crank
  • re-parent the slots

The little red thingies you can see in the animation were quite convenient to visualize aileron deflection. The transparent "wings" are two faces defining the max up and down deflection angles, and the "rod", parented to the aileron, acts as a visual deflection indicator.

Once the proper ratio is achieved, you only have to fine tune the actual excursion. There are two ways of doing it. You can simply adjust the servo/crank link (increasing the crank linkage distance will diminish the exursion and vice-versa), or you can play on the hinge length. I prefer this solution, as it keeps the crank as big as possible.

To modify the rod length, you only have to move the hinge end along its axis. Of course, moving this point in any other direction will spoil the hinge orientation and ruin the whole rig, so proceed with care. The tip of the rod can then be adjusted to follow a perpendicular direction. Note that the tip of the rod is not necessary for the rig to work; adjusting it only provides visual consistency.

Modeling the crank

Once the rig is tuned, finding the end points of the slots is as easy as moving the servo arm to its extreme positions (+-45°) and see where the contact point moves.

With all the reference points available, the actual crank object can be modelled any shape you like, as long as it is big enough to include the hinge, the servo linkage point and the slots (and does not collide with other parts of the model).

It could even be possible to design a crank that would support various settings: if you keep track of the positions of each components and tune the rig to achieve a couple of different up/down ratios, it's easy to design a shape with a couple of slots and holes, just like a servo arm has 2 or 3 different holes to adjust linkage amplitude.

Validating the concept

One advantage of this rig is that you can visually see the precision of the simulation by looking at the distance between the computed contact point and the tail of the aileron IK chain: precision context

If you zoom on the contact point, you can see some slight misalignment, no doubt due to the iteration errors of the IK chains and/or constraints. precision zoom

This kind of precision can only be achieved if various model parts (especially the wing and ailerons) are properly aligned. I actually had to redo a bit of the right aileron to come up with a nice symetrical rig.

Studying the response curve (i.e. actual aileron deflection vs. servo arm rotation) confirms the non-linearity of the system : a given servo rotation increment will have more effect on the upward tilt.

Clearly, this response curve could replace the whole rig, but the advantage of the rig is that it can be tuned much more easily for different configurations than what could be achieved by "guessing" the proper response by fiddling with some F-curve!

Some further work

I'm rather new to blender, so I have no doubt there are many ways of doing the same thing more easily/elegantly.

I would be glad to hear about possible improvements.

Anyway, getting this thing to work was fun :).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.