Добавлен ASP-модуль
This commit is contained in:
parent
8bf8235add
commit
42762512c8
2 changed files with 153 additions and 1 deletions
12
README.md
12
README.md
|
@ -45,4 +45,14 @@ name_of_part
|
|||
└── model.config
|
||||
|
||||
```
|
||||
This packages will placed by default in your FreeCAD Document's folder and could be moved to gazebo model's folder for using them in sumulator.
|
||||
This packages will placed by default in your FreeCAD Document's folder and could be moved to gazebo model's folder for using them in sumulator.
|
||||
|
||||
# Генератор последовательности сборки (ASP)
|
||||
|
||||
Данный программный модуль(cad_parts_adjacency_matrix.py) предназначен для решения задачи планирования сборки. Он формирует граф сборки состоящий из И/ИЛИ и оценивает полученные там решения по набору из 4-ёх формальных правил для проверки сгенерированного графа, давая обратную связь для инженеров-конструкторов.
|
||||
|
||||
Формальный правила называются предикатами. Модуль ASP предусматривает следующие разновидности предикатов:
|
||||
- __Предикат геометрической осуществимости__. Верен для тех последовательностей сборки, которые удовлетворяют критерию геометрической осуществимости - когда все части графа сборки могут соприкосаться в определенной последовательности без каких либо столконовений.
|
||||
- __Предикат механической осуществимость__. Верна для последовательности сборки, когда инструменты сборки могут осуществлять указанную операцию без каких либо коллизий с изделием.
|
||||
- __Предикат стабильной осуществимости__. Верен для последовательности сборки, когда сборка на каждом из этапов приходит к стабильному состоянию.
|
||||
- __Предикат степеней свободы__. Формируется на основе уже сгенерированных графов/графа сборки. В каких степенях свободы возможно перемещать деталь.
|
||||
|
|
142
cad_parts_adjacency_matrix.py
Normal file
142
cad_parts_adjacency_matrix.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
import FreeCAD as App
|
||||
import uuid
|
||||
|
||||
collision_squares_labels = []
|
||||
|
||||
meshCoordinates = []
|
||||
detailSquares = {}
|
||||
|
||||
class ClearWorkSpaceDocument(object):
|
||||
def call(self):
|
||||
for key in detailSquares:
|
||||
for renderPrimitive in detailSquares[key]:
|
||||
primitivePart = App.ActiveDocument.getObjectsByLabel(renderPrimitive.cadLabel)[0]
|
||||
App.ActiveDocument.removeObject(primitivePart.Name)
|
||||
|
||||
|
||||
class MeshGeometryCoordinateModel(object):
|
||||
|
||||
def __init__(self, x, y, z, label,):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
self.label = label
|
||||
self.cadLabel = ''
|
||||
|
||||
def initializePrimitivesByCoordinate(self):
|
||||
uuidDoc = str(uuid.uuid1())
|
||||
App.ActiveDocument.addObject("Part::Box", "Box")
|
||||
App.ActiveDocument.ActiveObject.Label = uuidDoc
|
||||
App.ActiveDocument.recompute()
|
||||
part = App.ActiveDocument.getObjectsByLabel(uuidDoc)[0]
|
||||
collision_squares_labels.append(uuidDoc)
|
||||
part.Width = 2
|
||||
part.Height = 2
|
||||
part.Length = 2
|
||||
part.Placement = App.Placement(
|
||||
App.Vector(self.x - 1, self.y - 1, self.z - 1),
|
||||
App.Rotation(App.Vector(0.00, 0.00, 1.00), 0.00))
|
||||
if(detailSquares.get(self.label) is None):
|
||||
detailSquares[self.label] = []
|
||||
detailSquares[self.label].append(self)
|
||||
self.cadLabel = uuidDoc
|
||||
App.ActiveDocument.recompute()
|
||||
|
||||
|
||||
|
||||
class FreeCadMetaModel(object):
|
||||
|
||||
def __init__(self, label, vertex) -> None:
|
||||
self.label = label
|
||||
self.vertex = vertex
|
||||
|
||||
class InitPartsParseUseCase():
|
||||
|
||||
def call(self) -> list[FreeCadMetaModel]:
|
||||
product_details = []
|
||||
for part in App.ActiveDocument.Objects:
|
||||
if part is not None:
|
||||
model = FreeCadMetaModel(part.Label,part.Shape.Vertexes)
|
||||
if(model is not None):
|
||||
product_details.append(model)
|
||||
return product_details
|
||||
|
||||
|
||||
|
||||
class GetCollisionAtPrimitives(object):
|
||||
|
||||
def call(self,freeCadMetaModels: list[FreeCadMetaModel] ):
|
||||
for model in freeCadMetaModels:
|
||||
activePart = App.ActiveDocument.getObjectsByLabel(model.label)[0]
|
||||
for key in detailSquares:
|
||||
if(model.label != key):
|
||||
for renderPrimitive in detailSquares[key]:
|
||||
primitivePart = App.ActiveDocument.getObjectsByLabel(renderPrimitive.cadLabel)[0]
|
||||
collisionResult:int = int(activePart.Shape.distToShape(primitivePart.Shape)[0])
|
||||
# print(collisionResult)
|
||||
if(collisionResult == 0):
|
||||
print(model.label+ ' ' + renderPrimitive.label)
|
||||
|
||||
|
||||
|
||||
|
||||
class GetPartPrimitiveCoordinatesUseCase(object):
|
||||
|
||||
def call(self,freeCadMetaModels: list[FreeCadMetaModel]) -> list[MeshGeometryCoordinateModel]:
|
||||
meshCoordinates:list[MeshGeometryCoordinateModel] = []
|
||||
for model in freeCadMetaModels:
|
||||
vertexesDetail = model.vertex
|
||||
labelDetail = model.label
|
||||
for coords in vertexesDetail:
|
||||
detailVertex = MeshGeometryCoordinateModel(
|
||||
coords.X,
|
||||
coords.Y,
|
||||
coords.Z,
|
||||
labelDetail,
|
||||
)
|
||||
meshCoordinates.append(detailVertex)
|
||||
|
||||
return meshCoordinates
|
||||
|
||||
class RenderPrimitiveUseCase(object):
|
||||
|
||||
def call(self,meshModels :list[MeshGeometryCoordinateModel]) -> None:
|
||||
for mesh in meshModels:
|
||||
mesh.initializePrimitivesByCoordinate()
|
||||
|
||||
class RenderPrimitivesScenario(object):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
initPartsParseUseCase: InitPartsParseUseCase,
|
||||
getPartPrimitiveCoordinatesUseCase:GetPartPrimitiveCoordinatesUseCase,
|
||||
renderPrimitiveUseCase:RenderPrimitiveUseCase,
|
||||
getCollisionAtPrimitives:GetCollisionAtPrimitives,
|
||||
clearWorkSpaceDocument:ClearWorkSpaceDocument,
|
||||
) -> None:
|
||||
self.initPartsParseUseCase = initPartsParseUseCase
|
||||
self.getPartPrimitiveCoordinatesUseCase = getPartPrimitiveCoordinatesUseCase
|
||||
self.renderPrimitiveUseCase = renderPrimitiveUseCase
|
||||
self.getCollisionAtPrimitives = getCollisionAtPrimitives
|
||||
self.clearWorkSpaceDocument = clearWorkSpaceDocument
|
||||
|
||||
def call(self) -> None:
|
||||
parts = self.initPartsParseUseCase.call()
|
||||
meshCoordinates = self.getPartPrimitiveCoordinatesUseCase.call(parts)
|
||||
self.renderPrimitiveUseCase.call(meshCoordinates)
|
||||
self.getCollisionAtPrimitives.call(parts)
|
||||
self.clearWorkSpaceDocument.call()
|
||||
|
||||
|
||||
|
||||
def main() -> None:
|
||||
RenderPrimitivesScenario(
|
||||
InitPartsParseUseCase(),
|
||||
GetPartPrimitiveCoordinatesUseCase(),
|
||||
RenderPrimitiveUseCase(),
|
||||
GetCollisionAtPrimitives(),
|
||||
ClearWorkSpaceDocument(),
|
||||
).call()
|
||||
|
||||
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue