Community
Fusion Design, Validate & Document
Stuck on a workflow? Have a tricky question about a Fusion (formerly Fusion 360) feature? Share your project, tips and tricks, ask questions, and get advice from the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Understanding Joints inside instances of a component

13 REPLIES 13
Reply
Message 1 of 14
RogerInHawaii
1240 Views, 13 Replies

Understanding Joints inside instances of a component

Accessing Joints in instances.png

 

I have a componeint called "Hexagon Panel - Engines". I also have two INSTANCES of that component, so they are named "Hexagon Panel - Engines:1", "Hexagon Panel - Engines:2", and "Hexagon Panel - Engines:3".

 

Within the component I have a sub-component named "Rocket Engine Unit:1". (It, too, has an additional instance, but we can ignore that for this discussion). Rocket Engine Unit:1 has a revolute joint between it and the main part of the panel. That revolute joint object resides within the main "Hexagon Panel - Engines" component.

Now, if I were to make any edits to the "Hexagon Panel - Engines" component or the "Rocket Engine Unit:1" that is contained with it, that change would be reflected in the other instances of the "Hexagon Panel - Engines". All well and good. Exactly as expected.

But if I click on the revolute joint that controls the rotational position of the "Rocket Engine Unit:1" and select to Animate Model it ONLY animates that one selected joint, the other joints in the other INSTANCES of the "Hexagon Panel - Engines" don't move. That seems a bit odd to me. Since there are multiple INSTANCES of the component and all instances of a component refer back to just one basic component I would expect that the Joints in each of the instances ALSO just refer back to the basic component, meaning that an animation of the selected joint would implicitly show as animation of ALL the instances of the joint.

I've also written a C++ add-on script which gets access to that joint and makes it move. And even when THAT is manipulating the joint it only affects the single joint.

It's as if the joints in the several instances are somehow SEPARATE or INDEPENDENT of the base component, even though they reside within an instance of a common base component .

It appears that, for my C++ script, I need to access each instance separately (e.g. get a pointer to the instance) and locate the joint WITHIN each "Hexagon Panel - Engines" instance, in order to have control of the "Rocket Engine Unit:1" within each one.

13 REPLIES 13
Message 2 of 14

yes, your understanding is correct.  The way we say this in Fusion is:  "all sub-assemblies are flexible".  Meaning, joints inside a sub-assembly can have different positions in each instance of that sub-assembly.  The example we had in our heads when designing this is a door + doorframe as a sub-assembly.  If you make a room with 3 doors in it, you want the ability for the doors to be in different positions (as in real life).  You don't want to shut one door to a room, and have all the other doors shut as well.  That would be the behavior of "rigid sub-assemblies", where all instances of a sub-assembly must be in the same position.

 

Without getting into too much gory detail, this is done in Fusion using "joint occurrences".  (perhaps you remember this term from the great joint corruption fiasco of June, 2019.  "Fusion.RebuildOccurrences").   When you create an instance of a component which contains joints, we create a joint occurrence for that, which is owned by the top level component in the design.  If you reposition a joint in instance :1, the positions of the joint are captured in that joint occurrences.  If you reposition a joint in instance :2, that joint occurrence captures its positions.  This is also, just for more information, why, if your sub-assembly is an external design, and you edit that external design, and reposition the joint inside of the external design, then go back to the referencing design, and update, the positions of those components are NOT updated - because those are encapsulated in those joint occurrence objects.

 

Hope this helps...

 


Jeff Strater
Engineering Director
Message 3 of 14

@jeff_strater , Thank you for all that info.

Since all of those joint occurrences have the exact same name, at least from the perspective of the component instances that they reside in, what is the appropriate method of acquiring access to them from a C++ Add-In script so they can be individually manipulated? Is there any sample code for doing that?

Message 4 of 14

This can all easily be achieved by creating motion links between these joints.


EESignature

Message 5 of 14

@TrippyLighting The issue is NOT one of getting them all to work the same way at the same time.  The observation that moving one of them within a set of component instances does NOT move the others within that set simply showed that they are not implicitly linked to one another and that in order to move any specific one it is necessary to get access, i.e. get the pointer, to the specific one that we want to move. But each one of those joints has the exact same name, so it is not simply a matter of getting a joint by name.

