asm4 pddl
This commit is contained in:
parent
3d3a063a5d
commit
748fcd1351
8 changed files with 304 additions and 0 deletions
15
pddl/helper/fs.py
Normal file
15
pddl/helper/fs.py
Normal 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
27
pddl/main.py
Normal 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
86
pddl/mocks/asm4-mock.json
Normal 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
2
pddl/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
argparse
|
||||
unified_planning
|
90
pddl/src/model/asm4_structure.py
Normal file
90
pddl/src/model/asm4_structure.py
Normal 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)
|
19
pddl/src/usecases/asm4_to_assembly_use_case.py
Normal file
19
pddl/src/usecases/asm4_to_assembly_use_case.py
Normal 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)
|
37
pddl/src/usecases/assembly_to_pddl_use_case.py
Normal file
37
pddl/src/usecases/assembly_to_pddl_use_case.py
Normal 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
28
pddl/unit.test.py
Normal 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()
|
Loading…
Add table
Add a link
Reference in a new issue