Calculating a rotation with two parameters?

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
freedman
Veteran
Posts: 3439
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Calculating a rotation with two parameters?

Post by freedman »

What I want is to feed two variables ( as angles) into a function (starting at 0,0,0) and get out a rotation, I will insert the output values in a Placement Rotation. I see the rotation as Z = 0 to 360 and y = 0 to 360, ( or +- 180 for both), this should be enough to solve the rotation. Since X and Y are on the same plane they are somewhat redundant. I am presuming this can be done without trig. but I'm not sure how to get there with the axis and vector stuff, any thoughts could be helpful.
Thanks
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Calculating a rotation with two parameters?

Post by edwilliams16 »

A general rotation has three degrees of freedom, so to specify it with angles takes three - eg yaw, pitch and roll.

Code: Select all

yaw =20
pitch = 30
roll = 40
rot = App.Rotation(yaw, pitch, roll)
rot1 = App.Rotation(App.Vector(0,0,1), yaw) * App.Rotation(App.Vector(0, 1, 0), pitch) * App.Rotation(App.Vector(1, 0, 0), roll)
rot.isSame(rot1, 1e-8) # => True
rot.getYawPitchRoll() # => (20.0, 29.999999999999993, 40.0)
From your post, I think you are looking at the subset of rotations with roll=0 i.e App.Rotation(yaw, pitch, 0)
freedman
Veteran
Posts: 3439
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Calculating a rotation with two parameters?

Post by freedman »

Thanks Ed, and for the code. That looks like the right thing to use.
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Calculating a rotation with two parameters?

Post by onekk »

Code is simply telling you two ways of doing rotations.

Code: Select all

# first way very concise and similar to
# what you get using print(placement) 
rot = App.Rotation(yaw, pitch, roll)

# second way. NOTE order of multiplying 
rot1 = App.Rotation(App.Vector(0,0,1), yaw) * App.Rotation(App.Vector(0, 1, 0), pitch) * App.Rotation(App.Vector(1, 0, 0), roll)

# proof that the two ways are the same
rot.isSame(rot1, 1e-8) # => True
Note that there is an rotation order.

In first way it is ZYX so first Z is applied then Y and then the X.

If this what you have in mind you should specify a different "order of rotation" or multiply rotation accordingly.

@edwilliams16 has wrote something in some recent post, or in the FreeCAD blog if I remember correctly.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Calculating a rotation with two parameters?

Post by edwilliams16 »

@onekk @freedman

There's a discussion of these compound rotations in my blog article: https://blog.freecad.org/2023/01/16/the ... n-freecad/
Yaw/Pitch/Roll is illustrated in the wiki https://wiki.freecadweb.org/Placement#P ... h_and_Roll
If they lack clarity, let me know.
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Calculating a rotation with two parameters?

Post by onekk »

edwilliams16 wrote: Sat Jan 28, 2023 5:49 pm @onekk @freedman

There's a discussion of these compound rotations in my blog article: https://blog.freecad.org/2023/01/16/the ... n-freecad/
Yaw/Pitch/Roll is illustrated in the wiki https://wiki.freecadweb.org/Placement#P ... h_and_Roll
If they lack clarity, let me know.
Thanks for the links.

Not a problem on my side, once learned a couple of things that you kindly "teached" me in your works and forum posts.

Thanks to your help I'm coding slightly better now. Thanks again.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
dtay
Posts: 20
Joined: Fri Jan 17, 2020 12:52 pm

Re: Calculating a rotation with two parameters?

Post by dtay »

This got me curious about the Matrix API. https://wiki.freecadweb.org/Matrix_API

Here is an animation using a cube to visualize matrix rotations of Z & X:

Code: Select all

import Part, time, math

# Set ending angle for rotation
eAng = 75

# Zero for rotation steps
rx, rz = 0, 0

doc = App.ActiveDocument
Gui.ActiveDocument.ActiveView.setAxisCross(True)

# Add a colored box
box_obj = doc.addObject('Part::Box', 'Box')
box_obj.recompute()
blue, green, red = (0.,0.,1.,0.), (0.,0.4,0.,0.), (1.,0.,0.,0.)
box_obj.ViewObject.DiffuseColor = [blue, (0.,0.,0.,1.),green ,(0.,0.,1.,1.),red ,(0.,0.,1.,1.)]

#reposition Box xyz if you like, -5 is default Box center
box_obj.Placement.Base = (-5.0,-5.0,-5.0)

# Start loop for rotating the box around the z-axis
while rz < eAng:
    # Update the placement of the box object by 1 degree increments about z
    box_obj.Placement.Matrix.rotateZ(math.radians(1))
    # Increment the rotation value for the z-axis
    rz += 1
    # Update the gui and recompute the document
    App.Gui.updateGui()
    doc.recompute()
    # Wait for 0.01 seconds before continuing
    time.sleep(.01)