When you have a JointA within ComponentX and you create instances of ComponentX you get ComponentX:1, ComponentX:2,  ComponentX:3 and so on. But within each and every one of those component instances the name of the joint is always JointA. The question is, What has to be done in order to get access to, for example, JointA within instance ComponentX:2? Is there some sample code that will show me how to do  that?

Even if I do indeed want them all to move the same way at the same time by creating motion links between them, I still need to get access to each and every one of them individually in order to make those motion links.

Message 6 of 14


@RogerInHawaii wrote:

Even if I do indeed want them all to move the same way at the same time by creating motion links between them, I still need to get access to each and every one of them individually in order to make those motion links.


Yes, true. If you are using the "normal" UI controls that obviously in not a problem, but If you want to do this using C++ or Python, then you need to have an API interface to do this ...

This is a pretty rare question and you might get a better response in the API section of the forum.


EESignature

Message 7 of 14

hey @RogerInHawaii , I did find the answer to this, in case you didn't already get it from the API forum (I don't go there much, so I don't know if you have).  But, I was curious, so I thought I'd find out myself.

 

The short answer is:  The "allJoints" method on Component will return all the JointOccurrences owned by that component.  I created a simple case.  One component (component1), with 2 child components (component2 and component3), and a slider joint between component2 and component3.  I created two instances of component1, and set the slider value for one joint occurrence to be different than the other.  Then, I executed the following code:

 

import adsk.core, adsk.fusion, adsk.cam, traceback, time
app = adsk.core.Application.get()
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
rootcomponent = design.rootComponent
rootcompjoints = rootcomponent.allJoints
joint0 = rootcompjoints[0]
joint1 = rootcompjoints[1]
joint0Motion = adsk.fusion.SliderJointMotion.cast(joint0.jointMotion)
joint1Motion = adsk.fusion.SliderJointMotion.cast(joint1.jointMotion)
joint0Motion.slideValue
joint1Motion.slideValue

 

the first call to slideValue returned 0.0, the second returned 7.697654004246499

 

This is all very specialized code, but hopefully you get the idea.  Hope it helps.


Jeff Strater
Engineering Director
Message 8 of 14

@jeff_strater 

Once again I really appreciate you taking the time to look over a problem that I'm encountering.

The solution you propose, to use the allJoints property of a Component, does work ... sort of. In your example code you use the allJoints property of the ROOT component. And that does indeed list all the joints throughout the design. I wrote similar code (in C++) to do the same thing for my, much larger, design. I added some code to display the names of the joints that it finds, and it showed this:

Accessing Joints in instances 2.jpg

 

Notice that several of them have the exact same name. I don't see a way, from that approach, to distinguish one "Rev Rocket Engine Unit" joint from the others.

I HAVE been able to traverse down the hierarchy of Components and Occurrences to get to a specific Occurrence, namely ONE of the occurrences that has a "Rev Rocket Engine Unit" joint in it. And I tried using the joints parameter and the asBuiltJoints parameter to get access to its specific "Rev Rocket Engine Unit", but neither of those parameters have the actual joint. They're both empty lists. And on top of that, I don't see that the Occurrence actually HAS an allJoints parameter or method.

I SUPPOSE that each and every actual COMPONENT (as opposed to an OCCURRENCE) has that allJoints method and I SUPPOSE that I could go UP the hierarchy to a parent that is actually a Component and try using its allJoints method. But in my particular case there are several (sibling) Occurrences below that Component that have the same named joint, so I'd get the same issue as with the allJoints method, i.e. it lists more than one joint with the same name and, as far as I can tell, no way of knowing which is which. 

So, I seem to be back at square one. I succeeded in getting access to a specific Occurrence, but I still can't seem to individually access the joint in that occurrence. 

 

Message 9 of 14

And just to make it a bit clearer as to what I'm trying to access, here's what it looks like in the browser.

Accessing Joints in instances 3.jpg

 

Message 10 of 14

