Добавлен ASP-модуль

This commit is contained in:
Igor Brylyov 2023-01-15 12:37:01 +00:00
parent 8bf8235add
commit 42762512c8
2 changed files with 153 additions and 1 deletions

View file

@ -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 предусматривает следующие разновидности предикатов:
- __Предикат геометрической осуществимости__. Верен для тех последовательностей сборки, которые удовлетворяют критерию геометрической осуществимости - когда все части графа сборки могут соприкосаться в определенной последовательности без каких либо столконовений.
- __Предикат механической осуществимость__. Верна для последовательности сборки, когда инструменты сборки могут осуществлять указанную операцию без каких либо коллизий с изделием.
- __Предикат стабильной осуществимости__. Верен для последовательности сборки, когда сборка на каждом из этапов приходит к стабильному состоянию.
- __Предикат степеней свободы__. Формируется на основе уже сгенерированных графов/графа сборки. В каких степенях свободы возможно перемещать деталь.

View 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()