asm4 pddl

This commit is contained in:
IDONTSUDO 2023-03-05 16:58:37 +03:00
parent 3d3a063a5d
commit 748fcd1351
8 changed files with 304 additions and 0 deletions

15
pddl/helper/fs.py Normal file
View file

@ -0,0 +1,15 @@
import os
import json
class FS:
def readJSON(path:str):
return json.loads((open(path)).read())
def writeFile(data, filePath, fileName):
file_to_open = filePath + fileName
f = open(file_to_open, 'w', )
f.write(data)

27
pddl/main.py Normal file
View file

@ -0,0 +1,27 @@
import argparse
from helper.fs import FS
from src.model.asm4_structure import Asm4Structure
from src.usecases.asm4_to_assembly_use_case import Asm4ToAssemblyUseCase
from src.usecases.assembly_to_pddl_use_case import AssemblyToPddlUseCase
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--asm4Path', help='asm4 json FreeCad')
parser.add_argument('--outPath', help='save pddl path')
args = parser.parse_args()
if args.asm4Path == None or args.outPath == None:
parser.print_help()
data = FS.readJSON(args.asm4Path)
asm4 = Asm4Structure.parse(data)
asm4usecase = Asm4ToAssemblyUseCase().call(asm4)
assemblyToPddlUseCase = AssemblyToPddlUseCase.call(assembly=asm4usecase['asm'],rootLabel=asm4usecase['rootLabel'])
FS.writeFile(assemblyToPddlUseCase['problem'] ,args.outPath, 'problem.pddl')
FS.writeFile(assemblyToPddlUseCase['domain'] ,args.outPath, 'domain.pddl')

86
pddl/mocks/asm4-mock.json Normal file
View file

@ -0,0 +1,86 @@
[
{
"level": 1,
"attachedTo": "Parent Assembly",
"label": "Model",
"axis": [
"LCS_Origin"
]
},
{
"level": 1,
"attachedTo": [
"Parent Assembly",
"LCS_Origin"
],
"label": "CubePart001",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
"CubePart001",
"LCS_0"
],
"label": "CubePart002",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
"CubePart001",
"LCS_0"
],
"label": "CubePart003",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
""
],
"label": "CubePart004",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
"CubePart001",
"LCS_0"
],
"label": "CubePart005",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
"CubePart005",
"LCS_0"
],
"label": "CubePart006",
"axis": [
"LCS_0"
]
},
{
"level": 1,
"attachedTo": [
"CubePart006",
"LCS_0"
],
"label": "CubePart007",
"axis": [
"LCS_0"
]
}
]

2
pddl/requirements.txt Normal file
View file

@ -0,0 +1,2 @@
argparse
unified_planning

View file