@RogerInHawaii - yes, those two joints will certainly have the same name, as they are, at some level, the same joint.  As far as "I don't see a way, from that approach, to distinguish one "Rev Rocket Engine Unit" joint from the others.", it depends what you want to do as far as distinguishing these from each other.  In my little code snippet, I had joint0 and joint1 as variables.  So, in that way, they are "distinguished" from each other.  But, if what you really want to know is:  "does joint0 reside in 'Hexagon Panel - Engines:1'/'Rocket Engine Unit:3' ?", then the only way that I see to do that is to do a bit of inference from the occurrenceOne and occurrenceTwo properties.  These give the occurrence information of the joint operand components, via the fullPathName property, which returns a string like "Sub1:1+Sub2:1+PartA:1", where the delimiters are the "+".  I don't know if there are utilities that can parse this path and return a list of component references, or if you'd have to do that on your own.  But, you can at least use those paths to try to distinguish each these from each other.

 

And that's about the limit of my API knowledge.  You'll probably have to get more info from the API forum if you need more than that.


Jeff Strater
Engineering Director
Message 11 of 14

@jeff_strater  Again, thank you for providing incredibly helpful info.

Yes, my concern was, first, about accessing the jointMotion objects so that those joints could actually be manipulated, and your suggestion of accessing the allJoints property of the Root does get to the entire set of Joints, and then through those Joints to their individual jointMotion properties. It does not, as you pointed out, actually let you know which joint in the model each one relates to, you only know that you've got, not which joint relates to which component.

And, also as you pointed out, there may well be a way to kind of "back track" from each one to find its path through the hierarchy. But ... YOIKS!

My attempt at finding the right one was to start from the top and wend my way down the hierarchy to get to the specific Occurrence that contained the joint. I was indeed able to do that. But when I finally got down there I discovered that the Occurrence object itself has no comparable allJoints property.  It DOES have a joints property, and the description of that property (in the API documentation) describes it thusly...

Returns the joints that affect the position of this occurrence. For example, if a joint has been created between this occurrence and another occurrence, this property will return that joint. If the occurrence is a proxy, the joints returned will also be proxies in the same context as the occurrence.

 

And that SEEMS to mean that I should be able to access the joint that I want through that, but I can't, and that's because that joints property (and its comparable asBuiltJoints property) are empty. Although maybe I'm just not understanding what that description means.

As it turns out, for my particular design, while it would be really nice to be able to manipulate each one individually, SPECIFICALLY, so that I could, for example, rotate the left one in the  first engine panel, it's actually not required. I can make do with having them all move at the same time or just kind of randomly sequenced by how they happen to appear in the root's allJoints  array.

 

But it does still leave the situation of finding SPECIFIC ones rather difficult, what with that "backtrack the path" approach. It would be really helpful if the Occurrence object had something similar to the allJoints property of the root. OR, if the joints and asBuiltJoints properties of the Occurrence object actually conform to what their definitions appear to indicate.

Anyway, thank you again. You did indeed, as usual, provide a useful solution to my problem.

Message 12 of 14

Oh, and I should have expected this... The joints that I have been dealing with thus far have all been regular old run-of-the-mill joints, so accessing the Root's allJoints array worked just fine to find the ones associated with occurrences (as opposed to just components). But then I went on to deal with some other joints and SOME of them were actually AS-BUILT joints, which is a whole different (well, somewhat different) animal. It means that, to generalize my code that picks up the joints and accesses the jointMotion properties of them, when I detect that scanning the root->allJoint array doesn't find all the ones I expect, I ALSO have to scan the roots->allAsBuiltJoints array.

Having these things as different kinds of joints, regular and as-built, has bit me in the butt several times in the past and just makes it very awkward to program cleanly. I sure wish they had just put some kind of flag in a SINGLE joint structure to distinguish the two rather than have two distinct types.

Message 13 of 14

here is some more info/assistance.  This script was written by @prainsberry , I just modified it a bit.  It shows how to navigate upward through the AssemblyContext objects from a joint.  This is way easier than trying to parse the path.  We both learned something about how these AssemblyContext objects work...

 


Jeff Strater
Engineering Director
Message 14 of 14

screencast of this script running

 


Jeff Strater
Engineering Director

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report