Use 3d-vectors so you can do the 2d planar displacements on any orientation of reference plane in 3d-space. If you want something even more general like rigid-body displacement in 3-d space then one approach is screw displacements. Look up Chasles or Mozzi-Chasles theorem. A while back (over a year ago), I posted the Chasles theorem with a very rough demo code and some (boring) video. I would go over the vector math of that code and polish it up. Note that i did NOT control for edge cases. Also, I think i posted a paper on how to use this in constructing constrained motion but screw-displacement theory is not the only approach.project4 wrote: ↑Wed Jul 25, 2018 2:59 pmOhhh... I don't know how to transform that to math in the code...Mark Szlazak wrote: ↑Wed Jul 25, 2018 2:37 pmHere is a video showing how to do it. The only exception is when the perpendiculars are parallel in which case you just rectilinearly translate the rigid body to it’s new location. All displacements can be done this way without exception.project4 wrote: ↑Wed Jul 25, 2018 10:02 amOhhh... You mean like in the image below, points B and C are the rotation refPoints and point A is the intersection of the angles from those refPoint.
So the point D of perpendicular D-E will show the location of the rotation point, right?
In that case we'll need to calculate a lot of intersection points... My way is probably easier...
imgC.gif
Another approach to assembly solver (A2plus)
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
-
- Posts: 439
- Joined: Tue Apr 04, 2017 6:06 pm
- Location: SF Bay Area, California
Re: Another approach to assembly solver (A2plus)
Re: Another approach to assembly solver (A2plus)
Please take 2 PRs that should fix both issues.kbwbe wrote: ↑Wed Jul 25, 2018 12:34 pm @project4,
just tested new PR's.
I found some errors. Find attached a small assembly "group-001.fcstd".
When using partial solving, it is not able to solve and i get an error in console "nested recomputes".
Solving alltogether works.
.
group-001.png
.
The hierarchy file shows false constraint-types.
.
Hierarchy.png
Re: Another approach to assembly solver (A2plus)
That's a great model for rotation explorations, only few parts and takes lots of steps, even in partial mode.kbwbe wrote: ↑Wed Jul 25, 2018 1:35 pm @project4,
tested again move+rotation steps.
find attached another test-assemby and the solversystem.py with which i assembled.
1) move steps where to big. i multiplied them with factor 0.5
2) rotation is correct, but much to small steps.
3) i weighted the rotation for "refPointAttractions" again factor 6. It is still to slow !
I you start solving with solversystem.py above: i activated 10 steps only, 1/2 second delay between steps, with visualisation per step.
You can see a 'video' of movement. (You will see that rotation is to slow)
PS: enlarged factor 6.0 to 100.0. Great ! 6DOF is as fast as it had been some versions ago. I think that's it ...
(tested with max 150.000 steps and no visualisation again)
I'll probably have time to play with it on the weekend.
Re: Another approach to assembly solver (A2plus)
Hi @project4,project4 wrote: ↑Wed Jul 25, 2018 4:46 pmPlease take 2 PRs that should fix both issues.kbwbe wrote: ↑Wed Jul 25, 2018 12:34 pm @project4,
just tested new PR's.
I found some errors. Find attached a small assembly "group-001.fcstd".
When using partial solving, it is not able to solve and i get an error in console "nested recomputes".
Solving alltogether works.
.
group-001.png
.
The hierarchy file shows false constraint-types.
.
Hierarchy.png
both PR's are merged. I also pushed changes to the branch "solver-stabilization". Now rotation caused by "refPointAttraction" got a weight.
Also linearMove was weighted, as it was to big in some usecases. 6DOF is fast again. Main problems may exist within long chains of parts as Manuel's crankshaft. In total it solved more testcases for me.
KBWBE
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
Re: Another approach to assembly solver (A2plus)
@project4,
just tested your PR's. Everything is fine now. Good to have the button to toggle between solvermode "AllTogether" and "partial".
Manuels crankshaft is no problem anymore, using partial system.
Good work !
just tested your PR's. Everything is fine now. Good to have the button to toggle between solvermode "AllTogether" and "partial".
Manuels crankshaft is no problem anymore, using partial system.
Good work !
KBWBE
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
Re: Another approach to assembly solver (A2plus)
I had the crankshaft assembled before all the changes. All other models didn't work for me.
Didn't test your latest changes yet. Probably could get back to that only on the weekend.
Re: Another approach to assembly solver (A2plus)
Hi @project4,
i updated branch "solver-stabilization".
Changes are:
bugfix in calculate chain, i recognized a double entry in worklist and system could not be solved. Now it looks as:
solveSystem() has been modified. Now it only loads once complete system and only once updates the solution.
SolveSystem now looks as:
There are some small functions been added. solverSystem.prepareRestart(), rigid.prepareRestart(), dependency.disable()
I have attached a new assembled pump-testfile. I now can be solved in partial solvermode. In "alltogether mode" it will not work without adding some "helper" constraints.
i updated branch "solver-stabilization".
Changes are:
bugfix in calculate chain, i recognized a double entry in worklist and system could not be solved. Now it looks as:
Code: Select all
def calculateChain(self, doc):
self.stepCount = 0
rigCalcCount = 0
haveMore = True
workList = []
if a2plib.isPartialProcessing():
FreeCAD.Console.PrintMessage( "Solvermode = partialProcessing !\n")
# start from fixed rigids and its children
for rig in self.rigids:
if rig.fixed:
workList.append(rig);
workList.extend(rig.getCandidates())
else:
FreeCAD.Console.PrintMessage( "Solvermode = solve all Parts at once !\n")
workList.extend(self.rigids)
while haveMore:
solutionFound = self.calculateWorkList(doc, workList)
if not solutionFound: return False
addList = []
for rig in workList:
candidates = rig.getCandidates()
for candidate in candidates:
if candidate not in addList:
addList.append(candidate)
workList.extend(addList)
haveMore = (len(addList) > 0)
self.printList("AddList", addList)
return True
SolveSystem now looks as:
Code: Select all
def solveSystem(self,doc):
self.level_of_accuracy=1
FreeCAD.Console.PrintMessage( "\n===== Start Solving System ====== \n" )
startTime = int(round(time.time() * 1000))
self.loadSystem(doc)
self.assignParentship(doc)
loadTime = int(round(time.time() * 1000))
while True:
systemSolved = self.calculateChain(doc)
totalTime = int(round(time.time() * 1000))
#FreeCAD.Console.PrintMessage( "Position Accuracy: %f\n" % self.mySOLVER_POS_ACCURACY )
#FreeCAD.Console.PrintMessage( "Max positionerror: %f\n" % poserror )
#FreeCAD.Console.PrintMessage( "Spin Accuracy: %f\n" % self.mySOLVER_SPIN_ACCURACY )
#FreeCAD.Console.PrintMessage( "Max spinerror: %f\n" % spinerror )
FreeCAD.Console.PrintMessage( "Total steps used: %d\n" % self.stepCount)
FreeCAD.Console.PrintMessage( "LoadTime (ms): %d\n" % (loadTime - startTime) )
FreeCAD.Console.PrintMessage( "CalcTime (ms): %d\n" % (totalTime - loadTime) )
FreeCAD.Console.PrintMessage( "TotalTime (ms): %d\n" % (totalTime - startTime) )
if systemSolved:
FreeCAD.Console.PrintMessage( "===== System solved ! ====== \n" )
self.mySOLVER_SPIN_ACCURACY *= 1e-1
self.mySOLVER_POS_ACCURACY *= 1e-1
self.level_of_accuracy+=1
if self.level_of_accuracy == 4:
self.solutionToParts(doc)
break
self.prepareRestart()
else:
FreeCAD.Console.PrintMessage( "===== Could not solve system ====== \n" )
msg = \
'''
Constraints inconsistent. Cannot solve System.
Please delete your last created constraint !
'''
QtGui.QMessageBox.information( QtGui.QApplication.activeWindow(), "Constraint mismatch", msg )
break
self.mySOLVER_SPIN_ACCURACY = SOLVER_SPIN_ACCURACY
self.mySOLVER_POS_ACCURACY = SOLVER_POS_ACCURACY
I have attached a new assembled pump-testfile. I now can be solved in partial solvermode. In "alltogether mode" it will not work without adding some "helper" constraints.
- Attachments
-
- pump-2018-07-26.fcstd
- (760.88 KiB) Downloaded 32 times
KBWBE
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
Re: Another approach to assembly solver (A2plus)
Hi,kbwbe wrote: ↑Thu Jul 26, 2018 12:43 pm Hi @project4,
i updated branch "solver-stabilization".
Changes are:
bugfix in calculate chain, i recognized a double entry in worklist and system could not be solved. Now it looks as:solveSystem() has been modified. Now it only loads once complete system and only once updates the solution.Code: Select all
def calculateChain(self, doc): self.stepCount = 0 rigCalcCount = 0 haveMore = True workList = [] if a2plib.isPartialProcessing(): FreeCAD.Console.PrintMessage( "Solvermode = partialProcessing !\n") # start from fixed rigids and its children for rig in self.rigids: if rig.fixed: workList.append(rig); workList.extend(rig.getCandidates()) else: FreeCAD.Console.PrintMessage( "Solvermode = solve all Parts at once !\n") workList.extend(self.rigids) while haveMore: solutionFound = self.calculateWorkList(doc, workList) if not solutionFound: return False addList = [] for rig in workList: candidates = rig.getCandidates() for candidate in candidates: if candidate not in addList: addList.append(candidate) workList.extend(addList) haveMore = (len(addList) > 0) self.printList("AddList", addList) return True
SolveSystem now looks as:There are some small functions been added. solverSystem.prepareRestart(), rigid.prepareRestart(), dependency.disable()Code: Select all
def solveSystem(self,doc): self.level_of_accuracy=1 FreeCAD.Console.PrintMessage( "\n===== Start Solving System ====== \n" ) startTime = int(round(time.time() * 1000)) self.loadSystem(doc) self.assignParentship(doc) loadTime = int(round(time.time() * 1000)) while True: systemSolved = self.calculateChain(doc) totalTime = int(round(time.time() * 1000)) #FreeCAD.Console.PrintMessage( "Position Accuracy: %f\n" % self.mySOLVER_POS_ACCURACY ) #FreeCAD.Console.PrintMessage( "Max positionerror: %f\n" % poserror ) #FreeCAD.Console.PrintMessage( "Spin Accuracy: %f\n" % self.mySOLVER_SPIN_ACCURACY ) #FreeCAD.Console.PrintMessage( "Max spinerror: %f\n" % spinerror ) FreeCAD.Console.PrintMessage( "Total steps used: %d\n" % self.stepCount) FreeCAD.Console.PrintMessage( "LoadTime (ms): %d\n" % (loadTime - startTime) ) FreeCAD.Console.PrintMessage( "CalcTime (ms): %d\n" % (totalTime - loadTime) ) FreeCAD.Console.PrintMessage( "TotalTime (ms): %d\n" % (totalTime - startTime) ) if systemSolved: FreeCAD.Console.PrintMessage( "===== System solved ! ====== \n" ) self.mySOLVER_SPIN_ACCURACY *= 1e-1 self.mySOLVER_POS_ACCURACY *= 1e-1 self.level_of_accuracy+=1 if self.level_of_accuracy == 4: self.solutionToParts(doc) break self.prepareRestart() else: FreeCAD.Console.PrintMessage( "===== Could not solve system ====== \n" ) msg = \ ''' Constraints inconsistent. Cannot solve System. Please delete your last created constraint ! ''' QtGui.QMessageBox.information( QtGui.QApplication.activeWindow(), "Constraint mismatch", msg ) break self.mySOLVER_SPIN_ACCURACY = SOLVER_SPIN_ACCURACY self.mySOLVER_POS_ACCURACY = SOLVER_POS_ACCURACY
I have attached a new assembled pump-testfile. I now can be solved in partial solvermode. In "alltogether mode" it will not work without adding some "helper" constraints.
You don't have to remove the duplicates yourself, that's done in the getCandidates function already:
Code: Select all
def getCandidates(self):
candidates = []
for rig in self.childRigids:
if not rig.tempfixed and rig.areAllParentTempFixed():
candidates.append(rig)
return list(set(candidates)) # <----- list(set(...)) removes the duplicates
Actually after reading the stackoverflow explanation again, we don't really need the list() call, which restores the order, since the order is not important in our case.
Are you sure you saw the duplicates on latest version?
I've added the list(set()) to getCandidates in the last change you took from me...
Re: Another approach to assembly solver (A2plus)
Yes. But only 1 duplicate in 1 testcase. It was the motor of the pump. Therefore i could not solve the pump assembly. After my changes, it worked. !?
KBWBE
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
https://github.com/kbwbe/A2plus
latest release: v0.4.56, installable via FreeCAD's addon manager
Tutorial: gripper assembly https://www.youtube.com/watch?v=QMxcQ5tssWk
Documentation: https://www.freecadweb.org/wiki/A2plus_Workbench
Re: Another approach to assembly solver (A2plus)
Just wanted to say it's nice to see such ongoing developer collaboration on a project like assembly solver for FreeCAD.