Open unrealBob opened 3 months ago
.param
is in radians AFAICT. Probably it should be marked as private (_parmas
).
angles = [0, 45, 0, -90, 0]
rotX = []
for angle in angles:
# changing the angle and solving assembly
assy.constraints[-1].param = (radians(angle), 0, 0)
assy.solve()
Thank you very much for the fast response!
The issue is not with the radians or degree conversion. In the example from the documentation its written in degree:
# fix b2 rotational degrees of freedom too
assy.constrain("b2", "FixedRotation", (45, 0, 45))
When querying the body rotation within a solved assembly however, it is in radians.
The issue is that when solving the assembly for the first time, the returned body rotation is correct, when solving it the second (or any other) time with a changed param value, it is off by 1.29 (obviously regardless of rad or deg), but consistently.
What I can see is that the last solve in your example is not fully converged (assy.solve(5)
to get some diagnostics). If you rerun the last solve, it does return the correct value. I do not get the off by 1.29 statement.
Is it an issue with the starting point? I can reproduce the not fully converged result with this example:
import cadquery as cq
b1 = cq.Workplane().box(1, 1, 1)
b2 = cq.Workplane().rect(0.1, 0.1).extrude(1)
# bad starting point
starting_rot = (-90, 0, 0)
# optimal solution found
# starting_rot = (10, 0, 0)
assy = (
cq.Assembly()
.add(b1, name="b1")
.add(
b2,
loc=cq.Location((0, 0, 0), starting_rot),
name="b2",
color=cq.Color("red"),
)
)
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", (0, 0, 0))
assy.solve(5)
print(f'after solve: = {assy.objects.get("b2").loc.toTuple()}')
Okay I think I know where my issue comes from. Lets take a look at the following lines:
# set the initial rotation to 45 degree
assy.constrain("b2", "FixedRotation", param = (45, 0, 0))
assy.solve()
print("initial solve: ", round(assy.objects.get("b2").loc.toTuple()[1][0] * 180/pi, 5))
# changing the desired angle of the body to 90 degree
assy.constraints[-1].param = (pi/2, 0, 0)
assy.solve()
print("second solve: ", round(assy.objects.get("b2").loc.toTuple()[1][0] * 180/pi, 5))
When creating the FixedRotation constraint and defining param = (45,0,0)
, the angle after solving is 45 degree as expected.
When updating the constraint with assy.constraints[-1].param = (pi/2, 0, 0)
the angle indeed needs to be set in rad. Now I get the expected angle of 90 degrees. This really confused me.
Thank you very much @adam-urbanczyk. Your first answer was correct.
TLDR:
param
is in DEGparam
is in RAD
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?