Another transformation matrix question

Another transformation matrix question

rbin_robotik
Contributor Contributor
2,331 Views
12 Replies
Message 1 of 13

Another transformation matrix question

rbin_robotik
Contributor
Contributor

Hello all,

 

I am trying to get the joint origin coordinates relative to the world coordinates but I am having some issues.

 

Let me start from what I am doing: I have a bunch of models which have revolute and slider (prismatic) joints and these models are created in separate files in my project. I am creating a new file and inserting these models as linked components. When the model is inserted to the new file, Move/Rotate dialog box opens and I provide a translation and rotation to the models. Finally, I import a model with slider joints and using a rigid joint, I fix that model to the end of the one of the previously inserted models.

 

Before posting this question, I've found very useful code snippets in Python and C++ and a perfect tutorial in Japanese (thanks, Google Translate! :)) on Fusion 360 assembly context structure. I've tested using some of those examples and they are working fine and I was able to get correct transformation matrices for the models when I provide an initial translation and rotation.

 

On the other hand, when I fix a model to the end of another model using a rigid joint, I cannot get the correct transformation matrix.

 

The above explanation probably sounds confusing. I believe you should be able to reproduce the issue by following the steps below.

 

1. Insert a new model using right click -> Insert Into Current Design

2. Add a random translation and rotate by some degrees, e.g. -45, using the Move/Copy window

3. Insert the same model as (1) using right click -> Insert Into Current Design

4. Add a random translation and rotate by some degrees, e.g. 90, , using the Move/Copy window

5. Add another model using right click -> Insert Into Current Design

7. Do not add any translation or rotation, just click OK button on the Move/Copy window

8. Create a root joint between (5) and (3)

9. Get the transformation matrix of the occurrence (5) relative to root (using the Python API from transform or transform2 properties of the Occurrence object)

 

Since we haven't added any transformation on step (7), I get a unit transformation matrix when I query the API as described on step (9).

 

I also used Modify -> Compute All but it didn't change anything.

 

I am sure I am missing something here but I couldn't find the missing or incorrect thing. I'd appreciate any help or comments at this point.

 

Thanks!

0 Likes
Accepted solutions (1)
2,332 Views
12 Replies
Replies (12)
Message 2 of 13

BrianEkins
Mentor
Mentor

What exactly is the problem? You described the steps of how to build a model to demonstrate it but I'm not sure what exactly you're trying to extract from the assembly and what you're getting that is wrong.

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 3 of 13

rbin_robotik
Contributor
Contributor

@BrianEkins, the problem is API returning incorrect transformation matrix when two occurrences are connected using a rigid joint.

 

Let me explain it with a screenshot. Here is a sample a created with cylinders and boxes.

 

cadorb_0-1649207913580.png

 

"tool0_1" is a rigid joint between "REx v1:1" and "Simple Gripper 2 v2:1" occurrences.

 

When I query the transformation matrix of "Simple Gripper 2 v2:1" using "Occurrence.transform", I get an identity matrix. However, as you may see from the screenshot, the occurrence of "Simple Gripper v2" is not located at the origin point of the world.

 

I understand that, since I haven't added any translation or rotation when I added "Simple Gripper v2" to the design, it returns the identity matrix. If I add a translation after adding "Simple Gripper v2", "Occurrence.transform" returns the transformation matrix with the initial translation added. However, that transformation matrix won't represent the position and the rotation of the "Simple Gripper v2" occurrence after the rigid joint added.

 

I hope the problem is more clear now.

0 Likes
Message 4 of 13

rbin_robotik
Contributor
Contributor

I also would like to share a very small script that prints the transformation matrix of "Simple Gripper 2 v2:1" from the previous post:

 

#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback
from pprint import pprint

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = adsk.fusion.Design.cast(app.activeProduct)
        root_component = design.rootComponent
        for occ in root_component.allOccurrences:
            if occ.name == "Simple Gripper 2 v2:1":
                pprint(occ.transform.asArray())

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

0 Likes
Message 5 of 13

kandennti
Mentor
Mentor

Hi @rbin_robotik .

 

I don't understand the details of the problem, but the new Occurrence.transform2 property was added a while ago in an Update because of a problem with Occurrence.transform.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-7231EE6E-FB14-4370-AEE5-F9AE7419B97B 

Wouldn't this solve the problem?

0 Likes
Message 6 of 13

rbin_robotik
Contributor
Contributor

@kandennti, unfortunately "Occurrence.transform" and "Occurrence.transform2" both return the identity matrix.

 

 

#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback
from pprint import pprint

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = adsk.fusion.Design.cast(app.activeProduct)
        root_component = design.rootComponent
        for occ in root_component.allOccurrences:
            if occ.name == "Simple Gripper 2 v2:1":
                pprint(occ.transform2.asArray())

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

0 Likes
Message 7 of 13

rbin_robotik
Contributor
Contributor

It looks like the transformation is being applied to the individual components of the "Simple Gripper 2 v2:1" occurrence when the rigid joint is added, not the occurrence itself.

0 Likes
Message 8 of 13

kandennti
Mentor
Mentor

@rbin_robotik .

 

The Matrix3D.getAsCoordinateSystem method can be used to obtain information as a 3DCAD coordinate system.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-957d3c2d-294a-4fdb-8301-26ec31234655 

For xAxis, yAxis, and zAxis, I believe the unit vector is correct.

 

 

As for the difference between transform and transform2, it affects deep Occurrences, and there is no difference for RootComponent's child Occurrences.

 

