# Bidirectional constraint

I’m trying to create mechanisms that can both drive and be driven. The simplest example is two gears – rotating one would cause the other to rotate, and either of them can be the driving force. When I googled for the answer I got discussions about circular dependency and mutual recursion, which gave me the sense that this might not be as simple as I thought it would be.
In parametric modelers like Solidworks this is elementary – constraints are bidirectional by default. But then those are fundamentally different programs.

I tried using drivers but the result is just like setting two constraints – a lock (driving a parameter makes it only receive its value from one source).

I think it would be relatively simple to script this – just monitor the state of each one and adjust the other – but this isn’t practical once you get into anything more involved, you’re going to have use too much code (outside the drivers) and connecting (chaining) mechanisms would become too complicated.

Another way would be to use the rigid body physics system to do this, but the overhead would be huge and almost entirely unnecessary. I don’t really need a simulation, I just need a constraint that functions both ways.

I’m hoping there’s a simple way to do this that I’ve overlooked. If anyone has any experience doing this, or any ideas, help would be appreciated.

I would make a separate controller that allows you to switch between the two. A bone or an empty or something that you can grab and move, and a driver would use that location data to turn each gear’s copy rotation constraint’s influence to either 1 or 0 corresponding to whether it is receiving or driving.

Here’s a demo:
GearSwitch.blend (504 KB)

Grab the empty and drag it to switch. Whichever gear it is above, that gear is in charge. Rotate that gear and the other will follow. You’re correct that there is no way to have truly bi-directional constraints in Blender, but this may serve for some of the cases where you would want that feature.

This is a very interesting setup, I’ve learned several new things just going over this, thanks!

It seems that object data can only flow in one direction, it can either drive or be driven, not both. Even if you add a driver variable and point it to the transform channel of the object itself (which is possible), that transform channel is still locked. If you try to modify it it gives you the “can’t edit driven number value” error message.

I was playing around with having a third object act as a “container” to a variable, but in the end you still need to be able to have that variable drive the original object. You can have two objects effecting a third object (like having the sum of their values drive one of its own), but I don’t think this would lead to anything because you’d need to parent the third object to one of them and this will almost certainly either lock, glitch, or crash… (though maybe I should try it anyway)

Sounds like the problem is similar to arms or legs with the solution being the equivalent of an IK/FK system.

Yeah rontarrant, I basically saw his question and thought “Why don’t you just make like an IK/FK switch for it?” :rolleyes:

Because that’s a switch… I want the two objects effecting each other, without knowing in advance which one will drive which. The scenarios will change the object doing the driving on the fly (a transmission system is an example, or mechanical logic gates). I don’t want to have to pick which one is doing the driving each time they reverse roles – not because I’m lazy, but because I don’t have that information in advance.

Best way is to Create a Controller object that drives both gears… and make the Gears unselectable…

Blender just isn’t designed to simulate that sort of thing. It’s meant as an animation tool, not a mechanical logic gate simulator. You’re trying to use constraints for something other than their intended purpose.

(I apologize in advance if this post gets a bit philosophical)
K Horseman: I only switched to using Blender as my main tool about 8 months ago, but it only takes a couple of weeks of interacting with the Blender community to see what permeates it: hacking. There are a LOT of people trying a lot of crazy things, all the time, and it’s (almost) always encouraged. Every release there are new features added, and the first thing that many Blender enthusiasts do is try to use those features for things they weren’t designed for. The logs of the open movie projects are full of designers/developers managing to hack a feature into doing something completely wild which, once people were aware of it, is adopted and becomes widespread.
Then there’s the amazing things people do with the game engine, which is used to simulate all sorts of creative ideas. The game engine, arguably, is as broad-purposed as it can be, since the idea is for people to create new techniques and uses. Sometimes they’re new game mechanics, and sometimes they’re something the designer came up with just to challenge themselves.

Blender is obviously optimized for specific purposes, but phrases like “isn’t designed for” or “isn’t meant to” are far more applicable to Autodesk software, where the official answer to a question is, quite often: “the particular program you’re using doesn’t do X, but this other program we sell does do X, and we’ll be happy to sell you this other program for many thousands of dollars and then maybe discontinue that program next year because it wasn’t as profitable as we expected”.
The culture around Blender, it appears to me, takes “Blender can’t do that” as a challenge, rather than a dead end.

I think that Blender becomes a mechanical logic gate simulator once someone, anyone, tries to simulate a mechanical logic gate using Blender. That’s just my opinion.

Maybe I should rephrase slightly: Blender’s constraint system, as it is currently written, has not been designed with your goal in mind. There’s no reason in principle why a future system couldn’t be written with that goal in mind, but this one wasn’t. Its basic data-passing mechanism is largely incompatible with your specific goal, so the best that can likely be done with the current system is to fake the effect with constraint switching. Blender in general is designed to be a 3D mesh modeling and animation program, and any simulation capabilities it has have been implemented with that goal in mind.

As such, “simulation” in this case means “giving the visual appearance of” not “physically replicating in a measurably similar way.” For instance the fluid simulation system cannot be used to simulate and test physical fluid dynamic behaviors; it merely creates an effect that looks mostly like a small amount of liquid (a large bathtub’s worth at most, without some extra trickery). So you can make something that looks like a glass of wine being poured, but you can’t check to see how well a particular turbine design would work.

Similarly, the constraint system is not designed to replicate the way physical objects push against each other. It is designed to transfer specific property data dynamically from one thing to another. Properties like scale for example, which is a property with no real-world analog. Things are the size that they are. That is, real objects all have a scale of 1, but not so in CG.

So you’re right that someone could write a constraint system that passes data as a two-way street, but the current system as it exists right now just doesn’t handle data that way on a fundamental level. You can build a fake on top of that using a switch like I have so that you get the effect of rotation being able to pass in either direction, but you can’t make the system itself pass data both ways. It isn’t designed with that capability. The constraint system itself was written with a particular goal and data paradigm, and this ain’t it. Whether or not someone could come along and change that in the future is irrelevant, until the day that someone actually does so.

If such a constraint system is that important to you, you or someone else is going to have to code it. Until then, you can use a switch to fake the effect.

I agree with derGoldstein in principal …

Blender is obviously optimized for specific purposes, but phrases like “isn’t designed for” or “isn’t meant to” are far more applicable to Autodesk software, where the official answer to a question is, quite often: "the particular program you’re using doesn’t do X, but this other program we sell does do X, and we’ll be happy to sell you this

the number one reason why I am even investing my time in Blender is in Moral opposition to the Nazi like Tyranny of AutoDesk…

but in practicallity… I have to agree with K Horseman

The constraint system itself was written with a particular goal and data paradigm, and this ain’t it.

That’s a nail on the head there…
I have used the Rigging System of just about every commerical 3D software there is … Lightwave… Maya… Max… SoftImage… and some most have never heard of… Surprizingly IMHO Blender hold’s it’s own with these other softwares… but it is a Character Animation centric Application…
but then again … this is only true because the previous users of Blender were using it for that purpose… and thus the Software was engineered in that direction…

what certainly needs too happen is guys like derGoldstein need to keep pointing out … “hey I wish it could do this…” and put that down on the list… Which I believe there is a ‘feature request list’ somewhere…
and guys like K Horseman need to keep reminding us why Blender currently doesn’t support that particular thing… and show us some kind of work arounds for the time being… because we all need to be spending our time getting some work done …

Right?

K Horseman: Thank you for your reply, and thanks for pointing me to the concept of an IK/FK switch, which I simply wasn’t aware of. This is kind of funny since I’ve been doing mechanical visualizations for a while and you’d think that would have popped up. Looking around, the IK/FK switch primarily seems to be used in armatures, and in scenarios where you explicitly want either one behavior or another.
I guess the reason I’m surprised that there’s no easy way to do bidirectional constraints is because, programmatically, this is ostensibly simple. Either set up an an event for both occurrences (whenever either object is altered), or use a watchdog timer to check both their positions, for example, once per-frame (and use a short history log to see which one changed first). That said, I can also see the possible cause-and-effect scenarios which would end up in an infinite loop (or just a race condition), for either method.
Since open-source developers don’t have “financial calendar” motivations (ie – “we should not release this feature now since we need to give them a reason to buy the release after that”), I’m going to assume that I’m just unaware of the problems inherent with bidirectional constraints.
I suppose my best bet is to try to script something, even if it’s relatively primitive and doesn’t cover every contingency.

norvman: Then our motivations are similar – I couldn’t stand using 3DsMax for another minute, and once I got used to Blender I kicked myself for not getting into it years ago. Much of my work over the past few years was with parametric modelers, which are specifically designed for rigging mechanical interactions. What I found is that Blender can actually mimic much of that functionality, you just have to know which combination of constraints and armatures to use in which scenario.

I guess it’s just a matter of time until any given functionality is implemented. Until then, there’s python.

I’m not going to repeat everything K Horseman has said because he’s said it very succinctly and well, but I’d like to add that although the driver system and constraint system are meant to be unidirectional, you can use python conditionals in the driver expression that allows you to ‘hide’ the switch that K H describes in the driver itself. In effect this would give the illusion of bidirectionality. (But of course the simple rig you describe doesn’t need anything that complicated.)

Of course, you can add enough 'but’s to your requirements that it makes it not possible. One such would be that you don’t want to use a rig of any sort, as in an empty or a bone. That would be a stopper.

