[solved] Goal seek macro
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
[solved] Goal seek macro
Could somebody help creating a "goal seek" macro?
The idea is that you have a design and in it a parameter that needs to be adjusted (for example the internal volume of a glass cup) to a certain value (250ml) by adjusting some parameters. I expect that the rough (initial) design will require adjusting multiple parameters, but to get an exact result only one parameter should be tweaked at the end. My idea so far it to use two (probably selectable) DynamicData objects with three properties with predefined names - Parameter, Result , Goal. One uses Parameter in the design (Body.Pad.Height), sets Result to desired resulting parameter (Body.Shape.Volume) inputs the desired value in the Goal and runs the macro. The macro should change the value of the Parameter and recompute until Result reaches Goal within a threshold. Probably some other parameters might be required (Threshold, MaxSteps, MaxStep, StarChangeDirection, ...)
What I need is just a framework to access the data and I should be able to work it out from there.
The idea is that you have a design and in it a parameter that needs to be adjusted (for example the internal volume of a glass cup) to a certain value (250ml) by adjusting some parameters. I expect that the rough (initial) design will require adjusting multiple parameters, but to get an exact result only one parameter should be tweaked at the end. My idea so far it to use two (probably selectable) DynamicData objects with three properties with predefined names - Parameter, Result , Goal. One uses Parameter in the design (Body.Pad.Height), sets Result to desired resulting parameter (Body.Shape.Volume) inputs the desired value in the Goal and runs the macro. The macro should change the value of the Parameter and recompute until Result reaches Goal within a threshold. Probably some other parameters might be required (Threshold, MaxSteps, MaxStep, StarChangeDirection, ...)
What I need is just a framework to access the data and I should be able to work it out from there.
- Attachments
-
- GoalSeekTest001.FCStd
- (9.39 KiB) Downloaded 49 times
Last edited by kisolre on Mon Aug 15, 2022 5:12 am, edited 1 time in total.
Re: [Help] Goal seek macro
The main problem for such an algorithm is the number of ways a model can trigger an error when trying to compute it with 'random' values.
May we consider that we will only use positive values as parameter ?
May we consider that we will only use positive values as parameter ?
Re: [Help] Goal seek macro
I discovered scipy python package recently.
There is an optimization tool that can do that, even with multiple variables.
My math knowledge is a bit low to fully understand this tool, but I used it successfully to compute minimal curvature for CurvesWB BlendCurve.
There is an optimization tool that can do that, even with multiple variables.
My math knowledge is a bit low to fully understand this tool, but I used it successfully to compute minimal curvature for CurvesWB BlendCurve.
Re: [Help] Goal seek macro
If you can install python.scipy, this little script seems to work :
Code: Select all
import FreeCAD
from scipy.optimize import minimize
doc1 = FreeCAD.getDocument('GoalSeekTest001')
o1 = doc1.getObject('dd')
o2 = doc1.getObject('dd001')
def compute(value):
o1.ddParameter = value[0]
doc1.recompute()
return abs(o2.ddGoal.Value - o2.ddResult.Value)
res = minimize(compute, 1, method='Nelder-Mead', options={"maxiter": 2000, "disp": True})
print("For Height = {}, Volume = {}".format(o1.ddParameter, o2.ddResult))
-
- Posts: 529
- Joined: Fri Sep 18, 2020 5:40 pm
Re: [Help] Goal seek macro
Scipy is awesome, definitely the right way. You can even tell it to respect bounds on the parameters (i.e max and min value)
by changing method to e.g "L-BFGS-B" and setting the bounds parameter to a list of (min, max) tuples.
Re: [Help] Goal seek macro
Looks like it comes with the latest Windows LibPack (12.4.2) so the macro runs here and is Awesome \
Here is a little revised script and I need it to brake when the recompute fails. But clearly this is not the way
Code: Select all
import FreeCAD
from scipy.optimize import minimize
sel = Gui.Selection.getSelectionEx()
if len(sel)!=2:
raise Exception("Select 2 DD objects - Parameter and Goal")
o1=sel[0].Object
o2=sel[1].Object
def compute(value):
o1.ddParameter = value[0]
print(o1.ddParameter)
if not(App.ActiveDocument.recompute()):
brake
return abs(o2.ddGoal.Value - o2.ddResult.Value)
res = minimize(compute, o1.ddParameter, method='Nelder-Mead', options={"maxiter": 100, "disp": True})
print("For Height = {}, Volume = {}".format(o1.ddParameter, o2.ddResult))
- Attachments
-
- GoalSeekTest002.FCStd
- (581.28 KiB) Downloaded 78 times
Re: [Help] Goal seek macro
Here is another example calculating the internal volume of a cup, 3d printed in Vase mode with wall thickness 0.8mm.
.
.
- Attachments
-
- GoalSeekTest003.FCStd
- (690.64 KiB) Downloaded 63 times
-
- Veteran
- Posts: 3107
- Joined: Thu Sep 24, 2020 10:31 pm
- Location: Hawaii
- Contact:
Re: [Help] Goal seek macro
The minimization may work better usingdef compute(value):
o1.ddParameter = value[0]
doc1.recompute()
return abs(o2.ddGoal.Value - o2.ddResult.Value)
Code: Select all
return (o2.ddGoal.Value - o2.ddResult.Value)**2
Re: [Help] Goal seek macro
Yes, it definitely takes less iterations.