I ran the following script with the attached data.

 

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = adsk.fusion.Design.cast(app.activeProduct)
        root_component = design.rootComponent

        occ = root_component.allOccurrences.itemByName("Simple Gripper 2 v2:1")

        if not occ:
            return
        app.log('** transform **')
        origin, xAxis, yAxis, zAxis = occ.transform.getAsCoordinateSystem()
        dumpVector(origin, 'origin')
        dumpVector(xAxis, 'xAxis')
        dumpVector(yAxis, 'yAxis')
        dumpVector(zAxis, 'zAxis')

        app.log('** transform2 **')
        origin, xAxis, yAxis, zAxis = occ.transform2.getAsCoordinateSystem()
        dumpVector(origin, 'origin')
        dumpVector(xAxis, 'xAxis')
        dumpVector(yAxis, 'yAxis')
        dumpVector(zAxis, 'zAxis')


    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def dumpVector(vec: adsk.core.Vector3D, name: str):
    app = adsk.core.Application.get()
    ary = vec.asArray()
    if hasattr(vec, 'normalize'):
        vec.normalize()
        app.log(f'{name}:{ary} -nomalize-> {vec.asArray()}')
    else:
        app.log(f'{name}:{ary}')

 

1.png

Here are the results.

 

 ** transform **
 origin:(5.000000000000005, -5.0, 4.999999999999999)
 xAxis:(-4.449570435420714e-16, -1.2246467991473535e-16, -1.0) -nomalize-> (-4.449570435420714e-16, -1.2246467991473535e-16, -1.0)
 yAxis:(2.620911392523723e-32, -1.0, 1.2246467991473544e-16) -nomalize-> (2.620911392523723e-32, -1.0, 1.2246467991473544e-16)
 zAxis:(-1.0, -1.3618017116483324e-31, 4.449570435420714e-16) -nomalize-> (-1.0, -1.3618017116483324e-31, 4.449570435420714e-16)
 ** transform2 **
 origin:(6.062177826491076, 3.5, 6.999999999999999)
 xAxis:(-1.0119932472584473e-16, -6.036094125048033e-16, -1.0) -nomalize-> (-1.0119932472584473e-16, -6.036094125048033e-16, -1.0)
 yAxis:(0.4999999999999997, -0.8660254037844388, 4.721414228296379e-16) -nomalize-> (0.4999999999999997, -0.8660254037844388, 4.721414228296379e-16)
 zAxis:(-0.8660254037844388, -0.4999999999999997, 3.8944589231081375e-16) -nomalize-> (-0.8660254037844388, -0.4999999999999997, 3.8944589231081375e-16)

 

 

It has been posted many times on the forum in the past that Occurrence.transform does not return the correct values, but transform2 was added this year.
Occurrence.transform is It should not be used now because it is only left for compatibility.

Message 9 of 13

rbin_robotik
Contributor
Contributor

@kandenntithank you so much for the detailed response!

 

After testing a bit more, I realized that the original model I have been working has some issues for some reason and deleting and re-adding "Simple Gripper" fixed the transformation matrix issue. I am not sure what the problem is.

 

I was also thinking that assembling components with joints would add the transformation matrix to the occurrence. However, it would add to the component. So, I was wrong with my expectation.

 

Let me explain that: My initial though about the assembly is

 

REx occurrence -> rigid joint -> Simple Gripper occurrence

 

In this scenario, I'd expect to get the transformation matrix which represents the move of the Simple Gripper occurrence from (0, 0, 0) position to the end of REx occurrence. However, this is incorrect. The correct way of thinking the assembly is

 

link_3 component (of REx occurrence) -> tool0_1 rigid joint -> slider_hand component (of Simple Gripper occurrence)

 

and slider_hand is assembled to two other components via a slider joint.

 

Therefore, the transformation matrix is applied to the slider_hand component (and the other connected components) but not the Simple Gripper occurrence itself.

0 Likes
Message 10 of 13

kandennti
Mentor
Mentor

@rbin_robotik .

 

The reason why the coordinate values could not be obtained correctly may be because the position has not been determined.

 

You could use the Command.isPositionDependent property or the Design.snapshots.add method.

 

https://forums.autodesk.com/t5/fusion-360-api-and-scripts/transformation-on-occurrence-getting-reset... 

 

https://forums.autodesk.com/t5/fusion-360-api-and-scripts/quot-move-copy-quot-in-the-context-menu/m-... 

Message 11 of 13

BrianEkins
Mentor
Mentor

Do you have a simple assembly that demonstrates the problem?

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 12 of 13

rbin_robotik
Contributor
Contributor
Accepted solution

@BrianEkins, after intensely debugging the code and testing the issue with many alternative solutions, I'd say that this is a not a bug but something I was expecting to be different. Thanks for your offer to help.

 

At the end, I figured that what I needed is the output of Occurrence.transform (not Occurrence.transform2) as I ended up computing that to fix the issues on my add-in. Maybe due to some misinterpretation or misunderstanding, I was always thinking that the output of Occurrence.transform was incorrect for some reason. However, it is correct but relative to the assembly context of the Occurrence. transform2 seems to return the matrix relative to the root component (please correct me if I am wrong).

 

To be honest, @kandennti's examples above were extremely helpful in finding the solution and I really appreciate them.

 

If this is a good place for it, I'd like to make a suggestion on the Python documentation page that describes Occurrence.transform and Occurrence.transform2 properties. I have a feeling that it would be great if the documentation entry was a bit more detailed and supported by some examples (like GUI or Palette examples on different occasions). I can see that using transformation matrix is not something considered as super common and there is an option to search the forums, but it is not always easy to find the solution, especially there is an option to explain everything in a very structured way on the documentation.

Message 13 of 13

BrianEkins
Mentor
Mentor

It would still be good to have an example that demonstrates the issue you were seeing to determine if there is a problem with the API or a problem with understanding how the API works that can possibly be solved with some better documentation.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes