assembly without solver

Discussion about the development of the Assembly workbench.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

Zolko wrote: Sun Feb 10, 2019 11:20 pm I'll post the latest scripts here tomorrow
if it comes down to creating a test workbench to hold a few new python features to insert into the document, i would be glad to help. if i can. it's not functionally much different than macros on a toolbar, mostly packaging.

but i'm on windows and i don't compile (it's not fun like python), so my problem would be that i can only work with whatever windows version of A3 is available. i'm not the best candidate to put all this together, but if no one is eager to do it, i'd like to try.
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: assembly without solver

Post by Zolko »

emills2 wrote: Mon Feb 11, 2019 12:05 am
Zolko wrote: Sun Feb 10, 2019 11:20 pm I'll post the latest scripts here tomorrow
if it comes down to creating a test workbench to hold a few new python features to insert into the document, i would be glad to help.
Hello,

I uploaded my current scripts to my GitHub account:

https://github.com/Zolko-123/FreeCAD_aws

There is also an embryo of explanation:

https://github.com/Zolko-123/FreeCAD_aws/wiki

If you could try it out, and give your feedback on it, would be very helpful. As you can see, this is the very beginning. But still, if the scripts don't work as advertised, it's either a bug or bad explanation: you have the right to complain.
try the Assembly4 workbench for FreCAD — tutorials here and here
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

Zolko wrote: Mon Feb 11, 2019 11:32 pm
emills2 wrote: Mon Feb 11, 2019 12:05 am
Zolko wrote: Sun Feb 10, 2019 11:20 pm I'll post the latest scripts here tomorrow
if it comes down to creating a test workbench to hold a few new python features to insert into the document, i would be glad to help.
Hello,

I uploaded my current scripts to my GitHub account:

https://github.com/Zolko-123/FreeCAD_aws

There is also an embryo of explanation:

https://github.com/Zolko-123/FreeCAD_aws/wiki

If you could try it out, and give your feedback on it, would be very helpful. As you can see, this is the very beginning. But still, if the scripts don't work as advertised, it's either a bug or bad explanation: you have the right to complain.
thanks for sharing. i'll try to replicate this weekend.
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

after a hard start, i was able to place a part on an LCS defined in another part. so i'm hunting down things that cause errors.

you mentioned saving and closing before succeeding at certain steps. i've been doing that and haven't been able to identify the pattern that works.

after i succeeded at placing the LCS0 of 'part1' at LCS1 of 'part0', i tried to add a 2nd 'part0' on top of 'part1'. this never worked.

i examined the constraints at the top level, and i noticed that while the second instance of 'part0' had no placement property on its constraint, the first instance had multiples of those properties (from my repeated attempts to make a second instance work).

so i started over and gave unique names to the links as i added them, but now none of the constraint have the property! i think the unique names cause failure to add the placement property. see pic below.
AWS_01_error_AddLink.PNG
AWS_01_error_AddLink.PNG (172.85 KiB) Viewed 5267 times
once we make a class for the basic object with the right set of properties to start with this problem should go away.

if each constraint object only needs one placement and one offset, that'll be easy. i know how to make python features with any fixed number of properties all in one call, so there shouldn't be any name collisions.

at this point i'm still just poking around making sure i understand how it's all supposed to work.
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

alright i have a basic example working.
AWS_02_Basic_3Parts_with_Reuse.PNG
AWS_02_Basic_3Parts_with_Reuse.PNG (186.85 KiB) Viewed 5253 times
now i need to see if i can change the way link objects are inserted into the document, so that the file reference is a property of the link, not the identity of the link. this way, i can re-link the same file over and over, without having to save separate files with 1, 2, 3, 4 etc appended.

if the constraints then refer to the link ID, this can be unique, within the document.

the core of it worked though: i modeled parts in your new container, drew sketches on them where i wanted to attach them (and attach things to them, put LCSs on these sketches (i'd like the option to skip that and use the sketches as the LCSs personally), and then your macro 'snapped' the chosen LCS pairs together, while keeping the 'root' object fixed.

then i change the middle piece, hit recompute of the assembly, and BOOM.
AWS_03_Basic_3Parts_with_update.PNG
AWS_03_Basic_3Parts_with_update.PNG (188.92 KiB) Viewed 5253 times
To me, this ability to model static assemblies parametrically with 100% stability (no solver) is what stood out immediately on hearing your proposal.

so i'd like to propose this:
-gather the base classes and set the needed additional properties in derived classes, or build the classes fresh from a python features.
-separate the identity of a file link within an assembly from the identity of the file it links to.
-make sure the constraints refer to the link, not to the linked file.
-BOM stuff. super basic. rules for identifying components to prevent linking an assembly into itslef, and groundwork for complex BOM types.
-get rid of unique name issues, like 'Model'.

on that last topic, here is how i do it in my nurbs workbench.
here is an example command: https://github.com/edwardvmills/Silk/bl ... Curve_4.py

The key to object creation starts around line 34:

Code: Select all

		a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","CubicCurve_4")
		AN.CubicCurve_4(a,poly)
		a.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification)
		a.ViewObject.LineWidth = 1.00
		a.ViewObject.LineColor = (1.00,0.67,0.00)
		a.ViewObject.PointSize = 2.00
		a.ViewObject.PointColor = (1.00,1.00,0.00)
		FreeCAD.ActiveDocument.recompute()
i add an object 'a' to the document.
i pass a document tree name for that object, which is simply it's object type. if the name already exists, it just appends 001. i don't care.
i don't track the newly created object by it's document name. i track it by the variable i assigned the object to at its creation: 'a'
i give that object as a parameter to AN.CubicCurve_4, which is my cubic curve class. i also pass the poly from the selection.
i don't need to add any properties. all the properties of CubicCurve_4 objects are defined in AN ahead of time.
i still have access to the object handle, 'a', so i take the opportunity to set a default visual aspect using the existing ViewObject properties of all 'simple' feature python objects.

so i have one GUI selection / document object creation file for each workbench command, and one big library type file where i keep all the class definitions and function definitions. it uses FreeCAD modules at the lowest level possible, and doesn't even TOUCH selection processing or object creation. It could stand to get split into two or three, or ten pieces, but for now it feels comfy to have all my defs together (personally).

here is the corresponding definition for the function called above:

Code: Select all

class CubicCurve_4:
	def __init__(self, obj , poly):
		''' Add the properties '''
		FreeCAD.Console.PrintMessage("\nCubicCurve_4 class Init\n")
		obj.addProperty("App::PropertyLink","Poly","CubicCurve_4","control polygon").Poly = poly
		obj.Proxy = self

	def execute(self, fp):
		'''Do something when doing a recomputation, this method is mandatory'''
		# get the poles list from the poly. legacy shape function wants 'homogeneous' coords as [[x,y,z],w]
		WeightedPoles=[[fp.Poly.Poles[0],fp.Poly.Weights[0]],
				[fp.Poly.Poles[1],fp.Poly.Weights[1]],
				[fp.Poly.Poles[2],fp.Poly.Weights[2]],
				[fp.Poly.Poles[3],fp.Poly.Weights[3]]]
		# the legacy function below sets the degree and knot vector
		fp.Shape = Bezier_Cubic_curve(WeightedPoles).toShape()
the nice thing here is when i work on the function, i don't need to worry about the parameters. that is the workbench command's job

so if i were to try to help turn some of these into a workbench, i would like to use some aspects of this philosophy. specifically, separate the class and function definitions from all GUI selection processing and document object creation.

if you think this might lead to something useful to you, and the way you would like to see things run, let me know.

if we get this working, all the fancy pants constraint solver people :) could create fancy pants non static fully defined constraint types, and then they could run a solver on those fancy pants constraints, if they wanted to.

truth is, in solidworks, my end result for complex assemblies is completely nailed down with configurations. at the beginning, i let things slide around, rotate, etc. but once it gets serious, all subassemblies get nailed down to a few different configurations, those configurations then get nested in other configs, etc. the top level model with 1000s of parts is ALWAYS fully defined, and all states of interests can be quickly examined by switching configuration.

with 1000s of parts open at once, i don't trust for word censored that i can correctly push a cylinder rod to the true end of its travel just by dragging pixel in a 3D view, and then measure the correct resulting placement 20 parts over. but if i switch that cylinder to 'extended' config, then the assembly blinks to the new state, and measurements are valid, and so are interferences.
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

ppemawm wrote: Mon Dec 17, 2018 5:47 pm
Zolko wrote: Mon Dec 17, 2018 5:19 pm could I reuse the cylinder head to make a boxer ?
Of course, you simply export the body.
Zolko wrote: Mon Dec 17, 2018 5:19 pm And when I modify the cylinder head in the boxer, it's also modified in the star engine ?
Not yet...but wouldn't that be wonderful?
disclaimer 1: i'm not sure if you're still interested in this thread, but i wanted to chime in on this topic.
disclaimer 2: i've never build anything as beautiful or complicated as you have in FreeCAD.

the way i model assemblies i solidworks, i have the best of both world. absolutely 0 compromise on parametric integrity.

i model all the related custom parts of my assemblies in a single part of multiple bodies. so i have a shared parameter space, and all the holes lines up between parts, everytime. i never type the same input twice that i intend to match to something else.

but that file's bodies (parts) can't move, so it's risky to gauge the effects of motions. so i export links of individual bodies of the file into their own part files. these update parametrically based on the master layout multibody model. i make assemblies and sub-assemblies from the linked body parts.

this assembly is nice and clean, containing all my custom parts. now i can add as many purchased parts and standard hardware into the assembly and check fits and motion.

my master layout multibody model is unaffected by the assembly complexities and small hardware. when i update the master model, all the parts update, and the assembly updates. if i want to, i can start the master model around a central purchased component imported as a body, that still updates parametrically.

modeling environment for modeling, assembly environment for assembling. all data defined exactly ONCE. clean links and no data duplication.

obviously i cheat all the time, and slip on the discipline. every time i do i end up kicking myself when two holes don't line up or duplicate files show up.

all of this is to say, you can have it both ways.
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: assembly without solver

Post by Zolko »

EDIT : deleted, doublepost
Last edited by Zolko on Fri Feb 15, 2019 9:42 am, edited 1 time in total.
try the Assembly4 workbench for FreCAD — tutorials here and here
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: assembly without solver

Post by Zolko »

Wow, good stuff, thanx for testing and reporting.
emills2 wrote: Fri Feb 15, 2019 4:07 am you mentioned saving and closing before succeeding at certain steps. i've been doing that and haven't been able to identify the pattern that works.
this is an App::Link feature / limitation, nothing I can do about. What I understand is that since App::Link references objects by files, the file's path must exist.

From all the info you gave, I'll concentrate on the one that has annoyed me also the most: the unique naming things. But first, there are several concepts here:

  • the name of the App::Part, which is here the container for the top-level assembly. This App::Part object is colled most of the times 'Part' in FreeCAD, except here where it's 'Model'
  • the name of the link, which belongs to the previous App::Part container, which should rather be referred to as the name of the App::Link instance of an App::Part in another file. This doesn't have to be the same (at all) as the name of the part it links, but I personnally like it such, so that when reading the tree I can easily identify objects. This name (of the App::Link / instance of the part) must be unique, at least unique in it's container, it's a FreeCAD feature / limitation, but also something you see in all other CAD software. Several App::Links can link to a single file.
  • if the name of the App::Link instance (of an extarnal App::Part) at creation time does already exist, FreeCAD will assign a new name to it, adding 001 at the end (or 002, 003..). That's why the GUI for a link creation:
    • proposes as default the name of the file where the part is
    • allows the user to edit this name, and I do add a _1, _2, _3... at the end for each new instance
    • so the user is responsible for this unique identifier, which is of course wrong and the script should handle this, but I don't know how to
  • the label of the instance, which appears in the tree and can be changed at any time (whereas the name is given at creation time) but when you 'getObject('toto') it's the object with the name 'toto' that you'll get, not the object with the label 'toto'

i examined the constraints at the top level, and i noticed that while the second instance of 'part0' had no placement property on its constraint, the first instance had multiples of those properties (from my repeated attempts to make a second instance work).
yes, this is because you - probably - created part0 with the default name, which existed, so FreeCAD assigned it a new name, but the script didn't know about it and created a new constraint with the default name, which existed, so FreeCAD created a new one with 001 at the end, but again the script didn't know that, so it added the 'Offset' Placement to the previous constr_ feature which it thought was the good one, and which existed.

Code: Select all

	def onCreateLink(self):
...
		# get the name of the link (as it will appear in the tree)
		linkName = self.linkNameInput.text()
...
		PyFeatureName = PyFeaturePrefix + linkName
see, the name is decided by the script, without knowing whether FreeCAD will actually name the objects like that.

Code: Select all

...
		# create the App::Link to the previously selected model
		activeDoc.getObject('Model').newObject( 'App::Link', linkName ).LinkedObject = model
...
		activeDoc.getObject('Constraints').newObject( 'App::FeaturePython', PyFeatureName )
		# get the App::FeaturePython itself
		PyFeature = activeDoc.getObject( PyFeatureName )
		# add an App::Placement that will be the osffset between attachment and link LCS
		PyFeature.addProperty( 'App::PropertyPlacement', 'Offset', 'Placement' )
...

and the properties are added to the objects with these names, and if these names are wrong - because FreeCAD has done something else as we thought it would - it's all messed up. Yes, I know, it's the script's fault, it should make these checks.

so i started over and gave unique names to the links as i added them, but now none of the constraint have the property!

i think the unique names cause failure to add the placement property. see pic below.

AWS_01_error_AddLink.PNG
hum, strange, when I take care and do assign unique names to the instances, it works as described. What I do when I delete a link is that I also delete the corresponding constr_Feature, before re-importing the link. Did you do that too ? Could you try with a clean (empty, new) assembly ?
Last edited by Zolko on Fri Feb 15, 2019 3:20 pm, edited 1 time in total.
try the Assembly4 workbench for FreCAD — tutorials here and here
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: assembly without solver

Post by Zolko »

emills2 wrote: Fri Feb 15, 2019 6:54 am now i need to see if i can change the way link objects are inserted into the document, so that the file reference is a property of the link, not the identity of the link. this way, i can re-link the same file over and over, without having to save separate files with 1, 2, 3, 4 etc appended.
this should already work like that, if you give the link (instance) a unique name at creation time. Did you try to open the example.zip I provide on GitHub ? It has 2 instances of the Screw, but there is only I file.

if the constraints then refer to the link ID, this can be unique, within the document.
This is I think the biggest issue : how to do this properly ? Thinking about all you're saying, what do you think if the assembly itself contained a "database" of the linked objects, with the corresponding constraints associated with them ? For example a FeaturePython in the Constraints group. This way, a linked object could have several constraints associated with it, and so, later,

if we get this working, all the fancy pants constraint solver people :) could create fancy pants non static fully defined constraint types, and then they could run a solver on those fancy pants constraints, if they wanted to.