I couldn’t stand using 3DsMax for another minute, and once I got used to Blender I kicked myself for not getting into it years ago

One the things I found in the financially driven softwares was that there were ‘paid shills’ (paid trolls) who would frequent the forums to talk up features that the company was currently working on and and talk down those features that the company wasn’t… so that they could still make the claim… “see… we lissen to our customers!”
the Lightwave community was probably the most like that… their Animation Rigging system was just broken… and it was going to stay that way because there was an AddOn Rigging software that cost more than the origonal program … so there was a constant effort to try and say that Lightwave … all by it’s self… was perfectly capable of doing advanced Animation and Rigging… yet only after you had purchased the software and were 6 months in to learning it… Only then did you realise that it’s Animation Rigging system was broken… So most Lightwavers who do Character Rigging had to then spend more money than what they had origonally paid for the LW App… (the old bait and switch sales gimick) The forums would stay Rife with Flame wars… Tthe paid trolls doing their best to try to explain away how something that didn’t work acutally did work… and they did a good job of brainwashing people into feeling like they were idiots for just seeing Reality for what it was… all for the sake of a pay check…

Many of us began to suppliment our software with other software that could do the job… SoftImage XSI at one point sold good copies of it’s software for low prices… (before they got bought out by AutoDesk) XSI had an excellent Animation Package… so many of us for a while were using 3rd party software to do all our Character animation… then importing it over to LW and using lightwaves Hair systems and partical systems to Render out… (XSI had these things but you had to pay extra for those) (it was a work around that worked great for awhile) (till AutoDesk purchased XSI from Alias)

Anyway… I ran across Blender a few years ago when they redid the interface… (which is now very much like the old XSI interface) and since I liked XSI’s Interface so much… I stuck with Blender… it was an easy go for me… I discovered that Blenders animation tools were much better than Lightwave, Max and even Maya (in that I didn’t have to code alot of stuff to get the results I was looking for)…

Of coarse I speak from a paradigm that most of the things I want to do own my own involve some kind of character animation… and mechanical simulation is only something that is secondary to that…

One thing that makes Blender work… You have to stay pluged into the community… communicate on the forums… watch all the youtube tutorials (I say that… all my own tutorials are on Vimeo) and sooner or later those things that your conversing about get done by someone some time… the Open Source community is built on peoples ability to communicate a need… and figure out how to fill that need… It’s a problem solving system… as opposed to a profit making system…

Note Blender once a year has a thing called the “summer of code” where many programmers get to gether to write code to see if they can improve Blender… it’s kind of a cool thing…

I’m seeing that more and more. I thought that lurking was enough, but the Blender community is a rare thing. The only thing I can think of comparing it to is the Ubuntu community, where people fall over themselves trying to solve your problem. It’s rare selflessness – when someone figures out something new, they can’t wait to share it with others.
This isn’t true for all open-source development though – much of it is very competitive, and some communities are closed circles that don’t want anyone new to join.

I keep wanting to spend more time in FreeCAD, I want to ditch Autodesk software completely. People talk about how Adobe is terrible, but I think Autodesk is ahead in the evil empire race. I can talk about how Autodesk screws over their customers all day, but we’re already off-topic…

If I find a way to mimic bidirectional constraints that’s in some way better than the ones suggested, I’ll be sure to post it here.

The problem here is one of data dependency. That challenge to your bidirectional goal lies very deep in the program. Because of the way data is passed via constraints at a basic level, this just doesn’t work. Your best bet (if you don’t want to fake it with cleverly disguised switches that is) would really be to write a new constraint system from scratch. Perhaps not a direct replacement to this system, but one designed specifically for bidirectional use cases. That’d be pretty cool to have, but it would also probably be good to still have the current system. I suspect that there are stability and predictability advantages to a one-way flow of data that makes this appropriate for some cases and bidirectional appropriate for others.

Cool topic though.

Your best bet (if you don’t want to fake it with cleverly disguised switches that is) would really be to write a new constraint system from scratch. Perhaps not a direct replacement to this system, but one designed specifically for bidirectional use cases. That’d be pretty cool to have, but it would also probably be good to still have the current system.

This certainly seems a good way too go… there’s nothing to hold back a good programmer back from writing a Constraint Replacement addon system for Blender that is more parametric centric… I perhaps the main issue is going to be finding a good programmer willing to do the work…

So here’s a quickie anim, for the first 60 frames the empty on the left is driving everything, then it switches to the empty on the right. Nothing elese was animated. I assume this is not at all what you are trying to achieve wihen you say bidirectional? I didn’t spend any time matching the gear ratios, since it was just a throwaway shot.

Look, Mom! No switch!

I assume one of those rights you typed was meant to be a left?