RoboWaiter/BTExpansionCode/EXP/behavior_tree/ptml/ptmlTranslator.py

120 lines
3.8 KiB
Python

import shortuuid
import py_trees as ptree
from EXP.behavior_lib._base import Selector, Sequence
from antlr4 import *
if "." in __name__:
from .ptmlListener import ptmlListener
from .ptmlParser import ptmlParser
else:
from ptmlListener import ptmlListener
from ptmlParser import ptmlParser
short_uuid = lambda: shortuuid.ShortUUID().random(length=8)
class ptmlTranslator(ptmlListener):
"""Translate the ptml language to BT.
Args:
ptmlListener (_type_): _description_
"""
def __init__(self, scene, behaviour_lib_path) -> None:
super().__init__()
self.bt_root = None
self.stack = []
self.scene = scene
self.behaviour_lib_path = behaviour_lib_path
# Enter a parse tree produced by ptmlParser#root.
def enterRoot(self, ctx: ptmlParser.RootContext):
pass
# Exit a parse tree produced by ptmlParser#root.
def exitRoot(self, ctx: ptmlParser.RootContext):
pass
# Enter a parse tree produced by ptmlParser#tree.
def enterTree(self, ctx: ptmlParser.TreeContext):
type = str(ctx.internal_node().children[0])
if type== "sequence":
node = Sequence(name="Sequence", memory=False)
elif type=="selector":
node = Selector(name="Selector", memory=False)
elif type== "parallel":
tag = "parallel_" + short_uuid()
# threshold = int(ctx.children[1])
# default policy, success on all
node = ptree.composites.Parallel(
name=tag, policy=ptree.common.ParallelPolicy.SuccessOnAll
)
else:
raise TypeError("Unknown Composite Type: {}".format(type))
self.stack.append(node)
# Exit a parse tree produced by ptmlParser#tree.
def exitTree(self, ctx: ptmlParser.TreeContext):
if len(self.stack) >= 2:
child = self.stack.pop()
self.stack[-1].add_child(child)
else:
self.bt_root = self.stack[0]
# Enter a parse tree produced by ptmlParser#internal_node.
def enterInternal_node(self, ctx: ptmlParser.Internal_nodeContext):
pass
# Exit a parse tree produced by ptmlParser#internal_node.
def exitInternal_node(self, ctx: ptmlParser.Internal_nodeContext):
pass
# Enter a parse tree produced by ptmlParser#action_sign.
def enterAction_sign(self, ctx: ptmlParser.Action_signContext):
# cond / act
node_type = str(ctx.children[0])
name = str(ctx.String())
# if have params
args = []
if len(ctx.children) > 4:
params = ctx.action_parm()
for i in params.children:
if isinstance(i, ptmlParser.BooleanContext):
args.append(str(i.children[0]))
elif str(i) == ',':
args.append(',')
else:
args.append(f"'{i}'")
args = "".join(args)
exec(f"from {name} import {name}")
# tag = "cond_" + short_uuid() if node_type == "cond" else "task_" + short_uuid()
node = eval(f"{name}({args})")
node.set_scene(self.scene)
# connect
self.stack[-1].add_child(node)
# Exit a parse tree produced by ptmlParser#action_sign.
def exitAction_sign(self, ctx: ptmlParser.Action_signContext):
pass
# Enter a parse tree produced by ptmlParser#action_parm.
def enterAction_parm(self, ctx: ptmlParser.Action_parmContext):
pass
# Exit a parse tree produced by ptmlParser#action_parm.
def exitAction_parm(self, ctx: ptmlParser.Action_parmContext):
pass
# Enter a parse tree produced by ptmlParser#boolean.
def enterBoolean(self, ctx: ptmlParser.BooleanContext):
pass
# Exit a parse tree produced by ptmlParser#boolean.
def exitBoolean(self, ctx: ptmlParser.BooleanContext):
pass