the core of it worked though: i modeled parts in your new container, drew sketches on them where i wanted to attach them (and attach things to them, put LCSs on these sketches (i'd like the option to skip that and use the sketches as the LCSs personally), and then your macro 'snapped' the chosen LCS pairs together, while keeping the 'root' object fixed.

then i change the middle piece, hit recompute of the assembly, and BOOM.

AWS_03_Basic_3Parts_with_update.PNG

To me, this ability to model static assemblies parametrically with 100% stability (no solver) is what stood out immediately on hearing your proposal.
cool

so i'd like to propose this:
-gather the base classes and set the needed additional properties in derived classes, or build the classes fresh from a python features.
-separate the identity of a file link within an assembly from the identity of the file it links to.
-make sure the constraints refer to the link, not to the linked file.
Yes, I agree, but can you please re-read the naming concept and may-be cross-check that some of what you propose already works - or at least is supposed to work - like that ?

For the rest of your message, I'll need more time to understand, but basically, anything concerning Python and Pyside and coding, I have no clue how to do this right, so anything you can propose will be better than what I'll ever be able to do.
try the Assembly4 workbench for FreCAD — tutorials here and here
emills2
Posts: 868
Joined: Tue Apr 28, 2015 11:23 pm

Re: assembly without solver

Post by emills2 »

Zolko wrote: Fri Feb 15, 2019 9:40 am this should already work like that, if you give the link (instance) a unique name at creation time. Did you try to open the example.zip I provide on GitHub ? It has 2 instances of the Screw, but there is only I file.
i thought i had done that, but i must have missed something. started with a fresh file, and it works. multiple clean links to a single external file.

unexpected side effect: live edit of LCS within the parts from the top level assembly. because i always lay out my LCS from a sketch (long line x, short line y), i have a drag and drop interface to edit it :) and since i can access it from the link itself....
AWS_03_00.gif
AWS_03_00.gif (282.85 KiB) Viewed 5160 times
this is why i really like to define everything in a simple 2D sketch if i can: it gives 3D manipulator handles on steroids.

in the case here, the LCS1 on top of the rod was define so that z points away. joining it to the block's LCS1 means the solids end up interfering. i could use the constraint offset, but i'd have to do that everytime. instead i decide that LCS on top of the rod should always point into the solid.

i edit the sketch so the 'x' line goes left instead of right, and the z of the LCS flips. permanently. the nice thing for me, is i don't have to edit the placement of the LCS. i'll always make them O-X-Y. i'll even put that in a custom LCS script for sketches. now my sketch gives me flip and precise rotation control.
AWS_03_04.gif
AWS_03_04.gif (307.97 KiB) Viewed 5160 times
This, to me, feels like a lot of power, just from fixed constraints and a 2D solver.

i'm seriously considering starting a non 'toy' design project with FreeCAD. i know a lot of people do very serious work with FreeCAD, but for me so far it has been hobby and fun. clean linking and static stable assemblies...this changes things
Post Reply