@ -0,0 +1,90 @@
from typing import Optional, List, Union, Any, TypeVar, Callable, Type, cast
T = TypeVar("T")
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x
def from_none(x: Any) -> Any:
assert x is None
return x
def from_union(fs, x):
for f in fs:
try:
return f(x)
except:
pass
assert False
def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
assert isinstance(x, list)
return [f(y) for y in x]
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
def to_class(c: Type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
class Asm4Structure:
level: Optional[int]
attached_to: Optional[Union[List[str], str]]
label: Optional[str]
axis: Optional[List[str]]
def __init__(self, level: Optional[int], attached_to: Optional[Union[List[str], str]], label: Optional[str], axis: Optional[List[str]]) -> None:
self.level = level
self.attached_to = attached_to
self.label = label
self.axis = axis
@staticmethod
def from_dict(obj: Any) -> 'Asm4Structure':
assert isinstance(obj, dict)
level = from_union([from_int, from_none], obj.get("level"))
attached_to = from_union([lambda x: from_list(from_str, x), from_str, from_none], obj.get("attachedTo"))
label = from_union([from_str, from_none], obj.get("label"))
axis = from_union([lambda x: from_list(from_str, x), from_none], obj.get("axis"))
return Asm4Structure(level, attached_to, label, axis)
def to_dict(self) -> dict:
result: dict = {}
if self.level is not None:
result["level"] = from_union([from_int, from_none], self.level)
if self.attached_to is not None:
result["attachedTo"] = from_union([lambda x: from_list(from_str, x), from_str, from_none], self.attached_to)
if self.label is not None:
result["label"] = from_union([from_str, from_none], self.label)
if self.axis is not None:
result["axis"] = from_union([lambda x: from_list(from_str, x), from_none], self.axis)
return result
def parse(data) -> List['Asm4Structure']:
structure:list = []
for i in data:
structure.append(Asm4Structure(
label=i['label'],
level=i['level'],
attached_to=i['attachedTo'],
axis=i['axis']
))
return structure
def asm4_structures_from_dict(s: Any) -> List[Asm4Structure]:
return from_list(Asm4Structure.from_dict, s)
def asm4_structures_to_dict(x: List[Asm4Structure]) -> Any:
return from_list(lambda x: to_class(Asm4Structure, x), x)

View file

@ -0,0 +1,19 @@
from src.model.asm4_structure import Asm4Structure
from typing import List
class Asm4ToAssemblyUseCase:
_asm4Assembly = []
def call(self,asm4:List[Asm4Structure] ):
rootPart = asm4[0]
self._asm4Assembly.append(rootPart.label)
for el in asm4[1:asm4.__len__()]:
self.parse(lead=el)
return {'asm':self._asm4Assembly[1:self._asm4Assembly.__len__()],'rootLabel':rootPart.label}
def parse(self,lead:Asm4Structure ):
if lead.attached_to[0] == 'Parent Assembly':
self._asm4Assembly.append(lead.label)
for i in self._asm4Assembly:
if i == lead.attached_to[0]:
self._asm4Assembly.append(lead.label)

View file

@ -0,0 +1,37 @@
from typing import List
from unified_planning.shortcuts import *
from unified_planning import *
class AssemblyToPddlUseCase:
def call(assembly: List[str], rootLabel: str):
partType = UserType("part")
assemblyType = UserType('assembly')
objectsPartPddl = []
objectsAsmToPddl = []
i = 0
for el in assembly:
objectsPartPddl.append(Object(el, partType))
problem = Problem(rootLabel)
for el in objectsPartPddl:
problem.add_object(el)
i = 0
for el in objectsPartPddl:
problem.add_object(Object('subasm' + str(i), assemblyType))
objectsAsmToPddl.append(Object('subasm' + str(i), assemblyType))
i = i+1
connected = Fluent('part-of', BoolType(),
l_from=partType, l_to=assemblyType)
i = 0
for el in objectsPartPddl:
problem.set_initial_value(connected(el, objectsAsmToPddl[i]), True)
i = i+1
goal = Fluent(rootLabel)
problem.add_goal(connected(objectsPartPddl[objectsPartPddl.__len__(
) - 1], objectsAsmToPddl[objectsAsmToPddl.__len__() - 1]),)
return {"problem": unified_planning.io.PDDLWriter(problem).get_problem(), 'domain': unified_planning.io.PDDLWriter(problem).get_domain()}

28
pddl/unit.test.py Normal file
View file

@ -0,0 +1,28 @@
import unittest
from src.usecases.asm4_to_assembly_use_case import Asm4ToAssemblyUseCase
from src.usecases.assembly_to_pddl_use_case import AssemblyToPddlUseCase
from src.model.asm4_structure import Asm4Structure
from helper.fs import FS
import os
mock = FS.readJSON(os.path.dirname(os.path.realpath(__file__)) + '/mocks/asm4-mock.json')
asm4 = Asm4Structure.parse(mock)
asm4usecase = Asm4ToAssemblyUseCase().call(asm4)
assemblyToPddl = AssemblyToPddlUseCase.call(assembly=asm4usecase['asm'],rootLabel=asm4usecase['rootLabel'])
class TestStringMethods(unittest.TestCase):
def test_problem(self):
self.assertIsInstance(assemblyToPddl["problem"], str)
def test_domain(self):
self.assertIsInstance(assemblyToPddl["domain"], str)
if __name__ == '__main__':
unittest.main()