cadquery icon indicating copy to clipboard operation
cadquery copied to clipboard

Body rotations from a repeatedly solved assembly seem to be off by factor 1.29

Open unrealBob opened this issue 1 year ago • 5 comments

I recently got into creating animations with CadQuery and jupyter_cadquery and wanted to animate more complex constrained assemblies (planar linkages). My approach currently is just changing the param of a fixed rotation constraint for given timesteps, solving the assembly and querying the location of the bodies. The locations can then be used to create an animation.

I noticed something strange when querying the rotation of the solved assembly. When solving the first time, the rotation is as expected but after the second solve, the angle of the body is consistently 1.29 times higher than the set angle, which results in the animation "overshooting".

I altered the example from the assembly documentation. Can this be reproduced or am I missing something obvious?

from math import pi
import cadquery as cq

b1 = cq.Workplane().box(1, 1, 1)
b2 = cq.Workplane().rect(0.1, 0.1).extrude(1)

assy = (
    cq.Assembly()
    .add(b1, name="b1")
    .add(b2, loc=cq.Location((0, 0, 4)), name="b2", color=cq.Color("red"))
)
assy.name = "assy"

# fix the position of b1
assy.constrain("b1", "Fixed")
# fix b2 bottom face position (but not rotation)
assy.constrain("b2@faces@<Z", "FixedPoint", (0, 0, 0.5))
# fix b2 rotational degrees of freedom too
assy.constrain("b2", "FixedRotation", (45, 0, 0))
assy.solve()
print("initial solve: ", round(assy.objects.get("b2").loc.toTuple()[1][0] * 180/pi, 5))

angles = [0, 45, 0, -90, 0]
rotX = []
for angle in angles:
    # changing the angle and solving assembly 
    assy.constraints[-1].param = (angle, 0, 0)
    assy.solve()

    # query the location ((tx, ty, tz), (rx, ry, rz)) of b2
    b2_loc = assy.objects.get("b2").loc.toTuple()
    # get rx value, round and put it in list as degree
    rotX.append(round(b2_loc[1][0] * 180/pi, 1))

    print(f"set Angle:\t {assy.constraints[-1].param[0]}")
    print(f"solved angle:\t {rotX[-1]}")

"""animation part, for the sake of completeness
from jupyter_cadquery.animation import Animation
from jupyter_cadquery.viewer.client import show
show(assy)
time = [0, 1, 2, 3, 4]
animation = Animation()
animation.add_track(f"/{assy.name}/b2", "rx", time, rotX)
animation.animate(2)
"""

unrealBob avatar Aug 23 '24 08:08 unrealBob