# loop rotating the box around the x-axis
while rx < eAng:
    box_obj.Placement.Matrix.rotateX(math.radians(1))
    rx += 1

    App.Gui.updateGui()
    doc.recompute()
    time.sleep(.01)
From the consol you can rest the cube with:

Code: Select all

App.ActiveDocument.Box.Placement.Matrix = App.Matrix() #will reset XYZ as well
#or
import math
App.ActiveDocument.Box.Placement.Matrix.rotateX(math.radians(-75))
App.ActiveDocument.Box.Placement.Matrix.rotateZ(math.radians(-75))
App.ActiveDocument.recompute()
edit: fix final angle
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Calculating a rotation with two parameters?

Post by edwilliams16 »

dtay wrote: Sun Jan 29, 2023 5:38 pm This got me curious about the Matrix API. https://wiki.freecadweb.org/Matrix_API
Looking at the reference, this is absurdly wrong:

Code: Select all

multiply(Matrix or Vector)
Description: Returns the cross product of a matrix or vector with this matrix

Returns: a Matrix
No such thing as the cross product of a matrix with a matrix or a vector.
It return the matrix product - which is either another matrix or a vector.

However it says not to edit it, but refers to the C++ code documentation which is correct but not completely apropos as the python wrapper is incomplete.

https://freecad.github.io/SourceDoc/d5/ ... rix4D.html
freedman
Veteran
Posts: 3439
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Calculating a rotation with two parameters?

Post by freedman »

dtay, I was also wondering about the matrix. Thanks for the code.

Wow! That is so simple to use and reads like a book. Perfect timing for what I needed.

Thank you
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Calculating a rotation with two parameters?

Post by edwilliams16 »

freedman wrote: Mon Jan 30, 2023 1:40 am Wow! That is so simple to use and reads like a book. Perfect timing for what I needed.
@dtay

You'll find the API for matrices is impoverished compared to that of Placements or Rotations.
For instance, suppose you want to rotate about an axis that isn't x, y or z. How would you generate the rotation matrix corresponding to

Code: Select all

rot = App.Rotation(App.Vector(1, 1, 1), 30)
or

Code: Select all

rot = App.Rotation(App.Vector(1, 0, 0), App.Vector(1,1,1))
using the Matrix API? You'd have to write a lot of code.

You could use

Code: Select all

mat = rot.Matrix
but then why bother with matrices?

Matrices allow you to scale and shear objects as well as translate and rotate them. Scaling is used in FreeCAD, shearing AFAIK only in macros. Don't bother with them unless they are actually required.

Here's the previous script. Run it with usematrix = True or False to see they are the same. How would you generalize both to rotate around the (1,1,1) axis?

Code: Select all

import Part, time, math

# Set ending angle for rotation
eAng = 75

# Zero for rotation steps
rx, rz = 0, 0

usematrix = False

doc = App.ActiveDocument
Gui.ActiveDocument.ActiveView.setAxisCross(True)

# Add a colored box
box_obj = doc.addObject('Part::Box', 'Box')
box_obj.recompute()
blue, green, red = (0.,0.,1.,0.), (0.,0.4,0.,0.), (1.,0.,0.,0.)
box_obj.ViewObject.DiffuseColor = [blue, (0.,0.,0.,1.),green ,(0.,0.,1.,1.),red ,(0.,0.,1.,1.)]

#reposition Box xyz if you like, -5 is default Box center
box_obj.Placement.Base = (-5.0,-5.0,-5.0)

# Start loop for rotating the box around the z-axis
while rz < eAng:
    # Update the placement of the box object by 1 degree increments about z
    pl1z = App.Placement(App.Vector(), App.Rotation(App.Vector(0, 0, 1), 1))
    if usematrix:
        box_obj.Placement.Matrix.rotateZ(math.radians(1))
    else:
        box_obj.Placement =  pl1z * box_obj.Placement
    
    # Increment the rotation value for the z-axis
    rz += 1
    # Update the gui and recompute the document
    App.Gui.updateGui()
    doc.recompute()
    # Wait for 0.01 seconds before continuing
    time.sleep(.01)


# loop rotating the box around the x-axis
while rx < eAng:
    rx += 1
    pl1x = App.Placement(App.Vector(), App.Rotation(App.Vector(1, 0, 0), 1))
    if usematrix:
        box_obj.Placement.Matrix.rotateX(math.radians(1))
    else:
        box_obj.Placement =  pl1x * box_obj.Placement

    App.Gui.updateGui()
    doc.recompute()
    time.sleep(.01)

Post Reply