From 1a7deb7e1c9d76289e4972dce551577a9aafb16d Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 18 May 2020 12:47:40 -0400 Subject: [PATCH 01/23] Init commit for domain creation templates and markdown file --- .../domain_creation_checklist.md | 70 ++++++++ .../templates/examples_template.txt | 64 +++++++ .../templates/methods_template.txt | 158 ++++++++++++++++++ .../templates/operators_template.txt | 81 +++++++++ midca/domains/domain_creation_checklist.md | 0 5 files changed, 373 insertions(+) create mode 100644 midca/domains/Domain_Parsing/domain_creation_checklist.md create mode 100644 midca/domains/Domain_Parsing/templates/examples_template.txt create mode 100644 midca/domains/Domain_Parsing/templates/methods_template.txt create mode 100644 midca/domains/Domain_Parsing/templates/operators_template.txt create mode 100644 midca/domains/domain_creation_checklist.md diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md new file mode 100644 index 00000000..65cdfb49 --- /dev/null +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -0,0 +1,70 @@ +# Domain Creation + +### What needs to happen in MIDCA when a new domain is created. +This file should act as a master list of files that need updated when a new domain is added, not necessarily a walkthrough for new users. + +https://github.com/COLAB2/midca/wiki/How-to-add-a-new-domain +tmp: https://github.com/TonePoems/midca/blob/zohreh-minecraft-metricff/midca/domains/minecraft/PDDL_util.py +tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domains/ffdomain/minecraft + +### What needs to be created +- midca\examples\.py + - Based off of a template currently being created + - examples_template.txt + + - Needs to regex replace "" within the template with the new domain name + + - Based on + - https://github.com/COLAB2/midca/blob/master/midca/examples/nbeacons_demo.py + - https://github.com/COLAB2/midca/blob/master/midca/examples/simple_run.py + - https://github.com/COLAB2/midca/blob/master/midca/examples/chicken_run.py + + - Needs to update the README.txt in the same directory + +- midca/domains//plan/methods.py + - Based off of a template currently being created + - methods_template.txt + + - Needs to regex replace "" within the template with the new domain name + + - Based on + - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/nbeacons/plan/methods_nbeacons.py#L126 + +- midca/domains//plan/operators.py + - Based off of a template currently being created + - operators_template.txt + + - Needs to regex replace "" within the template with the new domain name + + - Based on + - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/blocksworld/plan/operators.py#L81 + +### What needs updated +- midca\setup.py + - Add domain to packages list + + - Add any new file types to package_data + +- most likely have to update all of the midca\modules with a domain specific function + # TODO: Update the module references to be domain specific functions +# Add the modules which instantiate basic operation +myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) +myMidca.append_module("Perceive", perceive.PerfectObserver()) +myMidca.append_module("Interpret", guide.UserGoalInput()) +myMidca.append_module("Eval", evaluate.SimpleEval()) +myMidca.append_module("Intend", intend.SimpleIntend()) +myMidca.append_module("Plan", planning.GenericPyhopPlanner( + DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain +myMidca.append_module("Act", act.SimpleAct()) + + + +- midca\modules\guide.py + - Goals need to come from a state file for the domain + + - Add class for goal generator + + - Can use UserGoalInput for any domain + + - Used in the examples\.py for the interpret module being appended or inserted + diff --git a/midca/domains/Domain_Parsing/templates/examples_template.txt b/midca/domains/Domain_Parsing/templates/examples_template.txt new file mode 100644 index 00000000..15854cef --- /dev/null +++ b/midca/domains/Domain_Parsing/templates/examples_template.txt @@ -0,0 +1,64 @@ +import midca +from midca import base +from midca.modules import simulator, guide, evaluate, perceive, intend, planning, act, note, assess +from midca.worldsim import domainread, stateread +import inspect, os + +# Domain Specific Imports +from midca.domains. import _util +# TODO: This will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings +from midca.domains..plan import methods_, operators_ + +''' +This template has been automatically created for your new domain, . +runs a simple version of MIDCA in a trivial domain where chickens cross the road. +''' + +# Setup +thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +MIDCA_ROOT = thisDir + "/../" + +### Domain Specific Variables +DOMAIN_ROOT = MIDCA_ROOT + "domains//" +# TODO: Next 2 lines will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings +DOMAIN_FILE = DOMAIN_ROOT + "domains/domain.sim" +STATE_FILE = DOMAIN_ROOT + "states/state.sim" +DISPLAY_FUNC = print +DECLARE_METHODS_FUNC = methods.declare_methods # TODO: add your domain methods to midca/domains//plan/methods.py +DECLARE_OPERATORS_FUNC = operators.declare_ops # TODO: add your domain operators to midca/domains//plan/operators.py + + +# Load Domain Files +world = domainread.load_domain(DOMAIN_FILE) +stateread.apply_state_file(world, STATE_FILE) + +# Creates a PhaseManager object, which wraps a MIDCA object +myMidca = base.PhaseManager(world, display = DISPLAY_FUNC, verbose=4) + +# Add phases by name +for phase in ["Simulate", "Perceive", "Interpret", "Eval", "Intend", "Plan", "Act"]: + myMidca.append_phase(phase) + + +# TODO: Update the module references to be domain specific functions +# Add the modules which instantiate basic operation +myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) +myMidca.append_module("Perceive", perceive.PerfectObserver()) +myMidca.append_module("Interpret", guide.UserGoalInput()) +myMidca.append_module("Eval", evaluate.SimpleEval()) +myMidca.append_module("Intend", intend.SimpleIntend()) +myMidca.append_module("Plan", planning.GenericPyhopPlanner( + DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain +myMidca.append_module("Act", act.SimpleAct()) + +# Set world viewer with your specified DISPLAY_FUNC +myMidca.set_display_function(DISPLAY_FUNC) + +# Tells the PhaseManager to copy and store MIDCA states so they can be accessed later. +# Note: Turning this on drastically increases MIDCA's running time. +myMidca.storeHistory = False +myMidca.mem.logEachAccess = False + +# Initialize and start running! +myMidca.init() +myMidca.run() \ No newline at end of file diff --git a/midca/domains/Domain_Parsing/templates/methods_template.txt b/midca/domains/Domain_Parsing/templates/methods_template.txt new file mode 100644 index 00000000..0c677284 --- /dev/null +++ b/midca/domains/Domain_Parsing/templates/methods_template.txt @@ -0,0 +1,158 @@ +""" +Blocks World methods for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from midca.modules._plan import pyhop + + +""" +Here are some helper functions that are used in the methods' preconditions. +""" + +def is_done(b1,state,goal): + if b1 == 'table': return True + if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: + return False + if state.pos[b1] == 'table': return True + if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): + return False + return is_done(state.pos[b1],state,goal) + +def status(b1,state,goal): + if is_done(b1,state,goal): + return 'done' + elif not (state.clear[b1] or state.pos[b1] == "in-arm"): + return 'inaccessible' + elif not (b1 in goal.pos) or goal.pos[b1] == 'table': + return 'move-to-table' + elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: + return 'move-to-block' + else: + return 'waiting' + +def all_blocks(state): + return state.clear.keys() + + +""" +In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. +""" + +### methods for "move_blocks" + +def moveb_m(state,goal): + """ + This method implements the following block-stacking algorithm: + If there's a block that can be moved to its final position, then + do so and call move_blocks recursively. Otherwise, if there's a + block that needs to be moved and can be moved to the table, then + do so and call move_blocks recursively. Otherwise, no blocks need + to be moved. + """ + for b1 in all_blocks(state): + s = status(b1,state,goal) + if s == 'move-to-table': + return [('move_one',b1,'table'),('move_blocks',goal)] + elif s == 'move-to-block': + return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] + else: + continue + # + # if we get here, no blocks can be moved to their final locations + b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) + if b1 != None: + return [('move_one',b1,'table'), ('move_blocks',goal)] + # + # if we get here, there are no blocks that need moving + return [] + +""" +declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. +""" + + +### methods for "move_one" + +def move1(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest. + """ + if state.pos[b1] == "in-arm": + return [('put', b1,dest)] + else: + return [('get', b1), ('put', b1,dest)] + +### methods for "get" + +def get_by_unstack(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack_task',b1)] + return False + +def get_by_pickup(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup_task',b1)] + return False + +### methods for "pickup_task" + +def pickup_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup',b1)] + return False + +### methods for "unstack_task" + +def unstack_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack',b1,state.pos[b1])] + return False + +### methods for "put" + +def put_m(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + if state.holding == b1: + if b2 == 'table': + return [('putdown',b1)] + else: + return [('stack',b1,b2)] + else: + return False + +def put_out_m(state, b1): + if state.fire[b1]: + return [("putoutfire", b1)] + else: + return [] + +def quick_apprehend_m(state, perp): + if state.free[perp]: + return [("apprehend", perp)] + else: + return [] + +def long_apprehend_m(state, perp): + if state.free[perp]: + return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] + else: + return [] + +def declare_methods(longApprehend = True): + if longApprehend: + pyhop.declare_methods("catch_arsonist", long_apprehend_m) + else: + pyhop.declare_methods("catch_arsonist", quick_apprehend_m) + pyhop.declare_methods("put_out", put_out_m) + pyhop.declare_methods('put',put_m) + pyhop.declare_methods('unstack_task',unstack_m) + pyhop.declare_methods('pickup_task',pickup_m) + pyhop.declare_methods('get',get_by_pickup,get_by_unstack) + pyhop.declare_methods('move_one',move1) + pyhop.declare_methods('move_blocks',moveb_m) + diff --git a/midca/domains/Domain_Parsing/templates/operators_template.txt b/midca/domains/Domain_Parsing/templates/operators_template.txt new file mode 100644 index 00000000..ddd4faba --- /dev/null +++ b/midca/domains/Domain_Parsing/templates/operators_template.txt @@ -0,0 +1,81 @@ +""" +Blocks World domain definition for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" +import sys +sys.path.append("../") +from midca.modules._plan import pyhop + +"""Each Pyhop planning operator is a Python function. The 1st argument is +the current state, and the others are the planning operator's usual arguments. +This is analogous to how methods are defined for Python classes (where +the first argument is always the name of the class instance). For example, +the function pickup(state,b) implements the planning operator for the task +('pickup', b). + +The blocks-world operators use three state variables: +- pos[b] = block b's position, which may be 'table', 'hand', or another block. +- clear[b] = False if a block is on b or the hand is holding b, else True. +- holding = name of the block being held, or False if the hand is empty. +""" + +def pickup(state,b): + if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + return state + else: return False + +def unstack(state,b,c): + if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + state.clear[c] = True + return state + else: return False + +def putdown(state,b): + if state.pos[b] == 'hand': + state.pos[b] = 'table' + state.clear[b] = True + state.holding = False + return state + else: return False + +def stack(state,b,c): + print(state.pos[b]) + print(state.clear[c]) + if state.pos[b] == 'hand' and state.clear[c] == True: + state.pos[b] = c + state.clear[b] = True + state.holding = False + state.clear[c] = False + return state + else: return False + +def putoutfire(state, b): if state.fire[b] == True: + state.fire[b] = False + return state + else: + return False + +def apprehend(state, perp): + if state.free[perp] == True: + state.free[perp] = False + return state + else: + return False + +def searchfor(state, perp): + return state + +""" +Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop +what the operators are. Note that the operator names are *not* quoted. +""" + +def declare_ops(): + pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor) diff --git a/midca/domains/domain_creation_checklist.md b/midca/domains/domain_creation_checklist.md new file mode 100644 index 00000000..e69de29b From 1196e018e785a4addd81e9b9f2ae536574de2adb Mon Sep 17 00:00:00 2001 From: Anthony Mitchell <37274918+TonePoems@users.noreply.github.com> Date: Mon, 18 May 2020 12:51:40 -0400 Subject: [PATCH 02/23] Delete domain_creation_checklist.md --- midca/domains/domain_creation_checklist.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 midca/domains/domain_creation_checklist.md diff --git a/midca/domains/domain_creation_checklist.md b/midca/domains/domain_creation_checklist.md deleted file mode 100644 index e69de29b..00000000 From 78b06c25ec5d9bbb185d10207d43ceed032b5052 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 18 May 2020 12:58:08 -0400 Subject: [PATCH 03/23] fixed .md escape char usage --- midca/domains/Domain_Parsing/domain_creation_checklist.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 65cdfb49..04bdd1b1 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -12,7 +12,7 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Based off of a template currently being created - examples_template.txt - - Needs to regex replace "" within the template with the new domain name + - Needs to regex replace within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/master/midca/examples/nbeacons_demo.py @@ -25,7 +25,7 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Based off of a template currently being created - methods_template.txt - - Needs to regex replace "" within the template with the new domain name + - Needs to regex replace within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/nbeacons/plan/methods_nbeacons.py#L126 @@ -34,7 +34,7 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Based off of a template currently being created - operators_template.txt - - Needs to regex replace "" within the template with the new domain name + - Needs to regex replace within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/blocksworld/plan/operators.py#L81 @@ -46,7 +46,7 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Add any new file types to package_data - most likely have to update all of the midca\modules with a domain specific function - # TODO: Update the module references to be domain specific functions +TODO: Update the module references to be domain specific functions # Add the modules which instantiate basic operation myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) myMidca.append_module("Perceive", perceive.PerfectObserver()) From 17b9bc0861da9c1a503a5ba80117e05819f7fb77 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 18 May 2020 13:13:35 -0400 Subject: [PATCH 04/23] fixed readability with codeblocks --- .../Domain_Parsing/domain_creation_checklist.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 04bdd1b1..d66d1b72 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -12,7 +12,7 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Based off of a template currently being created - examples_template.txt - - Needs to regex replace within the template with the new domain name + - Needs to regex replace "\" within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/master/midca/examples/nbeacons_demo.py @@ -21,20 +21,20 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Needs to update the README.txt in the same directory -- midca/domains//plan/methods.py +- midca/domains/\/plan/methods.py - Based off of a template currently being created - methods_template.txt - - Needs to regex replace within the template with the new domain name + - Needs to regex replace "\" within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/nbeacons/plan/methods_nbeacons.py#L126 -- midca/domains//plan/operators.py +- midca/domains/\/plan/operators.py - Based off of a template currently being created - operators_template.txt - - Needs to regex replace within the template with the new domain name + - Needs to regex replace "\" within the template with the new domain name - Based on - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/blocksworld/plan/operators.py#L81 @@ -46,7 +46,8 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Add any new file types to package_data - most likely have to update all of the midca\modules with a domain specific function -TODO: Update the module references to be domain specific functions +``` +# TODO: Update the module references to be domain specific functions # Add the modules which instantiate basic operation myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) myMidca.append_module("Perceive", perceive.PerfectObserver()) @@ -56,6 +57,7 @@ myMidca.append_module("Intend", intend.SimpleIntend()) myMidca.append_module("Plan", planning.GenericPyhopPlanner( DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain myMidca.append_module("Act", act.SimpleAct()) +``` From 1723e853974ede2a4b8677123822e406c9612eb1 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 18 May 2020 13:16:03 -0400 Subject: [PATCH 05/23] fixed readability with codeblocks --- midca/domains/Domain_Parsing/domain_creation_checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index d66d1b72..2359129a 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -8,7 +8,7 @@ tmp: https://github.com/TonePoems/midca/blob/zohreh-minecraft-metricff/midca/dom tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domains/ffdomain/minecraft ### What needs to be created -- midca\examples\.py +- midca/examples/\.py - Based off of a template currently being created - examples_template.txt From 427120b56fda15ef4d18c1898ba95298ad3c2ffe Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 20 May 2020 11:46:49 -0400 Subject: [PATCH 06/23] set up links for midca modules --- .../domain_creation_checklist.md | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 2359129a..5982f4a1 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -40,12 +40,12 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/blocksworld/plan/operators.py#L81 ### What needs updated -- midca\setup.py +- [midca/setup.py](https://github.com/TonePoems/midca/blob/master/setup.py) - Add domain to packages list - Add any new file types to package_data -- most likely have to update all of the midca\modules with a domain specific function +- Midca/modules with domain specific functions ``` # TODO: Update the module references to be domain specific functions # Add the modules which instantiate basic operation @@ -59,14 +59,29 @@ myMidca.append_module("Plan", planning.GenericPyhopPlanner( myMidca.append_module("Act", act.SimpleAct()) ``` + - [midca/modules/simulator.py](https://github.com/TonePoems/midca/blob/master/midca/modules/simulator.py) + - + - [midca/modules/perceive.py](https://github.com/TonePoems/midca/blob/master/midca/modules/perceive.py) + - -- midca\modules\guide.py - - Goals need to come from a state file for the domain + - [midca/modules/guide.py](https://github.com/TonePoems/midca/blob/master/midca/modules/guide.py) + - Goals need to come from a state file for the domain - - Add class for goal generator - - - Can use UserGoalInput for any domain - - - Used in the examples\.py for the interpret module being appended or inserted + - Add class for goal generator + + - Can use UserGoalInput for any domain + + - Used in the examples/\.py for the interpret module being appended or inserted + + - [midca/modules/evaluate.py](https://github.com/TonePoems/midca/blob/master/midca/modules/evaluate.py) + - + + - [midca/modules/intend.py](https://github.com/TonePoems/midca/blob/master/midca/modules/intend.py) + - + + - [midca/modules/planning.py](https://github.com/TonePoems/midca/blob/master/midca/modules/planning.py) + - + - [midca/modules/act.py](https://github.com/TonePoems/midca/blob/master/midca/modules/act.py) + - From d2cbd9efbf4344289e52c0bc75865bac5812f120 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 20 May 2020 11:52:38 -0400 Subject: [PATCH 07/23] fixed tab spacing for links --- .../domain_creation_checklist.md | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 5982f4a1..0f1c86e8 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -46,26 +46,26 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Add any new file types to package_data - Midca/modules with domain specific functions -``` -# TODO: Update the module references to be domain specific functions -# Add the modules which instantiate basic operation -myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) -myMidca.append_module("Perceive", perceive.PerfectObserver()) -myMidca.append_module("Interpret", guide.UserGoalInput()) -myMidca.append_module("Eval", evaluate.SimpleEval()) -myMidca.append_module("Intend", intend.SimpleIntend()) -myMidca.append_module("Plan", planning.GenericPyhopPlanner( - DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain -myMidca.append_module("Act", act.SimpleAct()) -``` + ``` + # TODO: Update the module references to be domain specific functions + # Add the modules which instantiate basic operation + myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) + myMidca.append_module("Perceive", perceive.PerfectObserver()) + myMidca.append_module("Interpret", guide.UserGoalInput()) + myMidca.append_module("Eval", evaluate.SimpleEval()) + myMidca.append_module("Intend", intend.SimpleIntend()) + myMidca.append_module("Plan", planning.GenericPyhopPlanner( + DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain + myMidca.append_module("Act", act.SimpleAct()) + ``` - - [midca/modules/simulator.py](https://github.com/TonePoems/midca/blob/master/midca/modules/simulator.py) + - [midca/modules/simulator.py](https://github.com/TonePoems/midca/blob/master/midca/modules/simulator.py) - - - [midca/modules/perceive.py](https://github.com/TonePoems/midca/blob/master/midca/modules/perceive.py) + - [midca/modules/perceive.py](https://github.com/TonePoems/midca/blob/master/midca/modules/perceive.py) - - - [midca/modules/guide.py](https://github.com/TonePoems/midca/blob/master/midca/modules/guide.py) + - [midca/modules/guide.py](https://github.com/TonePoems/midca/blob/master/midca/modules/guide.py) - Goals need to come from a state file for the domain - Add class for goal generator @@ -74,14 +74,14 @@ myMidca.append_module("Act", act.SimpleAct()) - Used in the examples/\.py for the interpret module being appended or inserted - - [midca/modules/evaluate.py](https://github.com/TonePoems/midca/blob/master/midca/modules/evaluate.py) + - [midca/modules/evaluate.py](https://github.com/TonePoems/midca/blob/master/midca/modules/evaluate.py) - - - [midca/modules/intend.py](https://github.com/TonePoems/midca/blob/master/midca/modules/intend.py) + - [midca/modules/intend.py](https://github.com/TonePoems/midca/blob/master/midca/modules/intend.py) - - - [midca/modules/planning.py](https://github.com/TonePoems/midca/blob/master/midca/modules/planning.py) + - [midca/modules/planning.py](https://github.com/TonePoems/midca/blob/master/midca/modules/planning.py) - - - [midca/modules/act.py](https://github.com/TonePoems/midca/blob/master/midca/modules/act.py) + - [midca/modules/act.py](https://github.com/TonePoems/midca/blob/master/midca/modules/act.py) - From 510cc30c74237cf475e9b03a4121a13162177375 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Fri, 29 May 2020 11:47:29 -0400 Subject: [PATCH 08/23] start of newDomainScript --- .../domain_creation_checklist.md | 36 ++++- midca/domains/New_Domain_Script.py | 150 ++++++++++++++++++ 2 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 midca/domains/New_Domain_Script.py diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 0f1c86e8..7bbb4e08 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -1,5 +1,8 @@ # Domain Creation +The script has been started and is called New_Domain_Script.py and is found in midca/domains +(C:\Users\Anthony\Anaconda3\python.exe New_Domain_Script.py minecraft/minecraft.pddl) + ### What needs to happen in MIDCA when a new domain is created. This file should act as a master list of files that need updated when a new domain is added, not necessarily a walkthrough for new users. @@ -8,6 +11,9 @@ tmp: https://github.com/TonePoems/midca/blob/zohreh-minecraft-metricff/midca/dom tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domains/ffdomain/minecraft ### What needs to be created +- midca/domains/\/init.py + -blank file needed for MIDCA + - midca/examples/\.py - Based off of a template currently being created - examples_template.txt @@ -21,6 +27,15 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Needs to update the README.txt in the same directory +- midca/domains/\/\.sim + - Created by the PDDL_util.py function from Zoreh + +- midca/domains/\/util.py + - Based off of a template currently being created + - util_template.txt + + - Needs to regex replace "\" within the template with the new domain name + - midca/domains/\/plan/methods.py - Based off of a template currently being created - methods_template.txt @@ -60,28 +75,37 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain ``` - [midca/modules/simulator.py](https://github.com/TonePoems/midca/blob/master/midca/modules/simulator.py) - - - - - [midca/modules/perceive.py](https://github.com/TonePoems/midca/blob/master/midca/modules/perceive.py) - - + - simulator_template.txt will be added to the .py file + + - Reference by `myMidca.append_module("Simulate", simulator.Simulator())` in midca/examples/\.py - [midca/modules/guide.py](https://github.com/TonePoems/midca/blob/master/midca/modules/guide.py) + - + + - Reference by `myMidca.append_module("Interpret", guide.Goal())` in midca/examples/\.py + - Goals need to come from a state file for the domain - Add class for goal generator - Can use UserGoalInput for any domain - - - Used in the examples/\.py for the interpret module being appended or inserted - [midca/modules/evaluate.py](https://github.com/TonePoems/midca/blob/master/midca/modules/evaluate.py) - + + - Reference by `myMidca.append_module("Eval", evaluate.Eval())` in midca/examples/\.py - [midca/modules/intend.py](https://github.com/TonePoems/midca/blob/master/midca/modules/intend.py) - + + - Reference by `myMidca.append_module("Intend", intend.Intend())` in midca/examples/\.py - [midca/modules/planning.py](https://github.com/TonePoems/midca/blob/master/midca/modules/planning.py) - + + - Reference by `myMidca.append_module("Plan", planning.GenericPyhopPlanner(DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC))` in midca/examples/\.py - [midca/modules/act.py](https://github.com/TonePoems/midca/blob/master/midca/modules/act.py) - + + - Reference by `myMidca.append_module("Act", act.Act())` in midca/examples/\.py diff --git a/midca/domains/New_Domain_Script.py b/midca/domains/New_Domain_Script.py new file mode 100644 index 00000000..05d690ad --- /dev/null +++ b/midca/domains/New_Domain_Script.py @@ -0,0 +1,150 @@ +''' +This is the start of the script for users to easily create domains from their .PDDL files +Based on the file PDDL_util.py from Zoreh +''' + +import sys +import inspect +import shutil # copy file +import os +import re + +# Setup for directory navigation +newDomainName = "" +thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +MIDCA_ROOT = thisDir + "/../" +newDirectoryRoot = "" + + +# Parsing function for PDDL to .sim +def outermost_parentheses(input): + return re.search("\((.*)\)", input).group(1) + + +# Parsing function for PDDL to .sim +def parenthetic_contents(string): + """Generate parenthesized contents in string as pairs (level, contents).""" + stack = [] + for i, c in enumerate(string): + if c == '(': + stack.append(i) + elif c == ')' and stack: + start = stack.pop() + yield (len(stack), string[start + 1: i]) + + +# Parsing function for PDDL to .sim +def PDDL_to_MIDCA_DOMAIN(pddl_file, midca_file): + file = open(pddl_file, "r") + pddl = file.read() + + elements = list(parenthetic_contents(pddl)) + f = open(midca_file, 'w') + + for (d, elm) in elements: + if (elm.startswith(":types")): + lines = elm.split("\n") + for line in lines[1:]: + if line.strip() != "": + f.write("type(" + line.split("-")[0].strip() + ")\n") + + if (elm.startswith(":predicates")): + + lines = parenthetic_contents(elm) + for (l, line) in lines: + objs = "" + types = "" + pairs = line.split("?") + f.write("\n predicate(" + pairs[0].strip() + ",") + for pair in pairs[1:]: + obj_type = pair.split("-") + objs = objs + "," + obj_type[0].strip() + types = types + "," + obj_type[1].strip() + + f.write("[" + objs[1:].strip() + "], [" + types[1:].strip() + "])") + + if (elm.startswith(":action")): + f.write("\n operator (") + lines = elm.split(":") + action_name = lines[1].split(" ")[1] + f.write(action_name + ",") + for line in lines[2:]: + if line.startswith("parameters"): + parameters = outermost_parentheses(line).split("?")[1:] + # print(parameters) + p = "" + for parameter in parameters: + obj_type = parameter.split("-") + p = p + ", (" + obj_type[0].strip() + "," + obj_type[1].strip() + " )" + + p = p[1:] + f.write("args = [" + p.strip() + "],") + # print("args = [" + p.strip() + "],") + + if line.startswith("precondition"): + f.write("preconditions = [") + precondition = list(parenthetic_contents(line)) + for (l, pre) in precondition: + precon = "" + if l == 1: + # (player-at ?target) + condition = pre.split(" ") + f.write("condition(" + condition[0].strip()) + for c in condition[1:]: + precon = precon + ", " + c.strip() + + f.write(" [" + precon[1:].strip() + "]),\n") + f.write("],") + if line.startswith("effect"): + f.write("results=[") + effect = list(parenthetic_contents(line)) + for (l, pre) in effect: + precon = "" + if l == 1: + # (player-at ?target) + condition = pre.split(" ") + f.write("condition(" + condition[0].strip() + ",") + for c in condition[1:]: + precon = precon + ", " + c.strip() + + f.write(" [" + precon[1:].strip() + "]),\n") + f.write("])") + + +# Function for creating __init__.py files at the specified directory +def create_init(location): + # create an empty __init__.py file at the specified directory + f = open(location + "/__init__.py", "w") + + +# Function for creating the runnable file in the examples folder and update the readme +def update_examples_directory(): + # uses the example_template.txt + shutil.copy(thisDir + "/Domain_Parsing/templates/examples_template.txt", + MIDCA_ROOT + "/examples/" + newDomainName + "_run.py") + + # TODO: regex replace "" within the template with the new domain name + # print("New Domain Name: " + newDomainName) + + +# Function regex replaces "" within the file specified with the new domain name +def regex_filename(file): + pass + + +if __name__ == "__main__": + # get /.pddl file to convert and pull the domain name from + PDDL_file = sys.argv[1] + newDomainName = re.split('/', PDDL_file)[0] # TODO: get domain name with either / or \ file scheme, only does / + + newDirectoryRoot = thisDir + "/" + newDomainName + + if not os.path.exists(newDirectoryRoot + "/problems"): + os.makedirs(newDirectoryRoot + "/problems") # create the new problems sub-directory + + create_init(newDirectoryRoot) # create the empty __init__.py file needed in the new domain directory + update_examples_directory() + + # TODO: pass the .ppdl filename to the function to open the correct one + # TODO: reopen the below function call + PDDL_to_MIDCA_DOMAIN(PDDL_file, newDirectoryRoot + "/" + newDomainName + ".sim") From 34db8f236fb587ae1a165b7f3c333bd0ec192d2d Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Thu, 1 Oct 2020 21:12:31 -0400 Subject: [PATCH 09/23] Stashed for testing Zohrehs domain --- .../Domain_Parsing/domain_creation_checklist.md | 17 ----------------- .../templates/examples_template.txt | 1 - 2 files changed, 18 deletions(-) diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 7bbb4e08..4eb5acf8 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -36,23 +36,6 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - Needs to regex replace "\" within the template with the new domain name -- midca/domains/\/plan/methods.py - - Based off of a template currently being created - - methods_template.txt - - - Needs to regex replace "\" within the template with the new domain name - - - Based on - - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/nbeacons/plan/methods_nbeacons.py#L126 - -- midca/domains/\/plan/operators.py - - Based off of a template currently being created - - operators_template.txt - - - Needs to regex replace "\" within the template with the new domain name - - - Based on - - https://github.com/COLAB2/midca/blob/931a0430f72083227f952e0cb57f445c15e51548/midca/domains/blocksworld/plan/operators.py#L81 ### What needs updated - [midca/setup.py](https://github.com/TonePoems/midca/blob/master/setup.py) diff --git a/midca/domains/Domain_Parsing/templates/examples_template.txt b/midca/domains/Domain_Parsing/templates/examples_template.txt index 15854cef..892196a8 100644 --- a/midca/domains/Domain_Parsing/templates/examples_template.txt +++ b/midca/domains/Domain_Parsing/templates/examples_template.txt @@ -11,7 +11,6 @@ from midca.domains..plan import methods_, operators_. -runs a simple version of MIDCA in a trivial domain where chickens cross the road. ''' # Setup From 0b65dbaa72174c6145336985abcef612279b335f Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 30 Nov 2020 16:46:12 -0500 Subject: [PATCH 10/23] Move to working with language for domain hierarchy --- .../domain_creation_checklist.md | 76 +---- .../templates/examples_template.txt | 63 ---- midca/domains/New_Domain_Script.py | 48 +-- midca/domains/Object_Hierarchy_Tree.py | 148 +++++++++ midca/domains/blocksworld_Updated/__init__.py | 0 .../domains/blocksworld_Updated/arsonist.sim | 95 ++++++ midca/domains/blocksworld_Updated/block.py | 47 +++ .../domains/blocksworld_Updated/blockstate.py | 46 +++ .../blocksworld_Updated/plan/__init__.py | 0 .../plan/blocks_world_mortar_examples.py | 300 ++++++++++++++++++ .../plan/bw_ran_problems_5.shp | 10 + .../plan/methods.py} | 0 .../plan/methods_broken.py | 157 +++++++++ .../plan/methods_extinguish.py | 169 ++++++++++ .../blocksworld_Updated/plan/methods_midca.py | 179 +++++++++++ .../plan/methods_mortar.py | 220 +++++++++++++ .../plan/operators.py} | 3 +- .../plan/operators_extinguish.py | 95 ++++++ .../plan/operators_midca.py | 83 +++++ .../plan/operators_mortar.py | 115 +++++++ .../plan/sample_methods.py | 82 +++++ .../plan/sample_operators.py | 24 ++ midca/domains/blocksworld_Updated/scene.py | 111 +++++++ .../states/blocksworld.shp | 107 +++++++ .../states/bw_ran_problems_5.shp | 12 + .../blocksworld_Updated/states/defstate.sim | 26 ++ .../states/defstate_fire.sim | 27 ++ .../defstate_fire_pyhop_inducing_bug.sim | 24 ++ .../states/defstate_jshop.sim | 26 ++ .../states/defstate_mortar.sim | 26 ++ .../states/extinguisher_state.sim | 26 ++ .../states/sample_state.sim | 20 ++ midca/domains/blocksworld_Updated/util.py | 292 +++++++++++++++++ .../blocks_world/bw_ran_problems_5.shp | 4 +- midca/domains/minecraft.pddl | 180 +++++++++++ midca/domains/minecraft/__init__.py | 0 midca/domains/minecraft/minecraft.sim | 87 +++++ midca/domains/split1.txt | 12 + midca/domains/split2.txt | 6 + midca/domains/test.txt | 11 + midca/domains/test2.txt | 10 + 41 files changed, 2811 insertions(+), 156 deletions(-) delete mode 100644 midca/domains/Domain_Parsing/templates/examples_template.txt create mode 100644 midca/domains/Object_Hierarchy_Tree.py create mode 100644 midca/domains/blocksworld_Updated/__init__.py create mode 100644 midca/domains/blocksworld_Updated/arsonist.sim create mode 100644 midca/domains/blocksworld_Updated/block.py create mode 100644 midca/domains/blocksworld_Updated/blockstate.py create mode 100644 midca/domains/blocksworld_Updated/plan/__init__.py create mode 100644 midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py create mode 100644 midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp rename midca/domains/{Domain_Parsing/templates/methods_template.txt => blocksworld_Updated/plan/methods.py} (100%) create mode 100644 midca/domains/blocksworld_Updated/plan/methods_broken.py create mode 100644 midca/domains/blocksworld_Updated/plan/methods_extinguish.py create mode 100644 midca/domains/blocksworld_Updated/plan/methods_midca.py create mode 100644 midca/domains/blocksworld_Updated/plan/methods_mortar.py rename midca/domains/{Domain_Parsing/templates/operators_template.txt => blocksworld_Updated/plan/operators.py} (97%) create mode 100644 midca/domains/blocksworld_Updated/plan/operators_extinguish.py create mode 100644 midca/domains/blocksworld_Updated/plan/operators_midca.py create mode 100644 midca/domains/blocksworld_Updated/plan/operators_mortar.py create mode 100644 midca/domains/blocksworld_Updated/plan/sample_methods.py create mode 100644 midca/domains/blocksworld_Updated/plan/sample_operators.py create mode 100644 midca/domains/blocksworld_Updated/scene.py create mode 100644 midca/domains/blocksworld_Updated/states/blocksworld.shp create mode 100644 midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp create mode 100644 midca/domains/blocksworld_Updated/states/defstate.sim create mode 100644 midca/domains/blocksworld_Updated/states/defstate_fire.sim create mode 100644 midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim create mode 100644 midca/domains/blocksworld_Updated/states/defstate_jshop.sim create mode 100644 midca/domains/blocksworld_Updated/states/defstate_mortar.sim create mode 100644 midca/domains/blocksworld_Updated/states/extinguisher_state.sim create mode 100644 midca/domains/blocksworld_Updated/states/sample_state.sim create mode 100644 midca/domains/blocksworld_Updated/util.py create mode 100644 midca/domains/minecraft.pddl create mode 100644 midca/domains/minecraft/__init__.py create mode 100644 midca/domains/minecraft/minecraft.sim create mode 100644 midca/domains/split1.txt create mode 100644 midca/domains/split2.txt create mode 100644 midca/domains/test.txt create mode 100644 midca/domains/test2.txt diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md index 4eb5acf8..65244284 100644 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ b/midca/domains/Domain_Parsing/domain_creation_checklist.md @@ -14,81 +14,15 @@ tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domain - midca/domains/\/init.py -blank file needed for MIDCA -- midca/examples/\.py - - Based off of a template currently being created - - examples_template.txt - - - Needs to regex replace "\" within the template with the new domain name - - - Based on - - https://github.com/COLAB2/midca/blob/master/midca/examples/nbeacons_demo.py - - https://github.com/COLAB2/midca/blob/master/midca/examples/simple_run.py - - https://github.com/COLAB2/midca/blob/master/midca/examples/chicken_run.py - - - Needs to update the README.txt in the same directory - - midca/domains/\/\.sim - Created by the PDDL_util.py function from Zoreh -- midca/domains/\/util.py - - Based off of a template currently being created - - util_template.txt - - - Needs to regex replace "\" within the template with the new domain name - ### What needs updated - [midca/setup.py](https://github.com/TonePoems/midca/blob/master/setup.py) - Add domain to packages list - - - Add any new file types to package_data - -- Midca/modules with domain specific functions - ``` - # TODO: Update the module references to be domain specific functions - # Add the modules which instantiate basic operation - myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) - myMidca.append_module("Perceive", perceive.PerfectObserver()) - myMidca.append_module("Interpret", guide.UserGoalInput()) - myMidca.append_module("Eval", evaluate.SimpleEval()) - myMidca.append_module("Intend", intend.SimpleIntend()) - myMidca.append_module("Plan", planning.GenericPyhopPlanner( - DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain - myMidca.append_module("Act", act.SimpleAct()) - ``` - - - [midca/modules/simulator.py](https://github.com/TonePoems/midca/blob/master/midca/modules/simulator.py) - - simulator_template.txt will be added to the .py file - - - Reference by `myMidca.append_module("Simulate", simulator.Simulator())` in midca/examples/\.py - - - [midca/modules/guide.py](https://github.com/TonePoems/midca/blob/master/midca/modules/guide.py) - - - - - Reference by `myMidca.append_module("Interpret", guide.Goal())` in midca/examples/\.py - - - Goals need to come from a state file for the domain - - - Add class for goal generator - - - Can use UserGoalInput for any domain - - - [midca/modules/evaluate.py](https://github.com/TonePoems/midca/blob/master/midca/modules/evaluate.py) - - - - - Reference by `myMidca.append_module("Eval", evaluate.Eval())` in midca/examples/\.py - - - [midca/modules/intend.py](https://github.com/TonePoems/midca/blob/master/midca/modules/intend.py) - - - - - Reference by `myMidca.append_module("Intend", intend.Intend())` in midca/examples/\.py - - - [midca/modules/planning.py](https://github.com/TonePoems/midca/blob/master/midca/modules/planning.py) - - - - - Reference by `myMidca.append_module("Plan", planning.GenericPyhopPlanner(DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC))` in midca/examples/\.py - - - [midca/modules/act.py](https://github.com/TonePoems/midca/blob/master/midca/modules/act.py) - - - - - Reference by `myMidca.append_module("Act", act.Act())` in midca/examples/\.py + -Insert domain below + ```python + packages=['midca', + 'midca.domains'," + ``` \ No newline at end of file diff --git a/midca/domains/Domain_Parsing/templates/examples_template.txt b/midca/domains/Domain_Parsing/templates/examples_template.txt deleted file mode 100644 index 892196a8..00000000 --- a/midca/domains/Domain_Parsing/templates/examples_template.txt +++ /dev/null @@ -1,63 +0,0 @@ -import midca -from midca import base -from midca.modules import simulator, guide, evaluate, perceive, intend, planning, act, note, assess -from midca.worldsim import domainread, stateread -import inspect, os - -# Domain Specific Imports -from midca.domains. import _util -# TODO: This will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings -from midca.domains..plan import methods_, operators_ - -''' -This template has been automatically created for your new domain, . -''' - -# Setup -thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -MIDCA_ROOT = thisDir + "/../" - -### Domain Specific Variables -DOMAIN_ROOT = MIDCA_ROOT + "domains//" -# TODO: Next 2 lines will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings -DOMAIN_FILE = DOMAIN_ROOT + "domains/domain.sim" -STATE_FILE = DOMAIN_ROOT + "states/state.sim" -DISPLAY_FUNC = print -DECLARE_METHODS_FUNC = methods.declare_methods # TODO: add your domain methods to midca/domains//plan/methods.py -DECLARE_OPERATORS_FUNC = operators.declare_ops # TODO: add your domain operators to midca/domains//plan/operators.py - - -# Load Domain Files -world = domainread.load_domain(DOMAIN_FILE) -stateread.apply_state_file(world, STATE_FILE) - -# Creates a PhaseManager object, which wraps a MIDCA object -myMidca = base.PhaseManager(world, display = DISPLAY_FUNC, verbose=4) - -# Add phases by name -for phase in ["Simulate", "Perceive", "Interpret", "Eval", "Intend", "Plan", "Act"]: - myMidca.append_phase(phase) - - -# TODO: Update the module references to be domain specific functions -# Add the modules which instantiate basic operation -myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) -myMidca.append_module("Perceive", perceive.PerfectObserver()) -myMidca.append_module("Interpret", guide.UserGoalInput()) -myMidca.append_module("Eval", evaluate.SimpleEval()) -myMidca.append_module("Intend", intend.SimpleIntend()) -myMidca.append_module("Plan", planning.GenericPyhopPlanner( - DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain -myMidca.append_module("Act", act.SimpleAct()) - -# Set world viewer with your specified DISPLAY_FUNC -myMidca.set_display_function(DISPLAY_FUNC) - -# Tells the PhaseManager to copy and store MIDCA states so they can be accessed later. -# Note: Turning this on drastically increases MIDCA's running time. -myMidca.storeHistory = False -myMidca.mem.logEachAccess = False - -# Initialize and start running! -myMidca.init() -myMidca.run() \ No newline at end of file diff --git a/midca/domains/New_Domain_Script.py b/midca/domains/New_Domain_Script.py index 05d690ad..95e8ed5e 100644 --- a/midca/domains/New_Domain_Script.py +++ b/midca/domains/New_Domain_Script.py @@ -3,16 +3,20 @@ Based on the file PDDL_util.py from Zoreh ''' +from __future__ import print_function import sys import inspect import shutil # copy file import os import re +import argparse +import fileinput # supports inplace editing + # Setup for directory navigation newDomainName = "" thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -MIDCA_ROOT = thisDir + "/../" +MIDCA_ROOT = thisDir + "/../../" newDirectoryRoot = "" @@ -117,34 +121,42 @@ def create_init(location): f = open(location + "/__init__.py", "w") -# Function for creating the runnable file in the examples folder and update the readme -def update_examples_directory(): - # uses the example_template.txt - shutil.copy(thisDir + "/Domain_Parsing/templates/examples_template.txt", - MIDCA_ROOT + "/examples/" + newDomainName + "_run.py") - - # TODO: regex replace "" within the template with the new domain name - # print("New Domain Name: " + newDomainName) +# Function regex replaces "" within the file specified with the new domain name +def regex_filename(filename): + file = fileinput.FileInput(filename, inplace=True) + for line in file: + print(line.replace('', newDomainName), end='') -# Function regex replaces "" within the file specified with the new domain name -def regex_filename(file): - pass + file.close() if __name__ == "__main__": - # get /.pddl file to convert and pull the domain name from - PDDL_file = sys.argv[1] - newDomainName = re.split('/', PDDL_file)[0] # TODO: get domain name with either / or \ file scheme, only does / + # manage args + parser = argparse.ArgumentParser() + parser.add_argument("domain", help="name of new domain") + parser.add_argument("pddl", help="name of .pddl file to create domain with") + + # get and validate args + args = parser.parse_args() + newDomainName = args.domain + pddl_file = args.pddl + if not pddl_file.endswith('.pddl'): # ensure pddl_file name includes '.pddl' + pddl_file = pddl_file + '.pddl' newDirectoryRoot = thisDir + "/" + newDomainName + + # create desired directory structure + if not os.path.exists(newDirectoryRoot): + os.makedirs(newDirectoryRoot) # create the new domain directory + + if not os.path.exists(newDirectoryRoot + "/plan"): + os.makedirs(newDirectoryRoot + "/plan") # create the new plan sub-directory if not os.path.exists(newDirectoryRoot + "/problems"): os.makedirs(newDirectoryRoot + "/problems") # create the new problems sub-directory create_init(newDirectoryRoot) # create the empty __init__.py file needed in the new domain directory - update_examples_directory() # TODO: pass the .ppdl filename to the function to open the correct one - # TODO: reopen the below function call - PDDL_to_MIDCA_DOMAIN(PDDL_file, newDirectoryRoot + "/" + newDomainName + ".sim") + PDDL_to_MIDCA_DOMAIN(pddl_file, newDirectoryRoot + "/" + newDomainName + ".sim") diff --git a/midca/domains/Object_Hierarchy_Tree.py b/midca/domains/Object_Hierarchy_Tree.py new file mode 100644 index 00000000..18e78c87 --- /dev/null +++ b/midca/domains/Object_Hierarchy_Tree.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# coding: utf-8 + +# In[ ]: + + +#MIDCA API +# Created August 2019 by Danielle Brown via CoLab2 +#Reads in a file of the format specification,object2,object1 +#Specification can be a type, i.e. a spoon (object2) is a utensil (object1) +#or specification can be an attribute, i.e., a utensil (object2) can be a color (object1) +#Requirement: Be able to take in input and add it to the object hierarchy tree +#Requirement: Act as an interface between ros and MIDCA for objects + +#To Do still: +# #Ideas from meeting with Mike Cox and Sampath Gogineni on 10/8/2019 +#Detector -> type, xblock, isablock +#then it is passed to MIDCA from interface +#All objects have types and possibly attributes. Attributes have values (ie type color has values +#green, red, etc) +#uniform naming via the type system and simple attributes +#Each action has a piece of code to handle and determine when its over +#define predicate formulation +#Be Able to ultimately define a new domain +# detect object types, what are predicates in domain, do actions, when is action done, and +# naming of objects and handling of attributes +# Naming -> type + unique identifier, decrement unique identifier if item disappears so +# block2 doesn't become block3 when it reappears + +#robot -> be able to list objects, then the robot detects objects, and can click to assign objects? + +#TODO: Attribute and AttributeValue need to be separate things + +import sys +import csv +import fileinput #for command line file name + +from collections import defaultdict + +directedGraph = defaultdict(list) +attributesAndValues = defaultdict(list) +enumerationList = [] + +#Adds node to the directedGraph +def addEdge(directedGraph, u, v): + directedGraph[u].append(v) + +#Adds the directional relationship between objects +def generate_edges(directedGraph): + edges = [] + # for each node in directedGraph + for node in directedGraph: + # for each relation node of a single node + for relation in directedGraph[node]: + # if edge exists then append + edges.append((node, relation)) + return edges + + +#box object class +def blockShape(self): + return 0 + +#Plate object class +def plateShape(self): + return 0 + +#fork object class +def forkShape(self): + return 0 + +#spoon object class +def spoonShape(self): + return 0 + +#function that prints out the enumeration list of attributes with index values +def printEnumerationList(enumerationList): + for idx, (object, attribute) in enumerate(enumerationList): + print("index is %d, name is %s, and attribute is %s" + % (idx, object, attribute)) + +#main function that reads in a file of data and creates a directed tree of types +#and directed tree of attributes as well as an enumeration list of attributes +def objectInput(directedGraph, enumerationList, newFile2): + index = 0 + #create directed graph tree off of information provided in document + #newFile2 = open('test.txt') + fileText2 = csv.reader(newFile2, delimiter = ',') + for row in fileText2: + #if it is a type it is added to the type tree + if row[0] == "type": + directedGraph[row[2]].insert(index, row[1]) + index += 1 + #if it is an attribute, then it addes it to the attribute tree + #and enumeration list + elif row[0] == "attribute": + attributesAndValues[row[1]].insert(index, row[2]) + tempTupple = (row[2], row[1]) + enumerationList.append(tempTupple) + + #newFile2.close() + + +def printPDDL(directedGraph): + # print PDDL types + print('\t(:types') + for node in directedGraph: + #print('' + node) + + for relation in directedGraph[node]: + print('\t ' + relation + ' -' + node) + + print('\t)\n') + + +# prints tree with DFS +def printTree(directedGraph, node): + visited = set() # Set to keep track of visited nodes. + + dfs(visited, directedGraph, node, 0) + +def dfs(visited, graph, node, depth): + if node not in visited: + print('\t' * depth + '+-- ' + node) + visited.add(node) + for neighbour in graph[node]: + dfs(visited, graph, neighbour, depth + 1) + + + + +objectInput(directedGraph, enumerationList, fileinput.input()) #fileinput.input() is for passed cmd line files + +# print generated trees and edges +#print("Edges of type tree: " + str(generate_edges(directedGraph))) +#print ("Type Tree: " + (str)(directedGraph)) +#print("Edges of attribute tree: " + str (generate_edges(attributesAndValues))) +stringAttributeAndValues = (str)(attributesAndValues) +#print ("Attribute Tree: " + stringAttributeAndValues) +#printEnumerationList(enumerationList) + +# test type values from input +printPDDL(directedGraph) + + +#API ENFORCES ENTITY PARENT +printTree(directedGraph, 'entity') + diff --git a/midca/domains/blocksworld_Updated/__init__.py b/midca/domains/blocksworld_Updated/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/midca/domains/blocksworld_Updated/arsonist.sim b/midca/domains/blocksworld_Updated/arsonist.sim new file mode 100644 index 00000000..dd1f6fa3 --- /dev/null +++ b/midca/domains/blocksworld_Updated/arsonist.sim @@ -0,0 +1,95 @@ + +type(BLOCK) +type(ARSONIST) + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(hasmortar, [blk], [BLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/block.py b/midca/domains/blocksworld_Updated/block.py new file mode 100644 index 00000000..143a1f68 --- /dev/null +++ b/midca/domains/blocksworld_Updated/block.py @@ -0,0 +1,47 @@ + +# single block, a square, a triangle, or a table. These are the blocks of which +# scenes are composed. +# Possible predicates involving blocks: +# -square(x) +# -triangle(x) +# -table(x) +# -clear(x) +# -on(x,y) +class Block: + SQUARE = 1 # constant + TRIANGLE = 2 + TABLE = 3 + + def __init__(self, type, id): + self.type = type + self.id = id + self.on = None + self.clear = True + self.onfire = False + + # place self block onto onto block + def place(self, onto): + if self.on: + self.on.clear() + self.on = onto + self.on.unclear() + + # set the block to not clear + def unclear(self): + self.isclear = False + + # set the block to clear + def clear(self): + self.isclear = True + + def __str__(self): + return self.id + + def __hash__(self): + return hash(self.id) + + def __eq__(self, other): + try: + return self.id == other.id + except Exception: + return False diff --git a/midca/domains/blocksworld_Updated/blockstate.py b/midca/domains/blocksworld_Updated/blockstate.py new file mode 100644 index 00000000..d14cd3c5 --- /dev/null +++ b/midca/domains/blocksworld_Updated/blockstate.py @@ -0,0 +1,46 @@ +from midca.domains.blocksworld.block import Block +from midca.worldsim import worldsim + +def b(name): + return "b" + str(name) + +def get_block_list(world): + blocks = {} + for obj in world.objects.values(): + if obj.type.name != "BLOCK": + continue + block = None + if world.atom_true(worldsim.Atom(world.predicates["table"], [obj])): + block = Block(Block.TABLE, obj.name) + elif world.atom_true(worldsim.Atom(world.predicates["triangle"], [obj])): + block = Block(Block.TRIANGLE, obj.name) + elif world.atom_true(worldsim.Atom(world.predicates["block"], [obj])): + block = Block(Block.SQUARE, obj.name) + if not block: + continue + block.clear = False + block.on = None + block.onfire = False + block.hasmortar = False + if block.type == block.TABLE: + table = block + blocks[obj.name] = block + for atom in world.atoms: + try: # some domains won't use stable-on, so if we get a KeyError just ignore + if atom.predicate == world.predicates["stable-on"]: + blocks[atom.args[0].name].on = blocks[atom.args[1].name] + except KeyError: + pass + + if atom.predicate == world.predicates["on"]: # or : + blocks[atom.args[0].name].on = blocks[atom.args[1].name] + elif atom.predicate == world.predicates["on-table"]: + blocks[atom.args[0].name].on = table + elif atom.predicate == world.predicates["clear"]: + blocks[atom.args[0].name].clear = True + elif atom.predicate == world.predicates["onfire"]: + blocks[atom.args[0].name].onfire = True + elif "hasmortar" in world.predicates.keys() and atom.predicate == world.predicates["hasmortar"]: + blocks[atom.args[0].name].hasmortar = True + return sorted(blocks.values(), key = lambda x: x.id) + diff --git a/midca/domains/blocksworld_Updated/plan/__init__.py b/midca/domains/blocksworld_Updated/plan/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py b/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py new file mode 100644 index 00000000..b626f62e --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py @@ -0,0 +1,300 @@ +""" +TESTING for mortar + +Blocks-world test data for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from __future__ import print_function +from pyhop import * + +import time + +import operators_mortar +print('') +operators_mortar.declare_ops() +print_operators() + +import methods_mortar +print('') +methods_mortar.declare_methods() +#methods_broken.declare_methods() +print_methods() + + +############# beginning of tests ################ + + +print(""" +**************************************** +First, test pyhop on some of the operators and smaller tasks +**************************************** +""") + +print("- Define state1: a on b, b on tale, c on table") + +""" +A state is a collection of all of the state variables and their values. Every state variable in the domain should have a value. +""" + +state1 = State('state1') +state1.pos={'a':'b', 'b':'table', 'c':'table','d':'table','e':'table'} +state1.clear={'c':True, 'b':False,'a':True,'d':True,'e':True} +state1.holding=False + +# make sure no blocks have mortar on them; start with initial quantity +# of mortar +state1.hasmortar = {} +for blockid in state1.pos.keys(): + state1.hasmortar[blockid] = False + +state1.mortaravailable = {} # key is id, value is Available/Used +num_mortar = 5 +for i in range(num_mortar): + key = 'M'+str(i) + state1.mortaravailable[key] = True + +print_state(state1) +print('') + +print('- these should fail:') +pyhop(state1,[('pickup','a')], verbose=1) +pyhop(state1,[('pickup','b')], verbose=1) +print('- these should succeed:') +pyhop(state1,[('pickup','c')], verbose=1) +pyhop(state1,[('unstack','a','b')], verbose=1) +pyhop(state1,[('get','a')], verbose=1) +print('- this should fail:') +pyhop(state1,[('get','b')], verbose=1) +print('- this should succeed:') +pyhop(state1,[('get','c')], verbose=1) + +print(' - testing stack mortared') +print_state(state1) +goal1a = Goal('goal1a') +goal1a.pos={'c':'b', 'b':'a', 'a':'e', 'e':'d', 'd':'table'} +pyhop(state1,[('move_blocks', goal1a)],verbose=1) + +print(' - testing unstack mortared') +state2 = State('state2') +state2.hasmortar = {'D_': False, 'B_': 'M5', 'C_': 'M4', 'A_': False} +state2.fire = {'D_': False, 'B_': False, 'C_': False, 'A_': False} +state2.clear = {'D_': True, 'B_': False, 'C_': False, 'A_': False} +state2.pos = {'D_': 'C_', 'B_': 'A_', 'C_': 'B_', 'A_': 'table'} +state2.free = {'Gui Montag': True} +state2.mortaravailable = {'M5': False, 'M4': False, 'M1': True, 'M3': True, 'M2': True, 'M6':True, 'M7':True} +state2.holding = False +print_state(state2) +goal2 = Goal('goal2') +goal2.pos={'D_':'B_'} +pyhop(state2,[('move_blocks', goal2)],verbose=4) + +# +# print(""" +# **************************************** +# Run pyhop on two block-stacking problems, both of which start in state1. +# The goal for the 2nd problem omits some of the conditions in the goal +# of the 1st problem, but those conditions will need to be achieved +# anyway, so both goals should produce the same plan. +# **************************************** +# """) +# +# print("- Define goal1a:") +# +# """ +# A goal is a collection of some (but not necessarily all) of the state variables and their desired values. Below, both goal1a and goal1b specify c on b, and b on a. The difference is that goal1a also specifies that a is on table and the hand is empty. +# """ +# +# goal1a = Goal('goal1a') +# goal1a.pos={'c':'b', 'b':'a', 'a':'table'} +# goal1a.clear={'c':True, 'b':False, 'a':False} +# goal1a.holding=False +# +# print_goal(goal1a) +# print('') +# +# print("- Define goal1b:") +# +# goal1b = Goal('goal1b') +# goal1b.pos={'c':'b', 'b':'a'} +# +# print_goal(goal1b) + +### goal1b omits some of the conditions of goal1a, +### but those conditions will need to be achieved anyway + + +# pyhop(state1,[('move_blocks', goal1a)], verbose=2) +# +# print_state(newstate) +# +# time.sleep(15) +# +# pyhop(state1,[('move_blocks', goal1b)], verbose=2) +# +# print_state(newstate) +# +# time.sleep(15) + + +# +# print(""" +# **************************************** +# Run pyhop on two more planning problems. As before, the 2nd goal omits +# some of the conditions in the 1st goal, but both goals should produce +# the same plan. +# **************************************** +# """) +# +# print("- Define state 2:") +# +# state2 = State('state2') +# state2.pos={'a':'c', 'b':'d', 'c':'table', 'd':'table'} +# state2.clear={'a':True, 'c':False,'b':True, 'd':False} +# state2.holding=False +# +# ## make sure no blocks have mortar on them; start with initial quantity +# # of mortar +# state2.mortared = {} +# for blockid in state2.pos.keys(): +# state2.mortared[blockid] = False +# +# state2.mortar_quantity = 10 +# +# print_state(state2) +# print('') +# +# print("- Define goal2a:") +# +# goal2a = Goal('goal2a') +# goal2a.pos={'a':'b', 'b':'c', 'c':'d', 'd':'table'} +# goal2a.clear={'a':True, 'c':False,'b':True, 'd':False} +# goal2a.holding=False +# +# print_goal(goal2a) +# print('') +# +# print("- Define goal2b:") +# +# goal2b = Goal('goal2b') +# goal2b.pos={'b':'c', 'a':'d'} +# +# print_goal(goal2b) +# print('') +# +# +# ### goal2b omits some of the conditions of goal2a, +# ### but those conditions will need to be achieved anyway. +# #time.sleep(1000) +# pyhop(state2,[('move_blocks', goal2a)], verbose=1) +# print_state(state2) +# time.sleep(10) +# +# pyhop(state2,[('move_blocks', goal2b)], verbose=1) +# print_state(state2) +# time.sleep(10) +# +# print(""" +# **************************************** +# Test pyhop on planning problem bw_large_d from the SHOP distribution. +# **************************************** +# """) +# +# print("- Define state3:") +# +# state3 = State('state3') +# state3.pos = {1:12, 12:13, 13:'table', 11:10, 10:5, 5:4, 4:14, 14:15, 15:'table', 9:8, 8:7, 7:6, 6:'table', 19:18, 18:17, 17:16, 16:3, 3:2, 2:'table'} +# state3.clear = {x:False for x in range(1,20)} +# state3.clear.update({1:True, 11:True, 9:True, 19:True}) +# state3.holding = False +# +# print_state(state3) +# print('') +# +# print("- Define goal3:") +# +# goal3 = Goal('goal3') +# goal3.pos = {15:13, 13:8, 8:9, 9:4, 4:'table', 12:2, 2:3, 3:16, 16:11, 11:7, 7:6, 6:'table'} +# goal3.clear = {17:True, 15:True, 12:True} +# +# print_goal(goal3) +# print('') +# +# pyhop(state3,[('move_blocks', goal3)], verbose=1) +# +# +# print(""" +# **************************************** +# Load a modified version of the blocks_world methods, in which the +# method for 'get' is replaced with two methods that will sometimes +# cause backtracking. +# **************************************** +# """) +# +# # import blocks_world_methods2 +# # print_methods() +# +# # print("""\n=== In the next call to pyhop, it should backtrack: +# # the recursion depth should go up, then down, then up again.===\n""") +# +# # # verbose=2 tells pyhop to print out a message at each recursion depth +# +# # pyhop(state1,[('get', 'a')], verbose=2) +# +# # print("""\n=== This time it shouldn't backtrack.===\n""") +# +# +# # pyhop(state1,[('get', 'c')], verbose=2) +# +# # print("""\n=== This time it should fail.===\n""") +# +# # pyhop(state1,[('get', 'b')], verbose=2) +# +# +# +# # print(""" +# # **************************************** +# # demonstrate different levels of verbosity +# # **************************************** +# # """) +# +# # print('- verbosity 0:') +# # pyhop(state1,[('get','a')], verbose=0) +# # print('- verbosity 1:') +# # pyhop(state1,[('get','a')], verbose=1) +# # print('- verbosity 2:') +# # pyhop(state1,[('get','a')], verbose=2) +# # print('- verbosity 3:') +# # pyhop(state1,[('get','a')], verbose=3) +# +# print(""" +# **************************************** +# Demonstrates planning issue; added by mpaisner 8/28/13 +# **************************************** +# """) +# #import blocks_world_methods3 +# state4 = State('state4') +# state4.pos = {1:'table', 2:1, 3:2, 4:'table'} +# state4.clear = {1:False, 2:False, 3:True, 4:True} +# state4.holding = False +# +# goal4 = Goal('goal4') +# goal4.pos = {4:2} +# print_goal(goal4) +# print('') +# +# pyhop(state4,[('move_blocks', goal4)], verbose=1) +# +# #import blocks_world_methods3 +# state5 = State('state5') +# state5.pos = {'A_':'table', 'B_':'A_', 'D_':'B_', 'C_':'table'} +# state5.clear = {'A_':False, 'B_':False, 'D_':True, 'C_':True} +# state5.holding = False +# +# goal5 = Goal('goal5') +# goal5.pos = {'C_':'B_'} +# print_goal(goal5) +# print('') +# +# pyhop(state4,[('move_blocks', goal4)], verbose=1) diff --git a/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp b/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp new file mode 100644 index 00000000..07e038e8 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp @@ -0,0 +1,10 @@ + +(defproblem bw-ran-5-1 blocks-normal ((arm-empty) +(clear d) +(on-table c) +(on b a) +(on d b) +(clear c) +(on-table a) +) + ((achieve-goals ( list diff --git a/midca/domains/Domain_Parsing/templates/methods_template.txt b/midca/domains/blocksworld_Updated/plan/methods.py similarity index 100% rename from midca/domains/Domain_Parsing/templates/methods_template.txt rename to midca/domains/blocksworld_Updated/plan/methods.py diff --git a/midca/domains/blocksworld_Updated/plan/methods_broken.py b/midca/domains/blocksworld_Updated/plan/methods_broken.py new file mode 100644 index 00000000..cfdd0115 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/methods_broken.py @@ -0,0 +1,157 @@ +""" +Blocks World methods for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from midca.modules._plan import pyhop + +""" +Here are some helper functions that are used in the methods' preconditions. +""" + +def is_done(b1,state,goal): + if b1 == 'table': return True + if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: + return False + if state.pos[b1] == 'table': return True + return is_done(state.pos[b1],state,goal) + +def status(b1,state,goal): + if is_done(b1,state,goal): + return 'done' + elif not (state.clear[b1] or state.pos[b1] == "in-arm"): + return 'inaccessible' + elif not (b1 in goal.pos) or goal.pos[b1] == 'table': + return 'move-to-table' + elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: + return 'move-to-block' + else: + return 'waiting' + +def all_blocks(state): + return state.clear.keys() + + +""" +In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. +""" + +### methods for "move_blocks" + +def moveb_m(state,goal): + """ + This method implements the following block-stacking algorithm: + If there's a block that can be moved to its final position, then + do so and call move_blocks recursively. Otherwise, if there's a + block that needs to be moved and can be moved to the table, then + do so and call move_blocks recursively. Otherwise, no blocks need + to be moved. + """ + + + for b1 in all_blocks(state): + s = status(b1,state,goal) + if s == 'move-to-table': + return [('move_one',b1,'table'),('move_blocks',goal)] + elif s == 'move-to-block': + return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] + else: + continue + # + # if we get here, no blocks can be moved to their final locations + b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) + if b1 != None: + return [('move_one',b1,'table'), ('move_blocks',goal)] + # + # if we get here, there are no blocks that need moving + return [] + +""" +declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. +""" + + +### methods for "move_one" + +def move1(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest. + """ + if state.pos[b1] == "in-arm": + return [('put', b1,dest)] + else: + return [('get', b1), ('put', b1,dest)] + +### methods for "get" + +def get_by_unstack(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack_task',b1)] + return False + +def get_by_pickup(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup_task',b1)] + return False + +### methods for "pickup_task" + +def pickup_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup',b1)] + return False + +### methods for "unstack_task" + +def unstack_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack',b1,state.pos[b1])] + return False + +### methods for "put" + +def put_m(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + if state.holding == b1: + if b2 == 'table': + return [('putdown',b1)] + else: + return [('stack',b1,b2)] + else: + return False + +def put_out_m(state, b1): + if state.fire[b1]: + return [("putoutfire", b1)] + else: + return [] + +def quick_apprehend_m(state, perp): + if state.free[perp]: + return [("apprehend", perp)] + else: + return [] + +def long_apprehend_m(state, perp): + if state.free[perp]: + return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] + else: + return [] + +def declare_methods(longApprehend = True): + if longApprehend: + pyhop.declare_methods("catch_arsonist", long_apprehend_m) + else: + pyhop.declare_methods("catch_arsonist", quick_apprehend_m) + pyhop.declare_methods("put_out", put_out_m) + pyhop.declare_methods('put',put_m) + pyhop.declare_methods('unstack_task',unstack_m) + pyhop.declare_methods('pickup_task',pickup_m) + pyhop.declare_methods('get',get_by_pickup,get_by_unstack) + pyhop.declare_methods('move_one',move1) + pyhop.declare_methods('move_blocks',moveb_m) + diff --git a/midca/domains/blocksworld_Updated/plan/methods_extinguish.py b/midca/domains/blocksworld_Updated/plan/methods_extinguish.py new file mode 100644 index 00000000..4da8346f --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/methods_extinguish.py @@ -0,0 +1,169 @@ +""" +Blocks World methods for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from midca.modules._plan import pyhop +import random + +""" +Here are some helper functions that are used in the methods' preconditions. +""" + +def is_done(b1,state,goal): + if b1 == 'table': return True + if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: + return False + if state.pos[b1] == 'table': return True + if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): + return False + return is_done(state.pos[b1],state,goal) + +def status(b1,state,goal): + if is_done(b1,state,goal): + return 'done' + elif not (state.clear[b1] or state.pos[b1] == "in-arm"): + return 'inaccessible' + elif not (b1 in goal.pos) or goal.pos[b1] == 'table': + return 'move-to-table' + elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: + return 'move-to-block' + else: + return 'waiting' + +def all_blocks(state): + return state.clear.keys() + + +""" +In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. +""" + +### methods for "move_blocks" + +def moveb_m(state,goal): + """ + This method implements the following block-stacking algorithm: + If there's a block that can be moved to its final position, then + do so and call move_blocks recursively. Otherwise, if there's a + block that needs to be moved and can be moved to the table, then + do so and call move_blocks recursively. Otherwise, no blocks need + to be moved. + """ + for b1 in all_blocks(state): + s = status(b1,state,goal) + if s == 'move-to-table': + return [('move_one',b1,'table'),('move_blocks',goal)] + elif s == 'move-to-block': + return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] + else: + continue + # + # if we get here, no blocks can be moved to their final locations + b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) + if b1 != None: + return [('move_one',b1,'table'), ('move_blocks',goal)] + # + # if we get here, there are no blocks that need moving + return [] + +""" +declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. +""" + + +### methods for "move_one" + +def move1(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest. + """ + if state.pos[b1] == "in-arm": + return [('put', b1,dest)] + else: + return [('get', b1), ('put', b1,dest)] + +### methods for "get" + +def get_by_unstack(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack_task',b1)] + return False + +def get_by_pickup(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup_task',b1)] + return False + +### methods for "pickup_task" + +def pickup_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup',b1)] + return False + +### methods for "unstack_task" + +def unstack_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack',b1,state.pos[b1])] + return False + +### methods for "put" + +def put_m(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + if state.holding == b1: + if b2 == 'table': + return [('putdown',b1)] + else: + return [('stack',b1,b2)] + else: + return False + +def put_out_m(state, b1): + if state.fire[b1]: + if state.holdingfireext: + return [("putoutfire", b1, state.holdingfireext)] + elif state.fire_ext_avail: + ext = random.choice(list(state.fire_ext_avail)) + return [('get_extinguisher', ext), ("putoutfire", b1, ext)] + else: + return [] + +def get_extinguisher_m(state, extinguisher): + if extinguisher in state.fire_ext_avail and not state.holdingfireext: + return [("pickup_extinguisher", extinguisher)] + else: + return False + +def quick_apprehend_m(state, perp): + if state.free[perp]: + return [("apprehend", perp)] + else: + return [] + +def long_apprehend_m(state, perp): + if state.free[perp]: + return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] + else: + return [] + +def declare_methods(longApprehend = True): + if longApprehend: + pyhop.declare_methods("catch_arsonist", long_apprehend_m) + else: + pyhop.declare_methods("catch_arsonist", quick_apprehend_m) + pyhop.declare_methods("put_out", put_out_m) + pyhop.declare_methods('put',put_m) + pyhop.declare_methods('unstack_task',unstack_m) + pyhop.declare_methods('pickup_task',pickup_m) + pyhop.declare_methods('get',get_by_pickup,get_by_unstack) + pyhop.declare_methods('move_one',move1) + pyhop.declare_methods('move_blocks',moveb_m) + pyhop.declare_methods('get_extinguisher',get_extinguisher_m) + diff --git a/midca/domains/blocksworld_Updated/plan/methods_midca.py b/midca/domains/blocksworld_Updated/plan/methods_midca.py new file mode 100644 index 00000000..059efba9 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/methods_midca.py @@ -0,0 +1,179 @@ +""" +Blocks World methods for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from midca.modules._plan import pyhop + + +""" +Here are some helper functions that are used in the methods' preconditions. +""" + +def is_done(b1,state,goal): + if b1 == 'table': return True + if b1 in goal.pos and not state.is_true("on", [b1, goal.pos[b1]]): + return False + if b1 in goal.pos.values() and not state.is_true("clear", [b1]): + return False + print b1, state.is_true("on-table", [b1]) + if state.is_true("on-table", [b1]): return True + for atom in state.atoms: + if atom.predicate.name == "on" and atom.args[0].name == b1: + return is_done(atom.args[1].name, state, goal) + if state.is_true("holding", [b1]): + return True + print b1, state + for atom in state.atoms: + print atom + raise Exception("Block is neither on anything or being held") + +def status(b1,state,goal): + if is_done(b1,state,goal): + return 'done' + elif not (state.is_true("clear", [b1]) or state.is_true("holding", [b1])): + print "inaccessible", b1, state.is_true("clear", [b1]) + for atom in state.atoms: + if atom.predicate.name == "clear": + print atom + return 'inaccessible' + elif not (b1 in goal.pos) or goal.pos[b1] == 'table': + return 'move-to-table' + elif is_done(goal.pos[b1],state,goal) and state.is_true("clear", [goal.pos[b1]]): + return 'move-to-block' + else: + return 'waiting' + +def all_blocks(state): + return [name for name, object in state.objects.items() if object.type.name.lower() == "block"] + + +""" +In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. +""" + +### methods for "move_blocks" + +def moveb_m(state,goal): + """ + This method implements the following block-stacking algorithm: + If there's a block that can be moved to its final position, then + do so and call move_blocks recursively. Otherwise, if there's a + block that needs to be moved and can be moved to the table, then + do so and call move_blocks recursively. Otherwise, no blocks need + to be moved. + """ + print state + for b1 in all_blocks(state): + s = status(b1,state,goal) + print b1, "stat:", s + if s == 'move-to-table': + return [('move_one',b1,'table'),('move_blocks',goal)] + elif s == 'move-to-block': + return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] + else: + continue + + b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) + if b1 != None: + return [('move_one',b1,'table'), ('move_blocks',goal)] + # + # if we get here, there are no blocks that need moving + return [] + +""" +declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. +""" + + +### methods for "move_one" + +def move1(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest. + """ + if state.is_true("holding", [b1]): + return [('put', b1, dest)] + if state.is_true("arm-empty"): + return [('get', b1), ('put', b1,dest)] + for atom in state.atoms: + if atom.predicate.name == "holding": + heldBlock = atoms.args[0].name + return [('put', heldBlock, 'table'), ('get', b1), ('put', b1,dest)] + +### methods for "get" + +def get_by_unstack(state,b1): + """Generate a pickup subtask.""" + if state.is_true("clear", [b1]): return [('unstack_task',b1)] + return False + +def get_by_pickup(state,b1): + """Generate a pickup subtask.""" + if state.is_true("clear", [b1]): return [('pickup_task',b1)] + return False + +### methods for "pickup_task" + +def pickup_m(state,b1): + """Generate a pickup subtask.""" + if state.is_true("clear", [b1]): return [('pickup',b1)] + return False + +### methods for "unstack_task" + +def unstack_m(state,b1): + """Generate a pickup subtask.""" + if state.is_true("clear", [b1]): + for atom in state.atoms: + if atom.predicate.name == "on" and atom.args[0].name == b1: + return [('unstack',b1,atom.args[1].name)] + return False + +### methods for "put" + +def put_m(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + if state.is_true("holding", [b1]): + if b2 == 'table': + return [('putdown',b1)] + else: + return [('stack',b1,b2)] + else: + return False + +def put_out_m(state, b1): + if state.is_true("onfire", [b1]): + return [("putoutfire", b1)] + else: + return [] + +def quick_apprehend_m(state, perp): + if state.is_true("free", [perp]): + return [("apprehend", perp)] + else: + return [] + +def long_apprehend_m(state, perp): + if state.is_true("free", [perp]): + return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] + else: + return [] + +def declare_methods(longApprehend = True): + if longApprehend: + pyhop.declare_methods("catch_arsonist", long_apprehend_m) + else: + pyhop.declare_methods("catch_arsonist", quick_apprehend_m) + pyhop.declare_methods("put_out", put_out_m) + pyhop.declare_methods('put',put_m) + pyhop.declare_methods('unstack_task',unstack_m) + pyhop.declare_methods('pickup_task',pickup_m) + pyhop.declare_methods('get',get_by_pickup,get_by_unstack) + pyhop.declare_methods('move_one',move1) + pyhop.declare_methods('move_blocks',moveb_m) + diff --git a/midca/domains/blocksworld_Updated/plan/methods_mortar.py b/midca/domains/blocksworld_Updated/plan/methods_mortar.py new file mode 100644 index 00000000..379e89d8 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/methods_mortar.py @@ -0,0 +1,220 @@ +""" +Blocks World* methods for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +""" +* Modified by Dustin Dannenhauer: Added a new operator for stacking with mortar + +""" + +from midca.modules._plan import pyhop + +""" +Here are some helper functions that are used in the methods' preconditions. +""" + +def is_done(b1,state,goal): + if b1 == 'table': return True + if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: + return False + if state.pos[b1] == 'table': return True + if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): + return False + return is_done(state.pos[b1],state,goal) + +def status(b1,state,goal): + if is_done(b1,state,goal): + return 'done' + elif not (state.clear[b1] or state.pos[b1] == "in-arm"): + return 'inaccessible' + elif not (b1 in goal.pos) or goal.pos[b1] == 'table': + return 'move-to-table' + elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: + btmblk = goal.pos[b1] + if btmblk in goal.hasmortar.keys() and goal.hasmortar[btmblk]: + ''' This check adds a status so we move blocks with mortar different then without mortar ''' + return 'move-to-block-with-mortar' + else: + return 'move-to-block' + else: + return 'waiting' + +def all_blocks(state): + return state.clear.keys() + + +""" +In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. +""" + +### methods for "move_blocks" + +def moveb_m(state,goal): + """ + This method implements the following block-stacking algorithm: + If there's a block that can be moved to its final position, then + do so and call move_blocks recursively. Otherwise, if there's a + block that needs to be moved and can be moved to the table, then + do so and call move_blocks recursively. Otherwise, no blocks need + to be moved. + """ + for b1 in all_blocks(state): + s = status(b1,state,goal) + if s == 'move-to-table': + return [('move_one',b1,'table'),('move_blocks',goal)] + elif s == 'move-to-block': + return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] + elif s == 'move-to-block-with-mortar': + return [('move_one_mortar',b1,goal.pos[b1]), ('move_blocks',goal)] + else: + continue + # + # if we get here, no blocks can be moved to their final locations + b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) + if b1 != None: + return [('move_one',b1,'table'), ('move_blocks',goal)] + # + # if we get here, there are no blocks that need moving + return [] + +""" +declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. +""" + + +### methods for "move_one" + +def move1(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest. + """ + if state.pos[b1] == "in-arm": + return [('put', b1,dest)] + else: + return [('get', b1), ('put', b1,dest)] + +### methods for "move_one_mortar" + +def move1_mortar(state,b1,dest): + """ + Generate subtasks to get b1 and put it at dest (with mortar) + """ + if state.pos[b1] == "in-arm": + return [('put_mortar', b1,dest)] + else: + return [('get', b1), ('put_mortar', b1,dest)] + + +### methods for "get" + +def get_by_unstack(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('unstack_task',b1)] + return False + +def get_by_pickup(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup_task',b1)] + return False + +### methods for "pickup_task" + +def pickup_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: return [('pickup',b1)] + return False + +### methods for "unstack_task" + +def unstack_m(state,b1): + """Generate a pickup subtask.""" + if state.clear[b1]: + btmblk = state.pos[b1] + mortarblk = state.hasmortar[btmblk] + if mortarblk: + return [('unstack_mortared',b1,state.pos[b1],mortarblk)] + else: + return [('unstack',b1,state.pos[b1])] + return False + +### methods for "put" + +def put_m(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + + if state.holding == b1: + if b2 == 'table': + return [('putdown',b1)] + else: + return [('stack',b1,b2)] + else: + return False + +### Methods for put_mortar + +def put_m_mortar(state,b1,b2): + """ + Generate either a putdown or a stack subtask for b1. + b2 is b1's destination: either the table or another block. + """ + + available_mortar = [k for k,v in state.mortaravailable.items() if v] + mortar_block = False + if len(available_mortar) > 0: + mortar_block = available_mortar[0] + + if state.holding == b1: + if b2 == 'table': + return [('putdown',b1)] + elif mortar_block: + # new stack with mortar + #print("*-*-*-*-*-* stacking with mortar") + return [('stack_mortared',b1,b2,mortar_block)] + else: + # no mortar left, continue stacking like normal + return [('stack',b1,b2)] + #return False # change to use this line instead of above to fail on no more mortar + + else: + return False + + +def put_out_m(state, b1): + if state.fire[b1]: + return [("putoutfire", b1)] + else: + return [] + +def quick_apprehend_m(state, perp): + if state.free[perp]: + return [("apprehend", perp)] + else: + return [] + +def long_apprehend_m(state, perp): + if state.free[perp]: + return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] + else: + return [] + +def declare_methods(longApprehend = True): + if longApprehend: + pyhop.declare_methods("catch_arsonist", long_apprehend_m) + else: + pyhop.declare_methods("catch_arsonist", quick_apprehend_m) + pyhop.declare_methods("put_out", put_out_m) + pyhop.declare_methods('put',put_m) + pyhop.declare_methods('put_mortar',put_m_mortar) + pyhop.declare_methods('unstack_task',unstack_m) + pyhop.declare_methods('pickup_task',pickup_m) + pyhop.declare_methods('get',get_by_pickup,get_by_unstack) + pyhop.declare_methods('move_one',move1) + pyhop.declare_methods('move_one_mortar',move1_mortar) + pyhop.declare_methods('move_blocks',moveb_m) +# pyhop.declare_methods('put_with_mortar',put_with_mortar_m) + diff --git a/midca/domains/Domain_Parsing/templates/operators_template.txt b/midca/domains/blocksworld_Updated/plan/operators.py similarity index 97% rename from midca/domains/Domain_Parsing/templates/operators_template.txt rename to midca/domains/blocksworld_Updated/plan/operators.py index ddd4faba..ed22b185 100644 --- a/midca/domains/Domain_Parsing/templates/operators_template.txt +++ b/midca/domains/blocksworld_Updated/plan/operators.py @@ -56,7 +56,8 @@ def stack(state,b,c): return state else: return False -def putoutfire(state, b): if state.fire[b] == True: +def putoutfire(state, b): + if state.fire[b] == True: state.fire[b] = False return state else: diff --git a/midca/domains/blocksworld_Updated/plan/operators_extinguish.py b/midca/domains/blocksworld_Updated/plan/operators_extinguish.py new file mode 100644 index 00000000..7dae0936 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/operators_extinguish.py @@ -0,0 +1,95 @@ +""" +Blocks World domain definition for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" +import sys +sys.path.append("../") +from midca.modules._plan import pyhop + +"""Each Pyhop planning operator is a Python function. The 1st argument is +the current state, and the others are the planning operator's usual arguments. +This is analogous to how methods are defined for Python classes (where +the first argument is always the name of the class instance). For example, +the function pickup(state,b) implements the planning operator for the task +('pickup', b). + +The blocks-world operators use three state variables: +- pos[b] = block b's position, which may be 'table', 'hand', or another block. +- clear[b] = False if a block is on b or the hand is holding b, else True. +- holding = name of the block being held, or False if the hand is empty. +""" + +def pickup(state,b): + if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + return state + else: return False + +def unstack(state,b,c): + if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + state.clear[c] = True + return state + else: return False + +def putdown(state,b): + if state.pos[b] == 'hand': + state.pos[b] = 'table' + state.clear[b] = True + state.holding = False + return state + else: return False + +def stack(state,b,c): + if state.pos[b] == 'hand' and state.clear[c] == True: + state.pos[b] = c + state.clear[b] = True + state.holding = False + state.clear[c] = False + return state + else: return False + +def putoutfire(state, b, ext): + if state.fire[b] == True and state.holdingfireext == ext: + state.fire[b] == False + return state + else: + return False + +def pickup_extinguisher(state, extinguisher): + if extinguisher in state.fire_ext_avail and not state.holdingfireext: + state.holdingfireext = extinguisher + state.fire_ext_avail.remove(extinguisher) + return state + else: + return False + +def putdown_extinguisher(state, extinguisher): + if state.holdingfireext == extinguisher: + state.holdingfireext = None + state.fire_ext_avail.add(extinguisher) + return state + else: + return False + +def apprehend(state, perp): + if state.free[perp] == True: + state.free[perp] = False + return state + else: + return False + +def searchfor(state, perp): + return state + +""" +Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop +what the operators are. Note that the operator names are *not* quoted. +""" +def declare_ops(): + pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor, pickup_extinguisher, putdown_extinguisher) diff --git a/midca/domains/blocksworld_Updated/plan/operators_midca.py b/midca/domains/blocksworld_Updated/plan/operators_midca.py new file mode 100644 index 00000000..c7544740 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/operators_midca.py @@ -0,0 +1,83 @@ +""" +Blocks World domain definition for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + +from midca.modules._plan import pyhop + +"""Each Pyhop planning operator is a Python function. The 1st argument is +the current state, and the others are the planning operator's usual arguments. +This is analogous to how methods are defined for Python classes (where +the first argument is always the name of the class instance). For example, +the function pickup(state,b) implements the planning operator for the task +('pickup', b). + +The blocks-world operators use three state variables: +- pos[b] = block b's position, which may be 'table', 'hand', or another block. +- clear[b] = False if a block is on b or the hand is holding b, else True. +- holding = name of the block being held, or False if the hand is empty. +""" + +def pickup(state,b): + print "pickop_op", b + if state.is_true("on-table", [b]) and state.is_true("clear", [b]) and state.is_true("arm-empty"): + state.add_fact("holding", [b]) + state.remove_fact("clear", [b]) + state.remove_fact("on-table", [b]) + state.remove_fact("arm-empty") + return state + else: return False + +def unstack(state,b,c): + if state.is_true("on", [b, c]) and c != 'table' and state.is_true("clear", [b]) and state.is_true("arm-empty"): + state.add_fact("holding", [b]) + state.remove_fact("clear", [b]) + state.remove_fact("on", [b, c]) + state.remove_fact("arm-empty") + state.add_fact("clear", [c]) + return state + else: return False + +def putdown(state,b): + if state.is_true("holding", [b]): + state.add_fact("on-table", [b]) + state.add_fact("arm-empty") + state.add_fact("clear", [b]) + state.remove_fact("holding", [b]) + return state + else: return False + +def stack(state,b,c): + if state.is_true("holding", [b]) and state.is_true("clear", [c]): + state.remove_fact("holding", [b]) + state.add_fact("clear", [b]) + state.add_fact("on", [b, c]) + state.add_fact("arm-empty") + state.remove_fact("clear", [c]) + return state + else: return False + +def putoutfire(state, b): + if state.is_true("onfire", [b]): + state.remove_fact("onfire", [b]) + else: + return False + +def apprehend(state, perp): + if state.is_true("free", [perp]): + state.remove_fact("free", [perp]) + return state + else: + return False + +def searchfor(state, perp): + return state + +""" +Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop +what the operators are. Note that the operator names are *not* quoted. +""" + +def declare_ops(): + pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor) diff --git a/midca/domains/blocksworld_Updated/plan/operators_mortar.py b/midca/domains/blocksworld_Updated/plan/operators_mortar.py new file mode 100644 index 00000000..a7e20d14 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/operators_mortar.py @@ -0,0 +1,115 @@ +""" +Blocks World domain definition for Pyhop 1.1. +Author: Dana Nau , November 15, 2012 +This file should work correctly in both Python 2.7 and Python 3.2. +""" + + +from midca.modules._plan import pyhop +import random + +"""Each Pyhop planning operator is a Python function. The 1st argument is +the current state, and the others are the planning operator's usual arguments. +This is analogous to how methods are defined for Python classes (where +the first argument is always the name of the class instance). For example, +the function pickup(state,b) implements the planning operator for the task +('pickup', b). + +The blocks-world operators use three state variables: +- pos[b] = block b's position, which may be 'table', 'hand', or another block. +- clear[b] = False if a block is on b or the hand is holding b, else True. +- holding = name of the block being held, or False if the hand is empty. +""" + +def pickup(state,b): + if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + + # remove mortar if the block has it (just to be safe) + if hasattr(state, 'mortared') and state.mortared[b] == True: + state.mortared[b] == False + + return state + else: return False + +def unstack(state,b,c): + if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + state.clear[c] = True + + # to undo mortar but doesn't increase quantity + if hasattr(state, 'mortared') and state.mortared[b] == True: + state.mortared[b] == False + + return state + else: return False + +def unstack_mortared(state,b,c,m): + ''' m is for mortar ''' + if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: + state.pos[b] = 'hand' + state.clear[b] = False + state.holding = b + state.clear[c] = True + if state.hasmortar[b] == m: + state.hasmortar[b] = False + + return state + else: return False + +def putdown(state,b): + if state.pos[b] == 'hand': + state.pos[b] = 'table' + state.clear[b] = True + state.holding = False + return state + else: return False + +def stack(state,b,c): + if state.pos[b] == 'hand' and state.clear[c] == True: + state.pos[b] = c + state.clear[b] = True + state.holding = False + state.clear[c] = False + return state + else: return False + +def stack_mortared(state,b,c,m): + if state.pos[b] == 'hand' and state.clear[c] == True and state.mortaravailable[m]: + state.pos[b] = c + state.clear[b] = True + state.holding = False + state.clear[c] = False + state.hasmortar[b] = True + state.mortaravailable[m] = False + return state + else: return False + +def putoutfire(state, b): + if state.fire[b] == True: + state.fire[b] == False + return state + else: + return False + +def apprehend(state, perp): + if state.free[perp] == True: + state.free[perp] = False + return state + else: + return False + +def searchfor(state, perp): + return state + +""" +Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop +what the operators are. Note that the operator names are *not* quoted. +""" + +def declare_ops(): + pyhop.declare_operators(pickup, unstack, unstack_mortared, putdown, stack, stack_mortared, putoutfire, apprehend, searchfor) diff --git a/midca/domains/blocksworld_Updated/plan/sample_methods.py b/midca/domains/blocksworld_Updated/plan/sample_methods.py new file mode 100644 index 00000000..55353e73 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/sample_methods.py @@ -0,0 +1,82 @@ +''' +Sample pyhop methods file. This is used to generate plans in the chicken domain. +''' + +from midca.modules._plan import pyhop + +def goals_valid(state, goals): + ''' + checks to make sure no chicken is expected to be on both sides + ''' + left = set() + right = set() + for goal in goals: + try: + chicken = goal[0] + predicate = goal["predicate"] + negate = 'negate' in goal and goal['negate'] + except KeyError: + #invalid goal + return False + if predicate == "onleft" and negate or predicate == "onright" and not negate: + side = "right" + elif predicate == "onright" and negate or predicate == "onleft" and not negate: + side = "left" + else: + #invalid goal + return False + if side == "left": + if chicken in right: + #chicken supposed to be on both sides + return False + left.add(chicken) + else: + if chicken in left: + #chicken supposed to be on both sides + return False + right.add(chicken) + return True + +def achieve_goals_m(state, goals): + ''' + checks for conflicting goals. If there are none, plans for each goal in turn + assumes goals are one of: + onright(chicken), !onright(chicken), onleft(chicken), !onleft(chicken) + ''' + if not goals_valid(state, goals): + return False + return [("achieve_chicken_goals", goals)] + +def achieve_chicken_goals_m(state, goals): + ''' + pursues goals in order. + ''' + if goals: + return [("achieve_goal", goals[0]), ("achieve_chicken_goals", goals[1:])] + else: + return [] + +def achieve_goal_m(state, goal): + ''' + assumes goals are one of: + onright(chicken), !onright(chicken), onleft(chicken), !onleft(chicken) + ''' + chicken = goal[0] + predicate = goal["predicate"] + negate = "negate" in goal and goal["negate"] + if predicate == "onleft" and negate or predicate == "onright" and not negate: + side = "right" + elif predicate == "onright" and negate or predicate == "onleft" and not negate: + side = "left" + if state.is_true("onright", [chicken]) and side == "left": + return [("crossleft", chicken)] + elif state.is_true("onleft", [chicken]) and side == "right": + return [("crossright", chicken)] + else: + return [] + +def declare_methods(): + pyhop.declare_methods("achieve_goals", achieve_goals_m) + pyhop.declare_methods("achieve_chicken_goals", achieve_chicken_goals_m) + pyhop.declare_methods("achieve_goal", achieve_goal_m) + diff --git a/midca/domains/blocksworld_Updated/plan/sample_operators.py b/midca/domains/blocksworld_Updated/plan/sample_operators.py new file mode 100644 index 00000000..e83c21e8 --- /dev/null +++ b/midca/domains/blocksworld_Updated/plan/sample_operators.py @@ -0,0 +1,24 @@ +''' +Sample pyhop operators file. This is used to generate plans in the chicken domain. +''' + +from midca.modules._plan import pyhop + +def crossright(state, chicken): + if state.is_true("onleft", [chicken]): + state.remove_fact("onleft", [chicken]) + state.add_fact("onright", [chicken]) + return state + else: + return False + +def crossleft(state, chicken): + if state.is_true("onright", [chicken]): + state.remove_fact("onright", [chicken]) + state.add_fact("onleft", [chicken]) + return state + else: + return False + +def declare_ops(): + pyhop.declare_operators(crossright, crossleft) diff --git a/midca/domains/blocksworld_Updated/scene.py b/midca/domains/blocksworld_Updated/scene.py new file mode 100644 index 00000000..50dee2a5 --- /dev/null +++ b/midca/domains/blocksworld_Updated/scene.py @@ -0,0 +1,111 @@ +import copy +from midca.domains.blocksworld.block import Block + +class Scene: + blocks = [] # contains all blocks + + def __init__(self, blocks): + self.blocks = blocks + + def draw(self): + print self.layers_to_s(self._makelayers()) + + def __str__(self): + return self.layers_to_s(self._makelayers()) + + def _makelayers(self): + blockscopy = copy.deepcopy(self.blocks) + + layers = [] # each new layer will be appended to layers + currentlayer = [] # layer currently being prepared + + # find table + for i in range(len(blockscopy)): + if blockscopy[i].type == Block.TABLE: + block = blockscopy.pop(i) + currentlayer.append(block) + layers.append(currentlayer) + break + + # while there are more blocks above the current layer + while len(blockscopy) > 0: + nextlayer = [] + + #print len(currentlayer), len(blockscopy) + for i in range(len(currentlayer)): + for j in range(len(blockscopy)): + if blockscopy[j].on == currentlayer[i]: + nextlayer.append(blockscopy[j]) + + for i in range(len(nextlayer)): + blockscopy.remove(nextlayer[i]) + + currentlayer = nextlayer + layers.append(currentlayer) + if not currentlayer: + break + + return layers + + # layers - as made by _makelayers + def layers_to_s(self, layers): + assert len(layers[0]) == 1 and layers[0][0].type == Block.TABLE + + width = len(layers[1]) + + asciisquares = [] + asciisquares.append([("--------------", layers[0][0]) for tv in range(width + 1)]) + + for i in range(1, len(layers), 1): + asciisquares.append([("", None) for tv in range(width)]) + asciisquares.append([("", None) for tv in range(width)]) + asciisquares.append([("", None) for tv in range(width)]) + + for j in range(width): + written = False + for k in range(len(layers[i])): + if layers[i][k].on == asciisquares[-4][j][1]: + written = True + if layers[i][k].type == Block.TRIANGLE: + if layers[i][k].onfire: + asciisquares[-1][j] = (" / \\ ", layers[i][k]) + asciisquares[-2][j] = (" / * \\ ", layers[i][k]) + asciisquares[-3][j] = (" / *" + str(layers[i][k].id) + "*\\", layers[i][k]) + else: + asciisquares[-1][j] = (" / \\ ", layers[i][k]) + asciisquares[-2][j] = (" / \\ ", layers[i][k]) + asciisquares[-3][j] = (" / " + str(layers[i][k].id) + " \\", layers[i][k]) + elif layers[i][k].type == Block.SQUARE: + if layers[i][k].onfire and layers[i][k].hasmortar: + asciisquares[-1][j] = (" +++++++", layers[i][k]) + asciisquares[-2][j] = (" | *" + str(layers[i][k].id) + "* |", layers[i][k]) + asciisquares[-3][j] = (" -------", layers[i][k]) + elif layers[i][k].onfire: + asciisquares[-1][j] = (" -------", layers[i][k]) + asciisquares[-2][j] = (" | *" + str(layers[i][k].id) + "* |", layers[i][k]) + asciisquares[-3][j] = (" -------", layers[i][k]) + elif layers[i][k].hasmortar: + asciisquares[-1][j] = (" +++++++", layers[i][k]) + asciisquares[-2][j] = (" | " + str(layers[i][k].id) + " |", layers[i][k]) + asciisquares[-3][j] = (" -------", layers[i][k]) + else: + asciisquares[-1][j] = (" -------", layers[i][k]) + asciisquares[-2][j] = (" | " + str(layers[i][k].id) + " |", layers[i][k]) + asciisquares[-3][j] = (" -------", layers[i][k]) + layers[i].pop(k) + break + if not written: + asciisquares[-1][j] = (" ", None) + asciisquares[-2][j] = (" ", None) + asciisquares[-3][j] = (" ", None) + + toprint = "" + for i in range(len(asciisquares)-1, -1, -1): + for segment in asciisquares[i]: + toprint += segment[0] + toprint += "\n" + + return toprint + + + \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/states/blocksworld.shp b/midca/domains/blocksworld_Updated/states/blocksworld.shp new file mode 100644 index 00000000..53a3f770 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/blocksworld.shp @@ -0,0 +1,107 @@ +; This file contains a SHOP domain representation of the block-stacking +;;; algorithm from the following paper: +;;; N. Gupta and D. Nau, On the complexity of blocks-world planning, +;;; Artificial Intelligence 56(2-3):223-254, August 1992. + + +;;; ------------------------------------------------------------------------ +;;; Declare all the data +;;; ------------------------------------------------------------------------ + + +(defdomain blocks-normal + ( + ;; basic block-stacking operators + + (:operator (!pickup ?a) + () + ((clear ?a) (on-table ?a)) + ((holding ?a)) ) + + (:operator (!putdown ?b) + () + ((holding ?b)) + ((on-table ?b) (clear ?b)) ) + + (:operator (!stack ?c ?d) + () + ((holding ?c) (clear ?d)) + ((on ?c ?d) (clear ?c)) ) + + (:operator (!unstack ?e ?f) + () + ((clear ?e) (on ?e ?f)) + ((holding ?e) (clear ?f)) ) + + ;; book-keeping methods & ops, to keep track of what needs to be done + + (:operator (!assert ?g) + () + () + ?g + ;; Since !ASSERT isn't a real blocks-world operator, make its cost 0 + 0) + + (:method (achieve-goals ?goals) + () + ((assert-goals ?goals nil) (move-block nil))) + + (:method (assert-goals (list ?goal . ?goals) ?out) + () + ((assert-goals ?goals (list (goal ?goal) . ?out)))) + + (:method (assert-goals nil ?out) + () + ((!assert ?out))) + + ;; The methods and operators for doing the actual planning + + (:method (move-block ?nomove) + + ;; method for moving x from y to z + (:first (clear ?x) (not ( call member ?x ?nomove)) (on ?x ?y) + (goal (on ?x ?z)) (different ?x ?z) (clear ?z) (not (need-to-move ?z))) + ((!unstack ?x ?y) (!stack ?x ?z) (move-block (list ?x . ?nomove))) + + ;; method for moving x from y to table + (:first (clear ?x) ( not ( call member ?x ?nomove)) + (on ?x ?y) (goal (on-table ?x))) + ((!unstack ?x ?y) (!putdown ?x) (move-block (list ?x . ?nomove))) + + ;; method for moving x from table to y + (:first (clear ?x) (not ( call member ?x ?nomove)) + (on-table ?x) (goal (on ?x ?y)) (clear ?y) (not (need-to-move ?y))) + ((!pickup ?x) (!stack ?x ?y) (move-block (list ?x . ?nomove))) + + ;; method for moving x out of the way + ((clear ?x) (not (call member ?x ?nomove)) + (on ?x ?y) (need-to-move ?x)) + ((!unstack ?x ?y) (!putdown ?x) (move-block ?nomove)) + + ;; if nothing else matches, then we're done + () + ()) + + ;; state axioms + + (:- (different ?x ?y) ((not (same ?x ?y)))) + (:- (same ?x ?x) ()) + (:- (need-to-move ?x) + ;; need to move x if x needs to go from one block to another + ((on ?x ?y) (goal (on ?x ?z)) (different ?y ?z)) + ;; need to move x if x needs to go from table to block + ((on-table ?x) (goal (on ?x ?z))) + ;; need to move x if x needs to go from block to table + ((on ?x ?y) (goal (on-table ?x))) + ;; need to move x if x is on y and y needs to be clear + ((on ?x ?y) (goal (clear ?y))) + ;; need to move x if x is on z and something else needs to be on z + ((on ?x ?z) (goal (on ?y ?z)) (different ?x ?y)) + ;; need to move x if x is on something else that needs to be moved + ((on ?x ?w) (need-to-move ?w))) + (:- (moveable-to-goal ?x) + ((clear ?x) (on ?x ?y) (goal (on ?x ?z)) + (different ?x ?z) (clear ?z) (not (need-to-move ?z))) + ((clear ?x) (on ?x ?y) (goal (on-table ?x))) + ((clear ?x) (on-table ?x) (goal (on ?x ?y)) + (clear ?y) (not (need-to-move ?y)))))) diff --git a/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp b/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp new file mode 100644 index 00000000..cdaf0e47 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp @@ -0,0 +1,12 @@ + +(defproblem bw-ran-5-1 blocks-normal ((arm-empty) +(clear d) +(on-table a) +(on-table c) +(on b a) +(on d b) +(clear c) +) + ((achieve-goals ( list +(on c b) + )))) \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/states/defstate.sim b/midca/domains/blocksworld_Updated/states/defstate.sim new file mode 100644 index 00000000..70f61cb4 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/defstate.sim @@ -0,0 +1,26 @@ +BLOCK(A_) +BLOCK(B_) +BLOCK(C_) +BLOCK(table) +BLOCK(D_) +ARSONIST(Gui Montag) + +on(B_, A_) +on(D_, B_) +on-table(A_) +on-table(C_) + +block(A_) +block(B_) +block(C_) +triangle(D_) +table(table) + +clear(C_) +clear(D_) +arm-empty() + + + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_fire.sim b/midca/domains/blocksworld_Updated/states/defstate_fire.sim new file mode 100644 index 00000000..ce976fc0 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/defstate_fire.sim @@ -0,0 +1,27 @@ +BLOCK(A_) +BLOCK(B_) +BLOCK(C_) +BLOCK(table) +BLOCK(D_) +ARSONIST(Gui Montag) + +on(B_, A_) +on(D_, B_) +on-table(A_) +on-table(C_) +onfire(B_) + +block(A_) +block(B_) +block(C_) +triangle(D_) +table(table) + +clear(C_) +clear(D_) +arm-empty() + + + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim b/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim new file mode 100644 index 00000000..0893c427 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim @@ -0,0 +1,24 @@ +BLOCK(A_) +BLOCK(B_) +BLOCK(C_) +BLOCK(table) +ARSONIST(Gui Montag) + +on(A_, B_) +on-table(B_) +on-table(C_) +onfire(B_) + +block(A_) +block(B_) +block(C_) +table(table) + +clear(C_) +clear(A_) +arm-empty() + + + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_jshop.sim b/midca/domains/blocksworld_Updated/states/defstate_jshop.sim new file mode 100644 index 00000000..c0c4146d --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/defstate_jshop.sim @@ -0,0 +1,26 @@ +BLOCK(a) +BLOCK(b) +BLOCK(c) +BLOCK(table) +BLOCK(d) +ARSONIST(Gui Montag) + +on(b, a) +on(d, b) +on-table(a) +on-table(c) + +block(a) +block(b) +block(c) +triangle(d) +table(table) + +clear(c) +clear(d) +arm-empty() + + + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_mortar.sim b/midca/domains/blocksworld_Updated/states/defstate_mortar.sim new file mode 100644 index 00000000..e0a8d1bd --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/defstate_mortar.sim @@ -0,0 +1,26 @@ +BLOCK(A_) +BLOCK(B_) +BLOCK(C_) +BLOCK(table) +BLOCK(D_) +ARSONIST(Gui Montag) + + +on(B_, A_) +on(D_, B_) +on-table(A_) +on-table(C_) + +block(A_) +block(B_) +block(C_) +triangle(D_) +table(table) + + +clear(C_) +clear(D_) +arm-empty() + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/extinguisher_state.sim b/midca/domains/blocksworld_Updated/states/extinguisher_state.sim new file mode 100644 index 00000000..3805f354 --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/extinguisher_state.sim @@ -0,0 +1,26 @@ +BLOCK(A_) +BLOCK(B_) +BLOCK(C_) +BLOCK(table) +BLOCK(D_) +ARSONIST(Gui Montag) +FIRE-EXTINGUISHER(Fire Extinguisher 1) + +on(B_, A_) +on(D_, B_) +on-table(A_) +on-table(C_) + +block(A_) +block(B_) +block(C_) +triangle(D_) +table(table) +fire-extinguisher(Fire Extinguisher 1) + +clear(C_) +clear(D_) +arm-empty() + +free(Gui Montag) +arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/sample_state.sim b/midca/domains/blocksworld_Updated/states/sample_state.sim new file mode 100644 index 00000000..2f0cb35c --- /dev/null +++ b/midca/domains/blocksworld_Updated/states/sample_state.sim @@ -0,0 +1,20 @@ +#Sample state file using the MIDCA predicate world state definition language. +#These are comments. Multi-line comments are not supported. +#This file will define a state in the simple chicken crossing the road domain. +#This domain is defined in worldsim/domains/sample_domain.sim + +#note: in state files, the "functions" - e.g. CHICKEN, HEN, onright, onleft - +#are type names or predicate names defined in the domain file. A type name +#creates an object of that type with the given name. A predicate name creates +#a predicate + +#Create a chicken. Argument is the chicken's name. +CHICKEN(clucky) + +#Create a hen (subtype of chicken): +HEN(lady cluck) + +#place the two chickens on opposite sides of the road. Argument is the name of +#a chicken which has been created above. +onright(clucky) +onleft(lady cluck) diff --git a/midca/domains/blocksworld_Updated/util.py b/midca/domains/blocksworld_Updated/util.py new file mode 100644 index 00000000..fcd95177 --- /dev/null +++ b/midca/domains/blocksworld_Updated/util.py @@ -0,0 +1,292 @@ +''' +A collection of functions that are domain specific, which different MIDCA components use +''' +import os +from midca.domains.blocksworld import scene, blockstate +from midca.modules._plan import pyhop + +def asqiiDisplay(world): + ''' + Creates an asqii representation for blocksworld. + ''' + blocks = blockstate.get_block_list(world) + print(str(scene.Scene(blocks))) + +def preferApprehend(goal1, goal2): + if 'predicate' not in goal1 or 'predicate' not in goal2: + return 0 + elif goal1['predicate'] == 'free' and goal2['predicate'] != 'free': + return -1 + elif goal1['predicate'] != 'free' and goal2['predicate'] == 'free': + return 1 + elif goal1['predicate'] == 'onfire' and goal2['predicate'] != 'onfire': + return -1 + elif goal1['predicate'] != 'onfire' and goal2['predicate'] == 'onfire': + return 1 + return 0 + +def preferFire(goal1, goal2): + if 'predicate' not in goal1 or 'predicate' not in goal2: + return 0 + elif goal1['predicate'] == 'onfire' and goal2['predicate'] != 'onfire': + return -1 + elif goal1['predicate'] != 'onfire' and goal2['predicate'] == 'onfire': + return 1 + return 0 + +def jshop_state_from_world(world, STATE_FILE, name = "state"): +# thisDir = os.path.dirname(os.path.realpath(__file__)) +# MIDCA_ROOT = thisDir + "/../" +# STATE_FILE = MIDCA_ROOT + "jshop_domains/blocks_world/bw_ran_problems_500.shp" + try: + f = open(STATE_FILE, 'w') + + f.write('\n') + f.write('(defproblem bw-ran-5-1 blocks-normal ((arm-empty)\n') + + for atom in world.atoms: + if atom.predicate.name == "clear": + f.write("(clear " + atom.args[0].name+ ")\n") + elif atom.predicate.name == "on": + f.write("(on " + atom.args[0].name + " " + atom.args[1].name + ")\n") + elif atom.predicate.name == "on-table": + f.write("(on-table " + atom.args[0].name + ")\n") + + f.write(")\n") + f.close() + + except Exception: + print "could not read the state file. Check the path..." + + +def jshop_tasks_from_goals(goals,pyhopState, STATE_FILE): +# thisDir = os.path.dirname(os.path.realpath(__file__)) +# MIDCA_ROOT = thisDir + "/../" +# STATE_FILE = MIDCA_ROOT + "jshop_domains/blocks_world/bw_ran_problems_500.shp" + try: + f = open(STATE_FILE, 'a') + except Exception: + print "could not read the state file. Check the path..." + alltasks = [] + blkgoals = pyhop.Goal("goals") + blkgoals.pos = {} + f.write(" ((achieve-goals ( list\n") + for goal in goals: + #extract predicate + if 'predicate' in goal.kwargs: + predicate = str(goal.kwargs['predicate']) + elif 'Predicate' in goal.kwargs: + predicate = str(goal.kwargs['Predicate']) + elif goal.args: + predicate = str(goal.args[0]) + else: + raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") + args = [str(arg) for arg in goal.args] + if args[0] == predicate: + args.pop(0) + if predicate == "on": + f.write("(on " + args[0] + " " + args[1] + ")\n") + elif predicate == 'on-table': + f.write("(on-table" + blkgoals.pos[args[0]]+ ")\n") + + else: + raise Exception("No task corresponds to predicate " + predicate) + f.write(" ))))") + f.close() + +def pyhop_state_from_world(world, name = "state"): + s = pyhop.State(name) + s.pos = {} + s.clear = {} + s.holding = False + s.fire = {} + s.free = {} + s.fire_ext_avail = set() + s.holdingfireext = None + s.hasmortar = {} # keys are + s.mortaravailable = {} + mortarblocks = [] + blocks = [] + for objname in world.objects: + if world.objects[objname].type.name == "BLOCK" and objname != "table": + blocks.append(objname) + elif world.objects[objname].type.name == "ARSONIST": + s.free[objname] = False + elif world.objects[objname].type.name == "MORTARBLOCK": + mortarblocks.append(objname) + for atom in world.atoms: + if atom.predicate.name == "clear": + s.clear[atom.args[0].name] = True + elif atom.predicate.name == "holding": + s.holding = atom.args[0].name + elif atom.predicate.name == "fire-extinguisher": + s.fire_ext_avail.add(atom.args[0].name) + elif atom.predicate.name == "holdingextinguisher": + s.holdingfireext = atom.args[0].name + elif atom.predicate.name == "arm-empty": + s.holding = False + elif atom.predicate.name == "on": + s.pos[atom.args[0].name] = atom.args[1].name + elif atom.predicate.name == "on-table": + s.pos[atom.args[0].name] = "table" + elif atom.predicate.name == "onfire": + s.fire[atom.args[0].name] = True + elif atom.predicate.name == "free": + s.free[atom.args[0].name] = True + elif atom.predicate.name == "available": + s.mortaravailable[atom.args[0].name] = True + elif "hasmortar" in world.types and atom.predicate.name == "hasmortar": + s.hasmortar[atom.args[0].name] = atom.args[1].name + for block in blocks: + if block not in s.clear: + s.clear[block] = False + if block not in s.fire: + s.fire[block] = False + if block not in s.pos: + s.pos[block] = "in-arm" + if block not in s.hasmortar.keys(): + s.hasmortar[block] = False + + for mblock in mortarblocks: + if mblock not in s.mortaravailable.keys(): + s.mortaravailable[mblock] = False + + return s + +#note: str(arg) must evaluate to the name of the arg in the world representation for this method to work. +# pyhopState doesn't need to be used, but pyhop_tasks_from_goals() will be passed two arguments and needs +# to have it as an arg +def pyhop_tasks_from_goals(goals, pyhopState): + alltasks = [] + blkgoals = pyhop.Goal("goals") + blkgoals.pos = {} + for goal in goals: + #extract predicate + if 'predicate' in goal.kwargs: + predicate = str(goal.kwargs['predicate']) + elif 'Predicate' in goal.kwargs: + predicate = str(goal.kwargs['Predicate']) + elif goal.args: + predicate = str(goal.args[0]) + else: + raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") + + args = [str(arg) for arg in goal.args] + if args[0] == predicate: + args.pop(0) + if predicate == "on": + blkgoals.pos[args[0]] = args[1] + elif predicate == 'on-table': + blkgoals.pos[args[0]] = 'table' + elif predicate == "onfire" and 'negate' in goal and goal['negate'] == True: + alltasks.append(("put_out", args[0])) + elif predicate == "free" and 'negate' in goal and goal['negate'] == True: + alltasks.append(("catch_arsonist", args[0])) + else: + raise Exception("No task corresponds to predicate " + predicate) + if blkgoals.pos: + alltasks.append(("move_blocks", blkgoals)) + return alltasks + + +def mortar_pyhop_state_from_world(world, name = "state"): + s = pyhop.State(name) + s.pos = {} + s.clear = {} + s.holding = False + s.fire = {} + s.free = {} + s.fire_ext_avail = set() + s.holdingfireext = None + s.hasmortar = {} # keys are + s.mortaravailable = {} + mortarblocks = [] + blocks = [] + for objname in world.objects: + if world.objects[objname].type.name == "BLOCK" and objname != "table": + blocks.append(objname) + elif world.objects[objname].type.name == "ARSONIST": + s.free[objname] = False + elif world.objects[objname].type.name == "MORTARBLOCK": + mortarblocks.append(objname) + for atom in world.atoms: + if atom.predicate.name == "clear": + s.clear[atom.args[0].name] = True + elif atom.predicate.name == "holding": + s.holding = atom.args[0].name + elif atom.predicate.name == "fire-extinguisher": + s.fire_ext_avail.add(atom.args[0].name) + elif atom.predicate.name == "holdingextinguisher": + s.holdingfireext = atom.args[0].name + elif atom.predicate.name == "arm-empty": + s.holding = False + elif atom.predicate.name == "on": + s.pos[atom.args[0].name] = atom.args[1].name + s.clear[atom.args[1].name] = False + elif atom.predicate.name == "stable-on": + s.pos[atom.args[0].name] = atom.args[1].name + s.clear[atom.args[1].name] = False + #s.hasmortar[atom.args[1].name] = True # redundant + elif atom.predicate.name == "on-table": + s.pos[atom.args[0].name] = "table" + elif atom.predicate.name == "onfire": + s.fire[atom.args[0].name] = True + elif atom.predicate.name == "free": + s.free[atom.args[0].name] = True + elif atom.predicate.name == "available": + s.mortaravailable[atom.args[0].name] = True + elif atom.predicate.name == "hasmortar": + s.hasmortar[atom.args[0].name] = atom.args[1].name + for block in blocks: + if block not in s.clear: + s.clear[block] = False + if block not in s.fire: + s.fire[block] = False + if block not in s.pos: + s.pos[block] = "in-arm" + if block not in s.hasmortar.keys(): + s.hasmortar[block] = False + + for mblock in mortarblocks: + if mblock not in s.mortaravailable.keys(): + s.mortaravailable[mblock] = False + + return s + +#note: str(arg) must evaluate to the name of the arg in the world representation for this method to work. +def mortar_pyhop_tasks_from_goals(goals, pyhopState): + alltasks = [] + blkgoals = pyhop.Goal("goals") + blkgoals.pos = {} + blkgoals.hasmortar = {} + for goal in goals: + #extract predicate + if 'predicate' in goal.kwargs: + predicate = str(goal.kwargs['predicate']) + elif 'Predicate' in goal.kwargs: + predicate = str(goal.kwargs['Predicate']) + elif goal.args: + predicate = str(goal.args[0]) + else: + raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") + args = [str(arg) for arg in goal.args] + if args[0] == predicate: + args.pop(0) + if predicate == "on": + blkgoals.pos[args[0]] = args[1] + elif predicate == "stable-on": + blkgoals.pos[args[0]] = args[1] + blkgoals.hasmortar[args[1]] = True + elif predicate == 'on-table': + blkgoals.pos[args[0]] = 'table' + elif predicate == "onfire" and 'negate' in goal and goal['negate'] == True: + alltasks.append(("put_out", args[0])) + elif predicate == "free" and 'negate' in goal and goal['negate'] == True: + alltasks.append(("catch_arsonist", args[0])) + else: + raise Exception("No task corresponds to predicate " + predicate) + if blkgoals.pos: + alltasks.append(("move_blocks", blkgoals)) + return alltasks + + diff --git a/midca/domains/jshop_domains/blocks_world/bw_ran_problems_5.shp b/midca/domains/jshop_domains/blocks_world/bw_ran_problems_5.shp index 2b03f9ae..770fe5c1 100644 --- a/midca/domains/jshop_domains/blocks_world/bw_ran_problems_5.shp +++ b/midca/domains/jshop_domains/blocks_world/bw_ran_problems_5.shp @@ -1,12 +1,10 @@ (defproblem bw-ran-5-1 blocks-normal ((arm-empty) (clear d) -(on-table a) (on-table c) (on b a) (on d b) (clear c) +(on-table a) ) ((achieve-goals ( list -(on c b) - )))) \ No newline at end of file diff --git a/midca/domains/minecraft.pddl b/midca/domains/minecraft.pddl new file mode 100644 index 00000000..d81a7ac9 --- /dev/null +++ b/midca/domains/minecraft.pddl @@ -0,0 +1,180 @@ +(define (domain minecraft-beta) + (:requirements :typing :fluents :existential-preconditions) + (:types + resource - thing + mapgrid + player + ) + + (:types + resource - thing + material - thing + tool - thing + craftgrid + mapgrid + direction + player + monster - thing + weapon - thing + food - thing + potion - thing + Helmet - Armor + chestplates - Armor + ) + + (:predicates + (is-trap ?loc - mapgrid) + (looking-for ?res - resource) + (know-where ?res - resource ?loc - mapgrid) + (player-at ?loc - mapgrid) + (in-shelter) + (look-at ?direction - direction) + (monster-at ?zombie - monster ?loc - mapgrid) + (thing-at-map ?obj - resource ?loc - mapgrid) + (thing-at-loc ?obj - resource ?loc - mapgrid) + (known-loc ?obj - resource) + (placed-thing-at-map ?obj - material ?loc - mapgrid) + (resource-at-craft ?res - thing ?loc - craftgrid) + (craft-empty ?loc - craftgrid) + (connect ?from - mapgrid ?to - mapgrid) + (next-to ?from - direction ?to - direction) + (crafting) + (survive) + (eat ?food - food) + (is-attacked) + (is-trapped) + (is-dead ?player -player) + (is-alive ?player -player) + (head-armed) + (chest-armed) + ) + (:hidden is-trap thing-at-loc is-attacked is-trapped) + + (:functions + (self) - player + (thing-available ?obj - thing) - int + (current-harvest-duration) - int + (current-harvest-location) - int + (duration-need ?tool - tool ?res - resource) - int + (location-id ?loc - mapgrid) - int + (tool-id ?tool - tool) - int + (tool-in-hand) - int + (tool-max-health ?tool - tool) - int + (tool-current-health ?tool - tool) - int + (player-current-health) - int + (furnace-fuel) - int + (current-hunger-value) - int + (food-value ?f -food) - int + ) + + + + ;; ---------------------------------------------------- + (:action move + :parameters (?from - mapgrid ?to - mapgrid) + :precondition + (and + (player-at ?from) + (connect ?from ?to) + + ) + :effect + (and + (player-at ?to) + (not (player-at ?from)) + + ) + ) + ;;----------------------------------------------------- + + (:action event-fall-in-trap + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc arrow_trap ?loc) + + (not (is-trapped)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-trapped) + ) + ) + ;;------------------------------------------------------ + + (:action event-skeleton-attacked + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc skeleton ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + (:action event-monster-explosion + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc monster ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map monster-remains ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + + (:action event-die + :parameters (?player -player) + :precondition + ( and + (is-alive ?player) + (eq (player-current-health) 0) + ) + :effect + (and + (is-dead ?player) + ) + ) + + ;;--------------------------------------------- + + (:action event-find + :parameters (?res -resource ?loc -mapgrid ?player-loc -mapgrid) + :precondition + (and + (looking-for ?res) + (connected ?loc ?player-loc) + (thing-at-loc ?res ?loc) + ) + :effect + (and + (know-where ?res ?loc) + ) + + + ) + + +) \ No newline at end of file diff --git a/midca/domains/minecraft/__init__.py b/midca/domains/minecraft/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/midca/domains/minecraft/minecraft.sim b/midca/domains/minecraft/minecraft.sim new file mode 100644 index 00000000..2a11f253 --- /dev/null +++ b/midca/domains/minecraft/minecraft.sim @@ -0,0 +1,87 @@ +type(resource) +type(mapgrid) +type(player) +type(resource) +type(material) +type(tool) +type(craftgrid) +type(mapgrid) +type(direction) +type(player) +type(monster) +type(weapon) +type(food) +type(potion) +type(Helmet) +type(chestplates) + + predicate(is-trap,[loc], [mapgrid]) + predicate(looking-for,[res], [resource]) + predicate(know-where,[res,loc], [resource,mapgrid]) + predicate(player-at,[loc], [mapgrid]) + predicate(in-shelter,[], []) + predicate(look-at,[direction], [direction]) + predicate(monster-at,[zombie,loc], [monster,mapgrid]) + predicate(thing-at-map,[obj,loc], [resource,mapgrid]) + predicate(thing-at-loc,[obj,loc], [resource,mapgrid]) + predicate(known-loc,[obj], [resource]) + predicate(placed-thing-at-map,[obj,loc], [material,mapgrid]) + predicate(resource-at-craft,[res,loc], [thing,craftgrid]) + predicate(craft-empty,[loc], [craftgrid]) + predicate(connect,[from,to], [mapgrid,mapgrid]) + predicate(next-to,[from,to], [direction,direction]) + predicate(crafting,[], []) + predicate(survive,[], []) + predicate(eat,[food], [food]) + predicate(is-attacked,[], []) + predicate(is-trapped,[], []) + predicate(is-dead,[player], [player]) + predicate(is-alive,[player], [player]) + predicate(head-armed,[], []) + predicate(chest-armed,[], []) + operator (move +,args = [(from,mapgrid ), (to,mapgrid )],preconditions = [condition(player-at [?from]), +condition(connect [?from, ?to]), +],results=[condition(player-at, [?to]), +condition(not, [(player-at, ?from)]), +]) + operator (,args = [(loc1,mapgrid ), (loc,mapgrid )],preconditions = [condition(player-at [?loc1]), +condition(connect [?loc1, ?loc]), +condition(thing-at-loc [arrow_trap, ?loc]), +condition(not [(is-trapped)]), +condition(neq [(player-current-health), 0]), +],results=[condition(decrease, [(player-current-health), 5]), +condition(thing-at-map, [arrow, ?loc1]), +condition(is-trapped, []), +]) + operator (event-skeleton-attacked +,args = [(loc1,mapgrid ), (loc,mapgrid )],preconditions = [condition(player-at [?loc1]), +condition(connect [?loc1, ?loc]), +condition(thing-at-loc [skeleton, ?loc]), +condition(not [(is-attacked)]), +condition(neq [(player-current-health), 0]), +],results=[condition(decrease, [(player-current-health), 5]), +condition(thing-at-map, [arrow, ?loc1]), +condition(is-attacked, []), +]) + operator (event-monster-explosion +,args = [(loc1,mapgrid ), (loc,mapgrid )],preconditions = [condition(player-at [?loc1]), +condition(connect [?loc1, ?loc]), +condition(thing-at-loc [monster, ?loc]), +condition(not [(is-attacked)]), +condition(neq [(player-current-health), 0]), +],results=[condition(decrease, [(player-current-health), 5]), +condition(thing-at-map, [monster-remains, ?loc1]), +condition(is-attacked, []), +]) + operator (event-die +,args = [(player,player )],preconditions = [condition(is-alive [?player]), +condition(eq [(player-current-health), 0]), +],results=[condition(is-dead, [?player]), +]) + operator (event-find + ,args = [(res,resource ), (loc,mapgrid ), (player,loc )],preconditions = [condition(looking-for [?res]), +condition(connected [?loc, ?player-loc]), +condition(thing-at-loc [?res, ?loc]), +],results=[condition(know-where, [?res, ?loc]), +]) \ No newline at end of file diff --git a/midca/domains/split1.txt b/midca/domains/split1.txt new file mode 100644 index 00000000..d7c94030 --- /dev/null +++ b/midca/domains/split1.txt @@ -0,0 +1,12 @@ +type,utensil,entity +type,player,entity +type,fork,utensil +type,spoon,utensil +type,knife,utensil +type,salad,fork +type,dinner,fork +type,robot,player +attribute,id,X +attribute,color,blue +attribute,color,yellow +attribute,block,id \ No newline at end of file diff --git a/midca/domains/split2.txt b/midca/domains/split2.txt new file mode 100644 index 00000000..b863341e --- /dev/null +++ b/midca/domains/split2.txt @@ -0,0 +1,6 @@ +attribute,utensil,color +type,fork,utensil +type,spoon,utensil +type,robot,player +relation,on,flatware,table +assignAttribute,utensil,color,yellow \ No newline at end of file diff --git a/midca/domains/test.txt b/midca/domains/test.txt new file mode 100644 index 00000000..0c3ab00e --- /dev/null +++ b/midca/domains/test.txt @@ -0,0 +1,11 @@ +type,utensil,entity +attribute,id,X +attribute,color,blue +attribute,color,yellow +attribute,block,id +attribute,utensil,color +type,fork,utensil +type,spoon,utensil +type,robot,player +relation,on,flatware,table +assignAttribute,utensil,color,yellow \ No newline at end of file diff --git a/midca/domains/test2.txt b/midca/domains/test2.txt new file mode 100644 index 00000000..1a8e8366 --- /dev/null +++ b/midca/domains/test2.txt @@ -0,0 +1,10 @@ +type,utensil,entity +attributeValue,id,X +attributeValue,color,blue +attributeValue,color,yellow +attributeValue,block,id +attribute,utensil,color +type,fork,utensil +type,spoon,utensil +type,robot,player +relation,on,flatware,table \ No newline at end of file From c111e497322458c631ef7e011b77ec4e6f85e3d7 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 1 Dec 2020 14:54:22 -0500 Subject: [PATCH 11/23] Attributes combined from types ancestors --- midca/domains/Object_Hierarchy_Tree.py | 29 ++-- midca/domains/minecraft.txt | 23 +++ midca/domains/minecraft/plan/minecraft.pddl | 180 ++++++++++++++++++++ midca/domains/split1.txt | 8 +- midca/domains/split2.txt | 3 +- midca/domains/test.txt | 5 +- 6 files changed, 226 insertions(+), 22 deletions(-) create mode 100644 midca/domains/minecraft.txt create mode 100644 midca/domains/minecraft/plan/minecraft.pddl diff --git a/midca/domains/Object_Hierarchy_Tree.py b/midca/domains/Object_Hierarchy_Tree.py index 18e78c87..744705b1 100644 --- a/midca/domains/Object_Hierarchy_Tree.py +++ b/midca/domains/Object_Hierarchy_Tree.py @@ -37,6 +37,7 @@ from collections import defaultdict + directedGraph = defaultdict(list) attributesAndValues = defaultdict(list) enumerationList = [] @@ -114,19 +115,23 @@ def printPDDL(directedGraph): # prints tree with DFS -def printTree(directedGraph, node): +def printTree(directedGraph, node, printAttributesBool): visited = set() # Set to keep track of visited nodes. - - dfs(visited, directedGraph, node, 0) - -def dfs(visited, graph, node, depth): + attributes = attributesAndValues[node] + + dfs(visited, directedGraph, node, 0, printAttributesBool, attributes) + + +def dfs(visited, graph, node, depth, printAttributesBool, attributes): if node not in visited: print('\t' * depth + '+-- ' + node) + attributes = attributes + attributesAndValues[node] + if printAttributesBool: + #print('\t' * depth + ' ' + (str)(attributes)) # print all accumulated attributes + print('\t' * depth + ' ' + (str)(attributesAndValues[node])) # print only specific attributes visited.add(node) - for neighbour in graph[node]: - dfs(visited, graph, neighbour, depth + 1) - - + for child in graph[node]: + dfs(visited, graph, child, depth + 1, printAttributesBool, attributes) objectInput(directedGraph, enumerationList, fileinput.input()) #fileinput.input() is for passed cmd line files @@ -135,8 +140,7 @@ def dfs(visited, graph, node, depth): #print("Edges of type tree: " + str(generate_edges(directedGraph))) #print ("Type Tree: " + (str)(directedGraph)) #print("Edges of attribute tree: " + str (generate_edges(attributesAndValues))) -stringAttributeAndValues = (str)(attributesAndValues) -#print ("Attribute Tree: " + stringAttributeAndValues) +#print ("Attribute Tree: " + (str)(attributesAndValues)) #printEnumerationList(enumerationList) # test type values from input @@ -144,5 +148,6 @@ def dfs(visited, graph, node, depth): #API ENFORCES ENTITY PARENT -printTree(directedGraph, 'entity') +printAttributesBool = True +printTree(directedGraph, 'entity', printAttributesBool) diff --git a/midca/domains/minecraft.txt b/midca/domains/minecraft.txt new file mode 100644 index 00000000..a7e879b3 --- /dev/null +++ b/midca/domains/minecraft.txt @@ -0,0 +1,23 @@ +type,mob,entity +type,item,entity +type,block,item +type,tool,item +type,stone,block +type,grass,block +type,pickaxe,tool +type,sword,tool +type,player,mob +type,hostile,mob +type,passive,mob +type,creeper,hostile +type,skeleton,hostile +type,pig,passive +type,chicken,passive +attribute,mob,health +attribute,passive,age +attribute,block,breakable +attribute,item,craftable +attribute,sword,damage +attribute,pickaxe,speed +attribute,player,armor +attribute,skeleton,armor \ No newline at end of file diff --git a/midca/domains/minecraft/plan/minecraft.pddl b/midca/domains/minecraft/plan/minecraft.pddl new file mode 100644 index 00000000..d81a7ac9 --- /dev/null +++ b/midca/domains/minecraft/plan/minecraft.pddl @@ -0,0 +1,180 @@ +(define (domain minecraft-beta) + (:requirements :typing :fluents :existential-preconditions) + (:types + resource - thing + mapgrid + player + ) + + (:types + resource - thing + material - thing + tool - thing + craftgrid + mapgrid + direction + player + monster - thing + weapon - thing + food - thing + potion - thing + Helmet - Armor + chestplates - Armor + ) + + (:predicates + (is-trap ?loc - mapgrid) + (looking-for ?res - resource) + (know-where ?res - resource ?loc - mapgrid) + (player-at ?loc - mapgrid) + (in-shelter) + (look-at ?direction - direction) + (monster-at ?zombie - monster ?loc - mapgrid) + (thing-at-map ?obj - resource ?loc - mapgrid) + (thing-at-loc ?obj - resource ?loc - mapgrid) + (known-loc ?obj - resource) + (placed-thing-at-map ?obj - material ?loc - mapgrid) + (resource-at-craft ?res - thing ?loc - craftgrid) + (craft-empty ?loc - craftgrid) + (connect ?from - mapgrid ?to - mapgrid) + (next-to ?from - direction ?to - direction) + (crafting) + (survive) + (eat ?food - food) + (is-attacked) + (is-trapped) + (is-dead ?player -player) + (is-alive ?player -player) + (head-armed) + (chest-armed) + ) + (:hidden is-trap thing-at-loc is-attacked is-trapped) + + (:functions + (self) - player + (thing-available ?obj - thing) - int + (current-harvest-duration) - int + (current-harvest-location) - int + (duration-need ?tool - tool ?res - resource) - int + (location-id ?loc - mapgrid) - int + (tool-id ?tool - tool) - int + (tool-in-hand) - int + (tool-max-health ?tool - tool) - int + (tool-current-health ?tool - tool) - int + (player-current-health) - int + (furnace-fuel) - int + (current-hunger-value) - int + (food-value ?f -food) - int + ) + + + + ;; ---------------------------------------------------- + (:action move + :parameters (?from - mapgrid ?to - mapgrid) + :precondition + (and + (player-at ?from) + (connect ?from ?to) + + ) + :effect + (and + (player-at ?to) + (not (player-at ?from)) + + ) + ) + ;;----------------------------------------------------- + + (:action event-fall-in-trap + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc arrow_trap ?loc) + + (not (is-trapped)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-trapped) + ) + ) + ;;------------------------------------------------------ + + (:action event-skeleton-attacked + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc skeleton ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + (:action event-monster-explosion + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc monster ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map monster-remains ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + + (:action event-die + :parameters (?player -player) + :precondition + ( and + (is-alive ?player) + (eq (player-current-health) 0) + ) + :effect + (and + (is-dead ?player) + ) + ) + + ;;--------------------------------------------- + + (:action event-find + :parameters (?res -resource ?loc -mapgrid ?player-loc -mapgrid) + :precondition + (and + (looking-for ?res) + (connected ?loc ?player-loc) + (thing-at-loc ?res ?loc) + ) + :effect + (and + (know-where ?res ?loc) + ) + + + ) + + +) \ No newline at end of file diff --git a/midca/domains/split1.txt b/midca/domains/split1.txt index d7c94030..7732663b 100644 --- a/midca/domains/split1.txt +++ b/midca/domains/split1.txt @@ -6,7 +6,7 @@ type,knife,utensil type,salad,fork type,dinner,fork type,robot,player -attribute,id,X -attribute,color,blue -attribute,color,yellow -attribute,block,id \ No newline at end of file +attribute,utensil,color +attribute,utensil,price +attribute,fork,prongs +attribute,knife,sharpness \ No newline at end of file diff --git a/midca/domains/split2.txt b/midca/domains/split2.txt index b863341e..c80768e3 100644 --- a/midca/domains/split2.txt +++ b/midca/domains/split2.txt @@ -2,5 +2,4 @@ attribute,utensil,color type,fork,utensil type,spoon,utensil type,robot,player -relation,on,flatware,table -assignAttribute,utensil,color,yellow \ No newline at end of file +relation,on,flatware,table \ No newline at end of file diff --git a/midca/domains/test.txt b/midca/domains/test.txt index 0c3ab00e..9cff1eb6 100644 --- a/midca/domains/test.txt +++ b/midca/domains/test.txt @@ -1,11 +1,8 @@ type,utensil,entity attribute,id,X -attribute,color,blue -attribute,color,yellow attribute,block,id attribute,utensil,color type,fork,utensil type,spoon,utensil type,robot,player -relation,on,flatware,table -assignAttribute,utensil,color,yellow \ No newline at end of file +relation,on,flatware,table \ No newline at end of file From ff5a033378d2ca2ec99e948c3c9c83db88b9d452 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 10 Feb 2021 18:10:02 -0500 Subject: [PATCH 12/23] working code stub generation for detectors --- midca/domains/Object_Hierarchy_Tree.py | 221 +++++++++++++++--- midca/domains/coloredBlocksworld.txt | 13 ++ midca/domains/coloredBlocksworldDetectors.cpp | 40 ++++ .../coloredBlocksworldEntitiesHandler.py | 32 +++ midca/domains/minecraft/minecraft.txt | 27 +++ .../domains/minecraft/minecraftDetectors.cpp | 120 ++++++++++ .../minecraft/minecraftEntitiesHandler.py | 40 ++++ midca/domains/minecraftDetectors.cpp | 120 ++++++++++ midca/domains/minecraftEntitiesHandler.py | 40 ++++ midca/domains/templates/detectorsTemplate.txt | 33 +++ .../templates/entitiesHandlerTemplate.txt | 32 +++ 11 files changed, 690 insertions(+), 28 deletions(-) create mode 100644 midca/domains/coloredBlocksworld.txt create mode 100644 midca/domains/coloredBlocksworldDetectors.cpp create mode 100644 midca/domains/coloredBlocksworldEntitiesHandler.py create mode 100644 midca/domains/minecraft/minecraft.txt create mode 100644 midca/domains/minecraft/minecraftDetectors.cpp create mode 100644 midca/domains/minecraft/minecraftEntitiesHandler.py create mode 100644 midca/domains/minecraftDetectors.cpp create mode 100644 midca/domains/minecraftEntitiesHandler.py create mode 100644 midca/domains/templates/detectorsTemplate.txt create mode 100644 midca/domains/templates/entitiesHandlerTemplate.txt diff --git a/midca/domains/Object_Hierarchy_Tree.py b/midca/domains/Object_Hierarchy_Tree.py index 744705b1..f1dd6df0 100644 --- a/midca/domains/Object_Hierarchy_Tree.py +++ b/midca/domains/Object_Hierarchy_Tree.py @@ -31,16 +31,31 @@ #TODO: Attribute and AttributeValue need to be separate things +from __future__ import print_function import sys import csv -import fileinput #for command line file name +import fileinput # supports inplace editing +import argparse # handles cmd line args and verbose logging levels +import shutil # file copying from collections import defaultdict directedGraph = defaultdict(list) -attributesAndValues = defaultdict(list) +attributes = defaultdict(list) enumerationList = [] +attributeValues = defaultdict(list) +relations = defaultdict(list) +entityRelations = defaultdict(list) # associates relations to the key of entity + +# all inherited values for each entity +inheritedAttributes = defaultdict(list) +inheritedRelations = defaultdict(list) + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Graph Functions +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #Adds node to the directedGraph def addEdge(directedGraph, u, v): @@ -82,24 +97,30 @@ def printEnumerationList(enumerationList): #main function that reads in a file of data and creates a directed tree of types #and directed tree of attributes as well as an enumeration list of attributes -def objectInput(directedGraph, enumerationList, newFile2): +def objectInput(directedGraph, enumerationList, config): index = 0 #create directed graph tree off of information provided in document - #newFile2 = open('test.txt') - fileText2 = csv.reader(newFile2, delimiter = ',') - for row in fileText2: + configFile = open(config) + fileText = csv.reader(configFile, delimiter = ',') + for row in fileText: #if it is a type it is added to the type tree if row[0] == "type": directedGraph[row[2]].insert(index, row[1]) index += 1 - #if it is an attribute, then it addes it to the attribute tree + #if it is an attribute, then add it to the attribute tree #and enumeration list elif row[0] == "attribute": - attributesAndValues[row[1]].insert(index, row[2]) + attributes[row[1]].insert(index, row[2]) tempTupple = (row[2], row[1]) enumerationList.append(tempTupple) + elif row[0] == "attributeValue": + attributeValues[row[1]].insert(index, row[2]) + elif row[0] == "relation": + for type in row[2:]: # for each type in the relationship + relations[row[1]].insert(index, type) + entityRelations[row[2]].append(row[1]) # add relation as a child of the first entity - #newFile2.close() + configFile.close() def printPDDL(directedGraph): @@ -117,37 +138,181 @@ def printPDDL(directedGraph): # prints tree with DFS def printTree(directedGraph, node, printAttributesBool): visited = set() # Set to keep track of visited nodes. - attributes = attributesAndValues[node] + attrib = attributes[node] - dfs(visited, directedGraph, node, 0, printAttributesBool, attributes) + dfsPrint(visited, directedGraph, node, 0, printAttributesBool, attrib) -def dfs(visited, graph, node, depth, printAttributesBool, attributes): +def dfsPrint(visited, graph, node, depth, printAttributesBool, attrib): if node not in visited: print('\t' * depth + '+-- ' + node) - attributes = attributes + attributesAndValues[node] + attrib = attrib + attributes[node] if printAttributesBool: - #print('\t' * depth + ' ' + (str)(attributes)) # print all accumulated attributes - print('\t' * depth + ' ' + (str)(attributesAndValues[node])) # print only specific attributes + print('\t' * depth + ' ' + (str)(attributes[node])) # print only specific attributes + visited.add(node) + for child in graph[node]: + dfsPrint(visited, graph, child, depth + 1, printAttributesBool, attrib) + +# accumulate inherited attributes with DFS +def accumulateAttributes(directedGraph, node): + visited = set() # Set to keep track of visited nodes. + attrib = attributes[node] + eRelations = entityRelations[node] + + dfsAccumulate(visited, directedGraph, node, attrib, eRelations) + + +def dfsAccumulate(visited, graph, node, attrib, eRelations): + if node not in visited: + attrib = attrib + attributes[node] + eRelations = eRelations + entityRelations[node] visited.add(node) + + #only save accumulated attributes for leaf nodes + if len(graph[node]) == 0: + inheritedAttributes[node] = attrib + inheritedRelations[node] = eRelations + #print('{}: {}'.format(node, inheritedAttributes[node])) + #print('{}: {}'.format(node, inheritedRelations[node])) + for child in graph[node]: - dfs(visited, graph, child, depth + 1, printAttributesBool, attributes) + dfsAccumulate(visited, graph, child, attrib, eRelations) + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Writing Templates +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def modifyDetectors(filename): + file = fileinput.FileInput(filename, inplace=True) + #file = fileinput.FileInput(filename) # test output + + for line in file: + if '' in line: + print(line.replace('', filename.replace('Detectors.cpp', '')), end='') + + # Add methods for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + methodTxt = 'std::string detect_()\n{\n\t//TODO: create _attr string with the following attributes:\n\t//\n\n\treturn _attr;\n}\n' + methodTxt = methodTxt.replace('', attrib) + methodTxt = methodTxt.replace('', (str)(inheritedAttributes[attrib])) + + print(methodTxt) + # Add topics for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + topicTxt = '\tros::Publisher _pub = n.advertise("_attr", 1);' + topicTxt = topicTxt.replace('', attrib) + + print(topicTxt) + # Add publishers for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + publishTxt = '\t\t_pub.publish(_attr);' + publishTxt = publishTxt.replace('', attrib) + + print(publishTxt) + + else: + print(line, end='') + + file.close() + +def modifyHandler(filename): + file = fileinput.FileInput(filename, inplace=True) + #file = fileinput.FileInput(filename) # test output + #print(' ') + + for line in file: + if '' in line: + print(line.replace('', filename.replace('EntitiesHandler.py', '')), end='') + + # Add relations for each entity in domain + elif '' in line: + for relate in inheritedRelations: + print(' #{}: {}'.format(relate, (str)(inheritedRelations[relate]))) + else: + print(line, end='') + + file.close() + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Main +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if __name__ == "__main__": + # manage args + parser = argparse.ArgumentParser() + parser.add_argument("config", help="domain specific configuration file") + parser.add_argument("-v","--verbosity",action="count",default=0,help="increase output verbosity") + args = parser.parse_args() + + objectInput(directedGraph, enumerationList, args.config) #generate config from passed file + + # add output based on verbosity + if args.verbosity >= 1: + # print generated trees and edges + print("Edges of type tree: " + str(generate_edges(directedGraph))) + if args.verbosity >= 2: + print("Type Tree: " + (str)(directedGraph)) + + print("\nEdges of attribute tree: " + str (generate_edges(attributes))) + if args.verbosity >= 2: + print("Attribute Tree: " + (str)(attributes)) + # printEnumerationList(enumerationList) + + print("\nEdges of attributeValues tree: " + str (generate_edges(attributeValues))) + if args.verbosity >= 2: + print("Attribute Tree: " + (str)(attributeValues)) + + print("\nEdges of relations tree: " + str (generate_edges(relations))) + if args.verbosity >= 2: + print("Relations Tree: " + (str)(relations)) + + # test type values from input + # printPDDL(directedGraph) + if args.verbosity == 3: + #API ENFORCES ENTITY PARENT + print('') + printTree(directedGraph, 'entity', False) # print entity tree without attributes + elif args.verbosity >= 4: + #API ENFORCES ENTITY PARENT + print('') + printTree(directedGraph, 'entity', True) # print entity tree with attributes + + + accumulateAttributes(directedGraph, 'entity') + + # Test output for each entity with their attributes for object detection code stubs and helpers + # copy template to modify + src='templates/detectorsTemplate.txt' + dst= args.config.replace('.txt', 'Detectors.cpp') + shutil.copy(src,dst) + + modifyDetectors(dst) + + + # Test output for each entity and their predicates for perception to determine relations + + # copy template to modify + src='templates/entitiesHandlerTemplate.txt' + dst= args.config.replace('.txt', 'EntitiesHandler.py') + shutil.copy(src,dst) + + modifyHandler(dst) + + + + + + + + + -objectInput(directedGraph, enumerationList, fileinput.input()) #fileinput.input() is for passed cmd line files -# print generated trees and edges -#print("Edges of type tree: " + str(generate_edges(directedGraph))) -#print ("Type Tree: " + (str)(directedGraph)) -#print("Edges of attribute tree: " + str (generate_edges(attributesAndValues))) -#print ("Attribute Tree: " + (str)(attributesAndValues)) -#printEnumerationList(enumerationList) -# test type values from input -printPDDL(directedGraph) -#API ENFORCES ENTITY PARENT -printAttributesBool = True -printTree(directedGraph, 'entity', printAttributesBool) diff --git a/midca/domains/coloredBlocksworld.txt b/midca/domains/coloredBlocksworld.txt new file mode 100644 index 00000000..3f4a1b2f --- /dev/null +++ b/midca/domains/coloredBlocksworld.txt @@ -0,0 +1,13 @@ +type,block,entity +attribute,block,color +attribute,block,x +attribute,block,y +attribute,block,z +attributeValue,color,red +attributeValue,color,green +attributeValue,color,blue +attributeValue,x,INT +attributeValue,y,INT +attributeValue,z,INT +relation,on,block,block +relation,clear,block \ No newline at end of file diff --git a/midca/domains/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworldDetectors.cpp new file mode 100644 index 00000000..6f3afd34 --- /dev/null +++ b/midca/domains/coloredBlocksworldDetectors.cpp @@ -0,0 +1,40 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + +std::string detect_block() +{ + //TODO: create block_attr string with the following attributes: + //['color', 'z', 'y', 'x'] + + return block_attr; +} + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting coloredBlocksworld Entity Detectors node"); + + ros::init(argc, argv, "coloredBlocksworld_entity_detectors"); + ros::NodeHandle n; + + ros::Publisher block_pub = n.advertise("block_attr", 1); + + while (ros::ok()) + { + block_pub.publish(block_attr); + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworldEntitiesHandler.py new file mode 100644 index 00000000..b0c3739f --- /dev/null +++ b/midca/domains/coloredBlocksworldEntitiesHandler.py @@ -0,0 +1,32 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class coloredBlocksworldEntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + #block: ['on', 'clear'] diff --git a/midca/domains/minecraft/minecraft.txt b/midca/domains/minecraft/minecraft.txt new file mode 100644 index 00000000..51f78f47 --- /dev/null +++ b/midca/domains/minecraft/minecraft.txt @@ -0,0 +1,27 @@ +type,mob,entity +type,item,entity +type,block,item +type,tool,item +type,stone,block +type,grass,block +type,pickaxe,tool +type,sword,tool +type,player,mob +type,hostile,mob +type,passive,mob +type,creeper,hostile +type,skeleton,hostile +type,pig,passive +type,chicken,passive +attribute,mob,health +attribute,passive,age +attribute,block,breakable +attribute,item,craftable +attribute,sword,damage +attribute,pickaxe,speed +attribute,player,armor +attribute,skeleton,armor +relation,place,block +relation,kill,mob,mob +relation,break,block +relation,use,tool \ No newline at end of file diff --git a/midca/domains/minecraft/minecraftDetectors.cpp b/midca/domains/minecraft/minecraftDetectors.cpp new file mode 100644 index 00000000..cb2a56fa --- /dev/null +++ b/midca/domains/minecraft/minecraftDetectors.cpp @@ -0,0 +1,120 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + +std::string detect_stone() +{ + //TODO: create stone_attr string with the following attributes: + //['craftable', 'breakable'] + + return stone_attr; +} + +std::string detect_skeleton() +{ + //TODO: create skeleton_attr string with the following attributes: + //['health', 'armor'] + + return skeleton_attr; +} + +std::string detect_creeper() +{ + //TODO: create creeper_attr string with the following attributes: + //['health'] + + return creeper_attr; +} + +std::string detect_pig() +{ + //TODO: create pig_attr string with the following attributes: + //['health', 'age'] + + return pig_attr; +} + +std::string detect_player() +{ + //TODO: create player_attr string with the following attributes: + //['health', 'armor'] + + return player_attr; +} + +std::string detect_pickaxe() +{ + //TODO: create pickaxe_attr string with the following attributes: + //['craftable', 'speed'] + + return pickaxe_attr; +} + +std::string detect_sword() +{ + //TODO: create sword_attr string with the following attributes: + //['craftable', 'damage'] + + return sword_attr; +} + +std::string detect_chicken() +{ + //TODO: create chicken_attr string with the following attributes: + //['health', 'age'] + + return chicken_attr; +} + +std::string detect_grass() +{ + //TODO: create grass_attr string with the following attributes: + //['craftable', 'breakable'] + + return grass_attr; +} + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting minecraft/minecraft Entity Detectors node"); + + ros::init(argc, argv, "minecraft/minecraft_entity_detectors"); + ros::NodeHandle n; + + ros::Publisher stone_pub = n.advertise("stone_attr", 1); + ros::Publisher skeleton_pub = n.advertise("skeleton_attr", 1); + ros::Publisher creeper_pub = n.advertise("creeper_attr", 1); + ros::Publisher pig_pub = n.advertise("pig_attr", 1); + ros::Publisher player_pub = n.advertise("player_attr", 1); + ros::Publisher pickaxe_pub = n.advertise("pickaxe_attr", 1); + ros::Publisher sword_pub = n.advertise("sword_attr", 1); + ros::Publisher chicken_pub = n.advertise("chicken_attr", 1); + ros::Publisher grass_pub = n.advertise("grass_attr", 1); + + while (ros::ok()) + { + stone_pub.publish(stone_attr); + skeleton_pub.publish(skeleton_attr); + creeper_pub.publish(creeper_attr); + pig_pub.publish(pig_attr); + player_pub.publish(player_attr); + pickaxe_pub.publish(pickaxe_attr); + sword_pub.publish(sword_attr); + chicken_pub.publish(chicken_attr); + grass_pub.publish(grass_attr); + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/minecraft/minecraftEntitiesHandler.py b/midca/domains/minecraft/minecraftEntitiesHandler.py new file mode 100644 index 00000000..d72336bc --- /dev/null +++ b/midca/domains/minecraft/minecraftEntitiesHandler.py @@ -0,0 +1,40 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class minecraft/minecraftEntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(minecraft/minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + #stone: ['place', 'break'] + #skeleton: ['kill'] + #creeper: ['kill'] + #pig: ['kill'] + #player: ['kill'] + #pickaxe: ['use'] + #sword: ['use'] + #chicken: ['kill'] + #grass: ['place', 'break'] diff --git a/midca/domains/minecraftDetectors.cpp b/midca/domains/minecraftDetectors.cpp new file mode 100644 index 00000000..33c6d875 --- /dev/null +++ b/midca/domains/minecraftDetectors.cpp @@ -0,0 +1,120 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + +std::string detect_stone() +{ + //TODO: create stone_attr string with the following attributes: + //['craftable', 'breakable'] + + return stone_attr; +} + +std::string detect_skeleton() +{ + //TODO: create skeleton_attr string with the following attributes: + //['health', 'armor'] + + return skeleton_attr; +} + +std::string detect_creeper() +{ + //TODO: create creeper_attr string with the following attributes: + //['health'] + + return creeper_attr; +} + +std::string detect_pig() +{ + //TODO: create pig_attr string with the following attributes: + //['health', 'age'] + + return pig_attr; +} + +std::string detect_player() +{ + //TODO: create player_attr string with the following attributes: + //['health', 'armor'] + + return player_attr; +} + +std::string detect_pickaxe() +{ + //TODO: create pickaxe_attr string with the following attributes: + //['craftable', 'speed'] + + return pickaxe_attr; +} + +std::string detect_sword() +{ + //TODO: create sword_attr string with the following attributes: + //['craftable', 'damage'] + + return sword_attr; +} + +std::string detect_chicken() +{ + //TODO: create chicken_attr string with the following attributes: + //['health', 'age'] + + return chicken_attr; +} + +std::string detect_grass() +{ + //TODO: create grass_attr string with the following attributes: + //['craftable', 'breakable'] + + return grass_attr; +} + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting minecraft Entity Detectors node"); + + ros::init(argc, argv, "minecraft_entity_detectors"); + ros::NodeHandle n; + + ros::Publisher stone_pub = n.advertise("stone_attr", 1); + ros::Publisher skeleton_pub = n.advertise("skeleton_attr", 1); + ros::Publisher creeper_pub = n.advertise("creeper_attr", 1); + ros::Publisher pig_pub = n.advertise("pig_attr", 1); + ros::Publisher player_pub = n.advertise("player_attr", 1); + ros::Publisher pickaxe_pub = n.advertise("pickaxe_attr", 1); + ros::Publisher sword_pub = n.advertise("sword_attr", 1); + ros::Publisher chicken_pub = n.advertise("chicken_attr", 1); + ros::Publisher grass_pub = n.advertise("grass_attr", 1); + + while (ros::ok()) + { + stone_pub.publish(stone_attr); + skeleton_pub.publish(skeleton_attr); + creeper_pub.publish(creeper_attr); + pig_pub.publish(pig_attr); + player_pub.publish(player_attr); + pickaxe_pub.publish(pickaxe_attr); + sword_pub.publish(sword_attr); + chicken_pub.publish(chicken_attr); + grass_pub.publish(grass_attr); + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/minecraftEntitiesHandler.py b/midca/domains/minecraftEntitiesHandler.py new file mode 100644 index 00000000..94c38d42 --- /dev/null +++ b/midca/domains/minecraftEntitiesHandler.py @@ -0,0 +1,40 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class minecraftEntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + #stone: ['place', 'break'] + #skeleton: ['kill'] + #creeper: ['kill'] + #pig: ['kill'] + #player: ['kill'] + #pickaxe: ['use'] + #sword: ['use'] + #chicken: ['kill'] + #grass: ['place', 'break'] diff --git a/midca/domains/templates/detectorsTemplate.txt b/midca/domains/templates/detectorsTemplate.txt new file mode 100644 index 00000000..883fdeea --- /dev/null +++ b/midca/domains/templates/detectorsTemplate.txt @@ -0,0 +1,33 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting Entity Detectors node"); + + ros::init(argc, argv, "_entity_detectors"); + ros::NodeHandle n; + + + + while (ros::ok()) + { + + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/templates/entitiesHandlerTemplate.txt b/midca/domains/templates/entitiesHandlerTemplate.txt new file mode 100644 index 00000000..67a1646c --- /dev/null +++ b/midca/domains/templates/entitiesHandlerTemplate.txt @@ -0,0 +1,32 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class EntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(EntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + \ No newline at end of file From e99fbd36f1f8da9f642c86c064f185f4891be1f6 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 17 Feb 2021 14:58:43 -0500 Subject: [PATCH 13/23] rework to templated code placement in domain subdirectory --- midca/domains/Midca_Domain_API.py | 305 ++++++++++++++++++ .../coloredBlocksworld/coloredBlocksworld.cfg | 14 + .../ros/coloredBlocksworldDetectors.cpp | 40 +++ .../ros/coloredBlocksworldEntitiesHandler.py | 32 ++ .../{minecraft.txt => minecraft.cfg} | 0 .../{ => ros}/minecraftDetectors.cpp | 4 +- .../{ => ros}/minecraftEntitiesHandler.py | 4 +- 7 files changed, 395 insertions(+), 4 deletions(-) create mode 100644 midca/domains/Midca_Domain_API.py create mode 100644 midca/domains/coloredBlocksworld/coloredBlocksworld.cfg create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py rename midca/domains/minecraft/{minecraft.txt => minecraft.cfg} (100%) rename midca/domains/minecraft/{ => ros}/minecraftDetectors.cpp (95%) rename midca/domains/minecraft/{ => ros}/minecraftEntitiesHandler.py (88%) diff --git a/midca/domains/Midca_Domain_API.py b/midca/domains/Midca_Domain_API.py new file mode 100644 index 00000000..143991c5 --- /dev/null +++ b/midca/domains/Midca_Domain_API.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python +# coding: utf-8 + +# In[ ]: + + +#MIDCA DOMAIN API +#Reads in a file of the format specification,object2,object1 +#Specification can be a type, i.e. a spoon (object2) is a utensil (object1) +#or specification can be an attribute, i.e., a utensil (object2) can be a color (object1) +#Requirement: Be able to take in input and add it to the object hierarchy tree +#Requirement: Act as an interface between ros and MIDCA for objects + +#Detector -> type, xblock, isablock +#then it is passed to MIDCA from interface +#All objects have types and possibly attributes. Attributes have values (ie type color has values +#green, red, etc) +#uniform naming via the type system and simple attributes +#Each action has a piece of code to handle and determine when its over +#define predicate formulation +#Be Able to ultimately define a new domain +# detect object types, what are predicates in domain, do actions, when is action done, and +# naming of objects and handling of attributes +# Naming -> type + unique identifier, decrement unique identifier if item disappears so +# block2 doesn't become block3 when it reappears + +#robot -> be able to list objects, then the robot detects objects, and can click to assign objects? + +#TODO: Attribute and AttributeValue need to be separate things + +from __future__ import print_function +import sys +import os +import csv +import fileinput # supports inplace editing +import argparse # handles cmd line args and verbose logging levels +import shutil # file copying + +from collections import defaultdict + + +directedGraph = defaultdict(list) +attributes = defaultdict(list) +enumerationList = [] +attributeValues = defaultdict(list) +relations = defaultdict(list) +entityRelations = defaultdict(list) # associates relations to the key of entity + +# all inherited values for each entity +inheritedAttributes = defaultdict(list) +inheritedRelations = defaultdict(list) + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Graph Functions +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#Adds node to the directedGraph +def addEdge(directedGraph, u, v): + directedGraph[u].append(v) + +#Adds the directional relationship between objects +def generate_edges(directedGraph): + edges = [] + # for each node in directedGraph + for node in directedGraph: + # for each relation node of a single node + for relation in directedGraph[node]: + # if edge exists then append + edges.append((node, relation)) + return edges + +#function that prints out the enumeration list of attributes with index values +def printEnumerationList(enumerationList): + for idx, (object, attribute) in enumerate(enumerationList): + print("index is %d, name is %s, and attribute is %s" + % (idx, object, attribute)) + +#main function that reads in a file of data and creates a directed tree of types +#and directed tree of attributes as well as an enumeration list of attributes +def objectInput(directedGraph, enumerationList, config): + index = 0 + #create directed graph tree off of information provided in document + configFile = open(config) + fileText = csv.reader(configFile, delimiter = ',') + for row in fileText: + #if it is a type it is added to the type tree + if row[0] == "type": + directedGraph[row[2]].insert(index, row[1]) + index += 1 + #if it is an attribute, then add it to the attribute tree + #and enumeration list + elif row[0] == "attribute": + attributes[row[1]].insert(index, row[2]) + tempTupple = (row[2], row[1]) + enumerationList.append(tempTupple) + elif row[0] == "attributeValue": + attributeValues[row[1]].insert(index, row[2]) + elif row[0] == "relation": + for type in row[2:]: # for each type in the relationship + relations[row[1]].insert(index, type) + entityRelations[row[2]].append(row[1]) # add relation as a child of the first entity + + configFile.close() + + +def printPDDL(directedGraph): + # print PDDL types + print('\t(:types') + for node in directedGraph: + #print('' + node) + + for relation in directedGraph[node]: + print('\t ' + relation + ' -' + node) + + print('\t)\n') + + +# prints tree with DFS +def printTree(directedGraph, node, printAttributesBool): + visited = set() # Set to keep track of visited nodes. + attrib = attributes[node] + + dfsPrint(visited, directedGraph, node, 0, printAttributesBool, attrib) + + +def dfsPrint(visited, graph, node, depth, printAttributesBool, attrib): + if node not in visited: + print('\t' * depth + '+-- ' + node) + attrib = attrib + attributes[node] + if printAttributesBool: + print('\t' * depth + ' ' + (str)(attributes[node])) # print only specific attributes + visited.add(node) + for child in graph[node]: + dfsPrint(visited, graph, child, depth + 1, printAttributesBool, attrib) + +# accumulate inherited attributes with DFS +def accumulateAttributes(directedGraph, node): + visited = set() # Set to keep track of visited nodes. + attrib = attributes[node] + eRelations = entityRelations[node] + + dfsAccumulate(visited, directedGraph, node, attrib, eRelations) + + +def dfsAccumulate(visited, graph, node, attrib, eRelations): + if node not in visited: + attrib = attrib + attributes[node] + eRelations = eRelations + entityRelations[node] + visited.add(node) + + #only save accumulated attributes for leaf nodes + if len(graph[node]) == 0: + inheritedAttributes[node] = attrib + inheritedRelations[node] = eRelations + #print('{}: {}'.format(node, inheritedAttributes[node])) + #print('{}: {}'.format(node, inheritedRelations[node])) + + for child in graph[node]: + dfsAccumulate(visited, graph, child, attrib, eRelations) + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Writing Templates +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def modifyDetectors(filename): + file = fileinput.FileInput(filename, inplace=True) + #file = fileinput.FileInput(filename) # test output + + for line in file: + if '' in line: + print(line.replace('', filename.replace('Detectors.cpp', '')), end='') + + # Add methods for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + methodTxt = 'std::string detect_()\n{\n\t//TODO: create _attr string with the following attributes:\n\t//\n\n\treturn _attr;\n}\n' + methodTxt = methodTxt.replace('', attrib) + methodTxt = methodTxt.replace('', (str)(inheritedAttributes[attrib])) + + print(methodTxt) + # Add topics for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + topicTxt = '\tros::Publisher _pub = n.advertise("_attr", 1);' + topicTxt = topicTxt.replace('', attrib) + + print(topicTxt) + # Add publishers for each entity in domain + elif '' in line: + for attrib in inheritedAttributes: + publishTxt = '\t\t_pub.publish(_attr);' + publishTxt = publishTxt.replace('', attrib) + + print(publishTxt) + + else: + print(line, end='') + + file.close() + +def modifyHandler(filename): + file = fileinput.FileInput(filename, inplace=True) + #file = fileinput.FileInput(filename) # test output + #print(' ') + + for line in file: + if '' in line: + print(line.replace('', filename.replace('EntitiesHandler.py', '')), end='') + + # Add relations for each entity in domain + elif '' in line: + for relate in inheritedRelations: + print(' #{}: {}'.format(relate, (str)(inheritedRelations[relate]))) + else: + print(line, end='') + + file.close() + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Main +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if __name__ == "__main__": + # manage args + parser = argparse.ArgumentParser() + parser.add_argument("config", help="domain specific configuration file") + parser.add_argument("-v","--verbosity",action="count",default=0,help="increase output verbosity") + args = parser.parse_args() + + #determine domain name from passed filepath for arg + if not len(args.config.split('/')) == 2: + print('Error: Config file must be located directly within domain directory') + sys.exit() + + domain = (args.config.split('/'))[0] + + objectInput(directedGraph, enumerationList, args.config) #generate config from passed file + + # add output based on verbosity + if args.verbosity >= 1: + # print generated trees and edges + print("Edges of type tree: " + str(generate_edges(directedGraph))) + if args.verbosity >= 2: + print("Type Tree: " + (str)(directedGraph)) + + print("\nEdges of attribute tree: " + str (generate_edges(attributes))) + if args.verbosity >= 2: + print("Attribute Tree: " + (str)(attributes)) + # printEnumerationList(enumerationList) + + print("\nEdges of attributeValues tree: " + str (generate_edges(attributeValues))) + if args.verbosity >= 2: + print("Attribute Tree: " + (str)(attributeValues)) + + print("\nEdges of relations tree: " + str (generate_edges(relations))) + if args.verbosity >= 2: + print("Relations Tree: " + (str)(relations)) + + # test type values from input + # printPDDL(directedGraph) + if args.verbosity == 3: + #TODO: API ENFORCES ENTITY PARENT + print('') + printTree(directedGraph, 'entity', False) # print entity tree without attributes + elif args.verbosity >= 4: + #TODO: API ENFORCES ENTITY PARENT + print('') + printTree(directedGraph, 'entity', True) # print entity tree with attributes + + + accumulateAttributes(directedGraph, 'entity') # get all leaf nodes' inherited attributes + + if not os.path.exists(domain + "/ros"): + os.makedirs(domain + "/ros") # create the new ros sub-directory + + # templates for each entity with their attributes for object detection code stubs and helpers + src='templates/detectorsTemplate.txt' + dst= domain + '/ros/' + domain + 'Detectors.cpp' + shutil.copy(src,dst) # copy template to modify + + modifyDetectors(dst) + + # templates for each entity and their predicates for perception to determine relations + src='templates/entitiesHandlerTemplate.txt' + dst= domain + '/ros/' + domain + 'EntitiesHandler.py' + shutil.copy(src,dst) # copy template to modify + + modifyHandler(dst) + + + + + + + + + + + + + + + + diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg new file mode 100644 index 00000000..d64033c7 --- /dev/null +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -0,0 +1,14 @@ +type,block,entity +attribute,block,color +attribute,block,x +attribute,block,y +attribute,block,z +attributeValue,color,red +attributeValue,color,green +attributeValue,color,blue +attributeValue,x,INT +attributeValue,y,INT +attributeValue,z,INT +relation,on,block,block +relation,clear,block +action,pickup \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp new file mode 100644 index 00000000..6b97a752 --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp @@ -0,0 +1,40 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + +std::string detect_block() +{ + //TODO: create block_attr string with the following attributes: + //['color', 'z', 'y', 'x'] + + return block_attr; +} + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting coloredBlocksworld/ros/coloredBlocksworld Entity Detectors node"); + + ros::init(argc, argv, "coloredBlocksworld/ros/coloredBlocksworld_entity_detectors"); + ros::NodeHandle n; + + ros::Publisher block_pub = n.advertise("block_attr", 1); + + while (ros::ok()) + { + block_pub.publish(block_attr); + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py new file mode 100644 index 00000000..c02b4527 --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py @@ -0,0 +1,32 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + #block: ['on', 'clear'] diff --git a/midca/domains/minecraft/minecraft.txt b/midca/domains/minecraft/minecraft.cfg similarity index 100% rename from midca/domains/minecraft/minecraft.txt rename to midca/domains/minecraft/minecraft.cfg diff --git a/midca/domains/minecraft/minecraftDetectors.cpp b/midca/domains/minecraft/ros/minecraftDetectors.cpp similarity index 95% rename from midca/domains/minecraft/minecraftDetectors.cpp rename to midca/domains/minecraft/ros/minecraftDetectors.cpp index cb2a56fa..edcb7065 100644 --- a/midca/domains/minecraft/minecraftDetectors.cpp +++ b/midca/domains/minecraft/ros/minecraftDetectors.cpp @@ -85,9 +85,9 @@ std::string detect_grass() int main(int argc, char** argv) { - ROS_INFO_STREAM("Starting minecraft/minecraft Entity Detectors node"); + ROS_INFO_STREAM("Starting minecraft/ros/minecraft Entity Detectors node"); - ros::init(argc, argv, "minecraft/minecraft_entity_detectors"); + ros::init(argc, argv, "minecraft/ros/minecraft_entity_detectors"); ros::NodeHandle n; ros::Publisher stone_pub = n.advertise("stone_attr", 1); diff --git a/midca/domains/minecraft/minecraftEntitiesHandler.py b/midca/domains/minecraft/ros/minecraftEntitiesHandler.py similarity index 88% rename from midca/domains/minecraft/minecraftEntitiesHandler.py rename to midca/domains/minecraft/ros/minecraftEntitiesHandler.py index d72336bc..af31ebd4 100644 --- a/midca/domains/minecraft/minecraftEntitiesHandler.py +++ b/midca/domains/minecraft/ros/minecraftEntitiesHandler.py @@ -1,6 +1,6 @@ # https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py -class minecraft/minecraftEntitiesHandler(IncomingMsgHandler): +class minecraft/ros/minecraftEntitiesHandler(IncomingMsgHandler): ''' class that receives Point messages, where each message indicates that the given object @@ -13,7 +13,7 @@ def __init__(self, topic, midcaObject, memKey = None, history = None): callback = lambda strMsg: self.store(strMsg) msgType = String self.left = None - super(minecraft/minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + super(minecraft/ros/minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) #self.objID = objID if memKey: self.memKey = memKey From f20f68d02a5405cadc67c62b0b142dc6c4edce44 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Mon, 15 Mar 2021 11:00:11 -0400 Subject: [PATCH 14/23] removed misc files --- midca/.idea/workspace.xml | 576 +----------------- midca/domains/Midca_Domain_API.py | 7 + midca/domains/Object_Hierarchy_Tree.py | 318 ---------- midca/domains/coloredBlocksworld.txt | 13 - .../coloredBlocksworld/coloredBlocksworld.cfg | 5 +- midca/domains/coloredBlocksworldDetectors.cpp | 40 -- .../coloredBlocksworldEntitiesHandler.py | 32 - midca/domains/minecraft.pddl | 180 ------ midca/domains/minecraft.txt | 23 - midca/domains/minecraftDetectors.cpp | 120 ---- midca/domains/minecraftEntitiesHandler.py | 40 -- midca/domains/split1.txt | 12 - midca/domains/split2.txt | 5 - midca/domains/test.txt | 8 - midca/domains/test2.txt | 10 - setup.py | 2 +- 16 files changed, 23 insertions(+), 1368 deletions(-) delete mode 100644 midca/domains/Object_Hierarchy_Tree.py delete mode 100644 midca/domains/coloredBlocksworld.txt delete mode 100644 midca/domains/coloredBlocksworldDetectors.cpp delete mode 100644 midca/domains/coloredBlocksworldEntitiesHandler.py delete mode 100644 midca/domains/minecraft.pddl delete mode 100644 midca/domains/minecraft.txt delete mode 100644 midca/domains/minecraftDetectors.cpp delete mode 100644 midca/domains/minecraftEntitiesHandler.py delete mode 100644 midca/domains/split1.txt delete mode 100644 midca/domains/split2.txt delete mode 100644 midca/domains/test.txt delete mode 100644 midca/domains/test2.txt diff --git a/midca/.idea/workspace.xml b/midca/.idea/workspace.xml index 3ec6f10d..b637ee2b 100644 --- a/midca/.idea/workspace.xml +++ b/midca/.idea/workspace.xml @@ -1,111 +1,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - makeframegraph @@ -118,29 +24,10 @@ CURRENT_GOALS - - - - - \ No newline at end of file diff --git a/midca/domains/Midca_Domain_API.py b/midca/domains/Midca_Domain_API.py index 143991c5..6ac38cf5 100644 --- a/midca/domains/Midca_Domain_API.py +++ b/midca/domains/Midca_Domain_API.py @@ -45,6 +45,7 @@ attributeValues = defaultdict(list) relations = defaultdict(list) entityRelations = defaultdict(list) # associates relations to the key of entity +actions = defaultdict(list) # all inherited values for each entity inheritedAttributes = defaultdict(list) @@ -100,6 +101,9 @@ def objectInput(directedGraph, enumerationList, config): for type in row[2:]: # for each type in the relationship relations[row[1]].insert(index, type) entityRelations[row[2]].append(row[1]) # add relation as a child of the first entity + elif row[0] == "action": + for topic in row[2:]: # for each topic in the action + actions[row[1]].insert(index, topic) configFile.close() @@ -256,6 +260,9 @@ def modifyHandler(filename): print("\nEdges of relations tree: " + str (generate_edges(relations))) if args.verbosity >= 2: print("Relations Tree: " + (str)(relations)) + + if args.verbosity >= 2: + print("\nActions Tree: " + (str)(actions)) # test type values from input # printPDDL(directedGraph) diff --git a/midca/domains/Object_Hierarchy_Tree.py b/midca/domains/Object_Hierarchy_Tree.py deleted file mode 100644 index f1dd6df0..00000000 --- a/midca/domains/Object_Hierarchy_Tree.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# In[ ]: - - -#MIDCA API -# Created August 2019 by Danielle Brown via CoLab2 -#Reads in a file of the format specification,object2,object1 -#Specification can be a type, i.e. a spoon (object2) is a utensil (object1) -#or specification can be an attribute, i.e., a utensil (object2) can be a color (object1) -#Requirement: Be able to take in input and add it to the object hierarchy tree -#Requirement: Act as an interface between ros and MIDCA for objects - -#To Do still: -# #Ideas from meeting with Mike Cox and Sampath Gogineni on 10/8/2019 -#Detector -> type, xblock, isablock -#then it is passed to MIDCA from interface -#All objects have types and possibly attributes. Attributes have values (ie type color has values -#green, red, etc) -#uniform naming via the type system and simple attributes -#Each action has a piece of code to handle and determine when its over -#define predicate formulation -#Be Able to ultimately define a new domain -# detect object types, what are predicates in domain, do actions, when is action done, and -# naming of objects and handling of attributes -# Naming -> type + unique identifier, decrement unique identifier if item disappears so -# block2 doesn't become block3 when it reappears - -#robot -> be able to list objects, then the robot detects objects, and can click to assign objects? - -#TODO: Attribute and AttributeValue need to be separate things - -from __future__ import print_function -import sys -import csv -import fileinput # supports inplace editing -import argparse # handles cmd line args and verbose logging levels -import shutil # file copying - -from collections import defaultdict - - -directedGraph = defaultdict(list) -attributes = defaultdict(list) -enumerationList = [] -attributeValues = defaultdict(list) -relations = defaultdict(list) -entityRelations = defaultdict(list) # associates relations to the key of entity - -# all inherited values for each entity -inheritedAttributes = defaultdict(list) -inheritedRelations = defaultdict(list) - - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Graph Functions -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -#Adds node to the directedGraph -def addEdge(directedGraph, u, v): - directedGraph[u].append(v) - -#Adds the directional relationship between objects -def generate_edges(directedGraph): - edges = [] - # for each node in directedGraph - for node in directedGraph: - # for each relation node of a single node - for relation in directedGraph[node]: - # if edge exists then append - edges.append((node, relation)) - return edges - - -#box object class -def blockShape(self): - return 0 - -#Plate object class -def plateShape(self): - return 0 - -#fork object class -def forkShape(self): - return 0 - -#spoon object class -def spoonShape(self): - return 0 - -#function that prints out the enumeration list of attributes with index values -def printEnumerationList(enumerationList): - for idx, (object, attribute) in enumerate(enumerationList): - print("index is %d, name is %s, and attribute is %s" - % (idx, object, attribute)) - -#main function that reads in a file of data and creates a directed tree of types -#and directed tree of attributes as well as an enumeration list of attributes -def objectInput(directedGraph, enumerationList, config): - index = 0 - #create directed graph tree off of information provided in document - configFile = open(config) - fileText = csv.reader(configFile, delimiter = ',') - for row in fileText: - #if it is a type it is added to the type tree - if row[0] == "type": - directedGraph[row[2]].insert(index, row[1]) - index += 1 - #if it is an attribute, then add it to the attribute tree - #and enumeration list - elif row[0] == "attribute": - attributes[row[1]].insert(index, row[2]) - tempTupple = (row[2], row[1]) - enumerationList.append(tempTupple) - elif row[0] == "attributeValue": - attributeValues[row[1]].insert(index, row[2]) - elif row[0] == "relation": - for type in row[2:]: # for each type in the relationship - relations[row[1]].insert(index, type) - entityRelations[row[2]].append(row[1]) # add relation as a child of the first entity - - configFile.close() - - -def printPDDL(directedGraph): - # print PDDL types - print('\t(:types') - for node in directedGraph: - #print('' + node) - - for relation in directedGraph[node]: - print('\t ' + relation + ' -' + node) - - print('\t)\n') - - -# prints tree with DFS -def printTree(directedGraph, node, printAttributesBool): - visited = set() # Set to keep track of visited nodes. - attrib = attributes[node] - - dfsPrint(visited, directedGraph, node, 0, printAttributesBool, attrib) - - -def dfsPrint(visited, graph, node, depth, printAttributesBool, attrib): - if node not in visited: - print('\t' * depth + '+-- ' + node) - attrib = attrib + attributes[node] - if printAttributesBool: - print('\t' * depth + ' ' + (str)(attributes[node])) # print only specific attributes - visited.add(node) - for child in graph[node]: - dfsPrint(visited, graph, child, depth + 1, printAttributesBool, attrib) - -# accumulate inherited attributes with DFS -def accumulateAttributes(directedGraph, node): - visited = set() # Set to keep track of visited nodes. - attrib = attributes[node] - eRelations = entityRelations[node] - - dfsAccumulate(visited, directedGraph, node, attrib, eRelations) - - -def dfsAccumulate(visited, graph, node, attrib, eRelations): - if node not in visited: - attrib = attrib + attributes[node] - eRelations = eRelations + entityRelations[node] - visited.add(node) - - #only save accumulated attributes for leaf nodes - if len(graph[node]) == 0: - inheritedAttributes[node] = attrib - inheritedRelations[node] = eRelations - #print('{}: {}'.format(node, inheritedAttributes[node])) - #print('{}: {}'.format(node, inheritedRelations[node])) - - for child in graph[node]: - dfsAccumulate(visited, graph, child, attrib, eRelations) - - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Writing Templates -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -def modifyDetectors(filename): - file = fileinput.FileInput(filename, inplace=True) - #file = fileinput.FileInput(filename) # test output - - for line in file: - if '' in line: - print(line.replace('', filename.replace('Detectors.cpp', '')), end='') - - # Add methods for each entity in domain - elif '' in line: - for attrib in inheritedAttributes: - methodTxt = 'std::string detect_()\n{\n\t//TODO: create _attr string with the following attributes:\n\t//\n\n\treturn _attr;\n}\n' - methodTxt = methodTxt.replace('', attrib) - methodTxt = methodTxt.replace('', (str)(inheritedAttributes[attrib])) - - print(methodTxt) - # Add topics for each entity in domain - elif '' in line: - for attrib in inheritedAttributes: - topicTxt = '\tros::Publisher _pub = n.advertise("_attr", 1);' - topicTxt = topicTxt.replace('', attrib) - - print(topicTxt) - # Add publishers for each entity in domain - elif '' in line: - for attrib in inheritedAttributes: - publishTxt = '\t\t_pub.publish(_attr);' - publishTxt = publishTxt.replace('', attrib) - - print(publishTxt) - - else: - print(line, end='') - - file.close() - -def modifyHandler(filename): - file = fileinput.FileInput(filename, inplace=True) - #file = fileinput.FileInput(filename) # test output - #print(' ') - - for line in file: - if '' in line: - print(line.replace('', filename.replace('EntitiesHandler.py', '')), end='') - - # Add relations for each entity in domain - elif '' in line: - for relate in inheritedRelations: - print(' #{}: {}'.format(relate, (str)(inheritedRelations[relate]))) - else: - print(line, end='') - - file.close() - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Main -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -if __name__ == "__main__": - # manage args - parser = argparse.ArgumentParser() - parser.add_argument("config", help="domain specific configuration file") - parser.add_argument("-v","--verbosity",action="count",default=0,help="increase output verbosity") - args = parser.parse_args() - - objectInput(directedGraph, enumerationList, args.config) #generate config from passed file - - # add output based on verbosity - if args.verbosity >= 1: - # print generated trees and edges - print("Edges of type tree: " + str(generate_edges(directedGraph))) - if args.verbosity >= 2: - print("Type Tree: " + (str)(directedGraph)) - - print("\nEdges of attribute tree: " + str (generate_edges(attributes))) - if args.verbosity >= 2: - print("Attribute Tree: " + (str)(attributes)) - # printEnumerationList(enumerationList) - - print("\nEdges of attributeValues tree: " + str (generate_edges(attributeValues))) - if args.verbosity >= 2: - print("Attribute Tree: " + (str)(attributeValues)) - - print("\nEdges of relations tree: " + str (generate_edges(relations))) - if args.verbosity >= 2: - print("Relations Tree: " + (str)(relations)) - - # test type values from input - # printPDDL(directedGraph) - if args.verbosity == 3: - #API ENFORCES ENTITY PARENT - print('') - printTree(directedGraph, 'entity', False) # print entity tree without attributes - elif args.verbosity >= 4: - #API ENFORCES ENTITY PARENT - print('') - printTree(directedGraph, 'entity', True) # print entity tree with attributes - - - accumulateAttributes(directedGraph, 'entity') - - # Test output for each entity with their attributes for object detection code stubs and helpers - # copy template to modify - src='templates/detectorsTemplate.txt' - dst= args.config.replace('.txt', 'Detectors.cpp') - shutil.copy(src,dst) - - modifyDetectors(dst) - - - # Test output for each entity and their predicates for perception to determine relations - - # copy template to modify - src='templates/entitiesHandlerTemplate.txt' - dst= args.config.replace('.txt', 'EntitiesHandler.py') - shutil.copy(src,dst) - - modifyHandler(dst) - - - - - - - - - - - - - - - - diff --git a/midca/domains/coloredBlocksworld.txt b/midca/domains/coloredBlocksworld.txt deleted file mode 100644 index 3f4a1b2f..00000000 --- a/midca/domains/coloredBlocksworld.txt +++ /dev/null @@ -1,13 +0,0 @@ -type,block,entity -attribute,block,color -attribute,block,x -attribute,block,y -attribute,block,z -attributeValue,color,red -attributeValue,color,green -attributeValue,color,blue -attributeValue,x,INT -attributeValue,y,INT -attributeValue,z,INT -relation,on,block,block -relation,clear,block \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index d64033c7..0bb06205 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -11,4 +11,7 @@ attributeValue,y,INT attributeValue,z,INT relation,on,block,block relation,clear,block -action,pickup \ No newline at end of file +action,pickup,loc,grabbing,raise +action,putdown,loc,grabbing,release +action,stack,loc,grabbing,raise,release +action,unstack,loc,grabbing,raise,release \ No newline at end of file diff --git a/midca/domains/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworldDetectors.cpp deleted file mode 100644 index 6f3afd34..00000000 --- a/midca/domains/coloredBlocksworldDetectors.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/********************************************************************* - * - * - * For example, consider using PointCloudLab - * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) - * - * - *********************************************************************/ - -#include - - -std::string detect_block() -{ - //TODO: create block_attr string with the following attributes: - //['color', 'z', 'y', 'x'] - - return block_attr; -} - - -int main(int argc, char** argv) -{ - ROS_INFO_STREAM("Starting coloredBlocksworld Entity Detectors node"); - - ros::init(argc, argv, "coloredBlocksworld_entity_detectors"); - ros::NodeHandle n; - - ros::Publisher block_pub = n.advertise("block_attr", 1); - - while (ros::ok()) - { - block_pub.publish(block_attr); - - ros::spinOnce(); - } - - ros::spin(); - return 0; -} \ No newline at end of file diff --git a/midca/domains/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworldEntitiesHandler.py deleted file mode 100644 index b0c3739f..00000000 --- a/midca/domains/coloredBlocksworldEntitiesHandler.py +++ /dev/null @@ -1,32 +0,0 @@ -# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py - -class coloredBlocksworldEntitiesHandler(IncomingMsgHandler): - - ''' - class that receives Point messages, where each message indicates that the given object - has been identified at that location. Args include the topic to listen to, object id, - and midca object to whose memory observations will be stored. Optionally the memory - key to be stored to can also be specified. - ''' - - def __init__(self, topic, midcaObject, memKey = None, history = None): - callback = lambda strMsg: self.store(strMsg) - msgType = String - self.left = None - super(coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) - #self.objID = objID - if memKey: - self.memKey = memKey - else: - self.memKey = self.mem.ROS_OBJS_DETECTED - if history: - self.history = history - else: - self.history = self.mem.STATE_HISTORY - - def store(self, data): - if not self.mem: - rospy.logerr("Trying to store data to a nonexistent MIDCA object.") - - #TODO: Code should handle detecting the following relations (predicates): - #block: ['on', 'clear'] diff --git a/midca/domains/minecraft.pddl b/midca/domains/minecraft.pddl deleted file mode 100644 index d81a7ac9..00000000 --- a/midca/domains/minecraft.pddl +++ /dev/null @@ -1,180 +0,0 @@ -(define (domain minecraft-beta) - (:requirements :typing :fluents :existential-preconditions) - (:types - resource - thing - mapgrid - player - ) - - (:types - resource - thing - material - thing - tool - thing - craftgrid - mapgrid - direction - player - monster - thing - weapon - thing - food - thing - potion - thing - Helmet - Armor - chestplates - Armor - ) - - (:predicates - (is-trap ?loc - mapgrid) - (looking-for ?res - resource) - (know-where ?res - resource ?loc - mapgrid) - (player-at ?loc - mapgrid) - (in-shelter) - (look-at ?direction - direction) - (monster-at ?zombie - monster ?loc - mapgrid) - (thing-at-map ?obj - resource ?loc - mapgrid) - (thing-at-loc ?obj - resource ?loc - mapgrid) - (known-loc ?obj - resource) - (placed-thing-at-map ?obj - material ?loc - mapgrid) - (resource-at-craft ?res - thing ?loc - craftgrid) - (craft-empty ?loc - craftgrid) - (connect ?from - mapgrid ?to - mapgrid) - (next-to ?from - direction ?to - direction) - (crafting) - (survive) - (eat ?food - food) - (is-attacked) - (is-trapped) - (is-dead ?player -player) - (is-alive ?player -player) - (head-armed) - (chest-armed) - ) - (:hidden is-trap thing-at-loc is-attacked is-trapped) - - (:functions - (self) - player - (thing-available ?obj - thing) - int - (current-harvest-duration) - int - (current-harvest-location) - int - (duration-need ?tool - tool ?res - resource) - int - (location-id ?loc - mapgrid) - int - (tool-id ?tool - tool) - int - (tool-in-hand) - int - (tool-max-health ?tool - tool) - int - (tool-current-health ?tool - tool) - int - (player-current-health) - int - (furnace-fuel) - int - (current-hunger-value) - int - (food-value ?f -food) - int - ) - - - - ;; ---------------------------------------------------- - (:action move - :parameters (?from - mapgrid ?to - mapgrid) - :precondition - (and - (player-at ?from) - (connect ?from ?to) - - ) - :effect - (and - (player-at ?to) - (not (player-at ?from)) - - ) - ) - ;;----------------------------------------------------- - - (:action event-fall-in-trap - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc arrow_trap ?loc) - - (not (is-trapped)) - (neq (player-current-health) 0) - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map arrow ?loc1) - (is-trapped) - ) - ) - ;;------------------------------------------------------ - - (:action event-skeleton-attacked - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc skeleton ?loc) - (not (is-attacked)) - (neq (player-current-health) 0) - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map arrow ?loc1) - (is-attacked) - ) - ) - ;;---------------------------------------------- - (:action event-monster-explosion - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc monster ?loc) - (not (is-attacked)) - (neq (player-current-health) 0) - - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map monster-remains ?loc1) - (is-attacked) - ) - ) - ;;---------------------------------------------- - - (:action event-die - :parameters (?player -player) - :precondition - ( and - (is-alive ?player) - (eq (player-current-health) 0) - ) - :effect - (and - (is-dead ?player) - ) - ) - - ;;--------------------------------------------- - - (:action event-find - :parameters (?res -resource ?loc -mapgrid ?player-loc -mapgrid) - :precondition - (and - (looking-for ?res) - (connected ?loc ?player-loc) - (thing-at-loc ?res ?loc) - ) - :effect - (and - (know-where ?res ?loc) - ) - - - ) - - -) \ No newline at end of file diff --git a/midca/domains/minecraft.txt b/midca/domains/minecraft.txt deleted file mode 100644 index a7e879b3..00000000 --- a/midca/domains/minecraft.txt +++ /dev/null @@ -1,23 +0,0 @@ -type,mob,entity -type,item,entity -type,block,item -type,tool,item -type,stone,block -type,grass,block -type,pickaxe,tool -type,sword,tool -type,player,mob -type,hostile,mob -type,passive,mob -type,creeper,hostile -type,skeleton,hostile -type,pig,passive -type,chicken,passive -attribute,mob,health -attribute,passive,age -attribute,block,breakable -attribute,item,craftable -attribute,sword,damage -attribute,pickaxe,speed -attribute,player,armor -attribute,skeleton,armor \ No newline at end of file diff --git a/midca/domains/minecraftDetectors.cpp b/midca/domains/minecraftDetectors.cpp deleted file mode 100644 index 33c6d875..00000000 --- a/midca/domains/minecraftDetectors.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/********************************************************************* - * - * - * For example, consider using PointCloudLab - * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) - * - * - *********************************************************************/ - -#include - - -std::string detect_stone() -{ - //TODO: create stone_attr string with the following attributes: - //['craftable', 'breakable'] - - return stone_attr; -} - -std::string detect_skeleton() -{ - //TODO: create skeleton_attr string with the following attributes: - //['health', 'armor'] - - return skeleton_attr; -} - -std::string detect_creeper() -{ - //TODO: create creeper_attr string with the following attributes: - //['health'] - - return creeper_attr; -} - -std::string detect_pig() -{ - //TODO: create pig_attr string with the following attributes: - //['health', 'age'] - - return pig_attr; -} - -std::string detect_player() -{ - //TODO: create player_attr string with the following attributes: - //['health', 'armor'] - - return player_attr; -} - -std::string detect_pickaxe() -{ - //TODO: create pickaxe_attr string with the following attributes: - //['craftable', 'speed'] - - return pickaxe_attr; -} - -std::string detect_sword() -{ - //TODO: create sword_attr string with the following attributes: - //['craftable', 'damage'] - - return sword_attr; -} - -std::string detect_chicken() -{ - //TODO: create chicken_attr string with the following attributes: - //['health', 'age'] - - return chicken_attr; -} - -std::string detect_grass() -{ - //TODO: create grass_attr string with the following attributes: - //['craftable', 'breakable'] - - return grass_attr; -} - - -int main(int argc, char** argv) -{ - ROS_INFO_STREAM("Starting minecraft Entity Detectors node"); - - ros::init(argc, argv, "minecraft_entity_detectors"); - ros::NodeHandle n; - - ros::Publisher stone_pub = n.advertise("stone_attr", 1); - ros::Publisher skeleton_pub = n.advertise("skeleton_attr", 1); - ros::Publisher creeper_pub = n.advertise("creeper_attr", 1); - ros::Publisher pig_pub = n.advertise("pig_attr", 1); - ros::Publisher player_pub = n.advertise("player_attr", 1); - ros::Publisher pickaxe_pub = n.advertise("pickaxe_attr", 1); - ros::Publisher sword_pub = n.advertise("sword_attr", 1); - ros::Publisher chicken_pub = n.advertise("chicken_attr", 1); - ros::Publisher grass_pub = n.advertise("grass_attr", 1); - - while (ros::ok()) - { - stone_pub.publish(stone_attr); - skeleton_pub.publish(skeleton_attr); - creeper_pub.publish(creeper_attr); - pig_pub.publish(pig_attr); - player_pub.publish(player_attr); - pickaxe_pub.publish(pickaxe_attr); - sword_pub.publish(sword_attr); - chicken_pub.publish(chicken_attr); - grass_pub.publish(grass_attr); - - ros::spinOnce(); - } - - ros::spin(); - return 0; -} \ No newline at end of file diff --git a/midca/domains/minecraftEntitiesHandler.py b/midca/domains/minecraftEntitiesHandler.py deleted file mode 100644 index 94c38d42..00000000 --- a/midca/domains/minecraftEntitiesHandler.py +++ /dev/null @@ -1,40 +0,0 @@ -# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py - -class minecraftEntitiesHandler(IncomingMsgHandler): - - ''' - class that receives Point messages, where each message indicates that the given object - has been identified at that location. Args include the topic to listen to, object id, - and midca object to whose memory observations will be stored. Optionally the memory - key to be stored to can also be specified. - ''' - - def __init__(self, topic, midcaObject, memKey = None, history = None): - callback = lambda strMsg: self.store(strMsg) - msgType = String - self.left = None - super(minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) - #self.objID = objID - if memKey: - self.memKey = memKey - else: - self.memKey = self.mem.ROS_OBJS_DETECTED - if history: - self.history = history - else: - self.history = self.mem.STATE_HISTORY - - def store(self, data): - if not self.mem: - rospy.logerr("Trying to store data to a nonexistent MIDCA object.") - - #TODO: Code should handle detecting the following relations (predicates): - #stone: ['place', 'break'] - #skeleton: ['kill'] - #creeper: ['kill'] - #pig: ['kill'] - #player: ['kill'] - #pickaxe: ['use'] - #sword: ['use'] - #chicken: ['kill'] - #grass: ['place', 'break'] diff --git a/midca/domains/split1.txt b/midca/domains/split1.txt deleted file mode 100644 index 7732663b..00000000 --- a/midca/domains/split1.txt +++ /dev/null @@ -1,12 +0,0 @@ -type,utensil,entity -type,player,entity -type,fork,utensil -type,spoon,utensil -type,knife,utensil -type,salad,fork -type,dinner,fork -type,robot,player -attribute,utensil,color -attribute,utensil,price -attribute,fork,prongs -attribute,knife,sharpness \ No newline at end of file diff --git a/midca/domains/split2.txt b/midca/domains/split2.txt deleted file mode 100644 index c80768e3..00000000 --- a/midca/domains/split2.txt +++ /dev/null @@ -1,5 +0,0 @@ -attribute,utensil,color -type,fork,utensil -type,spoon,utensil -type,robot,player -relation,on,flatware,table \ No newline at end of file diff --git a/midca/domains/test.txt b/midca/domains/test.txt deleted file mode 100644 index 9cff1eb6..00000000 --- a/midca/domains/test.txt +++ /dev/null @@ -1,8 +0,0 @@ -type,utensil,entity -attribute,id,X -attribute,block,id -attribute,utensil,color -type,fork,utensil -type,spoon,utensil -type,robot,player -relation,on,flatware,table \ No newline at end of file diff --git a/midca/domains/test2.txt b/midca/domains/test2.txt deleted file mode 100644 index 1a8e8366..00000000 --- a/midca/domains/test2.txt +++ /dev/null @@ -1,10 +0,0 @@ -type,utensil,entity -attributeValue,id,X -attributeValue,color,blue -attributeValue,color,yellow -attributeValue,block,id -attribute,utensil,color -type,fork,utensil -type,spoon,utensil -type,robot,player -relation,on,flatware,table \ No newline at end of file diff --git a/setup.py b/setup.py index f3e25670..92926309 100755 --- a/setup.py +++ b/setup.py @@ -44,4 +44,4 @@ '': ['*.txt', 'midca.domains.logistics'], '': ['*.*', 'midca.modules._plan.jShop'], '': ['*.shp', 'midca.domains.jshop_domains.blocks_world']}, - ) + ) \ No newline at end of file From d56871c44f460b9866a6f09c866a4f1f38c6d5d8 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 16 Mar 2021 20:53:54 -0400 Subject: [PATCH 15/23] add parsing for actions/operators --- midca/domains/Midca_Domain_API.py | 44 ++++++++++++++++++- .../coloredBlocksworld/coloredBlocksworld.cfg | 4 +- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/midca/domains/Midca_Domain_API.py b/midca/domains/Midca_Domain_API.py index 6ac38cf5..6760ad8b 100644 --- a/midca/domains/Midca_Domain_API.py +++ b/midca/domains/Midca_Domain_API.py @@ -96,7 +96,8 @@ def objectInput(directedGraph, enumerationList, config): tempTupple = (row[2], row[1]) enumerationList.append(tempTupple) elif row[0] == "attributeValue": - attributeValues[row[1]].insert(index, row[2]) + for value in row[2:]: # for each value in the action + attributeValues[row[1]].insert(index, value) elif row[0] == "relation": for type in row[2:]: # for each type in the relationship relations[row[1]].insert(index, type) @@ -220,6 +221,40 @@ def modifyHandler(filename): else: print(line, end='') + file.close() + +def modifyAsync(filename): + file = fileinput.FileInput(filename, inplace=True) + #file = fileinput.FileInput(filename) # test output + + for line in file: + # Add topics for each operator in domain + if '' in line: + mergedTopics = [] + for operator in actions: + mergedTopics = mergedTopics + actions[operator] + for topic in set(mergedTopics): + print(topic.upper() + '_TOPIC = \"' + topic + '_cmd\"') + + # Add doOperator for each operator in domain + elif '' in line: + for operator in actions: + operatorText = fileinput.FileInput('templates/doOperatorTemplate.txt') + for text in operatorText: + if '' in text: + print(text.replace('', operator), end='') + + # Add topics formats for each entity in domain + elif '' in text: + formats = '' + for topic in actions[operator]: + formats = formats + ('\'' + topic + '\': {},') + print(text.replace('', formats), end='') + else: + print(text, end='') + else: + print(line, end='') + file.close() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -295,7 +330,12 @@ def modifyHandler(filename): modifyHandler(dst) - + # templates for each action and their associated topics + src='templates/asyncTemplate.txt' + dst= domain + '/ros/' + domain + '_async.py' + shutil.copy(src,dst) # copy template to modify + + modifyAsync(dst) diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index 0bb06205..597198de 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -3,9 +3,7 @@ attribute,block,color attribute,block,x attribute,block,y attribute,block,z -attributeValue,color,red -attributeValue,color,green -attributeValue,color,blue +attributeValue,color,red,green,blue attributeValue,x,INT attributeValue,y,INT attributeValue,z,INT From 743968243a02167b9e9d345d88a52b2dd98f64e9 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 16 Mar 2021 20:56:54 -0400 Subject: [PATCH 16/23] add templates for operators --- .../inspectionProfiles/Project_Default.xml | 14 + midca/.idea/vcs.xml | 6 + .../ros/coloredBlocksworld_async.py | 531 ++++++++++++++++++ midca/domains/templates/asyncTemplate.txt | 289 ++++++++++ .../domains/templates/doOperatorTemplate.txt | 60 ++ midca/examples/minecraft_run.py | 63 +++ .../simple_run_jshop_New_Domain_Structure.py | 90 +++ 7 files changed, 1053 insertions(+) create mode 100644 midca/.idea/inspectionProfiles/Project_Default.xml create mode 100644 midca/.idea/vcs.xml create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py create mode 100644 midca/domains/templates/asyncTemplate.txt create mode 100644 midca/domains/templates/doOperatorTemplate.txt create mode 100644 midca/examples/minecraft_run.py create mode 100644 midca/examples/simple_run_jshop_New_Domain_Structure.py diff --git a/midca/.idea/inspectionProfiles/Project_Default.xml b/midca/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..e96f6e02 --- /dev/null +++ b/midca/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/midca/.idea/vcs.xml b/midca/.idea/vcs.xml new file mode 100644 index 00000000..6c0b8635 --- /dev/null +++ b/midca/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py new file mode 100644 index 00000000..a58bfd6f --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py @@ -0,0 +1,531 @@ +from midca import rosrun, plans +from midca import midcatime +import traceback +from midca.examples.homography import * +import math +import copy +import numpy as np + + +try: + from geometry_msgs.msg import PointStamped + from geometry_msgs.msg import Point + from midca.examples import ObjectDetector + from std_msgs.msg import String + from scipy.spatial import distance +except: + pass #if ROS is not installed, an error message will already have been generated. + + +END_COLOR_CODE = '\033[0m' +NOT_STARTED = 0 +NS_COLOR_CODE = END_COLOR_CODE +IN_PROGRESS = 1 +IP_COLOR_CODE = '\033[92m' +COMPLETE = 2 +C_COLOR_CODE = '\033[94m' +FAILED = 3 +F_COLOR_CODE = '\033[91m' +FEEDBACK_KEY = "code" +CMD_ID_KEY = "cmd_id" + +RELEASE_TOPIC = "release_cmd" +LOC_TOPIC = "loc_cmd" +GRABBING_TOPIC = "grabbing_cmd" +RAISE_TOPIC = "raise_cmd" + +#set this to change output for all asynch actions. +verbose = 2 + +MAX_SIGHTING_LAG = 3.0 +MAX_SIGHTING_WAIT = 5.0 + +def allowed_sighting_lag(objectID): + ''' + returns how long ago an object can have been seen before MIDCA stops considering its + location known + ''' + return MAX_SIGHTING_LAG + +def allowed_sighting_wait(objectID): + ''' + returns the amount of midcatime MIDCA should wait to see an object before giving up. + ''' + return MAX_SIGHTING_WAIT + +''' +''' + +def get_asynch_action(midcaAction): + raise ArgumentException("midca action " + str(midcaAction) + " does not translate to a \ + valid asynchronous action.") + +def asynch_plan(mem, midcaPlan): + ''' + returns an asynchronous plan that corresponds to the given MIDCA plan. + ''' + actions = [] + goals = midcaPlan.goals + for midcaAction in midcaPlan.actions: + if midcaAction[0] == "block_until_seen": + actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) + elif midcaAction[0] == "point_to": + cmdID = rosrun.next_id() + actions.append(DoPoint(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + POINT_TOPIC, cmdID)) + + elif midcaAction[0] == "reach_to_pickup": + cmdID = rosrun.next_id() + actions.append(DoReach(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "reach_to_unstack": + cmdID = rosrun.next_id() + actions.append(DoUnstack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "grab": + cmdID = rosrun.next_id() + actions.append(DoGrab(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + GRAB_TOPIC, cmdID)) + elif midcaAction[0] == "release": + cmdID = rosrun.next_id() + actions.append(DoRelease(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RELEASE_TOPIC, cmdID)) + elif midcaAction[0] == "raising": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "raising_arm": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, ' ', + allowed_sighting_lag(' '), allowed_sighting_wait(' '), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "putdown": + cmdID = rosrun.next_id() + actions.append(DoPut(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "stack": + cmdID = rosrun.next_id() + actions.append(DoStack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + else: + if verbose >= 1: + print "MIDCA action", midcaAction, "does not correspond to an asynch", + "action. MIDCA will skip this action" + return AsynchPlan(actions, goals) + + +class AsynchPlan(plans.Plan): + + ''' + subclass of MIDCA Plan class that uses asynchronous actions. + ''' + + def finished(self): + ''' + overrides plan.finished(). Declares a plan complete if all its actions report + complete or failed. + ''' + for action in self.actions: + if action.status != COMPLETE and action.status != FAILED: + return False + return True + + @property + def status(self): + ''' + property that returns the plan's status. This can be NOT_STARTED, IN_PROGRESS, + FAILED, or COMPLETE. If any action fails, the plan is considered to have failed. + The plan is complete when all actions are complete. + ''' + status = COMPLETE + for action in self.actions: + if action.status == FAILED: + return FAILED + elif action.status == NOT_STARTED and status == COMPLETE: + status = NOT_STARTED + elif action.status == IN_PROGRESS: + status = IN_PROGRESS + return status + + def __str__(self): + s = "" + for action in self.actions: + if action.status == NOT_STARTED: + s += NS_COLOR_CODE + elif action.status == IN_PROGRESS: + s += IP_COLOR_CODE + elif action.status == FAILED: + s += F_COLOR_CODE + elif action.status == COMPLETE: + s += C_COLOR_CODE + + s += str(action) + " " + return s[:-1] + END_COLOR_CODE + +class AsynchAction: + + nextID = 0 + + def __init__(self, mem, midcaAction, executeFunc, isComplete, blocks): + self.status = NOT_STARTED + self.mem = mem + self.midcaAction = midcaAction + self.executeFunc = executeFunc + self.isComplete = isComplete + self.blocks = blocks + self.startTime = None + self.id = AsynchAction.nextID + AsynchAction.nextID += 1 + + def execute(self): + if not self.startTime: + self.startTime = midcatime.now() + self.status = IN_PROGRESS + if not self.executeFunc: + return + try: + self.executeFunc(self.mem, self.midcaAction, self.status) + except: + if verbose >= 2: + print "Error executing action", self, ":\n", traceback.format_exc(), + "\n\nAction assumed to be failed" + self.status = FAILED + + def check_complete(self): + if not self.startTime: + self.startTime = midcatime.now() + if not self.check_complete: + return + try: + complete = self.isComplete(self.mem, self.midcaAction, self.status) + if verbose >= 2 and not complete: + print "Action", self, "not complete." + if verbose >= 1 and complete: + print "Action", self, "complete." + if complete: + self.status = COMPLETE + return complete + except: + if verbose >= 1: + print "Error checking completion status for action", self, " - Assuming \ + failure:\n", traceback.format_exc() + self.status = FAILED + + def ros_msg(self, topic, d): + ''' + arg d should be a dictionary that contains the key/value pairs to be sent. + ''' + sent = rosrun.send_msg(topic, rosrun.dict_as_msg) + if not sent: + if verbose >= 1: + print "Unable to send msg; ", d, "on topic", topic, " Action", self, + "assumed failed." + self.status = FAILED + + def __str__(self): + return str(self.midcaAction) + +def get_last_position(mem, objectOrID): + state = mem.get(mem.STATE) + positions = state.all_pos(objectOrID) + if not positions: + return None + else: + for state_pos in reversed(positions): + if state_pos.position: + return (state_pos.position) + return None + +def get_last_location(mem, objectOrID): + world = mem.get(mem.STATE) + sightings = world.all_sightings(objectOrID) + if not sightings: + return None + else: + for detectionEvent in reversed(sightings): + if detectionEvent.loc: + return (detectionEvent.loc, detectionEvent.time) + return None + + + + +class AwaitCurrentLocation(AsynchAction): + + ''' + Action that blocks until there is a current (within last maxAllowedLag seconds) + observation of the object's location. + ''' + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + executeAction = None + completionCheck = lambda mem, midcaAction, status: self.completion_check() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + def completion_check(self): + t = midcatime.now() + if t - self.startTime > self.maxDuration: + if verbose >= 1: + print "max midcatime exceeded for action:", self, "- changing status to failed." + self.status = FAILED + return False + lastLocReport = get_last_location(self.mem, self.objectOrID) + if not lastLocReport: + return False + return t - lastLocReport[1] <= self.maxAllowedLag + + +class Dounstack(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'loc': {},'release': {},'raise': {},'grabbing': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class Dopickup(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'loc': {},'raise': {},'grabbing': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class Doputdown(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'loc': {},'release': {},'grabbing': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class Dostack(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'loc': {},'release': {},'raise': {},'grabbing': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + + diff --git a/midca/domains/templates/asyncTemplate.txt b/midca/domains/templates/asyncTemplate.txt new file mode 100644 index 00000000..80e90ccb --- /dev/null +++ b/midca/domains/templates/asyncTemplate.txt @@ -0,0 +1,289 @@ +from midca import rosrun, plans +from midca import midcatime +import traceback +from midca.examples.homography import * +import math +import copy +import numpy as np + + +try: + from geometry_msgs.msg import PointStamped + from geometry_msgs.msg import Point + from midca.examples import ObjectDetector + from std_msgs.msg import String + from scipy.spatial import distance +except: + pass #if ROS is not installed, an error message will already have been generated. + + +END_COLOR_CODE = '\033[0m' +NOT_STARTED = 0 +NS_COLOR_CODE = END_COLOR_CODE +IN_PROGRESS = 1 +IP_COLOR_CODE = '\033[92m' +COMPLETE = 2 +C_COLOR_CODE = '\033[94m' +FAILED = 3 +F_COLOR_CODE = '\033[91m' +FEEDBACK_KEY = "code" +CMD_ID_KEY = "cmd_id" + + + +#set this to change output for all asynch actions. +verbose = 2 + +MAX_SIGHTING_LAG = 3.0 +MAX_SIGHTING_WAIT = 5.0 + +def allowed_sighting_lag(objectID): + ''' + returns how long ago an object can have been seen before MIDCA stops considering its + location known + ''' + return MAX_SIGHTING_LAG + +def allowed_sighting_wait(objectID): + ''' + returns the amount of midcatime MIDCA should wait to see an object before giving up. + ''' + return MAX_SIGHTING_WAIT + +''' +''' + +def get_asynch_action(midcaAction): + raise ArgumentException("midca action " + str(midcaAction) + " does not translate to a \ + valid asynchronous action.") + +def asynch_plan(mem, midcaPlan): + ''' + returns an asynchronous plan that corresponds to the given MIDCA plan. + ''' + actions = [] + goals = midcaPlan.goals + for midcaAction in midcaPlan.actions: + if midcaAction[0] == "block_until_seen": + actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) + elif midcaAction[0] == "point_to": + cmdID = rosrun.next_id() + actions.append(DoPoint(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + POINT_TOPIC, cmdID)) + + elif midcaAction[0] == "reach_to_pickup": + cmdID = rosrun.next_id() + actions.append(DoReach(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "reach_to_unstack": + cmdID = rosrun.next_id() + actions.append(DoUnstack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "grab": + cmdID = rosrun.next_id() + actions.append(DoGrab(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + GRAB_TOPIC, cmdID)) + elif midcaAction[0] == "release": + cmdID = rosrun.next_id() + actions.append(DoRelease(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RELEASE_TOPIC, cmdID)) + elif midcaAction[0] == "raising": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "raising_arm": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, ' ', + allowed_sighting_lag(' '), allowed_sighting_wait(' '), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "putdown": + cmdID = rosrun.next_id() + actions.append(DoPut(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "stack": + cmdID = rosrun.next_id() + actions.append(DoStack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + else: + if verbose >= 1: + print "MIDCA action", midcaAction, "does not correspond to an asynch", + "action. MIDCA will skip this action" + return AsynchPlan(actions, goals) + + +class AsynchPlan(plans.Plan): + + ''' + subclass of MIDCA Plan class that uses asynchronous actions. + ''' + + def finished(self): + ''' + overrides plan.finished(). Declares a plan complete if all its actions report + complete or failed. + ''' + for action in self.actions: + if action.status != COMPLETE and action.status != FAILED: + return False + return True + + @property + def status(self): + ''' + property that returns the plan's status. This can be NOT_STARTED, IN_PROGRESS, + FAILED, or COMPLETE. If any action fails, the plan is considered to have failed. + The plan is complete when all actions are complete. + ''' + status = COMPLETE + for action in self.actions: + if action.status == FAILED: + return FAILED + elif action.status == NOT_STARTED and status == COMPLETE: + status = NOT_STARTED + elif action.status == IN_PROGRESS: + status = IN_PROGRESS + return status + + def __str__(self): + s = "" + for action in self.actions: + if action.status == NOT_STARTED: + s += NS_COLOR_CODE + elif action.status == IN_PROGRESS: + s += IP_COLOR_CODE + elif action.status == FAILED: + s += F_COLOR_CODE + elif action.status == COMPLETE: + s += C_COLOR_CODE + + s += str(action) + " " + return s[:-1] + END_COLOR_CODE + +class AsynchAction: + + nextID = 0 + + def __init__(self, mem, midcaAction, executeFunc, isComplete, blocks): + self.status = NOT_STARTED + self.mem = mem + self.midcaAction = midcaAction + self.executeFunc = executeFunc + self.isComplete = isComplete + self.blocks = blocks + self.startTime = None + self.id = AsynchAction.nextID + AsynchAction.nextID += 1 + + def execute(self): + if not self.startTime: + self.startTime = midcatime.now() + self.status = IN_PROGRESS + if not self.executeFunc: + return + try: + self.executeFunc(self.mem, self.midcaAction, self.status) + except: + if verbose >= 2: + print "Error executing action", self, ":\n", traceback.format_exc(), + "\n\nAction assumed to be failed" + self.status = FAILED + + def check_complete(self): + if not self.startTime: + self.startTime = midcatime.now() + if not self.check_complete: + return + try: + complete = self.isComplete(self.mem, self.midcaAction, self.status) + if verbose >= 2 and not complete: + print "Action", self, "not complete." + if verbose >= 1 and complete: + print "Action", self, "complete." + if complete: + self.status = COMPLETE + return complete + except: + if verbose >= 1: + print "Error checking completion status for action", self, " - Assuming \ + failure:\n", traceback.format_exc() + self.status = FAILED + + def ros_msg(self, topic, d): + ''' + arg d should be a dictionary that contains the key/value pairs to be sent. + ''' + sent = rosrun.send_msg(topic, rosrun.dict_as_msg) + if not sent: + if verbose >= 1: + print "Unable to send msg; ", d, "on topic", topic, " Action", self, + "assumed failed." + self.status = FAILED + + def __str__(self): + return str(self.midcaAction) + +def get_last_position(mem, objectOrID): + state = mem.get(mem.STATE) + positions = state.all_pos(objectOrID) + if not positions: + return None + else: + for state_pos in reversed(positions): + if state_pos.position: + return (state_pos.position) + return None + +def get_last_location(mem, objectOrID): + world = mem.get(mem.STATE) + sightings = world.all_sightings(objectOrID) + if not sightings: + return None + else: + for detectionEvent in reversed(sightings): + if detectionEvent.loc: + return (detectionEvent.loc, detectionEvent.time) + return None + + + + +class AwaitCurrentLocation(AsynchAction): + + ''' + Action that blocks until there is a current (within last maxAllowedLag seconds) + observation of the object's location. + ''' + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + executeAction = None + completionCheck = lambda mem, midcaAction, status: self.completion_check() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + def completion_check(self): + t = midcatime.now() + if t - self.startTime > self.maxDuration: + if verbose >= 1: + print "max midcatime exceeded for action:", self, "- changing status to failed." + self.status = FAILED + return False + lastLocReport = get_last_location(self.mem, self.objectOrID) + if not lastLocReport: + return False + return t - lastLocReport[1] <= self.maxAllowedLag + + + + diff --git a/midca/domains/templates/doOperatorTemplate.txt b/midca/domains/templates/doOperatorTemplate.txt new file mode 100644 index 00000000..104fafa9 --- /dev/null +++ b/midca/domains/templates/doOperatorTemplate.txt @@ -0,0 +1,60 @@ +class Do(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + diff --git a/midca/examples/minecraft_run.py b/midca/examples/minecraft_run.py new file mode 100644 index 00000000..03a7f916 --- /dev/null +++ b/midca/examples/minecraft_run.py @@ -0,0 +1,63 @@ +import midca +from midca import base +from midca.modules import simulator, guide, evaluate, perceive, intend, planning, act, note, assess +from midca.worldsim import domainread, stateread +import inspect, os + +# Domain Specific Imports +from midca.domains.minecraft import minecraft_util +# TODO: This will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings +from midca.domains.minecraft.plan import methods_minecraft, operators_minecraft + +''' +This template has been automatically created for your new domain, minecraft. +''' + +# Setup +thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +MIDCA_ROOT = thisDir + "/../" + +### Domain Specific Variables +DOMAIN_ROOT = MIDCA_ROOT + "domains/minecraft/" +# TODO: Next 2 lines will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings +DOMAIN_FILE = DOMAIN_ROOT + "domains/domain.sim" +STATE_FILE = DOMAIN_ROOT + "states/state.sim" +DISPLAY_FUNC = print +DECLARE_METHODS_FUNC = methods.declare_methods # TODO: add your domain methods to midca/domains/minecraft/plan/methods.py +DECLARE_OPERATORS_FUNC = operators.declare_ops # TODO: add your domain operators to midca/domains/minecraft/plan/operators.py + + +# Load Domain Files +world = domainread.load_domain(DOMAIN_FILE) +stateread.apply_state_file(world, STATE_FILE) + +# Creates a PhaseManager object, which wraps a MIDCA object +myMidca = base.PhaseManager(world, display = DISPLAY_FUNC, verbose=4) + +# Add phases by name +for phase in ["Simulate", "Perceive", "Interpret", "Eval", "Intend", "Plan", "Act"]: + myMidca.append_phase(phase) + + +# TODO: Update the module references to be domain specific functions +# Add the modules which instantiate basic operation +myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) +myMidca.append_module("Perceive", perceive.PerfectObserver()) +myMidca.append_module("Interpret", guide.UserGoalInput()) +myMidca.append_module("Eval", evaluate.SimpleEval()) +myMidca.append_module("Intend", intend.SimpleIntend()) +myMidca.append_module("Plan", planning.GenericPyhopPlanner( + DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC)) # set up planner for sample domain +myMidca.append_module("Act", act.SimpleAct()) + +# Set world viewer with your specified DISPLAY_FUNC +myMidca.set_display_function(DISPLAY_FUNC) + +# Tells the PhaseManager to copy and store MIDCA states so they can be accessed later. +# Note: Turning this on drastically increases MIDCA's running time. +myMidca.storeHistory = False +myMidca.mem.logEachAccess = False + +# Initialize and start running! +myMidca.init() +myMidca.run() \ No newline at end of file diff --git a/midca/examples/simple_run_jshop_New_Domain_Structure.py b/midca/examples/simple_run_jshop_New_Domain_Structure.py new file mode 100644 index 00000000..69fedad3 --- /dev/null +++ b/midca/examples/simple_run_jshop_New_Domain_Structure.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +from midca import base +from midca.modules import simulator, guide, evaluate, perceive, note, intend, planning, act + +from midca.worldsim import domainread, stateread +import inspect, os + +# Domain Specific Imports +# Use other util files for other domains +from midca.domains.blocksworld import util +from midca.domains.blocksworld.plan import methods, operators + + +''' +Simulation of tower construction +''' + + +###-Make sure put the domain file for jshop planner in JSHOP_DOMAIN_FILE. + +###-util.jshop_state_from_world transfers the state file in MIDCA to state file for JSHOP. You can find the +###generated file in domains/jshop_domains. Another util function put the goal in the state file too. + + + + + +#TODO: make the JSHOP.py to read the path. +thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +print thisDir + +MIDCA_ROOT = thisDir + "/../" +print MIDCA_ROOT +### Domain Specific Variables +DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld_Updated/" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist.sim" +STATE_FILE = DOMAIN_ROOT + "states/defstate_jshop.sim" + +### Domain Specific Variables for JSHOP planner +JSHOP_DOMAIN_FILE = DOMAIN_ROOT + "plan/blocksworld.shp" +JSHOP_STATE_FILE = DOMAIN_ROOT + "plan/bw_ran_problems_5.shp" + +DISPLAY_FUNC = util.asqiiDisplay + +GOAL_GRAPH_CMP_FUNC = util.preferApprehend + +world = domainread.load_domain(DOMAIN_FILE) +stateread.apply_state_file(world, STATE_FILE) +#creates a PhaseManager object, which wraps a MIDCA object +myMidca = base.PhaseManager(world, display = DISPLAY_FUNC, verbose=4) +#add phases by name +for phase in ["Simulate", "Perceive", "Interpret", "Eval", "Intend", "Plan", "Act"]: + myMidca.append_phase(phase) + +#add the modules which instantiate basic blocksworld operation +myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) +myMidca.append_module("Simulate", simulator.ASCIIWorldViewer(display=DISPLAY_FUNC)) +myMidca.append_module("Perceive", perceive.PerfectObserver()) +myMidca.append_module("Interpret", note.ADistanceAnomalyNoter()) +#myMidca.append_module("Interpret", guide.UserGoalInput()) +myMidca.append_module("Eval", evaluate.SimpleEval()) +myMidca.append_module("Intend", intend.SimpleIntend()) +myMidca.append_module("Plan", planning.JSHOPPlanner(util.jshop_state_from_world, + util.jshop_tasks_from_goals, + JSHOP_DOMAIN_FILE, + JSHOP_STATE_FILE + )) +myMidca.append_module("Act", act.SimpleAct()) + +myMidca.insert_module('Simulate', simulator.ArsonSimulator(arsonChance = 0.9, arsonStart = 10), 1) +myMidca.insert_module('Simulate', simulator.FireReset(), 0) +myMidca.insert_module('Interpret', guide.TFStack(), 1) +myMidca.insert_module('Interpret', guide.TFFire(), 2) +myMidca.insert_module('Interpret', guide.ReactiveApprehend(), 3) +myMidca.insert_module('Eval', evaluate.Scorer(), 1) # this needs to be a 1 so that Scorer happens AFTER SimpleEval + + +#tells the PhaseManager to copy and store MIDCA states so they can be accessed later. +myMidca.storeHistory = True +myMidca.initGoalGraph(cmpFunc = GOAL_GRAPH_CMP_FUNC) +myMidca.init() +myMidca.run() + +''' +The code below would print out MIDCA's goal set for the first 20 phases of the run above. Note that any memory values can be accessed in this way, assuming that the storeHistory value was set to True during the run. This code is left as an example, but commented out because it will throw an error if fewer than 20 cycles were simulated. + +for i in range(20): + print myMidca.history[i].mem.get(myMidca.midca.mem.CURRENT_GOALS) + +''' From 941f8fbea9081e53e55520bfadc843db3a32fa65 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 6 Apr 2021 17:28:39 -0400 Subject: [PATCH 17/23] updated file structure and removed test domains --- .../domain_creation_checklist.md | 28 -- midca/domains/Midca_Domain_API.py | 9 +- midca/domains/blocksworld_Updated/__init__.py | 0 .../domains/blocksworld_Updated/arsonist.sim | 95 ------ midca/domains/blocksworld_Updated/block.py | 47 --- .../domains/blocksworld_Updated/blockstate.py | 46 --- .../blocksworld_Updated/plan/__init__.py | 0 .../plan/blocks_world_mortar_examples.py | 300 ------------------ .../plan/bw_ran_problems_5.shp | 10 - .../blocksworld_Updated/plan/methods.py | 158 --------- .../plan/methods_broken.py | 157 --------- .../plan/methods_extinguish.py | 169 ---------- .../blocksworld_Updated/plan/methods_midca.py | 179 ----------- .../plan/methods_mortar.py | 220 ------------- .../blocksworld_Updated/plan/operators.py | 82 ----- .../plan/operators_extinguish.py | 95 ------ .../plan/operators_midca.py | 83 ----- .../plan/operators_mortar.py | 115 ------- .../plan/sample_methods.py | 82 ----- .../plan/sample_operators.py | 24 -- midca/domains/blocksworld_Updated/scene.py | 111 ------- .../states/blocksworld.shp | 107 ------- .../states/bw_ran_problems_5.shp | 12 - .../blocksworld_Updated/states/defstate.sim | 26 -- .../states/defstate_fire.sim | 27 -- .../defstate_fire_pyhop_inducing_bug.sim | 24 -- .../states/defstate_jshop.sim | 26 -- .../states/defstate_mortar.sim | 26 -- .../states/extinguisher_state.sim | 26 -- .../states/sample_state.sim | 20 -- midca/domains/blocksworld_Updated/util.py | 292 ----------------- .../coloredBlocksworld/coloredBlocksworld.cfg | 8 +- .../ros/coloredBlocksworld_async.py | 98 +++--- midca/domains/minecraft/minecraft.cfg | 7 +- midca/domains/templates/asyncTemplate.txt | 48 +-- .../domains/templates/doOperatorTemplate.txt | 4 +- 36 files changed, 57 insertions(+), 2704 deletions(-) delete mode 100644 midca/domains/Domain_Parsing/domain_creation_checklist.md delete mode 100644 midca/domains/blocksworld_Updated/__init__.py delete mode 100644 midca/domains/blocksworld_Updated/arsonist.sim delete mode 100644 midca/domains/blocksworld_Updated/block.py delete mode 100644 midca/domains/blocksworld_Updated/blockstate.py delete mode 100644 midca/domains/blocksworld_Updated/plan/__init__.py delete mode 100644 midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py delete mode 100644 midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp delete mode 100644 midca/domains/blocksworld_Updated/plan/methods.py delete mode 100644 midca/domains/blocksworld_Updated/plan/methods_broken.py delete mode 100644 midca/domains/blocksworld_Updated/plan/methods_extinguish.py delete mode 100644 midca/domains/blocksworld_Updated/plan/methods_midca.py delete mode 100644 midca/domains/blocksworld_Updated/plan/methods_mortar.py delete mode 100644 midca/domains/blocksworld_Updated/plan/operators.py delete mode 100644 midca/domains/blocksworld_Updated/plan/operators_extinguish.py delete mode 100644 midca/domains/blocksworld_Updated/plan/operators_midca.py delete mode 100644 midca/domains/blocksworld_Updated/plan/operators_mortar.py delete mode 100644 midca/domains/blocksworld_Updated/plan/sample_methods.py delete mode 100644 midca/domains/blocksworld_Updated/plan/sample_operators.py delete mode 100644 midca/domains/blocksworld_Updated/scene.py delete mode 100644 midca/domains/blocksworld_Updated/states/blocksworld.shp delete mode 100644 midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp delete mode 100644 midca/domains/blocksworld_Updated/states/defstate.sim delete mode 100644 midca/domains/blocksworld_Updated/states/defstate_fire.sim delete mode 100644 midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim delete mode 100644 midca/domains/blocksworld_Updated/states/defstate_jshop.sim delete mode 100644 midca/domains/blocksworld_Updated/states/defstate_mortar.sim delete mode 100644 midca/domains/blocksworld_Updated/states/extinguisher_state.sim delete mode 100644 midca/domains/blocksworld_Updated/states/sample_state.sim delete mode 100644 midca/domains/blocksworld_Updated/util.py diff --git a/midca/domains/Domain_Parsing/domain_creation_checklist.md b/midca/domains/Domain_Parsing/domain_creation_checklist.md deleted file mode 100644 index 65244284..00000000 --- a/midca/domains/Domain_Parsing/domain_creation_checklist.md +++ /dev/null @@ -1,28 +0,0 @@ -# Domain Creation - -The script has been started and is called New_Domain_Script.py and is found in midca/domains -(C:\Users\Anthony\Anaconda3\python.exe New_Domain_Script.py minecraft/minecraft.pddl) - -### What needs to happen in MIDCA when a new domain is created. -This file should act as a master list of files that need updated when a new domain is added, not necessarily a walkthrough for new users. - -https://github.com/COLAB2/midca/wiki/How-to-add-a-new-domain -tmp: https://github.com/TonePoems/midca/blob/zohreh-minecraft-metricff/midca/domains/minecraft/PDDL_util.py -tmp: https://github.com/COLAB2/midca/tree/zohreh-minecraft-metricff/midca/domains/ffdomain/minecraft - -### What needs to be created -- midca/domains/\/init.py - -blank file needed for MIDCA - -- midca/domains/\/\.sim - - Created by the PDDL_util.py function from Zoreh - - -### What needs updated -- [midca/setup.py](https://github.com/TonePoems/midca/blob/master/setup.py) - - Add domain to packages list - -Insert domain below - ```python - packages=['midca', - 'midca.domains'," - ``` \ No newline at end of file diff --git a/midca/domains/Midca_Domain_API.py b/midca/domains/Midca_Domain_API.py index 6760ad8b..073d34ee 100644 --- a/midca/domains/Midca_Domain_API.py +++ b/midca/domains/Midca_Domain_API.py @@ -234,7 +234,7 @@ def modifyAsync(filename): for operator in actions: mergedTopics = mergedTopics + actions[operator] for topic in set(mergedTopics): - print(topic.upper() + '_TOPIC = \"' + topic + '_cmd\"') + print(topic.upper() + '_TOPIC = \"' + topic + '\"') # Add doOperator for each operator in domain elif '' in line: @@ -252,6 +252,12 @@ def modifyAsync(filename): print(text.replace('', formats), end='') else: print(text, end='') + elif '' in line: + for operator in actions: + text = '\t\telif midcaAction[0] == \"\": \n\t\t\tcmdID = rosrun.next_id()\n\t\t\tactions.append((mem, midcaAction, midcaAction[1], \n\t\t\tallowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]),\n\t\t\t, cmdID))' + text = text.replace('', operator) + text = text.replace('', (str)(actions[operator])) + print(text) else: print(line, end='') @@ -299,7 +305,6 @@ def modifyAsync(filename): if args.verbosity >= 2: print("\nActions Tree: " + (str)(actions)) - # test type values from input # printPDDL(directedGraph) if args.verbosity == 3: #TODO: API ENFORCES ENTITY PARENT diff --git a/midca/domains/blocksworld_Updated/__init__.py b/midca/domains/blocksworld_Updated/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/midca/domains/blocksworld_Updated/arsonist.sim b/midca/domains/blocksworld_Updated/arsonist.sim deleted file mode 100644 index dd1f6fa3..00000000 --- a/midca/domains/blocksworld_Updated/arsonist.sim +++ /dev/null @@ -1,95 +0,0 @@ - -type(BLOCK) -type(ARSONIST) - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(hasmortar, [blk], [BLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/block.py b/midca/domains/blocksworld_Updated/block.py deleted file mode 100644 index 143a1f68..00000000 --- a/midca/domains/blocksworld_Updated/block.py +++ /dev/null @@ -1,47 +0,0 @@ - -# single block, a square, a triangle, or a table. These are the blocks of which -# scenes are composed. -# Possible predicates involving blocks: -# -square(x) -# -triangle(x) -# -table(x) -# -clear(x) -# -on(x,y) -class Block: - SQUARE = 1 # constant - TRIANGLE = 2 - TABLE = 3 - - def __init__(self, type, id): - self.type = type - self.id = id - self.on = None - self.clear = True - self.onfire = False - - # place self block onto onto block - def place(self, onto): - if self.on: - self.on.clear() - self.on = onto - self.on.unclear() - - # set the block to not clear - def unclear(self): - self.isclear = False - - # set the block to clear - def clear(self): - self.isclear = True - - def __str__(self): - return self.id - - def __hash__(self): - return hash(self.id) - - def __eq__(self, other): - try: - return self.id == other.id - except Exception: - return False diff --git a/midca/domains/blocksworld_Updated/blockstate.py b/midca/domains/blocksworld_Updated/blockstate.py deleted file mode 100644 index d14cd3c5..00000000 --- a/midca/domains/blocksworld_Updated/blockstate.py +++ /dev/null @@ -1,46 +0,0 @@ -from midca.domains.blocksworld.block import Block -from midca.worldsim import worldsim - -def b(name): - return "b" + str(name) - -def get_block_list(world): - blocks = {} - for obj in world.objects.values(): - if obj.type.name != "BLOCK": - continue - block = None - if world.atom_true(worldsim.Atom(world.predicates["table"], [obj])): - block = Block(Block.TABLE, obj.name) - elif world.atom_true(worldsim.Atom(world.predicates["triangle"], [obj])): - block = Block(Block.TRIANGLE, obj.name) - elif world.atom_true(worldsim.Atom(world.predicates["block"], [obj])): - block = Block(Block.SQUARE, obj.name) - if not block: - continue - block.clear = False - block.on = None - block.onfire = False - block.hasmortar = False - if block.type == block.TABLE: - table = block - blocks[obj.name] = block - for atom in world.atoms: - try: # some domains won't use stable-on, so if we get a KeyError just ignore - if atom.predicate == world.predicates["stable-on"]: - blocks[atom.args[0].name].on = blocks[atom.args[1].name] - except KeyError: - pass - - if atom.predicate == world.predicates["on"]: # or : - blocks[atom.args[0].name].on = blocks[atom.args[1].name] - elif atom.predicate == world.predicates["on-table"]: - blocks[atom.args[0].name].on = table - elif atom.predicate == world.predicates["clear"]: - blocks[atom.args[0].name].clear = True - elif atom.predicate == world.predicates["onfire"]: - blocks[atom.args[0].name].onfire = True - elif "hasmortar" in world.predicates.keys() and atom.predicate == world.predicates["hasmortar"]: - blocks[atom.args[0].name].hasmortar = True - return sorted(blocks.values(), key = lambda x: x.id) - diff --git a/midca/domains/blocksworld_Updated/plan/__init__.py b/midca/domains/blocksworld_Updated/plan/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py b/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py deleted file mode 100644 index b626f62e..00000000 --- a/midca/domains/blocksworld_Updated/plan/blocks_world_mortar_examples.py +++ /dev/null @@ -1,300 +0,0 @@ -""" -TESTING for mortar - -Blocks-world test data for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from __future__ import print_function -from pyhop import * - -import time - -import operators_mortar -print('') -operators_mortar.declare_ops() -print_operators() - -import methods_mortar -print('') -methods_mortar.declare_methods() -#methods_broken.declare_methods() -print_methods() - - -############# beginning of tests ################ - - -print(""" -**************************************** -First, test pyhop on some of the operators and smaller tasks -**************************************** -""") - -print("- Define state1: a on b, b on tale, c on table") - -""" -A state is a collection of all of the state variables and their values. Every state variable in the domain should have a value. -""" - -state1 = State('state1') -state1.pos={'a':'b', 'b':'table', 'c':'table','d':'table','e':'table'} -state1.clear={'c':True, 'b':False,'a':True,'d':True,'e':True} -state1.holding=False - -# make sure no blocks have mortar on them; start with initial quantity -# of mortar -state1.hasmortar = {} -for blockid in state1.pos.keys(): - state1.hasmortar[blockid] = False - -state1.mortaravailable = {} # key is id, value is Available/Used -num_mortar = 5 -for i in range(num_mortar): - key = 'M'+str(i) - state1.mortaravailable[key] = True - -print_state(state1) -print('') - -print('- these should fail:') -pyhop(state1,[('pickup','a')], verbose=1) -pyhop(state1,[('pickup','b')], verbose=1) -print('- these should succeed:') -pyhop(state1,[('pickup','c')], verbose=1) -pyhop(state1,[('unstack','a','b')], verbose=1) -pyhop(state1,[('get','a')], verbose=1) -print('- this should fail:') -pyhop(state1,[('get','b')], verbose=1) -print('- this should succeed:') -pyhop(state1,[('get','c')], verbose=1) - -print(' - testing stack mortared') -print_state(state1) -goal1a = Goal('goal1a') -goal1a.pos={'c':'b', 'b':'a', 'a':'e', 'e':'d', 'd':'table'} -pyhop(state1,[('move_blocks', goal1a)],verbose=1) - -print(' - testing unstack mortared') -state2 = State('state2') -state2.hasmortar = {'D_': False, 'B_': 'M5', 'C_': 'M4', 'A_': False} -state2.fire = {'D_': False, 'B_': False, 'C_': False, 'A_': False} -state2.clear = {'D_': True, 'B_': False, 'C_': False, 'A_': False} -state2.pos = {'D_': 'C_', 'B_': 'A_', 'C_': 'B_', 'A_': 'table'} -state2.free = {'Gui Montag': True} -state2.mortaravailable = {'M5': False, 'M4': False, 'M1': True, 'M3': True, 'M2': True, 'M6':True, 'M7':True} -state2.holding = False -print_state(state2) -goal2 = Goal('goal2') -goal2.pos={'D_':'B_'} -pyhop(state2,[('move_blocks', goal2)],verbose=4) - -# -# print(""" -# **************************************** -# Run pyhop on two block-stacking problems, both of which start in state1. -# The goal for the 2nd problem omits some of the conditions in the goal -# of the 1st problem, but those conditions will need to be achieved -# anyway, so both goals should produce the same plan. -# **************************************** -# """) -# -# print("- Define goal1a:") -# -# """ -# A goal is a collection of some (but not necessarily all) of the state variables and their desired values. Below, both goal1a and goal1b specify c on b, and b on a. The difference is that goal1a also specifies that a is on table and the hand is empty. -# """ -# -# goal1a = Goal('goal1a') -# goal1a.pos={'c':'b', 'b':'a', 'a':'table'} -# goal1a.clear={'c':True, 'b':False, 'a':False} -# goal1a.holding=False -# -# print_goal(goal1a) -# print('') -# -# print("- Define goal1b:") -# -# goal1b = Goal('goal1b') -# goal1b.pos={'c':'b', 'b':'a'} -# -# print_goal(goal1b) - -### goal1b omits some of the conditions of goal1a, -### but those conditions will need to be achieved anyway - - -# pyhop(state1,[('move_blocks', goal1a)], verbose=2) -# -# print_state(newstate) -# -# time.sleep(15) -# -# pyhop(state1,[('move_blocks', goal1b)], verbose=2) -# -# print_state(newstate) -# -# time.sleep(15) - - -# -# print(""" -# **************************************** -# Run pyhop on two more planning problems. As before, the 2nd goal omits -# some of the conditions in the 1st goal, but both goals should produce -# the same plan. -# **************************************** -# """) -# -# print("- Define state 2:") -# -# state2 = State('state2') -# state2.pos={'a':'c', 'b':'d', 'c':'table', 'd':'table'} -# state2.clear={'a':True, 'c':False,'b':True, 'd':False} -# state2.holding=False -# -# ## make sure no blocks have mortar on them; start with initial quantity -# # of mortar -# state2.mortared = {} -# for blockid in state2.pos.keys(): -# state2.mortared[blockid] = False -# -# state2.mortar_quantity = 10 -# -# print_state(state2) -# print('') -# -# print("- Define goal2a:") -# -# goal2a = Goal('goal2a') -# goal2a.pos={'a':'b', 'b':'c', 'c':'d', 'd':'table'} -# goal2a.clear={'a':True, 'c':False,'b':True, 'd':False} -# goal2a.holding=False -# -# print_goal(goal2a) -# print('') -# -# print("- Define goal2b:") -# -# goal2b = Goal('goal2b') -# goal2b.pos={'b':'c', 'a':'d'} -# -# print_goal(goal2b) -# print('') -# -# -# ### goal2b omits some of the conditions of goal2a, -# ### but those conditions will need to be achieved anyway. -# #time.sleep(1000) -# pyhop(state2,[('move_blocks', goal2a)], verbose=1) -# print_state(state2) -# time.sleep(10) -# -# pyhop(state2,[('move_blocks', goal2b)], verbose=1) -# print_state(state2) -# time.sleep(10) -# -# print(""" -# **************************************** -# Test pyhop on planning problem bw_large_d from the SHOP distribution. -# **************************************** -# """) -# -# print("- Define state3:") -# -# state3 = State('state3') -# state3.pos = {1:12, 12:13, 13:'table', 11:10, 10:5, 5:4, 4:14, 14:15, 15:'table', 9:8, 8:7, 7:6, 6:'table', 19:18, 18:17, 17:16, 16:3, 3:2, 2:'table'} -# state3.clear = {x:False for x in range(1,20)} -# state3.clear.update({1:True, 11:True, 9:True, 19:True}) -# state3.holding = False -# -# print_state(state3) -# print('') -# -# print("- Define goal3:") -# -# goal3 = Goal('goal3') -# goal3.pos = {15:13, 13:8, 8:9, 9:4, 4:'table', 12:2, 2:3, 3:16, 16:11, 11:7, 7:6, 6:'table'} -# goal3.clear = {17:True, 15:True, 12:True} -# -# print_goal(goal3) -# print('') -# -# pyhop(state3,[('move_blocks', goal3)], verbose=1) -# -# -# print(""" -# **************************************** -# Load a modified version of the blocks_world methods, in which the -# method for 'get' is replaced with two methods that will sometimes -# cause backtracking. -# **************************************** -# """) -# -# # import blocks_world_methods2 -# # print_methods() -# -# # print("""\n=== In the next call to pyhop, it should backtrack: -# # the recursion depth should go up, then down, then up again.===\n""") -# -# # # verbose=2 tells pyhop to print out a message at each recursion depth -# -# # pyhop(state1,[('get', 'a')], verbose=2) -# -# # print("""\n=== This time it shouldn't backtrack.===\n""") -# -# -# # pyhop(state1,[('get', 'c')], verbose=2) -# -# # print("""\n=== This time it should fail.===\n""") -# -# # pyhop(state1,[('get', 'b')], verbose=2) -# -# -# -# # print(""" -# # **************************************** -# # demonstrate different levels of verbosity -# # **************************************** -# # """) -# -# # print('- verbosity 0:') -# # pyhop(state1,[('get','a')], verbose=0) -# # print('- verbosity 1:') -# # pyhop(state1,[('get','a')], verbose=1) -# # print('- verbosity 2:') -# # pyhop(state1,[('get','a')], verbose=2) -# # print('- verbosity 3:') -# # pyhop(state1,[('get','a')], verbose=3) -# -# print(""" -# **************************************** -# Demonstrates planning issue; added by mpaisner 8/28/13 -# **************************************** -# """) -# #import blocks_world_methods3 -# state4 = State('state4') -# state4.pos = {1:'table', 2:1, 3:2, 4:'table'} -# state4.clear = {1:False, 2:False, 3:True, 4:True} -# state4.holding = False -# -# goal4 = Goal('goal4') -# goal4.pos = {4:2} -# print_goal(goal4) -# print('') -# -# pyhop(state4,[('move_blocks', goal4)], verbose=1) -# -# #import blocks_world_methods3 -# state5 = State('state5') -# state5.pos = {'A_':'table', 'B_':'A_', 'D_':'B_', 'C_':'table'} -# state5.clear = {'A_':False, 'B_':False, 'D_':True, 'C_':True} -# state5.holding = False -# -# goal5 = Goal('goal5') -# goal5.pos = {'C_':'B_'} -# print_goal(goal5) -# print('') -# -# pyhop(state4,[('move_blocks', goal4)], verbose=1) diff --git a/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp b/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp deleted file mode 100644 index 07e038e8..00000000 --- a/midca/domains/blocksworld_Updated/plan/bw_ran_problems_5.shp +++ /dev/null @@ -1,10 +0,0 @@ - -(defproblem bw-ran-5-1 blocks-normal ((arm-empty) -(clear d) -(on-table c) -(on b a) -(on d b) -(clear c) -(on-table a) -) - ((achieve-goals ( list diff --git a/midca/domains/blocksworld_Updated/plan/methods.py b/midca/domains/blocksworld_Updated/plan/methods.py deleted file mode 100644 index 0c677284..00000000 --- a/midca/domains/blocksworld_Updated/plan/methods.py +++ /dev/null @@ -1,158 +0,0 @@ -""" -Blocks World methods for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from midca.modules._plan import pyhop - - -""" -Here are some helper functions that are used in the methods' preconditions. -""" - -def is_done(b1,state,goal): - if b1 == 'table': return True - if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: - return False - if state.pos[b1] == 'table': return True - if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): - return False - return is_done(state.pos[b1],state,goal) - -def status(b1,state,goal): - if is_done(b1,state,goal): - return 'done' - elif not (state.clear[b1] or state.pos[b1] == "in-arm"): - return 'inaccessible' - elif not (b1 in goal.pos) or goal.pos[b1] == 'table': - return 'move-to-table' - elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: - return 'move-to-block' - else: - return 'waiting' - -def all_blocks(state): - return state.clear.keys() - - -""" -In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. -""" - -### methods for "move_blocks" - -def moveb_m(state,goal): - """ - This method implements the following block-stacking algorithm: - If there's a block that can be moved to its final position, then - do so and call move_blocks recursively. Otherwise, if there's a - block that needs to be moved and can be moved to the table, then - do so and call move_blocks recursively. Otherwise, no blocks need - to be moved. - """ - for b1 in all_blocks(state): - s = status(b1,state,goal) - if s == 'move-to-table': - return [('move_one',b1,'table'),('move_blocks',goal)] - elif s == 'move-to-block': - return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] - else: - continue - # - # if we get here, no blocks can be moved to their final locations - b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) - if b1 != None: - return [('move_one',b1,'table'), ('move_blocks',goal)] - # - # if we get here, there are no blocks that need moving - return [] - -""" -declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. -""" - - -### methods for "move_one" - -def move1(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest. - """ - if state.pos[b1] == "in-arm": - return [('put', b1,dest)] - else: - return [('get', b1), ('put', b1,dest)] - -### methods for "get" - -def get_by_unstack(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack_task',b1)] - return False - -def get_by_pickup(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup_task',b1)] - return False - -### methods for "pickup_task" - -def pickup_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup',b1)] - return False - -### methods for "unstack_task" - -def unstack_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack',b1,state.pos[b1])] - return False - -### methods for "put" - -def put_m(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - if state.holding == b1: - if b2 == 'table': - return [('putdown',b1)] - else: - return [('stack',b1,b2)] - else: - return False - -def put_out_m(state, b1): - if state.fire[b1]: - return [("putoutfire", b1)] - else: - return [] - -def quick_apprehend_m(state, perp): - if state.free[perp]: - return [("apprehend", perp)] - else: - return [] - -def long_apprehend_m(state, perp): - if state.free[perp]: - return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] - else: - return [] - -def declare_methods(longApprehend = True): - if longApprehend: - pyhop.declare_methods("catch_arsonist", long_apprehend_m) - else: - pyhop.declare_methods("catch_arsonist", quick_apprehend_m) - pyhop.declare_methods("put_out", put_out_m) - pyhop.declare_methods('put',put_m) - pyhop.declare_methods('unstack_task',unstack_m) - pyhop.declare_methods('pickup_task',pickup_m) - pyhop.declare_methods('get',get_by_pickup,get_by_unstack) - pyhop.declare_methods('move_one',move1) - pyhop.declare_methods('move_blocks',moveb_m) - diff --git a/midca/domains/blocksworld_Updated/plan/methods_broken.py b/midca/domains/blocksworld_Updated/plan/methods_broken.py deleted file mode 100644 index cfdd0115..00000000 --- a/midca/domains/blocksworld_Updated/plan/methods_broken.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -Blocks World methods for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from midca.modules._plan import pyhop - -""" -Here are some helper functions that are used in the methods' preconditions. -""" - -def is_done(b1,state,goal): - if b1 == 'table': return True - if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: - return False - if state.pos[b1] == 'table': return True - return is_done(state.pos[b1],state,goal) - -def status(b1,state,goal): - if is_done(b1,state,goal): - return 'done' - elif not (state.clear[b1] or state.pos[b1] == "in-arm"): - return 'inaccessible' - elif not (b1 in goal.pos) or goal.pos[b1] == 'table': - return 'move-to-table' - elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: - return 'move-to-block' - else: - return 'waiting' - -def all_blocks(state): - return state.clear.keys() - - -""" -In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. -""" - -### methods for "move_blocks" - -def moveb_m(state,goal): - """ - This method implements the following block-stacking algorithm: - If there's a block that can be moved to its final position, then - do so and call move_blocks recursively. Otherwise, if there's a - block that needs to be moved and can be moved to the table, then - do so and call move_blocks recursively. Otherwise, no blocks need - to be moved. - """ - - - for b1 in all_blocks(state): - s = status(b1,state,goal) - if s == 'move-to-table': - return [('move_one',b1,'table'),('move_blocks',goal)] - elif s == 'move-to-block': - return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] - else: - continue - # - # if we get here, no blocks can be moved to their final locations - b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) - if b1 != None: - return [('move_one',b1,'table'), ('move_blocks',goal)] - # - # if we get here, there are no blocks that need moving - return [] - -""" -declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. -""" - - -### methods for "move_one" - -def move1(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest. - """ - if state.pos[b1] == "in-arm": - return [('put', b1,dest)] - else: - return [('get', b1), ('put', b1,dest)] - -### methods for "get" - -def get_by_unstack(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack_task',b1)] - return False - -def get_by_pickup(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup_task',b1)] - return False - -### methods for "pickup_task" - -def pickup_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup',b1)] - return False - -### methods for "unstack_task" - -def unstack_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack',b1,state.pos[b1])] - return False - -### methods for "put" - -def put_m(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - if state.holding == b1: - if b2 == 'table': - return [('putdown',b1)] - else: - return [('stack',b1,b2)] - else: - return False - -def put_out_m(state, b1): - if state.fire[b1]: - return [("putoutfire", b1)] - else: - return [] - -def quick_apprehend_m(state, perp): - if state.free[perp]: - return [("apprehend", perp)] - else: - return [] - -def long_apprehend_m(state, perp): - if state.free[perp]: - return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] - else: - return [] - -def declare_methods(longApprehend = True): - if longApprehend: - pyhop.declare_methods("catch_arsonist", long_apprehend_m) - else: - pyhop.declare_methods("catch_arsonist", quick_apprehend_m) - pyhop.declare_methods("put_out", put_out_m) - pyhop.declare_methods('put',put_m) - pyhop.declare_methods('unstack_task',unstack_m) - pyhop.declare_methods('pickup_task',pickup_m) - pyhop.declare_methods('get',get_by_pickup,get_by_unstack) - pyhop.declare_methods('move_one',move1) - pyhop.declare_methods('move_blocks',moveb_m) - diff --git a/midca/domains/blocksworld_Updated/plan/methods_extinguish.py b/midca/domains/blocksworld_Updated/plan/methods_extinguish.py deleted file mode 100644 index 4da8346f..00000000 --- a/midca/domains/blocksworld_Updated/plan/methods_extinguish.py +++ /dev/null @@ -1,169 +0,0 @@ -""" -Blocks World methods for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from midca.modules._plan import pyhop -import random - -""" -Here are some helper functions that are used in the methods' preconditions. -""" - -def is_done(b1,state,goal): - if b1 == 'table': return True - if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: - return False - if state.pos[b1] == 'table': return True - if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): - return False - return is_done(state.pos[b1],state,goal) - -def status(b1,state,goal): - if is_done(b1,state,goal): - return 'done' - elif not (state.clear[b1] or state.pos[b1] == "in-arm"): - return 'inaccessible' - elif not (b1 in goal.pos) or goal.pos[b1] == 'table': - return 'move-to-table' - elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: - return 'move-to-block' - else: - return 'waiting' - -def all_blocks(state): - return state.clear.keys() - - -""" -In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. -""" - -### methods for "move_blocks" - -def moveb_m(state,goal): - """ - This method implements the following block-stacking algorithm: - If there's a block that can be moved to its final position, then - do so and call move_blocks recursively. Otherwise, if there's a - block that needs to be moved and can be moved to the table, then - do so and call move_blocks recursively. Otherwise, no blocks need - to be moved. - """ - for b1 in all_blocks(state): - s = status(b1,state,goal) - if s == 'move-to-table': - return [('move_one',b1,'table'),('move_blocks',goal)] - elif s == 'move-to-block': - return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] - else: - continue - # - # if we get here, no blocks can be moved to their final locations - b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) - if b1 != None: - return [('move_one',b1,'table'), ('move_blocks',goal)] - # - # if we get here, there are no blocks that need moving - return [] - -""" -declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. -""" - - -### methods for "move_one" - -def move1(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest. - """ - if state.pos[b1] == "in-arm": - return [('put', b1,dest)] - else: - return [('get', b1), ('put', b1,dest)] - -### methods for "get" - -def get_by_unstack(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack_task',b1)] - return False - -def get_by_pickup(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup_task',b1)] - return False - -### methods for "pickup_task" - -def pickup_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup',b1)] - return False - -### methods for "unstack_task" - -def unstack_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack',b1,state.pos[b1])] - return False - -### methods for "put" - -def put_m(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - if state.holding == b1: - if b2 == 'table': - return [('putdown',b1)] - else: - return [('stack',b1,b2)] - else: - return False - -def put_out_m(state, b1): - if state.fire[b1]: - if state.holdingfireext: - return [("putoutfire", b1, state.holdingfireext)] - elif state.fire_ext_avail: - ext = random.choice(list(state.fire_ext_avail)) - return [('get_extinguisher', ext), ("putoutfire", b1, ext)] - else: - return [] - -def get_extinguisher_m(state, extinguisher): - if extinguisher in state.fire_ext_avail and not state.holdingfireext: - return [("pickup_extinguisher", extinguisher)] - else: - return False - -def quick_apprehend_m(state, perp): - if state.free[perp]: - return [("apprehend", perp)] - else: - return [] - -def long_apprehend_m(state, perp): - if state.free[perp]: - return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] - else: - return [] - -def declare_methods(longApprehend = True): - if longApprehend: - pyhop.declare_methods("catch_arsonist", long_apprehend_m) - else: - pyhop.declare_methods("catch_arsonist", quick_apprehend_m) - pyhop.declare_methods("put_out", put_out_m) - pyhop.declare_methods('put',put_m) - pyhop.declare_methods('unstack_task',unstack_m) - pyhop.declare_methods('pickup_task',pickup_m) - pyhop.declare_methods('get',get_by_pickup,get_by_unstack) - pyhop.declare_methods('move_one',move1) - pyhop.declare_methods('move_blocks',moveb_m) - pyhop.declare_methods('get_extinguisher',get_extinguisher_m) - diff --git a/midca/domains/blocksworld_Updated/plan/methods_midca.py b/midca/domains/blocksworld_Updated/plan/methods_midca.py deleted file mode 100644 index 059efba9..00000000 --- a/midca/domains/blocksworld_Updated/plan/methods_midca.py +++ /dev/null @@ -1,179 +0,0 @@ -""" -Blocks World methods for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from midca.modules._plan import pyhop - - -""" -Here are some helper functions that are used in the methods' preconditions. -""" - -def is_done(b1,state,goal): - if b1 == 'table': return True - if b1 in goal.pos and not state.is_true("on", [b1, goal.pos[b1]]): - return False - if b1 in goal.pos.values() and not state.is_true("clear", [b1]): - return False - print b1, state.is_true("on-table", [b1]) - if state.is_true("on-table", [b1]): return True - for atom in state.atoms: - if atom.predicate.name == "on" and atom.args[0].name == b1: - return is_done(atom.args[1].name, state, goal) - if state.is_true("holding", [b1]): - return True - print b1, state - for atom in state.atoms: - print atom - raise Exception("Block is neither on anything or being held") - -def status(b1,state,goal): - if is_done(b1,state,goal): - return 'done' - elif not (state.is_true("clear", [b1]) or state.is_true("holding", [b1])): - print "inaccessible", b1, state.is_true("clear", [b1]) - for atom in state.atoms: - if atom.predicate.name == "clear": - print atom - return 'inaccessible' - elif not (b1 in goal.pos) or goal.pos[b1] == 'table': - return 'move-to-table' - elif is_done(goal.pos[b1],state,goal) and state.is_true("clear", [goal.pos[b1]]): - return 'move-to-block' - else: - return 'waiting' - -def all_blocks(state): - return [name for name, object in state.objects.items() if object.type.name.lower() == "block"] - - -""" -In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. -""" - -### methods for "move_blocks" - -def moveb_m(state,goal): - """ - This method implements the following block-stacking algorithm: - If there's a block that can be moved to its final position, then - do so and call move_blocks recursively. Otherwise, if there's a - block that needs to be moved and can be moved to the table, then - do so and call move_blocks recursively. Otherwise, no blocks need - to be moved. - """ - print state - for b1 in all_blocks(state): - s = status(b1,state,goal) - print b1, "stat:", s - if s == 'move-to-table': - return [('move_one',b1,'table'),('move_blocks',goal)] - elif s == 'move-to-block': - return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] - else: - continue - - b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) - if b1 != None: - return [('move_one',b1,'table'), ('move_blocks',goal)] - # - # if we get here, there are no blocks that need moving - return [] - -""" -declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. -""" - - -### methods for "move_one" - -def move1(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest. - """ - if state.is_true("holding", [b1]): - return [('put', b1, dest)] - if state.is_true("arm-empty"): - return [('get', b1), ('put', b1,dest)] - for atom in state.atoms: - if atom.predicate.name == "holding": - heldBlock = atoms.args[0].name - return [('put', heldBlock, 'table'), ('get', b1), ('put', b1,dest)] - -### methods for "get" - -def get_by_unstack(state,b1): - """Generate a pickup subtask.""" - if state.is_true("clear", [b1]): return [('unstack_task',b1)] - return False - -def get_by_pickup(state,b1): - """Generate a pickup subtask.""" - if state.is_true("clear", [b1]): return [('pickup_task',b1)] - return False - -### methods for "pickup_task" - -def pickup_m(state,b1): - """Generate a pickup subtask.""" - if state.is_true("clear", [b1]): return [('pickup',b1)] - return False - -### methods for "unstack_task" - -def unstack_m(state,b1): - """Generate a pickup subtask.""" - if state.is_true("clear", [b1]): - for atom in state.atoms: - if atom.predicate.name == "on" and atom.args[0].name == b1: - return [('unstack',b1,atom.args[1].name)] - return False - -### methods for "put" - -def put_m(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - if state.is_true("holding", [b1]): - if b2 == 'table': - return [('putdown',b1)] - else: - return [('stack',b1,b2)] - else: - return False - -def put_out_m(state, b1): - if state.is_true("onfire", [b1]): - return [("putoutfire", b1)] - else: - return [] - -def quick_apprehend_m(state, perp): - if state.is_true("free", [perp]): - return [("apprehend", perp)] - else: - return [] - -def long_apprehend_m(state, perp): - if state.is_true("free", [perp]): - return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] - else: - return [] - -def declare_methods(longApprehend = True): - if longApprehend: - pyhop.declare_methods("catch_arsonist", long_apprehend_m) - else: - pyhop.declare_methods("catch_arsonist", quick_apprehend_m) - pyhop.declare_methods("put_out", put_out_m) - pyhop.declare_methods('put',put_m) - pyhop.declare_methods('unstack_task',unstack_m) - pyhop.declare_methods('pickup_task',pickup_m) - pyhop.declare_methods('get',get_by_pickup,get_by_unstack) - pyhop.declare_methods('move_one',move1) - pyhop.declare_methods('move_blocks',moveb_m) - diff --git a/midca/domains/blocksworld_Updated/plan/methods_mortar.py b/midca/domains/blocksworld_Updated/plan/methods_mortar.py deleted file mode 100644 index 379e89d8..00000000 --- a/midca/domains/blocksworld_Updated/plan/methods_mortar.py +++ /dev/null @@ -1,220 +0,0 @@ -""" -Blocks World* methods for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -""" -* Modified by Dustin Dannenhauer: Added a new operator for stacking with mortar - -""" - -from midca.modules._plan import pyhop - -""" -Here are some helper functions that are used in the methods' preconditions. -""" - -def is_done(b1,state,goal): - if b1 == 'table': return True - if b1 in goal.pos and goal.pos[b1] != state.pos[b1]: - return False - if state.pos[b1] == 'table': return True - if state.pos[b1] in goal.pos.values() and (b1 not in goal.pos or goal.pos[b1] != state.pos[b1]): - return False - return is_done(state.pos[b1],state,goal) - -def status(b1,state,goal): - if is_done(b1,state,goal): - return 'done' - elif not (state.clear[b1] or state.pos[b1] == "in-arm"): - return 'inaccessible' - elif not (b1 in goal.pos) or goal.pos[b1] == 'table': - return 'move-to-table' - elif is_done(goal.pos[b1],state,goal) and state.clear[goal.pos[b1]]: - btmblk = goal.pos[b1] - if btmblk in goal.hasmortar.keys() and goal.hasmortar[btmblk]: - ''' This check adds a status so we move blocks with mortar different then without mortar ''' - return 'move-to-block-with-mortar' - else: - return 'move-to-block' - else: - return 'waiting' - -def all_blocks(state): - return state.clear.keys() - - -""" -In each Pyhop planning method, the first argument is the current state (this is analogous to Python methods, in which the first argument is the class instance). The rest of the arguments must match the arguments of the task that the method is for. For example, ('pickup', b1) has a method get_m(state,b1), as shown below. -""" - -### methods for "move_blocks" - -def moveb_m(state,goal): - """ - This method implements the following block-stacking algorithm: - If there's a block that can be moved to its final position, then - do so and call move_blocks recursively. Otherwise, if there's a - block that needs to be moved and can be moved to the table, then - do so and call move_blocks recursively. Otherwise, no blocks need - to be moved. - """ - for b1 in all_blocks(state): - s = status(b1,state,goal) - if s == 'move-to-table': - return [('move_one',b1,'table'),('move_blocks',goal)] - elif s == 'move-to-block': - return [('move_one',b1,goal.pos[b1]), ('move_blocks',goal)] - elif s == 'move-to-block-with-mortar': - return [('move_one_mortar',b1,goal.pos[b1]), ('move_blocks',goal)] - else: - continue - # - # if we get here, no blocks can be moved to their final locations - b1 = pyhop.find_if(lambda x: status(x,state,goal) == 'waiting', all_blocks(state)) - if b1 != None: - return [('move_one',b1,'table'), ('move_blocks',goal)] - # - # if we get here, there are no blocks that need moving - return [] - -""" -declare_methods must be called once for each taskname. Below, 'declare_methods('get',get_m)' tells Pyhop that 'get' has one method, get_m. Notice that 'get' is a quoted string, and get_m is the actual function. -""" - - -### methods for "move_one" - -def move1(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest. - """ - if state.pos[b1] == "in-arm": - return [('put', b1,dest)] - else: - return [('get', b1), ('put', b1,dest)] - -### methods for "move_one_mortar" - -def move1_mortar(state,b1,dest): - """ - Generate subtasks to get b1 and put it at dest (with mortar) - """ - if state.pos[b1] == "in-arm": - return [('put_mortar', b1,dest)] - else: - return [('get', b1), ('put_mortar', b1,dest)] - - -### methods for "get" - -def get_by_unstack(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('unstack_task',b1)] - return False - -def get_by_pickup(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup_task',b1)] - return False - -### methods for "pickup_task" - -def pickup_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: return [('pickup',b1)] - return False - -### methods for "unstack_task" - -def unstack_m(state,b1): - """Generate a pickup subtask.""" - if state.clear[b1]: - btmblk = state.pos[b1] - mortarblk = state.hasmortar[btmblk] - if mortarblk: - return [('unstack_mortared',b1,state.pos[b1],mortarblk)] - else: - return [('unstack',b1,state.pos[b1])] - return False - -### methods for "put" - -def put_m(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - - if state.holding == b1: - if b2 == 'table': - return [('putdown',b1)] - else: - return [('stack',b1,b2)] - else: - return False - -### Methods for put_mortar - -def put_m_mortar(state,b1,b2): - """ - Generate either a putdown or a stack subtask for b1. - b2 is b1's destination: either the table or another block. - """ - - available_mortar = [k for k,v in state.mortaravailable.items() if v] - mortar_block = False - if len(available_mortar) > 0: - mortar_block = available_mortar[0] - - if state.holding == b1: - if b2 == 'table': - return [('putdown',b1)] - elif mortar_block: - # new stack with mortar - #print("*-*-*-*-*-* stacking with mortar") - return [('stack_mortared',b1,b2,mortar_block)] - else: - # no mortar left, continue stacking like normal - return [('stack',b1,b2)] - #return False # change to use this line instead of above to fail on no more mortar - - else: - return False - - -def put_out_m(state, b1): - if state.fire[b1]: - return [("putoutfire", b1)] - else: - return [] - -def quick_apprehend_m(state, perp): - if state.free[perp]: - return [("apprehend", perp)] - else: - return [] - -def long_apprehend_m(state, perp): - if state.free[perp]: - return [("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("searchfor", perp), ("apprehend", perp)] - else: - return [] - -def declare_methods(longApprehend = True): - if longApprehend: - pyhop.declare_methods("catch_arsonist", long_apprehend_m) - else: - pyhop.declare_methods("catch_arsonist", quick_apprehend_m) - pyhop.declare_methods("put_out", put_out_m) - pyhop.declare_methods('put',put_m) - pyhop.declare_methods('put_mortar',put_m_mortar) - pyhop.declare_methods('unstack_task',unstack_m) - pyhop.declare_methods('pickup_task',pickup_m) - pyhop.declare_methods('get',get_by_pickup,get_by_unstack) - pyhop.declare_methods('move_one',move1) - pyhop.declare_methods('move_one_mortar',move1_mortar) - pyhop.declare_methods('move_blocks',moveb_m) -# pyhop.declare_methods('put_with_mortar',put_with_mortar_m) - diff --git a/midca/domains/blocksworld_Updated/plan/operators.py b/midca/domains/blocksworld_Updated/plan/operators.py deleted file mode 100644 index ed22b185..00000000 --- a/midca/domains/blocksworld_Updated/plan/operators.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -Blocks World domain definition for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" -import sys -sys.path.append("../") -from midca.modules._plan import pyhop - -"""Each Pyhop planning operator is a Python function. The 1st argument is -the current state, and the others are the planning operator's usual arguments. -This is analogous to how methods are defined for Python classes (where -the first argument is always the name of the class instance). For example, -the function pickup(state,b) implements the planning operator for the task -('pickup', b). - -The blocks-world operators use three state variables: -- pos[b] = block b's position, which may be 'table', 'hand', or another block. -- clear[b] = False if a block is on b or the hand is holding b, else True. -- holding = name of the block being held, or False if the hand is empty. -""" - -def pickup(state,b): - if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - return state - else: return False - -def unstack(state,b,c): - if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - state.clear[c] = True - return state - else: return False - -def putdown(state,b): - if state.pos[b] == 'hand': - state.pos[b] = 'table' - state.clear[b] = True - state.holding = False - return state - else: return False - -def stack(state,b,c): - print(state.pos[b]) - print(state.clear[c]) - if state.pos[b] == 'hand' and state.clear[c] == True: - state.pos[b] = c - state.clear[b] = True - state.holding = False - state.clear[c] = False - return state - else: return False - -def putoutfire(state, b): - if state.fire[b] == True: - state.fire[b] = False - return state - else: - return False - -def apprehend(state, perp): - if state.free[perp] == True: - state.free[perp] = False - return state - else: - return False - -def searchfor(state, perp): - return state - -""" -Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop -what the operators are. Note that the operator names are *not* quoted. -""" - -def declare_ops(): - pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor) diff --git a/midca/domains/blocksworld_Updated/plan/operators_extinguish.py b/midca/domains/blocksworld_Updated/plan/operators_extinguish.py deleted file mode 100644 index 7dae0936..00000000 --- a/midca/domains/blocksworld_Updated/plan/operators_extinguish.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -Blocks World domain definition for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" -import sys -sys.path.append("../") -from midca.modules._plan import pyhop - -"""Each Pyhop planning operator is a Python function. The 1st argument is -the current state, and the others are the planning operator's usual arguments. -This is analogous to how methods are defined for Python classes (where -the first argument is always the name of the class instance). For example, -the function pickup(state,b) implements the planning operator for the task -('pickup', b). - -The blocks-world operators use three state variables: -- pos[b] = block b's position, which may be 'table', 'hand', or another block. -- clear[b] = False if a block is on b or the hand is holding b, else True. -- holding = name of the block being held, or False if the hand is empty. -""" - -def pickup(state,b): - if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - return state - else: return False - -def unstack(state,b,c): - if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - state.clear[c] = True - return state - else: return False - -def putdown(state,b): - if state.pos[b] == 'hand': - state.pos[b] = 'table' - state.clear[b] = True - state.holding = False - return state - else: return False - -def stack(state,b,c): - if state.pos[b] == 'hand' and state.clear[c] == True: - state.pos[b] = c - state.clear[b] = True - state.holding = False - state.clear[c] = False - return state - else: return False - -def putoutfire(state, b, ext): - if state.fire[b] == True and state.holdingfireext == ext: - state.fire[b] == False - return state - else: - return False - -def pickup_extinguisher(state, extinguisher): - if extinguisher in state.fire_ext_avail and not state.holdingfireext: - state.holdingfireext = extinguisher - state.fire_ext_avail.remove(extinguisher) - return state - else: - return False - -def putdown_extinguisher(state, extinguisher): - if state.holdingfireext == extinguisher: - state.holdingfireext = None - state.fire_ext_avail.add(extinguisher) - return state - else: - return False - -def apprehend(state, perp): - if state.free[perp] == True: - state.free[perp] = False - return state - else: - return False - -def searchfor(state, perp): - return state - -""" -Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop -what the operators are. Note that the operator names are *not* quoted. -""" -def declare_ops(): - pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor, pickup_extinguisher, putdown_extinguisher) diff --git a/midca/domains/blocksworld_Updated/plan/operators_midca.py b/midca/domains/blocksworld_Updated/plan/operators_midca.py deleted file mode 100644 index c7544740..00000000 --- a/midca/domains/blocksworld_Updated/plan/operators_midca.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -Blocks World domain definition for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - -from midca.modules._plan import pyhop - -"""Each Pyhop planning operator is a Python function. The 1st argument is -the current state, and the others are the planning operator's usual arguments. -This is analogous to how methods are defined for Python classes (where -the first argument is always the name of the class instance). For example, -the function pickup(state,b) implements the planning operator for the task -('pickup', b). - -The blocks-world operators use three state variables: -- pos[b] = block b's position, which may be 'table', 'hand', or another block. -- clear[b] = False if a block is on b or the hand is holding b, else True. -- holding = name of the block being held, or False if the hand is empty. -""" - -def pickup(state,b): - print "pickop_op", b - if state.is_true("on-table", [b]) and state.is_true("clear", [b]) and state.is_true("arm-empty"): - state.add_fact("holding", [b]) - state.remove_fact("clear", [b]) - state.remove_fact("on-table", [b]) - state.remove_fact("arm-empty") - return state - else: return False - -def unstack(state,b,c): - if state.is_true("on", [b, c]) and c != 'table' and state.is_true("clear", [b]) and state.is_true("arm-empty"): - state.add_fact("holding", [b]) - state.remove_fact("clear", [b]) - state.remove_fact("on", [b, c]) - state.remove_fact("arm-empty") - state.add_fact("clear", [c]) - return state - else: return False - -def putdown(state,b): - if state.is_true("holding", [b]): - state.add_fact("on-table", [b]) - state.add_fact("arm-empty") - state.add_fact("clear", [b]) - state.remove_fact("holding", [b]) - return state - else: return False - -def stack(state,b,c): - if state.is_true("holding", [b]) and state.is_true("clear", [c]): - state.remove_fact("holding", [b]) - state.add_fact("clear", [b]) - state.add_fact("on", [b, c]) - state.add_fact("arm-empty") - state.remove_fact("clear", [c]) - return state - else: return False - -def putoutfire(state, b): - if state.is_true("onfire", [b]): - state.remove_fact("onfire", [b]) - else: - return False - -def apprehend(state, perp): - if state.is_true("free", [perp]): - state.remove_fact("free", [perp]) - return state - else: - return False - -def searchfor(state, perp): - return state - -""" -Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop -what the operators are. Note that the operator names are *not* quoted. -""" - -def declare_ops(): - pyhop.declare_operators(pickup, unstack, putdown, stack, putoutfire, apprehend, searchfor) diff --git a/midca/domains/blocksworld_Updated/plan/operators_mortar.py b/midca/domains/blocksworld_Updated/plan/operators_mortar.py deleted file mode 100644 index a7e20d14..00000000 --- a/midca/domains/blocksworld_Updated/plan/operators_mortar.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Blocks World domain definition for Pyhop 1.1. -Author: Dana Nau , November 15, 2012 -This file should work correctly in both Python 2.7 and Python 3.2. -""" - - -from midca.modules._plan import pyhop -import random - -"""Each Pyhop planning operator is a Python function. The 1st argument is -the current state, and the others are the planning operator's usual arguments. -This is analogous to how methods are defined for Python classes (where -the first argument is always the name of the class instance). For example, -the function pickup(state,b) implements the planning operator for the task -('pickup', b). - -The blocks-world operators use three state variables: -- pos[b] = block b's position, which may be 'table', 'hand', or another block. -- clear[b] = False if a block is on b or the hand is holding b, else True. -- holding = name of the block being held, or False if the hand is empty. -""" - -def pickup(state,b): - if state.pos[b] == 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - - # remove mortar if the block has it (just to be safe) - if hasattr(state, 'mortared') and state.mortared[b] == True: - state.mortared[b] == False - - return state - else: return False - -def unstack(state,b,c): - if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - state.clear[c] = True - - # to undo mortar but doesn't increase quantity - if hasattr(state, 'mortared') and state.mortared[b] == True: - state.mortared[b] == False - - return state - else: return False - -def unstack_mortared(state,b,c,m): - ''' m is for mortar ''' - if state.pos[b] == c and c != 'table' and state.clear[b] == True and state.holding == False: - state.pos[b] = 'hand' - state.clear[b] = False - state.holding = b - state.clear[c] = True - if state.hasmortar[b] == m: - state.hasmortar[b] = False - - return state - else: return False - -def putdown(state,b): - if state.pos[b] == 'hand': - state.pos[b] = 'table' - state.clear[b] = True - state.holding = False - return state - else: return False - -def stack(state,b,c): - if state.pos[b] == 'hand' and state.clear[c] == True: - state.pos[b] = c - state.clear[b] = True - state.holding = False - state.clear[c] = False - return state - else: return False - -def stack_mortared(state,b,c,m): - if state.pos[b] == 'hand' and state.clear[c] == True and state.mortaravailable[m]: - state.pos[b] = c - state.clear[b] = True - state.holding = False - state.clear[c] = False - state.hasmortar[b] = True - state.mortaravailable[m] = False - return state - else: return False - -def putoutfire(state, b): - if state.fire[b] == True: - state.fire[b] == False - return state - else: - return False - -def apprehend(state, perp): - if state.free[perp] == True: - state.free[perp] = False - return state - else: - return False - -def searchfor(state, perp): - return state - -""" -Below, 'declare_operators(pickup, unstack, putdown, stack)' tells Pyhop -what the operators are. Note that the operator names are *not* quoted. -""" - -def declare_ops(): - pyhop.declare_operators(pickup, unstack, unstack_mortared, putdown, stack, stack_mortared, putoutfire, apprehend, searchfor) diff --git a/midca/domains/blocksworld_Updated/plan/sample_methods.py b/midca/domains/blocksworld_Updated/plan/sample_methods.py deleted file mode 100644 index 55353e73..00000000 --- a/midca/domains/blocksworld_Updated/plan/sample_methods.py +++ /dev/null @@ -1,82 +0,0 @@ -''' -Sample pyhop methods file. This is used to generate plans in the chicken domain. -''' - -from midca.modules._plan import pyhop - -def goals_valid(state, goals): - ''' - checks to make sure no chicken is expected to be on both sides - ''' - left = set() - right = set() - for goal in goals: - try: - chicken = goal[0] - predicate = goal["predicate"] - negate = 'negate' in goal and goal['negate'] - except KeyError: - #invalid goal - return False - if predicate == "onleft" and negate or predicate == "onright" and not negate: - side = "right" - elif predicate == "onright" and negate or predicate == "onleft" and not negate: - side = "left" - else: - #invalid goal - return False - if side == "left": - if chicken in right: - #chicken supposed to be on both sides - return False - left.add(chicken) - else: - if chicken in left: - #chicken supposed to be on both sides - return False - right.add(chicken) - return True - -def achieve_goals_m(state, goals): - ''' - checks for conflicting goals. If there are none, plans for each goal in turn - assumes goals are one of: - onright(chicken), !onright(chicken), onleft(chicken), !onleft(chicken) - ''' - if not goals_valid(state, goals): - return False - return [("achieve_chicken_goals", goals)] - -def achieve_chicken_goals_m(state, goals): - ''' - pursues goals in order. - ''' - if goals: - return [("achieve_goal", goals[0]), ("achieve_chicken_goals", goals[1:])] - else: - return [] - -def achieve_goal_m(state, goal): - ''' - assumes goals are one of: - onright(chicken), !onright(chicken), onleft(chicken), !onleft(chicken) - ''' - chicken = goal[0] - predicate = goal["predicate"] - negate = "negate" in goal and goal["negate"] - if predicate == "onleft" and negate or predicate == "onright" and not negate: - side = "right" - elif predicate == "onright" and negate or predicate == "onleft" and not negate: - side = "left" - if state.is_true("onright", [chicken]) and side == "left": - return [("crossleft", chicken)] - elif state.is_true("onleft", [chicken]) and side == "right": - return [("crossright", chicken)] - else: - return [] - -def declare_methods(): - pyhop.declare_methods("achieve_goals", achieve_goals_m) - pyhop.declare_methods("achieve_chicken_goals", achieve_chicken_goals_m) - pyhop.declare_methods("achieve_goal", achieve_goal_m) - diff --git a/midca/domains/blocksworld_Updated/plan/sample_operators.py b/midca/domains/blocksworld_Updated/plan/sample_operators.py deleted file mode 100644 index e83c21e8..00000000 --- a/midca/domains/blocksworld_Updated/plan/sample_operators.py +++ /dev/null @@ -1,24 +0,0 @@ -''' -Sample pyhop operators file. This is used to generate plans in the chicken domain. -''' - -from midca.modules._plan import pyhop - -def crossright(state, chicken): - if state.is_true("onleft", [chicken]): - state.remove_fact("onleft", [chicken]) - state.add_fact("onright", [chicken]) - return state - else: - return False - -def crossleft(state, chicken): - if state.is_true("onright", [chicken]): - state.remove_fact("onright", [chicken]) - state.add_fact("onleft", [chicken]) - return state - else: - return False - -def declare_ops(): - pyhop.declare_operators(crossright, crossleft) diff --git a/midca/domains/blocksworld_Updated/scene.py b/midca/domains/blocksworld_Updated/scene.py deleted file mode 100644 index 50dee2a5..00000000 --- a/midca/domains/blocksworld_Updated/scene.py +++ /dev/null @@ -1,111 +0,0 @@ -import copy -from midca.domains.blocksworld.block import Block - -class Scene: - blocks = [] # contains all blocks - - def __init__(self, blocks): - self.blocks = blocks - - def draw(self): - print self.layers_to_s(self._makelayers()) - - def __str__(self): - return self.layers_to_s(self._makelayers()) - - def _makelayers(self): - blockscopy = copy.deepcopy(self.blocks) - - layers = [] # each new layer will be appended to layers - currentlayer = [] # layer currently being prepared - - # find table - for i in range(len(blockscopy)): - if blockscopy[i].type == Block.TABLE: - block = blockscopy.pop(i) - currentlayer.append(block) - layers.append(currentlayer) - break - - # while there are more blocks above the current layer - while len(blockscopy) > 0: - nextlayer = [] - - #print len(currentlayer), len(blockscopy) - for i in range(len(currentlayer)): - for j in range(len(blockscopy)): - if blockscopy[j].on == currentlayer[i]: - nextlayer.append(blockscopy[j]) - - for i in range(len(nextlayer)): - blockscopy.remove(nextlayer[i]) - - currentlayer = nextlayer - layers.append(currentlayer) - if not currentlayer: - break - - return layers - - # layers - as made by _makelayers - def layers_to_s(self, layers): - assert len(layers[0]) == 1 and layers[0][0].type == Block.TABLE - - width = len(layers[1]) - - asciisquares = [] - asciisquares.append([("--------------", layers[0][0]) for tv in range(width + 1)]) - - for i in range(1, len(layers), 1): - asciisquares.append([("", None) for tv in range(width)]) - asciisquares.append([("", None) for tv in range(width)]) - asciisquares.append([("", None) for tv in range(width)]) - - for j in range(width): - written = False - for k in range(len(layers[i])): - if layers[i][k].on == asciisquares[-4][j][1]: - written = True - if layers[i][k].type == Block.TRIANGLE: - if layers[i][k].onfire: - asciisquares[-1][j] = (" / \\ ", layers[i][k]) - asciisquares[-2][j] = (" / * \\ ", layers[i][k]) - asciisquares[-3][j] = (" / *" + str(layers[i][k].id) + "*\\", layers[i][k]) - else: - asciisquares[-1][j] = (" / \\ ", layers[i][k]) - asciisquares[-2][j] = (" / \\ ", layers[i][k]) - asciisquares[-3][j] = (" / " + str(layers[i][k].id) + " \\", layers[i][k]) - elif layers[i][k].type == Block.SQUARE: - if layers[i][k].onfire and layers[i][k].hasmortar: - asciisquares[-1][j] = (" +++++++", layers[i][k]) - asciisquares[-2][j] = (" | *" + str(layers[i][k].id) + "* |", layers[i][k]) - asciisquares[-3][j] = (" -------", layers[i][k]) - elif layers[i][k].onfire: - asciisquares[-1][j] = (" -------", layers[i][k]) - asciisquares[-2][j] = (" | *" + str(layers[i][k].id) + "* |", layers[i][k]) - asciisquares[-3][j] = (" -------", layers[i][k]) - elif layers[i][k].hasmortar: - asciisquares[-1][j] = (" +++++++", layers[i][k]) - asciisquares[-2][j] = (" | " + str(layers[i][k].id) + " |", layers[i][k]) - asciisquares[-3][j] = (" -------", layers[i][k]) - else: - asciisquares[-1][j] = (" -------", layers[i][k]) - asciisquares[-2][j] = (" | " + str(layers[i][k].id) + " |", layers[i][k]) - asciisquares[-3][j] = (" -------", layers[i][k]) - layers[i].pop(k) - break - if not written: - asciisquares[-1][j] = (" ", None) - asciisquares[-2][j] = (" ", None) - asciisquares[-3][j] = (" ", None) - - toprint = "" - for i in range(len(asciisquares)-1, -1, -1): - for segment in asciisquares[i]: - toprint += segment[0] - toprint += "\n" - - return toprint - - - \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/states/blocksworld.shp b/midca/domains/blocksworld_Updated/states/blocksworld.shp deleted file mode 100644 index 53a3f770..00000000 --- a/midca/domains/blocksworld_Updated/states/blocksworld.shp +++ /dev/null @@ -1,107 +0,0 @@ -; This file contains a SHOP domain representation of the block-stacking -;;; algorithm from the following paper: -;;; N. Gupta and D. Nau, On the complexity of blocks-world planning, -;;; Artificial Intelligence 56(2-3):223-254, August 1992. - - -;;; ------------------------------------------------------------------------ -;;; Declare all the data -;;; ------------------------------------------------------------------------ - - -(defdomain blocks-normal - ( - ;; basic block-stacking operators - - (:operator (!pickup ?a) - () - ((clear ?a) (on-table ?a)) - ((holding ?a)) ) - - (:operator (!putdown ?b) - () - ((holding ?b)) - ((on-table ?b) (clear ?b)) ) - - (:operator (!stack ?c ?d) - () - ((holding ?c) (clear ?d)) - ((on ?c ?d) (clear ?c)) ) - - (:operator (!unstack ?e ?f) - () - ((clear ?e) (on ?e ?f)) - ((holding ?e) (clear ?f)) ) - - ;; book-keeping methods & ops, to keep track of what needs to be done - - (:operator (!assert ?g) - () - () - ?g - ;; Since !ASSERT isn't a real blocks-world operator, make its cost 0 - 0) - - (:method (achieve-goals ?goals) - () - ((assert-goals ?goals nil) (move-block nil))) - - (:method (assert-goals (list ?goal . ?goals) ?out) - () - ((assert-goals ?goals (list (goal ?goal) . ?out)))) - - (:method (assert-goals nil ?out) - () - ((!assert ?out))) - - ;; The methods and operators for doing the actual planning - - (:method (move-block ?nomove) - - ;; method for moving x from y to z - (:first (clear ?x) (not ( call member ?x ?nomove)) (on ?x ?y) - (goal (on ?x ?z)) (different ?x ?z) (clear ?z) (not (need-to-move ?z))) - ((!unstack ?x ?y) (!stack ?x ?z) (move-block (list ?x . ?nomove))) - - ;; method for moving x from y to table - (:first (clear ?x) ( not ( call member ?x ?nomove)) - (on ?x ?y) (goal (on-table ?x))) - ((!unstack ?x ?y) (!putdown ?x) (move-block (list ?x . ?nomove))) - - ;; method for moving x from table to y - (:first (clear ?x) (not ( call member ?x ?nomove)) - (on-table ?x) (goal (on ?x ?y)) (clear ?y) (not (need-to-move ?y))) - ((!pickup ?x) (!stack ?x ?y) (move-block (list ?x . ?nomove))) - - ;; method for moving x out of the way - ((clear ?x) (not (call member ?x ?nomove)) - (on ?x ?y) (need-to-move ?x)) - ((!unstack ?x ?y) (!putdown ?x) (move-block ?nomove)) - - ;; if nothing else matches, then we're done - () - ()) - - ;; state axioms - - (:- (different ?x ?y) ((not (same ?x ?y)))) - (:- (same ?x ?x) ()) - (:- (need-to-move ?x) - ;; need to move x if x needs to go from one block to another - ((on ?x ?y) (goal (on ?x ?z)) (different ?y ?z)) - ;; need to move x if x needs to go from table to block - ((on-table ?x) (goal (on ?x ?z))) - ;; need to move x if x needs to go from block to table - ((on ?x ?y) (goal (on-table ?x))) - ;; need to move x if x is on y and y needs to be clear - ((on ?x ?y) (goal (clear ?y))) - ;; need to move x if x is on z and something else needs to be on z - ((on ?x ?z) (goal (on ?y ?z)) (different ?x ?y)) - ;; need to move x if x is on something else that needs to be moved - ((on ?x ?w) (need-to-move ?w))) - (:- (moveable-to-goal ?x) - ((clear ?x) (on ?x ?y) (goal (on ?x ?z)) - (different ?x ?z) (clear ?z) (not (need-to-move ?z))) - ((clear ?x) (on ?x ?y) (goal (on-table ?x))) - ((clear ?x) (on-table ?x) (goal (on ?x ?y)) - (clear ?y) (not (need-to-move ?y)))))) diff --git a/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp b/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp deleted file mode 100644 index cdaf0e47..00000000 --- a/midca/domains/blocksworld_Updated/states/bw_ran_problems_5.shp +++ /dev/null @@ -1,12 +0,0 @@ - -(defproblem bw-ran-5-1 blocks-normal ((arm-empty) -(clear d) -(on-table a) -(on-table c) -(on b a) -(on d b) -(clear c) -) - ((achieve-goals ( list -(on c b) - )))) \ No newline at end of file diff --git a/midca/domains/blocksworld_Updated/states/defstate.sim b/midca/domains/blocksworld_Updated/states/defstate.sim deleted file mode 100644 index 70f61cb4..00000000 --- a/midca/domains/blocksworld_Updated/states/defstate.sim +++ /dev/null @@ -1,26 +0,0 @@ -BLOCK(A_) -BLOCK(B_) -BLOCK(C_) -BLOCK(table) -BLOCK(D_) -ARSONIST(Gui Montag) - -on(B_, A_) -on(D_, B_) -on-table(A_) -on-table(C_) - -block(A_) -block(B_) -block(C_) -triangle(D_) -table(table) - -clear(C_) -clear(D_) -arm-empty() - - - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_fire.sim b/midca/domains/blocksworld_Updated/states/defstate_fire.sim deleted file mode 100644 index ce976fc0..00000000 --- a/midca/domains/blocksworld_Updated/states/defstate_fire.sim +++ /dev/null @@ -1,27 +0,0 @@ -BLOCK(A_) -BLOCK(B_) -BLOCK(C_) -BLOCK(table) -BLOCK(D_) -ARSONIST(Gui Montag) - -on(B_, A_) -on(D_, B_) -on-table(A_) -on-table(C_) -onfire(B_) - -block(A_) -block(B_) -block(C_) -triangle(D_) -table(table) - -clear(C_) -clear(D_) -arm-empty() - - - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim b/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim deleted file mode 100644 index 0893c427..00000000 --- a/midca/domains/blocksworld_Updated/states/defstate_fire_pyhop_inducing_bug.sim +++ /dev/null @@ -1,24 +0,0 @@ -BLOCK(A_) -BLOCK(B_) -BLOCK(C_) -BLOCK(table) -ARSONIST(Gui Montag) - -on(A_, B_) -on-table(B_) -on-table(C_) -onfire(B_) - -block(A_) -block(B_) -block(C_) -table(table) - -clear(C_) -clear(A_) -arm-empty() - - - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_jshop.sim b/midca/domains/blocksworld_Updated/states/defstate_jshop.sim deleted file mode 100644 index c0c4146d..00000000 --- a/midca/domains/blocksworld_Updated/states/defstate_jshop.sim +++ /dev/null @@ -1,26 +0,0 @@ -BLOCK(a) -BLOCK(b) -BLOCK(c) -BLOCK(table) -BLOCK(d) -ARSONIST(Gui Montag) - -on(b, a) -on(d, b) -on-table(a) -on-table(c) - -block(a) -block(b) -block(c) -triangle(d) -table(table) - -clear(c) -clear(d) -arm-empty() - - - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/defstate_mortar.sim b/midca/domains/blocksworld_Updated/states/defstate_mortar.sim deleted file mode 100644 index e0a8d1bd..00000000 --- a/midca/domains/blocksworld_Updated/states/defstate_mortar.sim +++ /dev/null @@ -1,26 +0,0 @@ -BLOCK(A_) -BLOCK(B_) -BLOCK(C_) -BLOCK(table) -BLOCK(D_) -ARSONIST(Gui Montag) - - -on(B_, A_) -on(D_, B_) -on-table(A_) -on-table(C_) - -block(A_) -block(B_) -block(C_) -triangle(D_) -table(table) - - -clear(C_) -clear(D_) -arm-empty() - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/extinguisher_state.sim b/midca/domains/blocksworld_Updated/states/extinguisher_state.sim deleted file mode 100644 index 3805f354..00000000 --- a/midca/domains/blocksworld_Updated/states/extinguisher_state.sim +++ /dev/null @@ -1,26 +0,0 @@ -BLOCK(A_) -BLOCK(B_) -BLOCK(C_) -BLOCK(table) -BLOCK(D_) -ARSONIST(Gui Montag) -FIRE-EXTINGUISHER(Fire Extinguisher 1) - -on(B_, A_) -on(D_, B_) -on-table(A_) -on-table(C_) - -block(A_) -block(B_) -block(C_) -triangle(D_) -table(table) -fire-extinguisher(Fire Extinguisher 1) - -clear(C_) -clear(D_) -arm-empty() - -free(Gui Montag) -arsonist(Gui Montag) diff --git a/midca/domains/blocksworld_Updated/states/sample_state.sim b/midca/domains/blocksworld_Updated/states/sample_state.sim deleted file mode 100644 index 2f0cb35c..00000000 --- a/midca/domains/blocksworld_Updated/states/sample_state.sim +++ /dev/null @@ -1,20 +0,0 @@ -#Sample state file using the MIDCA predicate world state definition language. -#These are comments. Multi-line comments are not supported. -#This file will define a state in the simple chicken crossing the road domain. -#This domain is defined in worldsim/domains/sample_domain.sim - -#note: in state files, the "functions" - e.g. CHICKEN, HEN, onright, onleft - -#are type names or predicate names defined in the domain file. A type name -#creates an object of that type with the given name. A predicate name creates -#a predicate - -#Create a chicken. Argument is the chicken's name. -CHICKEN(clucky) - -#Create a hen (subtype of chicken): -HEN(lady cluck) - -#place the two chickens on opposite sides of the road. Argument is the name of -#a chicken which has been created above. -onright(clucky) -onleft(lady cluck) diff --git a/midca/domains/blocksworld_Updated/util.py b/midca/domains/blocksworld_Updated/util.py deleted file mode 100644 index fcd95177..00000000 --- a/midca/domains/blocksworld_Updated/util.py +++ /dev/null @@ -1,292 +0,0 @@ -''' -A collection of functions that are domain specific, which different MIDCA components use -''' -import os -from midca.domains.blocksworld import scene, blockstate -from midca.modules._plan import pyhop - -def asqiiDisplay(world): - ''' - Creates an asqii representation for blocksworld. - ''' - blocks = blockstate.get_block_list(world) - print(str(scene.Scene(blocks))) - -def preferApprehend(goal1, goal2): - if 'predicate' not in goal1 or 'predicate' not in goal2: - return 0 - elif goal1['predicate'] == 'free' and goal2['predicate'] != 'free': - return -1 - elif goal1['predicate'] != 'free' and goal2['predicate'] == 'free': - return 1 - elif goal1['predicate'] == 'onfire' and goal2['predicate'] != 'onfire': - return -1 - elif goal1['predicate'] != 'onfire' and goal2['predicate'] == 'onfire': - return 1 - return 0 - -def preferFire(goal1, goal2): - if 'predicate' not in goal1 or 'predicate' not in goal2: - return 0 - elif goal1['predicate'] == 'onfire' and goal2['predicate'] != 'onfire': - return -1 - elif goal1['predicate'] != 'onfire' and goal2['predicate'] == 'onfire': - return 1 - return 0 - -def jshop_state_from_world(world, STATE_FILE, name = "state"): -# thisDir = os.path.dirname(os.path.realpath(__file__)) -# MIDCA_ROOT = thisDir + "/../" -# STATE_FILE = MIDCA_ROOT + "jshop_domains/blocks_world/bw_ran_problems_500.shp" - try: - f = open(STATE_FILE, 'w') - - f.write('\n') - f.write('(defproblem bw-ran-5-1 blocks-normal ((arm-empty)\n') - - for atom in world.atoms: - if atom.predicate.name == "clear": - f.write("(clear " + atom.args[0].name+ ")\n") - elif atom.predicate.name == "on": - f.write("(on " + atom.args[0].name + " " + atom.args[1].name + ")\n") - elif atom.predicate.name == "on-table": - f.write("(on-table " + atom.args[0].name + ")\n") - - f.write(")\n") - f.close() - - except Exception: - print "could not read the state file. Check the path..." - - -def jshop_tasks_from_goals(goals,pyhopState, STATE_FILE): -# thisDir = os.path.dirname(os.path.realpath(__file__)) -# MIDCA_ROOT = thisDir + "/../" -# STATE_FILE = MIDCA_ROOT + "jshop_domains/blocks_world/bw_ran_problems_500.shp" - try: - f = open(STATE_FILE, 'a') - except Exception: - print "could not read the state file. Check the path..." - alltasks = [] - blkgoals = pyhop.Goal("goals") - blkgoals.pos = {} - f.write(" ((achieve-goals ( list\n") - for goal in goals: - #extract predicate - if 'predicate' in goal.kwargs: - predicate = str(goal.kwargs['predicate']) - elif 'Predicate' in goal.kwargs: - predicate = str(goal.kwargs['Predicate']) - elif goal.args: - predicate = str(goal.args[0]) - else: - raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") - args = [str(arg) for arg in goal.args] - if args[0] == predicate: - args.pop(0) - if predicate == "on": - f.write("(on " + args[0] + " " + args[1] + ")\n") - elif predicate == 'on-table': - f.write("(on-table" + blkgoals.pos[args[0]]+ ")\n") - - else: - raise Exception("No task corresponds to predicate " + predicate) - f.write(" ))))") - f.close() - -def pyhop_state_from_world(world, name = "state"): - s = pyhop.State(name) - s.pos = {} - s.clear = {} - s.holding = False - s.fire = {} - s.free = {} - s.fire_ext_avail = set() - s.holdingfireext = None - s.hasmortar = {} # keys are - s.mortaravailable = {} - mortarblocks = [] - blocks = [] - for objname in world.objects: - if world.objects[objname].type.name == "BLOCK" and objname != "table": - blocks.append(objname) - elif world.objects[objname].type.name == "ARSONIST": - s.free[objname] = False - elif world.objects[objname].type.name == "MORTARBLOCK": - mortarblocks.append(objname) - for atom in world.atoms: - if atom.predicate.name == "clear": - s.clear[atom.args[0].name] = True - elif atom.predicate.name == "holding": - s.holding = atom.args[0].name - elif atom.predicate.name == "fire-extinguisher": - s.fire_ext_avail.add(atom.args[0].name) - elif atom.predicate.name == "holdingextinguisher": - s.holdingfireext = atom.args[0].name - elif atom.predicate.name == "arm-empty": - s.holding = False - elif atom.predicate.name == "on": - s.pos[atom.args[0].name] = atom.args[1].name - elif atom.predicate.name == "on-table": - s.pos[atom.args[0].name] = "table" - elif atom.predicate.name == "onfire": - s.fire[atom.args[0].name] = True - elif atom.predicate.name == "free": - s.free[atom.args[0].name] = True - elif atom.predicate.name == "available": - s.mortaravailable[atom.args[0].name] = True - elif "hasmortar" in world.types and atom.predicate.name == "hasmortar": - s.hasmortar[atom.args[0].name] = atom.args[1].name - for block in blocks: - if block not in s.clear: - s.clear[block] = False - if block not in s.fire: - s.fire[block] = False - if block not in s.pos: - s.pos[block] = "in-arm" - if block not in s.hasmortar.keys(): - s.hasmortar[block] = False - - for mblock in mortarblocks: - if mblock not in s.mortaravailable.keys(): - s.mortaravailable[mblock] = False - - return s - -#note: str(arg) must evaluate to the name of the arg in the world representation for this method to work. -# pyhopState doesn't need to be used, but pyhop_tasks_from_goals() will be passed two arguments and needs -# to have it as an arg -def pyhop_tasks_from_goals(goals, pyhopState): - alltasks = [] - blkgoals = pyhop.Goal("goals") - blkgoals.pos = {} - for goal in goals: - #extract predicate - if 'predicate' in goal.kwargs: - predicate = str(goal.kwargs['predicate']) - elif 'Predicate' in goal.kwargs: - predicate = str(goal.kwargs['Predicate']) - elif goal.args: - predicate = str(goal.args[0]) - else: - raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") - - args = [str(arg) for arg in goal.args] - if args[0] == predicate: - args.pop(0) - if predicate == "on": - blkgoals.pos[args[0]] = args[1] - elif predicate == 'on-table': - blkgoals.pos[args[0]] = 'table' - elif predicate == "onfire" and 'negate' in goal and goal['negate'] == True: - alltasks.append(("put_out", args[0])) - elif predicate == "free" and 'negate' in goal and goal['negate'] == True: - alltasks.append(("catch_arsonist", args[0])) - else: - raise Exception("No task corresponds to predicate " + predicate) - if blkgoals.pos: - alltasks.append(("move_blocks", blkgoals)) - return alltasks - - -def mortar_pyhop_state_from_world(world, name = "state"): - s = pyhop.State(name) - s.pos = {} - s.clear = {} - s.holding = False - s.fire = {} - s.free = {} - s.fire_ext_avail = set() - s.holdingfireext = None - s.hasmortar = {} # keys are - s.mortaravailable = {} - mortarblocks = [] - blocks = [] - for objname in world.objects: - if world.objects[objname].type.name == "BLOCK" and objname != "table": - blocks.append(objname) - elif world.objects[objname].type.name == "ARSONIST": - s.free[objname] = False - elif world.objects[objname].type.name == "MORTARBLOCK": - mortarblocks.append(objname) - for atom in world.atoms: - if atom.predicate.name == "clear": - s.clear[atom.args[0].name] = True - elif atom.predicate.name == "holding": - s.holding = atom.args[0].name - elif atom.predicate.name == "fire-extinguisher": - s.fire_ext_avail.add(atom.args[0].name) - elif atom.predicate.name == "holdingextinguisher": - s.holdingfireext = atom.args[0].name - elif atom.predicate.name == "arm-empty": - s.holding = False - elif atom.predicate.name == "on": - s.pos[atom.args[0].name] = atom.args[1].name - s.clear[atom.args[1].name] = False - elif atom.predicate.name == "stable-on": - s.pos[atom.args[0].name] = atom.args[1].name - s.clear[atom.args[1].name] = False - #s.hasmortar[atom.args[1].name] = True # redundant - elif atom.predicate.name == "on-table": - s.pos[atom.args[0].name] = "table" - elif atom.predicate.name == "onfire": - s.fire[atom.args[0].name] = True - elif atom.predicate.name == "free": - s.free[atom.args[0].name] = True - elif atom.predicate.name == "available": - s.mortaravailable[atom.args[0].name] = True - elif atom.predicate.name == "hasmortar": - s.hasmortar[atom.args[0].name] = atom.args[1].name - for block in blocks: - if block not in s.clear: - s.clear[block] = False - if block not in s.fire: - s.fire[block] = False - if block not in s.pos: - s.pos[block] = "in-arm" - if block not in s.hasmortar.keys(): - s.hasmortar[block] = False - - for mblock in mortarblocks: - if mblock not in s.mortaravailable.keys(): - s.mortaravailable[mblock] = False - - return s - -#note: str(arg) must evaluate to the name of the arg in the world representation for this method to work. -def mortar_pyhop_tasks_from_goals(goals, pyhopState): - alltasks = [] - blkgoals = pyhop.Goal("goals") - blkgoals.pos = {} - blkgoals.hasmortar = {} - for goal in goals: - #extract predicate - if 'predicate' in goal.kwargs: - predicate = str(goal.kwargs['predicate']) - elif 'Predicate' in goal.kwargs: - predicate = str(goal.kwargs['Predicate']) - elif goal.args: - predicate = str(goal.args[0]) - else: - raise ValueError("Goal " + str(goal) + " does not translate to a valid pyhop task") - args = [str(arg) for arg in goal.args] - if args[0] == predicate: - args.pop(0) - if predicate == "on": - blkgoals.pos[args[0]] = args[1] - elif predicate == "stable-on": - blkgoals.pos[args[0]] = args[1] - blkgoals.hasmortar[args[1]] = True - elif predicate == 'on-table': - blkgoals.pos[args[0]] = 'table' - elif predicate == "onfire" and 'negate' in goal and goal['negate'] == True: - alltasks.append(("put_out", args[0])) - elif predicate == "free" and 'negate' in goal and goal['negate'] == True: - alltasks.append(("catch_arsonist", args[0])) - else: - raise Exception("No task corresponds to predicate " + predicate) - if blkgoals.pos: - alltasks.append(("move_blocks", blkgoals)) - return alltasks - - diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index 597198de..3d4b5b3e 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -9,7 +9,7 @@ attributeValue,y,INT attributeValue,z,INT relation,on,block,block relation,clear,block -action,pickup,loc,grabbing,raise -action,putdown,loc,grabbing,release -action,stack,loc,grabbing,raise,release -action,unstack,loc,grabbing,raise,release \ No newline at end of file +action,pickup,loc +action,putdown,loc +action,stack,raise +action,unstack,loc,raise,lower \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py index a58bfd6f..5fdb7e5c 100644 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py @@ -29,10 +29,9 @@ FEEDBACK_KEY = "code" CMD_ID_KEY = "cmd_id" -RELEASE_TOPIC = "release_cmd" -LOC_TOPIC = "loc_cmd" -GRABBING_TOPIC = "grabbing_cmd" -RAISE_TOPIC = "raise_cmd" +LOC_TOPIC = "loc" +LOWER_TOPIC = "lower" +RAISE_TOPIC = "raise" #set this to change output for all asynch actions. verbose = 2 @@ -70,52 +69,27 @@ def asynch_plan(mem, midcaPlan): if midcaAction[0] == "block_until_seen": actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) - elif midcaAction[0] == "point_to": - cmdID = rosrun.next_id() - actions.append(DoPoint(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - POINT_TOPIC, cmdID)) - - elif midcaAction[0] == "reach_to_pickup": - cmdID = rosrun.next_id() - actions.append(DoReach(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "reach_to_unstack": - cmdID = rosrun.next_id() - actions.append(DoUnstack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "grab": - cmdID = rosrun.next_id() - actions.append(DoGrab(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - GRAB_TOPIC, cmdID)) - elif midcaAction[0] == "release": - cmdID = rosrun.next_id() - actions.append(DoRelease(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RELEASE_TOPIC, cmdID)) - elif midcaAction[0] == "raising": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "raising_arm": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, ' ', - allowed_sighting_lag(' '), allowed_sighting_wait(' '), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "putdown": - cmdID = rosrun.next_id() - actions.append(DoPut(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "stack": - cmdID = rosrun.next_id() - actions.append(DoStack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "unstack": + cmdID = rosrun.next_id() + actions.append(unstack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc', 'lower', 'raise'], cmdID)) + elif midcaAction[0] == "pickup": + cmdID = rosrun.next_id() + actions.append(pickup(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc'], cmdID)) + elif midcaAction[0] == "putdown": + cmdID = rosrun.next_id() + actions.append(putdown(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc'], cmdID)) + elif midcaAction[0] == "stack": + cmdID = rosrun.next_id() + actions.append(stack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['raise'], cmdID)) + else: if verbose >= 1: print "MIDCA action", midcaAction, "does not correspond to an asynch", @@ -288,7 +262,7 @@ def completion_check(self): return t - lastLocReport[1] <= self.maxAllowedLag -class Dounstack(AsynchAction): +class unstack(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -300,7 +274,8 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic - self.topicFormats = {'loc': {},'release': {},'raise': {},'grabbing': {},} + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},'lower': {},'raise': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() @@ -314,7 +289,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -348,7 +322,7 @@ def check_confirmation(self): return False return False -class Dopickup(AsynchAction): +class pickup(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -360,7 +334,8 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic - self.topicFormats = {'loc': {},'raise': {},'grabbing': {},} + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() @@ -374,7 +349,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -408,7 +382,7 @@ def check_confirmation(self): return False return False -class Doputdown(AsynchAction): +class putdown(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -420,7 +394,8 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic - self.topicFormats = {'loc': {},'release': {},'grabbing': {},} + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() @@ -434,7 +409,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -468,7 +442,7 @@ def check_confirmation(self): return False return False -class Dostack(AsynchAction): +class stack(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -480,7 +454,8 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic - self.topicFormats = {'loc': {},'release': {},'raise': {},'grabbing': {},} + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'raise': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() @@ -494,7 +469,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict diff --git a/midca/domains/minecraft/minecraft.cfg b/midca/domains/minecraft/minecraft.cfg index 51f78f47..612120f1 100644 --- a/midca/domains/minecraft/minecraft.cfg +++ b/midca/domains/minecraft/minecraft.cfg @@ -24,4 +24,9 @@ attribute,skeleton,armor relation,place,block relation,kill,mob,mob relation,break,block -relation,use,tool \ No newline at end of file +relation,use,tool +action,breakBlock,aim,swing,pickup +action,placeBlock,aim,swing +action,useBlock,aim,swing +action,drinkPotion,swing,potion +action,eat,swing,food \ No newline at end of file diff --git a/midca/domains/templates/asyncTemplate.txt b/midca/domains/templates/asyncTemplate.txt index 80e90ccb..b0af6eb5 100644 --- a/midca/domains/templates/asyncTemplate.txt +++ b/midca/domains/templates/asyncTemplate.txt @@ -67,52 +67,8 @@ def asynch_plan(mem, midcaPlan): if midcaAction[0] == "block_until_seen": actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) - elif midcaAction[0] == "point_to": - cmdID = rosrun.next_id() - actions.append(DoPoint(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - POINT_TOPIC, cmdID)) - - elif midcaAction[0] == "reach_to_pickup": - cmdID = rosrun.next_id() - actions.append(DoReach(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "reach_to_unstack": - cmdID = rosrun.next_id() - actions.append(DoUnstack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "grab": - cmdID = rosrun.next_id() - actions.append(DoGrab(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - GRAB_TOPIC, cmdID)) - elif midcaAction[0] == "release": - cmdID = rosrun.next_id() - actions.append(DoRelease(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RELEASE_TOPIC, cmdID)) - elif midcaAction[0] == "raising": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "raising_arm": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, ' ', - allowed_sighting_lag(' '), allowed_sighting_wait(' '), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "putdown": - cmdID = rosrun.next_id() - actions.append(DoPut(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "stack": - cmdID = rosrun.next_id() - actions.append(DoStack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) + + else: if verbose >= 1: print "MIDCA action", midcaAction, "does not correspond to an asynch", diff --git a/midca/domains/templates/doOperatorTemplate.txt b/midca/domains/templates/doOperatorTemplate.txt index 104fafa9..cc062e97 100644 --- a/midca/domains/templates/doOperatorTemplate.txt +++ b/midca/domains/templates/doOperatorTemplate.txt @@ -1,4 +1,4 @@ -class Do(AsynchAction): +class (AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -10,6 +10,7 @@ class Do(AsynchAction): self.complete = False self.msgID = msgID # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} self.topicFormats = {} executeAction = lambda mem, midcaAction, status: self.send_point() @@ -24,7 +25,6 @@ class Do(AsynchAction): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict From 73c7a655477364e9321f1d0efa852ba07b957bc8 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 6 Apr 2021 22:00:00 -0400 Subject: [PATCH 18/23] refactor of domains and example files to remove nested domain subdirectory --- .../domains/blocksworld/domains/arsonist.sim | 95 ---------- .../domains/arsonist_extinguish.sim | 117 ------------ .../blocksworld/domains/arsonist_mortar.sim | 131 ------------- .../blocksworld/domains/blocksworld.sim | 59 ------ .../blocksworld/domains/sample_domain.sim | 34 ---- .../coloredBlocksworld/coloredBlocksworld.cfg | 2 +- .../domains/arsonist_mortar_construction.sim | 178 ------------------ .../domains/arsonist_mortar_hierarchy.sim | 141 -------------- .../domains/restaurants.sim | 48 ----- midca/domains/logistics/domains/domain.sim | 68 ------- midca/domains/logistics/domains/domain2.sim | 66 ------- midca/domains/nbeacons/domains/nbeacons.sim | 121 ------------ .../restaurant_domain/domains/restaurant.sim | 63 ------- midca/examples/Logistics_jshop.py | 2 +- midca/examples/chicken_run.py | 2 +- midca/examples/cogsci_demo.py | 2 +- midca/examples/cogsci_demo_ma.py | 2 +- midca/examples/cogsci_demo_mortar.py | 2 +- .../cogsci_demo_mortar_construction.py | 2 +- .../cogsci_demo_mortar_goal_transforms.py | 2 +- midca/examples/minecraft_run.py | 2 +- midca/examples/nbeacons_aaai17_agent1.py | 2 +- midca/examples/nbeacons_aaai17_agent2.py | 2 +- midca/examples/nbeacons_aaai17_agent3.py | 2 +- midca/examples/nbeacons_demo.py | 2 +- midca/examples/restaurant_demo.py | 2 +- midca/examples/run_extinguish.py | 2 +- midca/examples/simple_run.py | 2 +- midca/examples/simple_run_arson.py | 2 +- .../simple_run_arson_broken_shop_methods.py | 2 +- .../simple_run_arson_not_prefer_fire.py | 2 +- midca/examples/simple_run_arson_trace.py | 2 +- midca/examples/simple_run_jshop.py | 2 +- .../simple_run_jshop_New_Domain_Structure.py | 90 --------- midca/examples/simple_run_log.py | 2 +- midca/examples/simple_run_trace.py | 2 +- 36 files changed, 23 insertions(+), 1234 deletions(-) delete mode 100644 midca/domains/blocksworld/domains/arsonist.sim delete mode 100644 midca/domains/blocksworld/domains/arsonist_extinguish.sim delete mode 100644 midca/domains/blocksworld/domains/arsonist_mortar.sim delete mode 100644 midca/domains/blocksworld/domains/blocksworld.sim delete mode 100644 midca/domains/blocksworld/domains/sample_domain.sim delete mode 100644 midca/domains/construction_domain/domains/arsonist_mortar_construction.sim delete mode 100644 midca/domains/construction_domain/domains/arsonist_mortar_hierarchy.sim delete mode 100644 midca/domains/construction_domain/domains/restaurants.sim delete mode 100644 midca/domains/logistics/domains/domain.sim delete mode 100644 midca/domains/logistics/domains/domain2.sim delete mode 100644 midca/domains/nbeacons/domains/nbeacons.sim delete mode 100644 midca/domains/restaurant_domain/domains/restaurant.sim delete mode 100644 midca/examples/simple_run_jshop_New_Domain_Structure.py diff --git a/midca/domains/blocksworld/domains/arsonist.sim b/midca/domains/blocksworld/domains/arsonist.sim deleted file mode 100644 index dd1f6fa3..00000000 --- a/midca/domains/blocksworld/domains/arsonist.sim +++ /dev/null @@ -1,95 +0,0 @@ - -type(BLOCK) -type(ARSONIST) - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(hasmortar, [blk], [BLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) \ No newline at end of file diff --git a/midca/domains/blocksworld/domains/arsonist_extinguish.sim b/midca/domains/blocksworld/domains/arsonist_extinguish.sim deleted file mode 100644 index 00d76c7e..00000000 --- a/midca/domains/blocksworld/domains/arsonist_extinguish.sim +++ /dev/null @@ -1,117 +0,0 @@ - -type(BLOCK) -type(ARSONIST) -type(FIRE-EXTINGUISHER) -type(SQUARE, BLOCK) -type(TRIANGLE, BLOCK) -type(TABLE, BLOCK) - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(fire-extinguisher, [fireExt], [FIRE-EXTINGUISHER]) -predicate(holdingextinguisher, [fireExt], [FIRE-EXTINGUISHER]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(pickup_extinguisher, -args = [(fireExt, FIRE-EXTINGUISHER)], -preconditions = [ - condition(holdingextinguisher, [fireExt], negate = True)], -results = [ - condition(holdingextinguisher, [fireExt])]) - -operator(putdown_extinguisher, -args = [(fireExt, FIRE-EXTINGUISHER)], -preconditions = [ - condition(holdingextinguisher, [fireExt])], -results = [ - condition(holdingextinguisher, [fireExt], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK), (fireExt, FIRE-EXTINGUISHER)], -preconditions = [ - condition(onfire, [blk]), - condition(holdingextinguisher, [fireExt])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) - - diff --git a/midca/domains/blocksworld/domains/arsonist_mortar.sim b/midca/domains/blocksworld/domains/arsonist_mortar.sim deleted file mode 100644 index 66c1113d..00000000 --- a/midca/domains/blocksworld/domains/arsonist_mortar.sim +++ /dev/null @@ -1,131 +0,0 @@ -type(root) -type(BLOCK) -type(ARSONIST) -type(MORTARBLOCK) - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) -predicate(used, [mortar], [MORTARBLOCK]) -predicate(available, [mortar], [MORTARBLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(stack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk]), - condition(available, [mortar])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar]), - condition(available, [mortar], negate = True), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(unstack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(stable-on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False), - condition(hasmortar, [btmblk, mortar], negate = True)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) diff --git a/midca/domains/blocksworld/domains/blocksworld.sim b/midca/domains/blocksworld/domains/blocksworld.sim deleted file mode 100644 index 749899d9..00000000 --- a/midca/domains/blocksworld/domains/blocksworld.sim +++ /dev/null @@ -1,59 +0,0 @@ -#simple blocksworld domain with triangular blocks added. - -type(BLOCK) - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - diff --git a/midca/domains/blocksworld/domains/sample_domain.sim b/midca/domains/blocksworld/domains/sample_domain.sim deleted file mode 100644 index 3f3d3070..00000000 --- a/midca/domains/blocksworld/domains/sample_domain.sim +++ /dev/null @@ -1,34 +0,0 @@ -#Sample domain file using the MIDCA predicate world domain language. -#These are comments. Multi-line comments are not supported. -#This file will define a very simple domain where chickens can be on either the -#left or right side of a road; e.g. state = {left(chicken1), right(chicken2)...} - -#create a new type. Convention is all caps for type. All values case-sensitive. -type(CHICKEN) -#creates a subtype. -type(HEN, CHICKEN) - -#create new predicates. Format is (name, argNameList, argTypeList). -predicate(onright, [chicken], [CHICKEN]) -predicate(onleft, [chicken], [CHICKEN]) - -#'operator' takes (args, preconditions, results). These define how actions work. -#args is list of (argName, argType) -#preconditions and results are lists of conditions -#a condition takes a predicateName, argNameList, and optional negate = False - -#crossing from left to right: -#in this case, a chicken must be on the left to cross right, and as a result it -#will no longer be on the left and will be on the right. -operator(crossright, - args = [(chicken, CHICKEN)], - preconditions = [condition(onleft, [chicken])], - results = [condition(onright, [chicken]), - condition(onleft, [chicken], negate = True)]) - -#crossing from right to left: -operator(crossleft, - args = [(chicken, CHICKEN)], - preconditions = [condition(onright, [chicken])], - results = [condition(onleft, [chicken]), - condition(onright, [chicken], negate = True)]) diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index 3d4b5b3e..9c0d8fc3 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -12,4 +12,4 @@ relation,clear,block action,pickup,loc action,putdown,loc action,stack,raise -action,unstack,loc,raise,lower \ No newline at end of file +action,unstack,loc \ No newline at end of file diff --git a/midca/domains/construction_domain/domains/arsonist_mortar_construction.sim b/midca/domains/construction_domain/domains/arsonist_mortar_construction.sim deleted file mode 100644 index 7b54e23f..00000000 --- a/midca/domains/construction_domain/domains/arsonist_mortar_construction.sim +++ /dev/null @@ -1,178 +0,0 @@ -type(root) -type(BLOCK,root) -type(ARSONIST,root) -type(MORTARBLOCK,root) -type(A_,BLOCK) -type(B_,BLOCK) -type(C_,BLOCK) -type(D_,BLOCK) -type(E_,BLOCK) -type(F_,BLOCK) -type(G_,BLOCK) -type(H_,BLOCK) -type(I_,BLOCK) -type(J_,BLOCK) -type(K_,BLOCK) -type(L_,BLOCK) -type(M_,BLOCK) -type(N_,BLOCK) -type(O_,BLOCK) -type(P_,BLOCK) -type(Q_,BLOCK) -type(R_,BLOCK) -type(S_,BLOCK) -type(T_,BLOCK) -type(U_,BLOCK) -type(V_,BLOCK) -type(W_,BLOCK) -type(X_,BLOCK) -type(Y_,BLOCK) -type(Z_,BLOCK) -type(Z_1_,BLOCK) -type(Z_2_,BLOCK) - -ptype(root) -ptype(on,root) -ptype(stable-on,on) - - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) -predicate(used, [mortar], [MORTARBLOCK]) -predicate(available, [mortar], [MORTARBLOCK]) -predicate(in_store, [blk], [BLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(stack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk]), - condition(available, [mortar])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar]), - condition(available, [mortar], negate = True), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(unstack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(stable-on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False), - condition(hasmortar, [btmblk, mortar], negate = True)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) - -operator(get_from_store, -args = [(blk, BLOCK)], -preconditions = [ - condition(in_store, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(in_store, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - diff --git a/midca/domains/construction_domain/domains/arsonist_mortar_hierarchy.sim b/midca/domains/construction_domain/domains/arsonist_mortar_hierarchy.sim deleted file mode 100644 index 912d7360..00000000 --- a/midca/domains/construction_domain/domains/arsonist_mortar_hierarchy.sim +++ /dev/null @@ -1,141 +0,0 @@ -type(root) -type(BLOCK,root) -type(ARSONIST,root) -type(MORTARBLOCK,root) -type(A_,BLOCK) -type(B_,BLOCK) -type(C_,BLOCK) -type(D_,BLOCK) - - -ptype(root) -ptype(on,root) -ptype(stable-on,on) - - -predicate(clear, [blk], [BLOCK]) -predicate(holding, [blk], [BLOCK]) -predicate(arm-empty, [], []) -predicate(on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) -predicate(on-table, [blk], [BLOCK]) -predicate(block, [blk], [BLOCK]) -predicate(triangle, [blk], [BLOCK]) -predicate(table, [blk], [BLOCK]) -predicate(onfire, [blk], [BLOCK]) -predicate(arsonist, [ars], [ARSONIST]) -predicate(free, [ars], [ARSONIST]) -predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) -predicate(used, [mortar], [MORTARBLOCK]) -predicate(available, [mortar], [MORTARBLOCK]) - -operator(stack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(on, [topblk, btmblk]), - condition(arm-empty, [])]) - -operator(stack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [btmblk]), - condition(holding, [topblk]), - condition(available, [mortar])], -results = [ - condition(clear, [btmblk], negate = True), - condition(holding, [topblk], negate = True), - condition(clear, [topblk]), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar]), - condition(available, [mortar], negate = True), - condition(arm-empty, [])]) - -operator(unstack, -args = [(topblk, BLOCK), (btmblk, BLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(on, [topblk, btmblk])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False)]) - -operator(unstack_mortared, -args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], -preconditions = [ - condition(clear, [topblk]), - condition(arm-empty), - condition(stable-on, [topblk, btmblk]), - condition(hasmortar, [btmblk, mortar]), - condition(used, [mortar])], -results = [ - condition(clear, [topblk], negate = True), - condition(holding, [topblk]), - condition(arm-empty, [], negate = True), - condition(stable-on, [topblk, btmblk], negate = True), - condition(clear, [btmblk], negate = False), - condition(hasmortar, [btmblk, mortar], negate = True)]) - -operator(putdown, -args = [(blk, BLOCK)], -preconditions = [ - condition(holding, [blk])], -results = [ - condition(holding, [blk], negate = True), - condition(clear, [blk]), - condition(on-table, [blk]), - condition(arm-empty, [])]) - -operator(pickup, -args = [(blk, BLOCK)], -preconditions = [ - condition(on-table, [blk]), - condition(clear, [blk]), - condition(arm-empty, [])], -results = [ - condition(holding, [blk]), - condition(clear, [blk], negate = True), - condition(on-table, [blk], negate = True), - condition(arm-empty, [], negate = True)]) - -operator(putoutfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk])], -results = [ - condition(onfire, [blk], negate = True)]) - -operator(catchfire, -args = [(blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True)], -results = [ - condition(onfire, [blk])]) - -operator(lightonfire, -args = [(arsonist, ARSONIST), (blk, BLOCK)], -preconditions = [ - condition(onfire, [blk], negate = True), - condition(free, [arsonist])], -results = [ - condition(onfire, [blk])]) - -operator(apprehend, -args = [(arsonist, ARSONIST)], -preconditions = [ - condition(free, [arsonist])], -results = [ - condition(free, [arsonist], negate = True)]) - -operator(searchfor, -args = [(arsonist, ARSONIST)]) diff --git a/midca/domains/construction_domain/domains/restaurants.sim b/midca/domains/construction_domain/domains/restaurants.sim deleted file mode 100644 index 56ac2768..00000000 --- a/midca/domains/construction_domain/domains/restaurants.sim +++ /dev/null @@ -1,48 +0,0 @@ -type(root) -type(NUMBER,root) -type(DISH,root) -type(CHICKEN,DISH) -type(SALAD,DISH) -type(HASHBROWN,DISH) -type(EGGMUFFIN,DISH) -type(MOCKTAIL,DISH) -type(STRAWBERYCAKE,DISH) -type(A_,PERSON) -type(B_,PERSON) -type(C_,PERSON) -type(D_,PERSON) -type(E_,PERSON) - -predicate(costofdish, [dsh, num], [DISH, NUMBER]) -predicate(timetomakedish, [dsh, num], [DISH, NUMBER]) -predicate(order_received, [per, dsh], [PERSON, DISH]) -predicate(order_pending, [per, dsh], [DISH, PERSON]) -predicate(order_prepared, [per, dsh], [DISH, PERSON]) -predicate(order_served, [per, dsh], [DISH, PERSON]) - -operator(take_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_received, [per, dsh], negate = True)], -results = [ - condition(order_received, [per, dsh]), - condition(order_pending, [per, dsh])]) - -operator(prepare_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_pending, [per, dsh])], -results = [ - condition(order_pending, [per, dsh], negate= True), - condition(order_prepared, [per, dsh])]) - -operator(serve_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_prepared, [per, dsh])], -results = [ - condition(order_served, [per, dsh]), - condition(order_received, [per, dsh], negate = True)]) - - - diff --git a/midca/domains/logistics/domains/domain.sim b/midca/domains/logistics/domains/domain.sim deleted file mode 100644 index 2fddf704..00000000 --- a/midca/domains/logistics/domains/domain.sim +++ /dev/null @@ -1,68 +0,0 @@ -type(SAIRPLANE) -type(AIRPLANE) -type(CITY) -type(TRUCK) -type(LOCATION) -type(PACKAGE) -type(AIRPORT) - -predicate(airplane-at, [plane1,aport1], [AIRPLANE,AIRPORT]) -predicate(in-truck, [obj,truck], [PACKAGE,TRUCK]) -predicate(in-airplane, [obj,plane], [PACKAGE,AIRPLANE]) -predicate(sairplane-at, [splane1,aport1], [SAIRPLANE,AIRPORT]) -predicate(NearBy, [city1,city2], [CITY,CITY]) -predicate(truck-at, [truck1, loc1], [TRUCK, LOCATION]) -predicate(IN-CITY, [loc,city], [LOCATION,CITY]) -predicate(IN-CITY-A, [loc,city], [AIRPORT,CITY]) -predicate(obj-at, [obj,loc3], [PACKAGE,LOCATION]) -predicate(obj-at-a, [obj,loc2], [PACKAGE,AIRPORT]) -predicate(deliver, [obj,loc1], [PACKAGE,LOCATION]) - -operator(load-truck, -args = [(obj, PACKAGE), (truck, TRUCK), (loc, LOCATION)], -preconditions = [ - condition(obj-at, [obj,loc]), - condition(truck-at, [truck,loc])], -results = [ - condition(in-truck, [obj, truck])]) - -operator(unload-truck, -args = [(obj, PACKAGE), (truck, TRUCK), (loc, LOCATION)], -preconditions = [ - condition(in-truck, [obj, truck]), - condition(truck-at, [truck,loc])], -results = [ - condition(obj-at, [obj,loc])]) - - -operator(load-airplane, -args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], -preconditions = [ - condition(obj-at-a, [obj, ap1]), - condition(airplane-at, [plane,ap1])], -results = [ - condition(in-airplane, [obj, plane])]) - - -operator(unload-airplane, -args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], -preconditions = [ - condition(in-airplane, [obj, plane]), - condition(airplane-at, [plane,ap1])], -results = [ - condition(obj-at-a, [obj,ap1])]) - - -operator(drive-truck, -args = [(truck, TRUCK), (loc1, LOCATION), (loc2, LOCATION)], -preconditions = [ - condition(truck-at, [truck,loc1])], -results = [ - condition(truck-at, [truck, loc2])]) - -operator(fly-airplane, -args = [(plane, AIRPLANE), (ap1, AIRPORT), (ap2, AIRPORT)], -preconditions = [ - condition(airplane-at, [plane,ap1])], -results = [ - condition(airplane-at, [plane, ap2])]) \ No newline at end of file diff --git a/midca/domains/logistics/domains/domain2.sim b/midca/domains/logistics/domains/domain2.sim deleted file mode 100644 index 9d4f86c1..00000000 --- a/midca/domains/logistics/domains/domain2.sim +++ /dev/null @@ -1,66 +0,0 @@ - -type(AIRPLANE) -type(CITY) -type(TRUCK) -type(PACKAGE) -type(AIRPORT) - -predicate(in-truck, [obj,truck], [PACKAGE,TRUCK]) -predicate(truck-c, [t,city], [TRUCK,CITY]) -predicate(in-airplane, [obj,plane], [PACKAGE,AIRPLANE]) -predicate(airplane-at, [plane1,aport1], [AIRPLANE,AIRPORT]) -predicate(NearBy, [city1,city2], [CITY,CITY]) -predicate(truck-at, [truck1, loc1], [TRUCK, AIRPORT]) -predicate(IN-CITY, [loc,city], [AIRPORT,CITY]) -predicate(IN-CITY-A, [loc,city], [AIRPORT,CITY]) -predicate(obj-at, [obj,loc3], [PACKAGE,AIRPORT]) -predicate(deliver, [obj,loc1], [PACKAGE,AIRPORT]) - -operator(load-truck, -args = [(obj, PACKAGE), (truck, TRUCK), (loc, AIRPORT)], -preconditions = [ - condition(obj-at, [obj,loc]), - condition(truck-at, [truck,loc])], -results = [ - condition(in-truck, [obj, truck])]) - -operator(unload-truck, -args = [(obj, PACKAGE), (truck, TRUCK), (loc, AIRPORT)], -preconditions = [ - condition(in-truck, [obj, truck]), - condition(truck-at, [truck,loc])], -results = [ - condition(obj-at, [obj,loc])]) - - -operator(load-airplane, -args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], -preconditions = [ - condition(obj-at, [obj, ap1]), - condition(airplane-at, [plane,ap1])], -results = [ - condition(in-airplane, [obj, plane])]) - - -operator(unload-airplane, -args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], -preconditions = [ - condition(in-airplane, [obj, plane]), - condition(airplane-at, [plane,ap1])], -results = [ - condition(obj-at, [obj,ap1])]) - - -operator(drive-truck, -args = [(truck, TRUCK), (loc1, AIRPORT), (loc2, AIRPORT)], -preconditions = [ - condition(truck-at, [truck,loc1])], -results = [ - condition(truck-at, [truck, loc2])]) - -operator(fly-airplane, -args = [(plane, AIRPLANE), (ap1, AIRPORT), (ap2, AIRPORT)], -preconditions = [ - condition(airplane-at, [plane,ap1])], -results = [ - condition(airplane-at, [plane, ap2])]) diff --git a/midca/domains/nbeacons/domains/nbeacons.sim b/midca/domains/nbeacons/domains/nbeacons.sim deleted file mode 100644 index 04cf8fc6..00000000 --- a/midca/domains/nbeacons/domains/nbeacons.sim +++ /dev/null @@ -1,121 +0,0 @@ -# NBEACONS domain (adapted from marsworld) - -type(DIM) -type(TILE) -type(AGENT) -type(BEACON) -type(BEACON-TYPE) - -predicate(agent-at, [agnt, loc], [AGENT, TILE]) -predicate(beacon-at, [bcn, loc], [BEACON, TILE]) -predicate(beacon-type, [bcn, bcntyp], [BEACON, BEACON-TYPE]) -predicate(activated, [bcn], [BEACON]) -predicate(adjacent-north, [loc1, loc2], [TILE, TILE]) -predicate(adjacent-south, [loc1, loc2], [TILE, TILE]) -predicate(adjacent-east, [loc1, loc2], [TILE, TILE]) -predicate(adjacent-west, [loc1, loc2], [TILE, TILE]) -predicate(quicksand, [loc], [TILE]) -predicate(stuck, [agnt], [AGENT]) -predicate(mostly-stuck, [agnt], [AGENT]) -predicate(somewhat-stuck, [agnt], [AGENT]) -predicate(partly-stuck, [agnt], [AGENT]) -predicate(barely-stuck, [agnt], [AGENT]) -predicate(free, [agnt], [AGENT]) - -operator(movenorth, -args = [(agnt, AGENT), (start, TILE), (dest, TILE)], -preconditions = [ - condition(free, [agnt]), - condition(agent-at, [agnt, start]), - condition(adjacent-north, [start, dest])], -results = [ - condition(agent-at, [agnt, start], negate = TRUE), - condition(agent-at, [agnt, dest])]) - -operator(movesouth, -args = [(agnt, AGENT), (start, TILE), (dest, TILE)], -preconditions = [ - condition(free, [agnt]), - condition(agent-at, [agnt, start]), - condition(adjacent-south, [start, dest])], -results = [ - condition(agent-at, [agnt, start], negate = TRUE), - condition(agent-at, [agnt, dest])]) - - -operator(moveeast, -args = [(agnt, AGENT), (start, TILE), (dest, TILE)], -preconditions = [ - condition(free, [agnt]), - condition(agent-at, [agnt, start]), - condition(adjacent-east, [start, dest])], -results = [ - condition(agent-at, [agnt, start], negate = TRUE), - condition(agent-at, [agnt, dest])]) - -operator(movewest, -args = [(agnt, AGENT), (start, TILE), (dest, TILE)], -preconditions = [ - condition(free, [agnt]), - condition(agent-at, [agnt, start]), - condition(adjacent-west, [start, dest])], -results = [ - condition(agent-at, [agnt, start], negate = TRUE), - condition(agent-at, [agnt, dest])]) - -operator(activatebeacon, -args = [(agnt, AGENT), (loc, TILE), (bcn, BEACON)], -preconditions = [ - condition(agent-at, [agnt, loc]), - condition(beacon-at, [bcn, loc]), - condition(activated, [bcn], negate = TRUE)], -results = [ - condition(activated, [bcn])]) - -# Note: this operator is not available to the agent via planning (i.e. pyhop) -operator(deactivatebeacon, -args = [(bcn, BEACON)], -preconditions = [ - condition(activated, [bcn])], -results = [ - condition(activated, [bcn], negate = TRUE)]) - -operator(push1, -args = [(agnt, AGENT)], -preconditions = [ - condition(stuck, [agnt])], -results = [ - condition(stuck, [agnt], negate= TRUE), - condition(mostly-stuck, [agnt])]) - -operator(push2, -args = [(agnt, AGENT)], -preconditions = [ - condition(mostly-stuck, [agnt])], -results = [ - condition(mostly-stuck, [agnt], negate= TRUE), - condition(somewhat-stuck, [agnt])]) - -operator(push3, -args = [(agnt, AGENT)], -preconditions = [ - condition(somewhat-stuck, [agnt])], -results = [ - condition(somewhat-stuck, [agnt], negate= TRUE), - condition(partly-stuck, [agnt])]) - -operator(push4, -args = [(agnt, AGENT)], -preconditions = [ - condition(partly-stuck, [agnt])], -results = [ - condition(partly-stuck, [agnt], negate= TRUE), - condition(barely-stuck, [agnt])]) - -operator(push5, -args = [(agnt, AGENT)], -preconditions = [ - condition(barely-stuck, [agnt])], -results = [ - condition(barely-stuck, [agnt], negate= TRUE), - condition(free, [agnt])]) \ No newline at end of file diff --git a/midca/domains/restaurant_domain/domains/restaurant.sim b/midca/domains/restaurant_domain/domains/restaurant.sim deleted file mode 100644 index a2c3c6ba..00000000 --- a/midca/domains/restaurant_domain/domains/restaurant.sim +++ /dev/null @@ -1,63 +0,0 @@ -type(root) -type(PERSON,root) -type(NUMBER,root) -type(DISH,root) -type(CHICKEN,DISH) -type(SALAD,DISH) -type(HASHBROWN,DISH) -type(EGGMUFFIN,DISH) -type(MOCKTAIL,DISH) -type(STRAWBERYCAKE,DISH) -type(VEGETARIAN_BURGER,DISH) -type(VEGIE_SANDWICH,DISH) -type(STRAWBERYCAKE,DISH) -type(WAFFLES,DISH) -type(GOLD_FISH,DISH) -type(TUNA_FISH,DISH) -type(HOT_DOG,DISH) -type(COOKIES,DISH) -type(ICE_CAKE,DISH) -type(A_,PERSON) -type(B_,PERSON) -type(C_,PERSON) -type(D_,PERSON) -type(E_,PERSON) -type(F_,PERSON) -type(G_,PERSON) -type(H_,PERSON) - - -predicate(costofdish, [dsh, num], [DISH, NUMBER]) -predicate(order_received, [per, dsh], [PERSON, DISH]) -predicate(order_pending, [per, dsh], [PERSON, DISH]) -predicate(order_prepared, [per, dsh], [PERSON, DISH]) -predicate(order_serve, [per, dsh], [PERSON, DISH]) - - -operator(take_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_received, [per, dsh], negate = True)], -results = [ - condition(order_received, [per, dsh]), - condition(order_pending, [per, dsh])]) - -operator(prepare_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_pending, [per, dsh])], -results = [ - condition(order_pending, [per, dsh], negate= True), - condition(order_prepared, [per, dsh])]) - -operator(serve_order, -args = [(per, PERSON), (dsh, DISH)], -preconditions = [ - condition(order_prepared, [per, dsh])], -results = [ - condition(order_serve, [per, dsh]), - condition(order_prepared, [per, dsh], negate = True), - condition(order_received, [per, dsh], negate = True)]) - - - diff --git a/midca/examples/Logistics_jshop.py b/midca/examples/Logistics_jshop.py index 4b3effc0..726a8310 100644 --- a/midca/examples/Logistics_jshop.py +++ b/midca/examples/Logistics_jshop.py @@ -24,7 +24,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/logistics/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/domain2.sim" +DOMAIN_FILE = DOMAIN_ROOT + "domain2.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate2.sim" ### Domain Specific Variables for JSHOP planner diff --git a/midca/examples/chicken_run.py b/midca/examples/chicken_run.py index 765f02d8..5e2170e4 100644 --- a/midca/examples/chicken_run.py +++ b/midca/examples/chicken_run.py @@ -19,7 +19,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/sample_domain.sim" +DOMAIN_FILE = DOMAIN_ROOT + "sample_domain.sim" STATE_FILE = DOMAIN_ROOT + "states/sample_state.sim" DISPLAY_FUNC = print DECLARE_METHODS_FUNC = sample_methods.declare_methods diff --git a/midca/examples/cogsci_demo.py b/midca/examples/cogsci_demo.py index 85a482d5..d03170a5 100644 --- a/midca/examples/cogsci_demo.py +++ b/midca/examples/cogsci_demo.py @@ -21,7 +21,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate.sim" DISPLAY_FUNC = util.asqiiDisplay DECLARE_METHODS_FUNC = methods.declare_methods diff --git a/midca/examples/cogsci_demo_ma.py b/midca/examples/cogsci_demo_ma.py index cc5bb896..ba75d588 100644 --- a/midca/examples/cogsci_demo_ma.py +++ b/midca/examples/cogsci_demo_ma.py @@ -29,7 +29,7 @@ util.pyhop_tasks_from_goals, DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC] -myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate.sim", display = DISPLAY_FUNC, argsPyHopPlanner=argsPyHopPlanner) +myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate.sim", display = DISPLAY_FUNC, argsPyHopPlanner=argsPyHopPlanner) myMidca.append_module('Perceive', perceive.MAReporter(writePort)) myMidca.insert_module('Simulate', simulator.ArsonSimulator(arsonChance = 0.9, arsonStart = 2), 1) diff --git a/midca/examples/cogsci_demo_mortar.py b/midca/examples/cogsci_demo_mortar.py index 93bcbe6f..0591c049 100644 --- a/midca/examples/cogsci_demo_mortar.py +++ b/midca/examples/cogsci_demo_mortar.py @@ -22,7 +22,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist_mortar.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist_mortar.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate_mortar.sim" DISPLAY_FUNC = util.asqiiDisplay DECLARE_METHODS_FUNC = methods_mortar.declare_methods diff --git a/midca/examples/cogsci_demo_mortar_construction.py b/midca/examples/cogsci_demo_mortar_construction.py index 118e9679..ebc9751e 100644 --- a/midca/examples/cogsci_demo_mortar_construction.py +++ b/midca/examples/cogsci_demo_mortar_construction.py @@ -25,7 +25,7 @@ MIDCA_ROOT = thisDir + "/../" DOMAIN_ROOT = MIDCA_ROOT + "domains/construction_domain/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist_mortar_construction.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist_mortar_construction.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate_construction.sim" DISPLAY_FUNC = util.asqiiDisplay diff --git a/midca/examples/cogsci_demo_mortar_goal_transforms.py b/midca/examples/cogsci_demo_mortar_goal_transforms.py index 4f223748..13cf41a0 100644 --- a/midca/examples/cogsci_demo_mortar_goal_transforms.py +++ b/midca/examples/cogsci_demo_mortar_goal_transforms.py @@ -27,7 +27,7 @@ MIDCA_ROOT = thisDir + "/../" ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist_mortar.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist_mortar.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate_mortar.sim" DISPLAY_FUNC = util.asqiiDisplay DECLARE_METHODS_FUNC = methods_mortar.declare_methods diff --git a/midca/examples/minecraft_run.py b/midca/examples/minecraft_run.py index 03a7f916..db132b8b 100644 --- a/midca/examples/minecraft_run.py +++ b/midca/examples/minecraft_run.py @@ -20,7 +20,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/minecraft/" # TODO: Next 2 lines will have to be reworked when the file system is updated. I do not have access to my office and whiteboard drawings -DOMAIN_FILE = DOMAIN_ROOT + "domains/domain.sim" +DOMAIN_FILE = DOMAIN_ROOT + "domain.sim" STATE_FILE = DOMAIN_ROOT + "states/state.sim" DISPLAY_FUNC = print DECLARE_METHODS_FUNC = methods.declare_methods # TODO: add your domain methods to midca/domains/minecraft/plan/methods.py diff --git a/midca/examples/nbeacons_aaai17_agent1.py b/midca/examples/nbeacons_aaai17_agent1.py index 5e4167c4..ffdca178 100644 --- a/midca/examples/nbeacons_aaai17_agent1.py +++ b/midca/examples/nbeacons_aaai17_agent1.py @@ -28,7 +28,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/nbeacons/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/nbeacons.sim" +DOMAIN_FILE = DOMAIN_ROOT + "nbeacons.sim" #STATE_FILE = DOMAIN_ROOT + "states/.sim" # state file is generated dynamically DISPLAY_FUNC = nbeacons_util.drawNBeaconsScene DECLARE_METHODS_FUNC = methods_nbeacons.declare_methods diff --git a/midca/examples/nbeacons_aaai17_agent2.py b/midca/examples/nbeacons_aaai17_agent2.py index c28d5a51..0e7aea5c 100644 --- a/midca/examples/nbeacons_aaai17_agent2.py +++ b/midca/examples/nbeacons_aaai17_agent2.py @@ -30,7 +30,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/nbeacons/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/nbeacons.sim" +DOMAIN_FILE = DOMAIN_ROOT + "nbeacons.sim" #STATE_FILE = DOMAIN_ROOT + "states/.sim" # state file is generated dynamically DISPLAY_FUNC = nbeacons_util.drawNBeaconsScene DECLARE_METHODS_FUNC = methods_nbeacons.declare_methods diff --git a/midca/examples/nbeacons_aaai17_agent3.py b/midca/examples/nbeacons_aaai17_agent3.py index fca24e52..6accf628 100644 --- a/midca/examples/nbeacons_aaai17_agent3.py +++ b/midca/examples/nbeacons_aaai17_agent3.py @@ -45,7 +45,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/nbeacons/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/nbeacons_avoid_mud.sim" +DOMAIN_FILE = DOMAIN_ROOT + "nbeacons_avoid_mud.sim" #STATE_FILE = DOMAIN_ROOT + "states/.sim" # state file is generated dynamically DISPLAY_FUNC = nbeacons_util.drawNBeaconsScene DECLARE_METHODS_FUNC = methods_nbeacons.declare_methods diff --git a/midca/examples/nbeacons_demo.py b/midca/examples/nbeacons_demo.py index 4ef4b806..403ec3b4 100644 --- a/midca/examples/nbeacons_demo.py +++ b/midca/examples/nbeacons_demo.py @@ -21,7 +21,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/nbeacons/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/nbeacons.sim" +DOMAIN_FILE = DOMAIN_ROOT + "nbeacons.sim" #STATE_FILE = DOMAIN_ROOT + "states/.sim" # state file is generated dynamically DISPLAY_FUNC = nbeacons_util.drawNBeaconsScene DECLARE_METHODS_FUNC = methods_nbeacons.declare_methods diff --git a/midca/examples/restaurant_demo.py b/midca/examples/restaurant_demo.py index eccd1dda..b2f26cf1 100644 --- a/midca/examples/restaurant_demo.py +++ b/midca/examples/restaurant_demo.py @@ -25,7 +25,7 @@ MIDCA_ROOT = thisDir + "/../" DOMAIN_ROOT = MIDCA_ROOT + "domains/restaurant_domain/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/restaurant.sim" +DOMAIN_FILE = DOMAIN_ROOT + "restaurant.sim" STATE_FILE = DOMAIN_ROOT + "states/restaurant_state.sim" DISPLAY_FUNC = util.shopping_display diff --git a/midca/examples/run_extinguish.py b/midca/examples/run_extinguish.py index 2116a9fe..0a756326 100644 --- a/midca/examples/run_extinguish.py +++ b/midca/examples/run_extinguish.py @@ -16,7 +16,7 @@ MIDCA_ROOT = thisDir + "/../" -domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist_extinguish.sim" +domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist_extinguish.sim" stateFile = MIDCA_ROOT + "domains/blocksworld/states/extinguisher_state.sim" extinguish = True diff --git a/midca/examples/simple_run.py b/midca/examples/simple_run.py index 6ce5f2e7..7db2e89f 100644 --- a/midca/examples/simple_run.py +++ b/midca/examples/simple_run.py @@ -25,7 +25,7 @@ myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + - "domains/blocksworld/domains/arsonist.sim", + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) #tells the PhaseManager to copy and store MIDCA states so they can be accessed later. Note: this drastically increases MIDCA's running time. diff --git a/midca/examples/simple_run_arson.py b/midca/examples/simple_run_arson.py index 850490f4..f18b5ff1 100644 --- a/midca/examples/simple_run_arson.py +++ b/midca/examples/simple_run_arson.py @@ -14,7 +14,7 @@ ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist_extinguish.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist_extinguish.sim" STATE_FILE = DOMAIN_ROOT + "states/extinguisher_state.sim" DISPLAY_FUNC = util.asqiiDisplay DECLARE_METHODS_FUNC = methods_extinguish.declare_methods diff --git a/midca/examples/simple_run_arson_broken_shop_methods.py b/midca/examples/simple_run_arson_broken_shop_methods.py index 4e697ed9..6e95ffe0 100644 --- a/midca/examples/simple_run_arson_broken_shop_methods.py +++ b/midca/examples/simple_run_arson_broken_shop_methods.py @@ -19,7 +19,7 @@ def asqiiDisplay(world): ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate_fire_pyhop_inducing_bug.sim" DISPLAY_FUNC = util.asqiiDisplay DECLARE_METHODS_FUNC = methods_broken.declare_methods diff --git a/midca/examples/simple_run_arson_not_prefer_fire.py b/midca/examples/simple_run_arson_not_prefer_fire.py index 4828adcc..d5a96634 100644 --- a/midca/examples/simple_run_arson_not_prefer_fire.py +++ b/midca/examples/simple_run_arson_not_prefer_fire.py @@ -19,7 +19,7 @@ DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC] -myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) +myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) myMidca.insert_module('Simulate', simulator.ArsonSimulator(arsonChance = 0.3, arsonStart = 2), 1) myMidca.insert_module('Interpret', guide.TFStack(), 1) diff --git a/midca/examples/simple_run_arson_trace.py b/midca/examples/simple_run_arson_trace.py index 4828adcc..d5a96634 100644 --- a/midca/examples/simple_run_arson_trace.py +++ b/midca/examples/simple_run_arson_trace.py @@ -19,7 +19,7 @@ DECLARE_METHODS_FUNC, DECLARE_OPERATORS_FUNC] -myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) +myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) myMidca.insert_module('Simulate', simulator.ArsonSimulator(arsonChance = 0.3, arsonStart = 2), 1) myMidca.insert_module('Interpret', guide.TFStack(), 1) diff --git a/midca/examples/simple_run_jshop.py b/midca/examples/simple_run_jshop.py index 32ac44e9..8020a88a 100644 --- a/midca/examples/simple_run_jshop.py +++ b/midca/examples/simple_run_jshop.py @@ -33,7 +33,7 @@ print MIDCA_ROOT ### Domain Specific Variables DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld/" -DOMAIN_FILE = DOMAIN_ROOT + "domains/arsonist.sim" +DOMAIN_FILE = DOMAIN_ROOT + "arsonist.sim" STATE_FILE = DOMAIN_ROOT + "states/defstate_jshop.sim" ### Domain Specific Variables for JSHOP planner diff --git a/midca/examples/simple_run_jshop_New_Domain_Structure.py b/midca/examples/simple_run_jshop_New_Domain_Structure.py deleted file mode 100644 index 69fedad3..00000000 --- a/midca/examples/simple_run_jshop_New_Domain_Structure.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python -from midca import base -from midca.modules import simulator, guide, evaluate, perceive, note, intend, planning, act - -from midca.worldsim import domainread, stateread -import inspect, os - -# Domain Specific Imports -# Use other util files for other domains -from midca.domains.blocksworld import util -from midca.domains.blocksworld.plan import methods, operators - - -''' -Simulation of tower construction -''' - - -###-Make sure put the domain file for jshop planner in JSHOP_DOMAIN_FILE. - -###-util.jshop_state_from_world transfers the state file in MIDCA to state file for JSHOP. You can find the -###generated file in domains/jshop_domains. Another util function put the goal in the state file too. - - - - - -#TODO: make the JSHOP.py to read the path. -thisDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -print thisDir - -MIDCA_ROOT = thisDir + "/../" -print MIDCA_ROOT -### Domain Specific Variables -DOMAIN_ROOT = MIDCA_ROOT + "domains/blocksworld_Updated/" -DOMAIN_FILE = DOMAIN_ROOT + "arsonist.sim" -STATE_FILE = DOMAIN_ROOT + "states/defstate_jshop.sim" - -### Domain Specific Variables for JSHOP planner -JSHOP_DOMAIN_FILE = DOMAIN_ROOT + "plan/blocksworld.shp" -JSHOP_STATE_FILE = DOMAIN_ROOT + "plan/bw_ran_problems_5.shp" - -DISPLAY_FUNC = util.asqiiDisplay - -GOAL_GRAPH_CMP_FUNC = util.preferApprehend - -world = domainread.load_domain(DOMAIN_FILE) -stateread.apply_state_file(world, STATE_FILE) -#creates a PhaseManager object, which wraps a MIDCA object -myMidca = base.PhaseManager(world, display = DISPLAY_FUNC, verbose=4) -#add phases by name -for phase in ["Simulate", "Perceive", "Interpret", "Eval", "Intend", "Plan", "Act"]: - myMidca.append_phase(phase) - -#add the modules which instantiate basic blocksworld operation -myMidca.append_module("Simulate", simulator.MidcaActionSimulator()) -myMidca.append_module("Simulate", simulator.ASCIIWorldViewer(display=DISPLAY_FUNC)) -myMidca.append_module("Perceive", perceive.PerfectObserver()) -myMidca.append_module("Interpret", note.ADistanceAnomalyNoter()) -#myMidca.append_module("Interpret", guide.UserGoalInput()) -myMidca.append_module("Eval", evaluate.SimpleEval()) -myMidca.append_module("Intend", intend.SimpleIntend()) -myMidca.append_module("Plan", planning.JSHOPPlanner(util.jshop_state_from_world, - util.jshop_tasks_from_goals, - JSHOP_DOMAIN_FILE, - JSHOP_STATE_FILE - )) -myMidca.append_module("Act", act.SimpleAct()) - -myMidca.insert_module('Simulate', simulator.ArsonSimulator(arsonChance = 0.9, arsonStart = 10), 1) -myMidca.insert_module('Simulate', simulator.FireReset(), 0) -myMidca.insert_module('Interpret', guide.TFStack(), 1) -myMidca.insert_module('Interpret', guide.TFFire(), 2) -myMidca.insert_module('Interpret', guide.ReactiveApprehend(), 3) -myMidca.insert_module('Eval', evaluate.Scorer(), 1) # this needs to be a 1 so that Scorer happens AFTER SimpleEval - - -#tells the PhaseManager to copy and store MIDCA states so they can be accessed later. -myMidca.storeHistory = True -myMidca.initGoalGraph(cmpFunc = GOAL_GRAPH_CMP_FUNC) -myMidca.init() -myMidca.run() - -''' -The code below would print out MIDCA's goal set for the first 20 phases of the run above. Note that any memory values can be accessed in this way, assuming that the storeHistory value was set to True during the run. This code is left as an example, but commented out because it will throw an error if fewer than 20 cycles were simulated. - -for i in range(20): - print myMidca.history[i].mem.get(myMidca.midca.mem.CURRENT_GOALS) - -''' diff --git a/midca/examples/simple_run_log.py b/midca/examples/simple_run_log.py index 69ed8253..70cc1104 100644 --- a/midca/examples/simple_run_log.py +++ b/midca/examples/simple_run_log.py @@ -24,7 +24,7 @@ DECLARE_OPERATORS_FUNC] -myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) +myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) #tells the PhaseManager to copy and store MIDCA states so they can be accessed later. Note: this drastically increases MIDCA's running time. myMidca.storeHistory = True diff --git a/midca/examples/simple_run_trace.py b/midca/examples/simple_run_trace.py index e255721f..bb442c2f 100644 --- a/midca/examples/simple_run_trace.py +++ b/midca/examples/simple_run_trace.py @@ -20,7 +20,7 @@ DECLARE_OPERATORS_FUNC] -myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/domains/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) +myMidca = predicateworld.UserGoalsMidca(domainFile = MIDCA_ROOT + "domains/blocksworld/arsonist.sim", stateFile = MIDCA_ROOT + "domains/blocksworld/states/defstate_fire.sim", argsPyHopPlanner=argsPyHopPlanner) #tells the PhaseManager to copy and store MIDCA states so they can be accessed later. myMidca.storeHistory = True From 4c159d74bd1d5e1fe0aa4250e9af85f1ff88654c Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Tue, 6 Apr 2021 22:02:17 -0400 Subject: [PATCH 19/23] add .sim files to domain specific level --- midca/domains/blocksworld/arsonist.sim | 95 +++ .../blocksworld/arsonist_extinguish.sim | 117 ++++ midca/domains/blocksworld/arsonist_mortar.sim | 131 ++++ midca/domains/blocksworld/blocksworld.sim | 59 ++ midca/domains/blocksworld/sample_domain.sim | 34 + .../arsonist_mortar_construction.sim | 178 ++++++ .../arsonist_mortar_hierarchy.sim | 141 +++++ .../construction_domain/restaurants.sim | 48 ++ midca/domains/logistics/domain.sim | 68 ++ midca/domains/logistics/domain2.sim | 66 ++ .../domains/minecraft/ros/minecraft_async.py | 592 ++++++++++++++++++ midca/domains/nbeacons/nbeacons.sim | 121 ++++ .../domains/restaurant_domain/restaurant.sim | 63 ++ 13 files changed, 1713 insertions(+) create mode 100644 midca/domains/blocksworld/arsonist.sim create mode 100644 midca/domains/blocksworld/arsonist_extinguish.sim create mode 100644 midca/domains/blocksworld/arsonist_mortar.sim create mode 100644 midca/domains/blocksworld/blocksworld.sim create mode 100644 midca/domains/blocksworld/sample_domain.sim create mode 100644 midca/domains/construction_domain/arsonist_mortar_construction.sim create mode 100644 midca/domains/construction_domain/arsonist_mortar_hierarchy.sim create mode 100644 midca/domains/construction_domain/restaurants.sim create mode 100644 midca/domains/logistics/domain.sim create mode 100644 midca/domains/logistics/domain2.sim create mode 100644 midca/domains/minecraft/ros/minecraft_async.py create mode 100644 midca/domains/nbeacons/nbeacons.sim create mode 100644 midca/domains/restaurant_domain/restaurant.sim diff --git a/midca/domains/blocksworld/arsonist.sim b/midca/domains/blocksworld/arsonist.sim new file mode 100644 index 00000000..dd1f6fa3 --- /dev/null +++ b/midca/domains/blocksworld/arsonist.sim @@ -0,0 +1,95 @@ + +type(BLOCK) +type(ARSONIST) + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(hasmortar, [blk], [BLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) \ No newline at end of file diff --git a/midca/domains/blocksworld/arsonist_extinguish.sim b/midca/domains/blocksworld/arsonist_extinguish.sim new file mode 100644 index 00000000..00d76c7e --- /dev/null +++ b/midca/domains/blocksworld/arsonist_extinguish.sim @@ -0,0 +1,117 @@ + +type(BLOCK) +type(ARSONIST) +type(FIRE-EXTINGUISHER) +type(SQUARE, BLOCK) +type(TRIANGLE, BLOCK) +type(TABLE, BLOCK) + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(fire-extinguisher, [fireExt], [FIRE-EXTINGUISHER]) +predicate(holdingextinguisher, [fireExt], [FIRE-EXTINGUISHER]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(pickup_extinguisher, +args = [(fireExt, FIRE-EXTINGUISHER)], +preconditions = [ + condition(holdingextinguisher, [fireExt], negate = True)], +results = [ + condition(holdingextinguisher, [fireExt])]) + +operator(putdown_extinguisher, +args = [(fireExt, FIRE-EXTINGUISHER)], +preconditions = [ + condition(holdingextinguisher, [fireExt])], +results = [ + condition(holdingextinguisher, [fireExt], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK), (fireExt, FIRE-EXTINGUISHER)], +preconditions = [ + condition(onfire, [blk]), + condition(holdingextinguisher, [fireExt])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) + + diff --git a/midca/domains/blocksworld/arsonist_mortar.sim b/midca/domains/blocksworld/arsonist_mortar.sim new file mode 100644 index 00000000..66c1113d --- /dev/null +++ b/midca/domains/blocksworld/arsonist_mortar.sim @@ -0,0 +1,131 @@ +type(root) +type(BLOCK) +type(ARSONIST) +type(MORTARBLOCK) + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) +predicate(used, [mortar], [MORTARBLOCK]) +predicate(available, [mortar], [MORTARBLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(stack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk]), + condition(available, [mortar])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar]), + condition(available, [mortar], negate = True), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(unstack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(stable-on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False), + condition(hasmortar, [btmblk, mortar], negate = True)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) diff --git a/midca/domains/blocksworld/blocksworld.sim b/midca/domains/blocksworld/blocksworld.sim new file mode 100644 index 00000000..749899d9 --- /dev/null +++ b/midca/domains/blocksworld/blocksworld.sim @@ -0,0 +1,59 @@ +#simple blocksworld domain with triangular blocks added. + +type(BLOCK) + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + diff --git a/midca/domains/blocksworld/sample_domain.sim b/midca/domains/blocksworld/sample_domain.sim new file mode 100644 index 00000000..3f3d3070 --- /dev/null +++ b/midca/domains/blocksworld/sample_domain.sim @@ -0,0 +1,34 @@ +#Sample domain file using the MIDCA predicate world domain language. +#These are comments. Multi-line comments are not supported. +#This file will define a very simple domain where chickens can be on either the +#left or right side of a road; e.g. state = {left(chicken1), right(chicken2)...} + +#create a new type. Convention is all caps for type. All values case-sensitive. +type(CHICKEN) +#creates a subtype. +type(HEN, CHICKEN) + +#create new predicates. Format is (name, argNameList, argTypeList). +predicate(onright, [chicken], [CHICKEN]) +predicate(onleft, [chicken], [CHICKEN]) + +#'operator' takes (args, preconditions, results). These define how actions work. +#args is list of (argName, argType) +#preconditions and results are lists of conditions +#a condition takes a predicateName, argNameList, and optional negate = False + +#crossing from left to right: +#in this case, a chicken must be on the left to cross right, and as a result it +#will no longer be on the left and will be on the right. +operator(crossright, + args = [(chicken, CHICKEN)], + preconditions = [condition(onleft, [chicken])], + results = [condition(onright, [chicken]), + condition(onleft, [chicken], negate = True)]) + +#crossing from right to left: +operator(crossleft, + args = [(chicken, CHICKEN)], + preconditions = [condition(onright, [chicken])], + results = [condition(onleft, [chicken]), + condition(onright, [chicken], negate = True)]) diff --git a/midca/domains/construction_domain/arsonist_mortar_construction.sim b/midca/domains/construction_domain/arsonist_mortar_construction.sim new file mode 100644 index 00000000..7b54e23f --- /dev/null +++ b/midca/domains/construction_domain/arsonist_mortar_construction.sim @@ -0,0 +1,178 @@ +type(root) +type(BLOCK,root) +type(ARSONIST,root) +type(MORTARBLOCK,root) +type(A_,BLOCK) +type(B_,BLOCK) +type(C_,BLOCK) +type(D_,BLOCK) +type(E_,BLOCK) +type(F_,BLOCK) +type(G_,BLOCK) +type(H_,BLOCK) +type(I_,BLOCK) +type(J_,BLOCK) +type(K_,BLOCK) +type(L_,BLOCK) +type(M_,BLOCK) +type(N_,BLOCK) +type(O_,BLOCK) +type(P_,BLOCK) +type(Q_,BLOCK) +type(R_,BLOCK) +type(S_,BLOCK) +type(T_,BLOCK) +type(U_,BLOCK) +type(V_,BLOCK) +type(W_,BLOCK) +type(X_,BLOCK) +type(Y_,BLOCK) +type(Z_,BLOCK) +type(Z_1_,BLOCK) +type(Z_2_,BLOCK) + +ptype(root) +ptype(on,root) +ptype(stable-on,on) + + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) +predicate(used, [mortar], [MORTARBLOCK]) +predicate(available, [mortar], [MORTARBLOCK]) +predicate(in_store, [blk], [BLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(stack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk]), + condition(available, [mortar])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar]), + condition(available, [mortar], negate = True), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(unstack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(stable-on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False), + condition(hasmortar, [btmblk, mortar], negate = True)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) + +operator(get_from_store, +args = [(blk, BLOCK)], +preconditions = [ + condition(in_store, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(in_store, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + diff --git a/midca/domains/construction_domain/arsonist_mortar_hierarchy.sim b/midca/domains/construction_domain/arsonist_mortar_hierarchy.sim new file mode 100644 index 00000000..912d7360 --- /dev/null +++ b/midca/domains/construction_domain/arsonist_mortar_hierarchy.sim @@ -0,0 +1,141 @@ +type(root) +type(BLOCK,root) +type(ARSONIST,root) +type(MORTARBLOCK,root) +type(A_,BLOCK) +type(B_,BLOCK) +type(C_,BLOCK) +type(D_,BLOCK) + + +ptype(root) +ptype(on,root) +ptype(stable-on,on) + + +predicate(clear, [blk], [BLOCK]) +predicate(holding, [blk], [BLOCK]) +predicate(arm-empty, [], []) +predicate(on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(stable-on, [blk1, blk2], [BLOCK, BLOCK]) +predicate(on-table, [blk], [BLOCK]) +predicate(block, [blk], [BLOCK]) +predicate(triangle, [blk], [BLOCK]) +predicate(table, [blk], [BLOCK]) +predicate(onfire, [blk], [BLOCK]) +predicate(arsonist, [ars], [ARSONIST]) +predicate(free, [ars], [ARSONIST]) +predicate(hasmortar, [blk, mortar], [BLOCK, MORTARBLOCK]) +predicate(used, [mortar], [MORTARBLOCK]) +predicate(available, [mortar], [MORTARBLOCK]) + +operator(stack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(on, [topblk, btmblk]), + condition(arm-empty, [])]) + +operator(stack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [btmblk]), + condition(holding, [topblk]), + condition(available, [mortar])], +results = [ + condition(clear, [btmblk], negate = True), + condition(holding, [topblk], negate = True), + condition(clear, [topblk]), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar]), + condition(available, [mortar], negate = True), + condition(arm-empty, [])]) + +operator(unstack, +args = [(topblk, BLOCK), (btmblk, BLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(on, [topblk, btmblk])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False)]) + +operator(unstack_mortared, +args = [(topblk, BLOCK), (btmblk, BLOCK), (mortar, MORTARBLOCK)], +preconditions = [ + condition(clear, [topblk]), + condition(arm-empty), + condition(stable-on, [topblk, btmblk]), + condition(hasmortar, [btmblk, mortar]), + condition(used, [mortar])], +results = [ + condition(clear, [topblk], negate = True), + condition(holding, [topblk]), + condition(arm-empty, [], negate = True), + condition(stable-on, [topblk, btmblk], negate = True), + condition(clear, [btmblk], negate = False), + condition(hasmortar, [btmblk, mortar], negate = True)]) + +operator(putdown, +args = [(blk, BLOCK)], +preconditions = [ + condition(holding, [blk])], +results = [ + condition(holding, [blk], negate = True), + condition(clear, [blk]), + condition(on-table, [blk]), + condition(arm-empty, [])]) + +operator(pickup, +args = [(blk, BLOCK)], +preconditions = [ + condition(on-table, [blk]), + condition(clear, [blk]), + condition(arm-empty, [])], +results = [ + condition(holding, [blk]), + condition(clear, [blk], negate = True), + condition(on-table, [blk], negate = True), + condition(arm-empty, [], negate = True)]) + +operator(putoutfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk])], +results = [ + condition(onfire, [blk], negate = True)]) + +operator(catchfire, +args = [(blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True)], +results = [ + condition(onfire, [blk])]) + +operator(lightonfire, +args = [(arsonist, ARSONIST), (blk, BLOCK)], +preconditions = [ + condition(onfire, [blk], negate = True), + condition(free, [arsonist])], +results = [ + condition(onfire, [blk])]) + +operator(apprehend, +args = [(arsonist, ARSONIST)], +preconditions = [ + condition(free, [arsonist])], +results = [ + condition(free, [arsonist], negate = True)]) + +operator(searchfor, +args = [(arsonist, ARSONIST)]) diff --git a/midca/domains/construction_domain/restaurants.sim b/midca/domains/construction_domain/restaurants.sim new file mode 100644 index 00000000..56ac2768 --- /dev/null +++ b/midca/domains/construction_domain/restaurants.sim @@ -0,0 +1,48 @@ +type(root) +type(NUMBER,root) +type(DISH,root) +type(CHICKEN,DISH) +type(SALAD,DISH) +type(HASHBROWN,DISH) +type(EGGMUFFIN,DISH) +type(MOCKTAIL,DISH) +type(STRAWBERYCAKE,DISH) +type(A_,PERSON) +type(B_,PERSON) +type(C_,PERSON) +type(D_,PERSON) +type(E_,PERSON) + +predicate(costofdish, [dsh, num], [DISH, NUMBER]) +predicate(timetomakedish, [dsh, num], [DISH, NUMBER]) +predicate(order_received, [per, dsh], [PERSON, DISH]) +predicate(order_pending, [per, dsh], [DISH, PERSON]) +predicate(order_prepared, [per, dsh], [DISH, PERSON]) +predicate(order_served, [per, dsh], [DISH, PERSON]) + +operator(take_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_received, [per, dsh], negate = True)], +results = [ + condition(order_received, [per, dsh]), + condition(order_pending, [per, dsh])]) + +operator(prepare_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_pending, [per, dsh])], +results = [ + condition(order_pending, [per, dsh], negate= True), + condition(order_prepared, [per, dsh])]) + +operator(serve_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_prepared, [per, dsh])], +results = [ + condition(order_served, [per, dsh]), + condition(order_received, [per, dsh], negate = True)]) + + + diff --git a/midca/domains/logistics/domain.sim b/midca/domains/logistics/domain.sim new file mode 100644 index 00000000..2fddf704 --- /dev/null +++ b/midca/domains/logistics/domain.sim @@ -0,0 +1,68 @@ +type(SAIRPLANE) +type(AIRPLANE) +type(CITY) +type(TRUCK) +type(LOCATION) +type(PACKAGE) +type(AIRPORT) + +predicate(airplane-at, [plane1,aport1], [AIRPLANE,AIRPORT]) +predicate(in-truck, [obj,truck], [PACKAGE,TRUCK]) +predicate(in-airplane, [obj,plane], [PACKAGE,AIRPLANE]) +predicate(sairplane-at, [splane1,aport1], [SAIRPLANE,AIRPORT]) +predicate(NearBy, [city1,city2], [CITY,CITY]) +predicate(truck-at, [truck1, loc1], [TRUCK, LOCATION]) +predicate(IN-CITY, [loc,city], [LOCATION,CITY]) +predicate(IN-CITY-A, [loc,city], [AIRPORT,CITY]) +predicate(obj-at, [obj,loc3], [PACKAGE,LOCATION]) +predicate(obj-at-a, [obj,loc2], [PACKAGE,AIRPORT]) +predicate(deliver, [obj,loc1], [PACKAGE,LOCATION]) + +operator(load-truck, +args = [(obj, PACKAGE), (truck, TRUCK), (loc, LOCATION)], +preconditions = [ + condition(obj-at, [obj,loc]), + condition(truck-at, [truck,loc])], +results = [ + condition(in-truck, [obj, truck])]) + +operator(unload-truck, +args = [(obj, PACKAGE), (truck, TRUCK), (loc, LOCATION)], +preconditions = [ + condition(in-truck, [obj, truck]), + condition(truck-at, [truck,loc])], +results = [ + condition(obj-at, [obj,loc])]) + + +operator(load-airplane, +args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], +preconditions = [ + condition(obj-at-a, [obj, ap1]), + condition(airplane-at, [plane,ap1])], +results = [ + condition(in-airplane, [obj, plane])]) + + +operator(unload-airplane, +args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], +preconditions = [ + condition(in-airplane, [obj, plane]), + condition(airplane-at, [plane,ap1])], +results = [ + condition(obj-at-a, [obj,ap1])]) + + +operator(drive-truck, +args = [(truck, TRUCK), (loc1, LOCATION), (loc2, LOCATION)], +preconditions = [ + condition(truck-at, [truck,loc1])], +results = [ + condition(truck-at, [truck, loc2])]) + +operator(fly-airplane, +args = [(plane, AIRPLANE), (ap1, AIRPORT), (ap2, AIRPORT)], +preconditions = [ + condition(airplane-at, [plane,ap1])], +results = [ + condition(airplane-at, [plane, ap2])]) \ No newline at end of file diff --git a/midca/domains/logistics/domain2.sim b/midca/domains/logistics/domain2.sim new file mode 100644 index 00000000..9d4f86c1 --- /dev/null +++ b/midca/domains/logistics/domain2.sim @@ -0,0 +1,66 @@ + +type(AIRPLANE) +type(CITY) +type(TRUCK) +type(PACKAGE) +type(AIRPORT) + +predicate(in-truck, [obj,truck], [PACKAGE,TRUCK]) +predicate(truck-c, [t,city], [TRUCK,CITY]) +predicate(in-airplane, [obj,plane], [PACKAGE,AIRPLANE]) +predicate(airplane-at, [plane1,aport1], [AIRPLANE,AIRPORT]) +predicate(NearBy, [city1,city2], [CITY,CITY]) +predicate(truck-at, [truck1, loc1], [TRUCK, AIRPORT]) +predicate(IN-CITY, [loc,city], [AIRPORT,CITY]) +predicate(IN-CITY-A, [loc,city], [AIRPORT,CITY]) +predicate(obj-at, [obj,loc3], [PACKAGE,AIRPORT]) +predicate(deliver, [obj,loc1], [PACKAGE,AIRPORT]) + +operator(load-truck, +args = [(obj, PACKAGE), (truck, TRUCK), (loc, AIRPORT)], +preconditions = [ + condition(obj-at, [obj,loc]), + condition(truck-at, [truck,loc])], +results = [ + condition(in-truck, [obj, truck])]) + +operator(unload-truck, +args = [(obj, PACKAGE), (truck, TRUCK), (loc, AIRPORT)], +preconditions = [ + condition(in-truck, [obj, truck]), + condition(truck-at, [truck,loc])], +results = [ + condition(obj-at, [obj,loc])]) + + +operator(load-airplane, +args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], +preconditions = [ + condition(obj-at, [obj, ap1]), + condition(airplane-at, [plane,ap1])], +results = [ + condition(in-airplane, [obj, plane])]) + + +operator(unload-airplane, +args = [(obj, PACKAGE), (plane, AIRPLANE), (ap1, AIRPORT)], +preconditions = [ + condition(in-airplane, [obj, plane]), + condition(airplane-at, [plane,ap1])], +results = [ + condition(obj-at, [obj,ap1])]) + + +operator(drive-truck, +args = [(truck, TRUCK), (loc1, AIRPORT), (loc2, AIRPORT)], +preconditions = [ + condition(truck-at, [truck,loc1])], +results = [ + condition(truck-at, [truck, loc2])]) + +operator(fly-airplane, +args = [(plane, AIRPLANE), (ap1, AIRPORT), (ap2, AIRPORT)], +preconditions = [ + condition(airplane-at, [plane,ap1])], +results = [ + condition(airplane-at, [plane, ap2])]) diff --git a/midca/domains/minecraft/ros/minecraft_async.py b/midca/domains/minecraft/ros/minecraft_async.py new file mode 100644 index 00000000..dc08d933 --- /dev/null +++ b/midca/domains/minecraft/ros/minecraft_async.py @@ -0,0 +1,592 @@ +from midca import rosrun, plans +from midca import midcatime +import traceback +from midca.examples.homography import * +import math +import copy +import numpy as np + + +try: + from geometry_msgs.msg import PointStamped + from geometry_msgs.msg import Point + from midca.examples import ObjectDetector + from std_msgs.msg import String + from scipy.spatial import distance +except: + pass #if ROS is not installed, an error message will already have been generated. + + +END_COLOR_CODE = '\033[0m' +NOT_STARTED = 0 +NS_COLOR_CODE = END_COLOR_CODE +IN_PROGRESS = 1 +IP_COLOR_CODE = '\033[92m' +COMPLETE = 2 +C_COLOR_CODE = '\033[94m' +FAILED = 3 +F_COLOR_CODE = '\033[91m' +FEEDBACK_KEY = "code" +CMD_ID_KEY = "cmd_id" + +AIM_TOPIC = "aim_cmd" +FOOD_TOPIC = "food_cmd" +PICKUP_TOPIC = "pickup_cmd" +POTION_TOPIC = "potion_cmd" +SWING_TOPIC = "swing_cmd" + +#set this to change output for all asynch actions. +verbose = 2 + +MAX_SIGHTING_LAG = 3.0 +MAX_SIGHTING_WAIT = 5.0 + +def allowed_sighting_lag(objectID): + ''' + returns how long ago an object can have been seen before MIDCA stops considering its + location known + ''' + return MAX_SIGHTING_LAG + +def allowed_sighting_wait(objectID): + ''' + returns the amount of midcatime MIDCA should wait to see an object before giving up. + ''' + return MAX_SIGHTING_WAIT + +''' +''' + +def get_asynch_action(midcaAction): + raise ArgumentException("midca action " + str(midcaAction) + " does not translate to a \ + valid asynchronous action.") + +def asynch_plan(mem, midcaPlan): + ''' + returns an asynchronous plan that corresponds to the given MIDCA plan. + ''' + actions = [] + goals = midcaPlan.goals + for midcaAction in midcaPlan.actions: + if midcaAction[0] == "block_until_seen": + actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) + elif midcaAction[0] == "point_to": + cmdID = rosrun.next_id() + actions.append(DoPoint(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + POINT_TOPIC, cmdID)) + + elif midcaAction[0] == "reach_to_pickup": + cmdID = rosrun.next_id() + actions.append(DoReach(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "reach_to_unstack": + cmdID = rosrun.next_id() + actions.append(DoUnstack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "grab": + cmdID = rosrun.next_id() + actions.append(DoGrab(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + GRAB_TOPIC, cmdID)) + elif midcaAction[0] == "release": + cmdID = rosrun.next_id() + actions.append(DoRelease(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RELEASE_TOPIC, cmdID)) + elif midcaAction[0] == "raising": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "raising_arm": + cmdID = rosrun.next_id() + actions.append(DoRaise(mem, midcaAction, ' ', + allowed_sighting_lag(' '), allowed_sighting_wait(' '), + RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "putdown": + cmdID = rosrun.next_id() + actions.append(DoPut(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + LOC_TOPIC, cmdID)) + elif midcaAction[0] == "stack": + cmdID = rosrun.next_id() + actions.append(DoStack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + RAISE_TOPIC, cmdID)) + else: + if verbose >= 1: + print "MIDCA action", midcaAction, "does not correspond to an asynch", + "action. MIDCA will skip this action" + return AsynchPlan(actions, goals) + + +class AsynchPlan(plans.Plan): + + ''' + subclass of MIDCA Plan class that uses asynchronous actions. + ''' + + def finished(self): + ''' + overrides plan.finished(). Declares a plan complete if all its actions report + complete or failed. + ''' + for action in self.actions: + if action.status != COMPLETE and action.status != FAILED: + return False + return True + + @property + def status(self): + ''' + property that returns the plan's status. This can be NOT_STARTED, IN_PROGRESS, + FAILED, or COMPLETE. If any action fails, the plan is considered to have failed. + The plan is complete when all actions are complete. + ''' + status = COMPLETE + for action in self.actions: + if action.status == FAILED: + return FAILED + elif action.status == NOT_STARTED and status == COMPLETE: + status = NOT_STARTED + elif action.status == IN_PROGRESS: + status = IN_PROGRESS + return status + + def __str__(self): + s = "" + for action in self.actions: + if action.status == NOT_STARTED: + s += NS_COLOR_CODE + elif action.status == IN_PROGRESS: + s += IP_COLOR_CODE + elif action.status == FAILED: + s += F_COLOR_CODE + elif action.status == COMPLETE: + s += C_COLOR_CODE + + s += str(action) + " " + return s[:-1] + END_COLOR_CODE + +class AsynchAction: + + nextID = 0 + + def __init__(self, mem, midcaAction, executeFunc, isComplete, blocks): + self.status = NOT_STARTED + self.mem = mem + self.midcaAction = midcaAction + self.executeFunc = executeFunc + self.isComplete = isComplete + self.blocks = blocks + self.startTime = None + self.id = AsynchAction.nextID + AsynchAction.nextID += 1 + + def execute(self): + if not self.startTime: + self.startTime = midcatime.now() + self.status = IN_PROGRESS + if not self.executeFunc: + return + try: + self.executeFunc(self.mem, self.midcaAction, self.status) + except: + if verbose >= 2: + print "Error executing action", self, ":\n", traceback.format_exc(), + "\n\nAction assumed to be failed" + self.status = FAILED + + def check_complete(self): + if not self.startTime: + self.startTime = midcatime.now() + if not self.check_complete: + return + try: + complete = self.isComplete(self.mem, self.midcaAction, self.status) + if verbose >= 2 and not complete: + print "Action", self, "not complete." + if verbose >= 1 and complete: + print "Action", self, "complete." + if complete: + self.status = COMPLETE + return complete + except: + if verbose >= 1: + print "Error checking completion status for action", self, " - Assuming \ + failure:\n", traceback.format_exc() + self.status = FAILED + + def ros_msg(self, topic, d): + ''' + arg d should be a dictionary that contains the key/value pairs to be sent. + ''' + sent = rosrun.send_msg(topic, rosrun.dict_as_msg) + if not sent: + if verbose >= 1: + print "Unable to send msg; ", d, "on topic", topic, " Action", self, + "assumed failed." + self.status = FAILED + + def __str__(self): + return str(self.midcaAction) + +def get_last_position(mem, objectOrID): + state = mem.get(mem.STATE) + positions = state.all_pos(objectOrID) + if not positions: + return None + else: + for state_pos in reversed(positions): + if state_pos.position: + return (state_pos.position) + return None + +def get_last_location(mem, objectOrID): + world = mem.get(mem.STATE) + sightings = world.all_sightings(objectOrID) + if not sightings: + return None + else: + for detectionEvent in reversed(sightings): + if detectionEvent.loc: + return (detectionEvent.loc, detectionEvent.time) + return None + + + + +class AwaitCurrentLocation(AsynchAction): + + ''' + Action that blocks until there is a current (within last maxAllowedLag seconds) + observation of the object's location. + ''' + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + executeAction = None + completionCheck = lambda mem, midcaAction, status: self.completion_check() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + def completion_check(self): + t = midcatime.now() + if t - self.startTime > self.maxDuration: + if verbose >= 1: + print "max midcatime exceeded for action:", self, "- changing status to failed." + self.status = FAILED + return False + lastLocReport = get_last_location(self.mem, self.objectOrID) + if not lastLocReport: + return False + return t - lastLocReport[1] <= self.maxAllowedLag + + +class DodrinkPotion(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'swing': {},'potion': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class DobreakBlock(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'aim': {},'swing': {},'pickup': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class DouseBlock(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'aim': {},'swing': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class Doeat(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'swing': {},'food': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class DoplaceBlock(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + self.topicFormats = {'aim': {},'swing': {}} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + + diff --git a/midca/domains/nbeacons/nbeacons.sim b/midca/domains/nbeacons/nbeacons.sim new file mode 100644 index 00000000..04cf8fc6 --- /dev/null +++ b/midca/domains/nbeacons/nbeacons.sim @@ -0,0 +1,121 @@ +# NBEACONS domain (adapted from marsworld) + +type(DIM) +type(TILE) +type(AGENT) +type(BEACON) +type(BEACON-TYPE) + +predicate(agent-at, [agnt, loc], [AGENT, TILE]) +predicate(beacon-at, [bcn, loc], [BEACON, TILE]) +predicate(beacon-type, [bcn, bcntyp], [BEACON, BEACON-TYPE]) +predicate(activated, [bcn], [BEACON]) +predicate(adjacent-north, [loc1, loc2], [TILE, TILE]) +predicate(adjacent-south, [loc1, loc2], [TILE, TILE]) +predicate(adjacent-east, [loc1, loc2], [TILE, TILE]) +predicate(adjacent-west, [loc1, loc2], [TILE, TILE]) +predicate(quicksand, [loc], [TILE]) +predicate(stuck, [agnt], [AGENT]) +predicate(mostly-stuck, [agnt], [AGENT]) +predicate(somewhat-stuck, [agnt], [AGENT]) +predicate(partly-stuck, [agnt], [AGENT]) +predicate(barely-stuck, [agnt], [AGENT]) +predicate(free, [agnt], [AGENT]) + +operator(movenorth, +args = [(agnt, AGENT), (start, TILE), (dest, TILE)], +preconditions = [ + condition(free, [agnt]), + condition(agent-at, [agnt, start]), + condition(adjacent-north, [start, dest])], +results = [ + condition(agent-at, [agnt, start], negate = TRUE), + condition(agent-at, [agnt, dest])]) + +operator(movesouth, +args = [(agnt, AGENT), (start, TILE), (dest, TILE)], +preconditions = [ + condition(free, [agnt]), + condition(agent-at, [agnt, start]), + condition(adjacent-south, [start, dest])], +results = [ + condition(agent-at, [agnt, start], negate = TRUE), + condition(agent-at, [agnt, dest])]) + + +operator(moveeast, +args = [(agnt, AGENT), (start, TILE), (dest, TILE)], +preconditions = [ + condition(free, [agnt]), + condition(agent-at, [agnt, start]), + condition(adjacent-east, [start, dest])], +results = [ + condition(agent-at, [agnt, start], negate = TRUE), + condition(agent-at, [agnt, dest])]) + +operator(movewest, +args = [(agnt, AGENT), (start, TILE), (dest, TILE)], +preconditions = [ + condition(free, [agnt]), + condition(agent-at, [agnt, start]), + condition(adjacent-west, [start, dest])], +results = [ + condition(agent-at, [agnt, start], negate = TRUE), + condition(agent-at, [agnt, dest])]) + +operator(activatebeacon, +args = [(agnt, AGENT), (loc, TILE), (bcn, BEACON)], +preconditions = [ + condition(agent-at, [agnt, loc]), + condition(beacon-at, [bcn, loc]), + condition(activated, [bcn], negate = TRUE)], +results = [ + condition(activated, [bcn])]) + +# Note: this operator is not available to the agent via planning (i.e. pyhop) +operator(deactivatebeacon, +args = [(bcn, BEACON)], +preconditions = [ + condition(activated, [bcn])], +results = [ + condition(activated, [bcn], negate = TRUE)]) + +operator(push1, +args = [(agnt, AGENT)], +preconditions = [ + condition(stuck, [agnt])], +results = [ + condition(stuck, [agnt], negate= TRUE), + condition(mostly-stuck, [agnt])]) + +operator(push2, +args = [(agnt, AGENT)], +preconditions = [ + condition(mostly-stuck, [agnt])], +results = [ + condition(mostly-stuck, [agnt], negate= TRUE), + condition(somewhat-stuck, [agnt])]) + +operator(push3, +args = [(agnt, AGENT)], +preconditions = [ + condition(somewhat-stuck, [agnt])], +results = [ + condition(somewhat-stuck, [agnt], negate= TRUE), + condition(partly-stuck, [agnt])]) + +operator(push4, +args = [(agnt, AGENT)], +preconditions = [ + condition(partly-stuck, [agnt])], +results = [ + condition(partly-stuck, [agnt], negate= TRUE), + condition(barely-stuck, [agnt])]) + +operator(push5, +args = [(agnt, AGENT)], +preconditions = [ + condition(barely-stuck, [agnt])], +results = [ + condition(barely-stuck, [agnt], negate= TRUE), + condition(free, [agnt])]) \ No newline at end of file diff --git a/midca/domains/restaurant_domain/restaurant.sim b/midca/domains/restaurant_domain/restaurant.sim new file mode 100644 index 00000000..a2c3c6ba --- /dev/null +++ b/midca/domains/restaurant_domain/restaurant.sim @@ -0,0 +1,63 @@ +type(root) +type(PERSON,root) +type(NUMBER,root) +type(DISH,root) +type(CHICKEN,DISH) +type(SALAD,DISH) +type(HASHBROWN,DISH) +type(EGGMUFFIN,DISH) +type(MOCKTAIL,DISH) +type(STRAWBERYCAKE,DISH) +type(VEGETARIAN_BURGER,DISH) +type(VEGIE_SANDWICH,DISH) +type(STRAWBERYCAKE,DISH) +type(WAFFLES,DISH) +type(GOLD_FISH,DISH) +type(TUNA_FISH,DISH) +type(HOT_DOG,DISH) +type(COOKIES,DISH) +type(ICE_CAKE,DISH) +type(A_,PERSON) +type(B_,PERSON) +type(C_,PERSON) +type(D_,PERSON) +type(E_,PERSON) +type(F_,PERSON) +type(G_,PERSON) +type(H_,PERSON) + + +predicate(costofdish, [dsh, num], [DISH, NUMBER]) +predicate(order_received, [per, dsh], [PERSON, DISH]) +predicate(order_pending, [per, dsh], [PERSON, DISH]) +predicate(order_prepared, [per, dsh], [PERSON, DISH]) +predicate(order_serve, [per, dsh], [PERSON, DISH]) + + +operator(take_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_received, [per, dsh], negate = True)], +results = [ + condition(order_received, [per, dsh]), + condition(order_pending, [per, dsh])]) + +operator(prepare_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_pending, [per, dsh])], +results = [ + condition(order_pending, [per, dsh], negate= True), + condition(order_prepared, [per, dsh])]) + +operator(serve_order, +args = [(per, PERSON), (dsh, DISH)], +preconditions = [ + condition(order_prepared, [per, dsh])], +results = [ + condition(order_serve, [per, dsh]), + condition(order_prepared, [per, dsh], negate = True), + condition(order_received, [per, dsh], negate = True)]) + + + From 4b36594b431ef1cfb4d4ddd34cfe939e6f1385a2 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 7 Apr 2021 09:42:45 -0400 Subject: [PATCH 20/23] move midca api to new folder at midca level --- midca/{domains => api}/Midca_Domain_API.py | 32 ++++++++++++++----- .../templates/asyncTemplate.txt | 1 - .../templates/detectorsTemplate.txt | 0 .../templates/doOperatorTemplate.txt | 0 .../templates/entitiesHandlerTemplate.txt | 0 .../ros/coloredBlocksworldDetectors.cpp | 4 +-- .../ros/coloredBlocksworldEntitiesHandler.py | 4 +-- .../ros/coloredBlocksworld_async.py | 6 ++-- 8 files changed, 30 insertions(+), 17 deletions(-) rename midca/{domains => api}/Midca_Domain_API.py (92%) rename midca/{domains => api}/templates/asyncTemplate.txt (99%) rename midca/{domains => api}/templates/detectorsTemplate.txt (100%) rename midca/{domains => api}/templates/doOperatorTemplate.txt (100%) rename midca/{domains => api}/templates/entitiesHandlerTemplate.txt (100%) diff --git a/midca/domains/Midca_Domain_API.py b/midca/api/Midca_Domain_API.py similarity index 92% rename from midca/domains/Midca_Domain_API.py rename to midca/api/Midca_Domain_API.py index 073d34ee..475746f8 100644 --- a/midca/domains/Midca_Domain_API.py +++ b/midca/api/Midca_Domain_API.py @@ -273,14 +273,28 @@ def modifyAsync(filename): parser.add_argument("-v","--verbosity",action="count",default=0,help="increase output verbosity") args = parser.parse_args() + # parse all possible formats for .cfg path name + domainPathAppend = '../domains/' + domainPath = '' + + if '../' not in args.config: # if cmd line arg does not include ../ + domainPath = domainPath + '../' + + if 'domains/' not in args.config: # if cmd line arg does not include domains/ + domainPath = domainPath + 'domains/' + + domainPath = domainPath + args.config # add at least domainName/ and .cfg filename + #determine domain name from passed filepath for arg - if not len(args.config.split('/')) == 2: + if not len(domainPath.split('/')) == 4: print('Error: Config file must be located directly within domain directory') sys.exit() - domain = (args.config.split('/'))[0] + domainName = (domainPath.split('/'))[2] + #print(domainPath) + #print(domainName) - objectInput(directedGraph, enumerationList, args.config) #generate config from passed file + objectInput(directedGraph, enumerationList, domainPath) #generate config from passed file # add output based on verbosity if args.verbosity >= 1: @@ -318,26 +332,28 @@ def modifyAsync(filename): accumulateAttributes(directedGraph, 'entity') # get all leaf nodes' inherited attributes - if not os.path.exists(domain + "/ros"): - os.makedirs(domain + "/ros") # create the new ros sub-directory + domainPath = domainPath.split('/')[0] +'/'+ domainPath.split('/')[1] +'/'+ domainPath.split('/')[2] # remove .cfg from this path + + if not os.path.exists(domainPath + "/ros"): + os.makedirs(domainPath + "/ros") # create the new ros sub-directory # templates for each entity with their attributes for object detection code stubs and helpers src='templates/detectorsTemplate.txt' - dst= domain + '/ros/' + domain + 'Detectors.cpp' + dst= domainPath + '/ros/' + domainName + 'Detectors.cpp' shutil.copy(src,dst) # copy template to modify modifyDetectors(dst) # templates for each entity and their predicates for perception to determine relations src='templates/entitiesHandlerTemplate.txt' - dst= domain + '/ros/' + domain + 'EntitiesHandler.py' + dst= domainPath + '/ros/' + domainName + 'EntitiesHandler.py' shutil.copy(src,dst) # copy template to modify modifyHandler(dst) # templates for each action and their associated topics src='templates/asyncTemplate.txt' - dst= domain + '/ros/' + domain + '_async.py' + dst= domainPath + '/ros/' + domainName + '_async.py' shutil.copy(src,dst) # copy template to modify modifyAsync(dst) diff --git a/midca/domains/templates/asyncTemplate.txt b/midca/api/templates/asyncTemplate.txt similarity index 99% rename from midca/domains/templates/asyncTemplate.txt rename to midca/api/templates/asyncTemplate.txt index b0af6eb5..abb93ee8 100644 --- a/midca/domains/templates/asyncTemplate.txt +++ b/midca/api/templates/asyncTemplate.txt @@ -68,7 +68,6 @@ def asynch_plan(mem, midcaPlan): actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) - else: if verbose >= 1: print "MIDCA action", midcaAction, "does not correspond to an asynch", diff --git a/midca/domains/templates/detectorsTemplate.txt b/midca/api/templates/detectorsTemplate.txt similarity index 100% rename from midca/domains/templates/detectorsTemplate.txt rename to midca/api/templates/detectorsTemplate.txt diff --git a/midca/domains/templates/doOperatorTemplate.txt b/midca/api/templates/doOperatorTemplate.txt similarity index 100% rename from midca/domains/templates/doOperatorTemplate.txt rename to midca/api/templates/doOperatorTemplate.txt diff --git a/midca/domains/templates/entitiesHandlerTemplate.txt b/midca/api/templates/entitiesHandlerTemplate.txt similarity index 100% rename from midca/domains/templates/entitiesHandlerTemplate.txt rename to midca/api/templates/entitiesHandlerTemplate.txt diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp index 6b97a752..25dd0927 100644 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp @@ -21,9 +21,9 @@ std::string detect_block() int main(int argc, char** argv) { - ROS_INFO_STREAM("Starting coloredBlocksworld/ros/coloredBlocksworld Entity Detectors node"); + ROS_INFO_STREAM("Starting ../domains/coloredBlocksworld/ros/coloredBlocksworld Entity Detectors node"); - ros::init(argc, argv, "coloredBlocksworld/ros/coloredBlocksworld_entity_detectors"); + ros::init(argc, argv, "../domains/coloredBlocksworld/ros/coloredBlocksworld_entity_detectors"); ros::NodeHandle n; ros::Publisher block_pub = n.advertise("block_attr", 1); diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py index c02b4527..ce0a7df4 100644 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py @@ -1,6 +1,6 @@ # https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py -class coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler(IncomingMsgHandler): +class ../domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler(IncomingMsgHandler): ''' class that receives Point messages, where each message indicates that the given object @@ -13,7 +13,7 @@ def __init__(self, topic, midcaObject, memKey = None, history = None): callback = lambda strMsg: self.store(strMsg) msgType = String self.left = None - super(coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + super(../domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) #self.objID = objID if memKey: self.memKey = memKey diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py index 5fdb7e5c..daf9612f 100644 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py @@ -30,7 +30,6 @@ CMD_ID_KEY = "cmd_id" LOC_TOPIC = "loc" -LOWER_TOPIC = "lower" RAISE_TOPIC = "raise" #set this to change output for all asynch actions. @@ -73,7 +72,7 @@ def asynch_plan(mem, midcaPlan): cmdID = rosrun.next_id() actions.append(unstack(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - ['loc', 'lower', 'raise'], cmdID)) + ['loc'], cmdID)) elif midcaAction[0] == "pickup": cmdID = rosrun.next_id() actions.append(pickup(mem, midcaAction, midcaAction[1], @@ -89,7 +88,6 @@ def asynch_plan(mem, midcaPlan): actions.append(stack(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), ['raise'], cmdID)) - else: if verbose >= 1: print "MIDCA action", midcaAction, "does not correspond to an asynch", @@ -275,7 +273,7 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.msgID = msgID # TODO: fill in formats for each topic # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} - self.topicFormats = {'loc': {},'lower': {},'raise': {},} + self.topicFormats = {'loc': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() From dfb16ebf61d126f85ef4623772136bd580d0a676 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Wed, 14 Apr 2021 08:02:22 -0400 Subject: [PATCH 21/23] general code cleaning and fixed entityHandler domain name issue --- midca/api/Midca_Domain_API.py | 54 ++----------------- .../ros/coloredBlocksworldEntitiesHandler.py | 4 +- 2 files changed, 7 insertions(+), 51 deletions(-) diff --git a/midca/api/Midca_Domain_API.py b/midca/api/Midca_Domain_API.py index 475746f8..6dff1a25 100644 --- a/midca/api/Midca_Domain_API.py +++ b/midca/api/Midca_Domain_API.py @@ -1,33 +1,3 @@ -#!/usr/bin/env python -# coding: utf-8 - -# In[ ]: - - -#MIDCA DOMAIN API -#Reads in a file of the format specification,object2,object1 -#Specification can be a type, i.e. a spoon (object2) is a utensil (object1) -#or specification can be an attribute, i.e., a utensil (object2) can be a color (object1) -#Requirement: Be able to take in input and add it to the object hierarchy tree -#Requirement: Act as an interface between ros and MIDCA for objects - -#Detector -> type, xblock, isablock -#then it is passed to MIDCA from interface -#All objects have types and possibly attributes. Attributes have values (ie type color has values -#green, red, etc) -#uniform naming via the type system and simple attributes -#Each action has a piece of code to handle and determine when its over -#define predicate formulation -#Be Able to ultimately define a new domain -# detect object types, what are predicates in domain, do actions, when is action done, and -# naming of objects and handling of attributes -# Naming -> type + unique identifier, decrement unique identifier if item disappears so -# block2 doesn't become block3 when it reappears - -#robot -> be able to list objects, then the robot detects objects, and can click to assign objects? - -#TODO: Attribute and AttributeValue need to be separate things - from __future__ import print_function import sys import os @@ -205,14 +175,14 @@ def modifyDetectors(filename): file.close() -def modifyHandler(filename): +def modifyHandler(filename, domainName): file = fileinput.FileInput(filename, inplace=True) #file = fileinput.FileInput(filename) # test output #print(' ') for line in file: if '' in line: - print(line.replace('', filename.replace('EntitiesHandler.py', '')), end='') + print(line.replace('', domainName), end='') # Add relations for each entity in domain elif '' in line: @@ -321,11 +291,11 @@ def modifyAsync(filename): # printPDDL(directedGraph) if args.verbosity == 3: - #TODO: API ENFORCES ENTITY PARENT + #Future work: HAVE API ENFORCE ENTITY AS PARENT NODE print('') printTree(directedGraph, 'entity', False) # print entity tree without attributes elif args.verbosity >= 4: - #TODO: API ENFORCES ENTITY PARENT + #Future work: HAVE API ENFORCE ENTITY AS PARENT NODE print('') printTree(directedGraph, 'entity', True) # print entity tree with attributes @@ -349,7 +319,7 @@ def modifyAsync(filename): dst= domainPath + '/ros/' + domainName + 'EntitiesHandler.py' shutil.copy(src,dst) # copy template to modify - modifyHandler(dst) + modifyHandler(dst, domainName) # templates for each action and their associated topics src='templates/asyncTemplate.txt' @@ -357,17 +327,3 @@ def modifyAsync(filename): shutil.copy(src,dst) # copy template to modify modifyAsync(dst) - - - - - - - - - - - - - - diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py index ce0a7df4..b0c3739f 100644 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py @@ -1,6 +1,6 @@ # https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py -class ../domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler(IncomingMsgHandler): +class coloredBlocksworldEntitiesHandler(IncomingMsgHandler): ''' class that receives Point messages, where each message indicates that the given object @@ -13,7 +13,7 @@ def __init__(self, topic, midcaObject, memKey = None, history = None): callback = lambda strMsg: self.store(strMsg) msgType = String self.left = None - super(../domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + super(coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) #self.objID = objID if memKey: self.memKey = memKey From dc768e40ab7aa0ccb6bcda8f8cea55edf75be458 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Sat, 24 Apr 2021 19:45:11 -0400 Subject: [PATCH 22/23] middleware keyword added --- midca/api/Midca_Domain_API.py | 58 +- midca/domains/New_Domain_Script.py | 1 + .../coloredBlocksworld/coloredBlocksworld.cfg | 1 + .../ros/coloredBlocksworldDetectors.cpp | 40 -- .../ros/coloredBlocksworldEntitiesHandler.py | 32 -- .../ros/coloredBlocksworld_async.py | 503 ------------------ midca/domains/minecraft/minecraft.cfg | 1 + .../minecraft/ros/minecraftDetectors.cpp | 4 +- .../minecraft/ros/minecraftEntitiesHandler.py | 4 +- .../domains/minecraft/ros/minecraft_async.py | 103 ++-- midca/domains/newMine/__init__.py | 0 midca/domains/newMine/plan/minecraft.pddl | 180 +++++++ 12 files changed, 264 insertions(+), 663 deletions(-) delete mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp delete mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py delete mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py create mode 100644 midca/domains/newMine/__init__.py create mode 100644 midca/domains/newMine/plan/minecraft.pddl diff --git a/midca/api/Midca_Domain_API.py b/midca/api/Midca_Domain_API.py index 6dff1a25..68203f9d 100644 --- a/midca/api/Midca_Domain_API.py +++ b/midca/api/Midca_Domain_API.py @@ -8,6 +8,7 @@ from collections import defaultdict +middleware = 'UNDEFINED' # for generating middleware specific code directedGraph = defaultdict(list) attributes = defaultdict(list) @@ -55,8 +56,11 @@ def objectInput(directedGraph, enumerationList, config): configFile = open(config) fileText = csv.reader(configFile, delimiter = ',') for row in fileText: + if row[0] == "middleware": + global middleware + middleware = row[1].lower() # auto lowercase #if it is a type it is added to the type tree - if row[0] == "type": + elif row[0] == "type": directedGraph[row[2]].insert(index, row[1]) index += 1 #if it is an attribute, then add it to the attribute tree @@ -304,26 +308,36 @@ def modifyAsync(filename): domainPath = domainPath.split('/')[0] +'/'+ domainPath.split('/')[1] +'/'+ domainPath.split('/')[2] # remove .cfg from this path - if not os.path.exists(domainPath + "/ros"): - os.makedirs(domainPath + "/ros") # create the new ros sub-directory - - # templates for each entity with their attributes for object detection code stubs and helpers - src='templates/detectorsTemplate.txt' - dst= domainPath + '/ros/' + domainName + 'Detectors.cpp' - shutil.copy(src,dst) # copy template to modify - - modifyDetectors(dst) - - # templates for each entity and their predicates for perception to determine relations - src='templates/entitiesHandlerTemplate.txt' - dst= domainPath + '/ros/' + domainName + 'EntitiesHandler.py' - shutil.copy(src,dst) # copy template to modify - - modifyHandler(dst, domainName) - # templates for each action and their associated topics - src='templates/asyncTemplate.txt' - dst= domainPath + '/ros/' + domainName + '_async.py' - shutil.copy(src,dst) # copy template to modify + print(middleware) + + if middleware == "UNDEFINED": + print("Error: no middleware defined") + elif middleware == "ros": + if not os.path.exists(domainPath + "/ros"): + os.makedirs(domainPath + "/ros") # create the new ros sub-directory - modifyAsync(dst) + # templates for each entity with their attributes for object detection code stubs and helpers + src='templates/detectorsTemplate.txt' + dst= domainPath + '/ros/' + domainName + 'Detectors.cpp' + shutil.copy(src,dst) # copy template to modify + + modifyDetectors(dst) + + # templates for each entity and their predicates for perception to determine relations + src='templates/entitiesHandlerTemplate.txt' + dst= domainPath + '/ros/' + domainName + 'EntitiesHandler.py' + shutil.copy(src,dst) # copy template to modify + + modifyHandler(dst, domainName) + + # templates for each action and their associated topics + src='templates/asyncTemplate.txt' + dst= domainPath + '/ros/' + domainName + '_async.py' + shutil.copy(src,dst) # copy template to modify + + modifyAsync(dst) + else: + print("Error: no " + middleware + " implementation") + + \ No newline at end of file diff --git a/midca/domains/New_Domain_Script.py b/midca/domains/New_Domain_Script.py index 95e8ed5e..19c1b58c 100644 --- a/midca/domains/New_Domain_Script.py +++ b/midca/domains/New_Domain_Script.py @@ -143,6 +143,7 @@ def regex_filename(filename): pddl_file = args.pddl if not pddl_file.endswith('.pddl'): # ensure pddl_file name includes '.pddl' pddl_file = pddl_file + '.pddl' + newDirectoryRoot = thisDir + "/" + newDomainName diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index 9c0d8fc3..cfc3f7d2 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -1,3 +1,4 @@ +middleware,moOSe type,block,entity attribute,block,color attribute,block,x diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp deleted file mode 100644 index 25dd0927..00000000 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/********************************************************************* - * - * - * For example, consider using PointCloudLab - * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) - * - * - *********************************************************************/ - -#include - - -std::string detect_block() -{ - //TODO: create block_attr string with the following attributes: - //['color', 'z', 'y', 'x'] - - return block_attr; -} - - -int main(int argc, char** argv) -{ - ROS_INFO_STREAM("Starting ../domains/coloredBlocksworld/ros/coloredBlocksworld Entity Detectors node"); - - ros::init(argc, argv, "../domains/coloredBlocksworld/ros/coloredBlocksworld_entity_detectors"); - ros::NodeHandle n; - - ros::Publisher block_pub = n.advertise("block_attr", 1); - - while (ros::ok()) - { - block_pub.publish(block_attr); - - ros::spinOnce(); - } - - ros::spin(); - return 0; -} \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py deleted file mode 100644 index b0c3739f..00000000 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py +++ /dev/null @@ -1,32 +0,0 @@ -# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py - -class coloredBlocksworldEntitiesHandler(IncomingMsgHandler): - - ''' - class that receives Point messages, where each message indicates that the given object - has been identified at that location. Args include the topic to listen to, object id, - and midca object to whose memory observations will be stored. Optionally the memory - key to be stored to can also be specified. - ''' - - def __init__(self, topic, midcaObject, memKey = None, history = None): - callback = lambda strMsg: self.store(strMsg) - msgType = String - self.left = None - super(coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) - #self.objID = objID - if memKey: - self.memKey = memKey - else: - self.memKey = self.mem.ROS_OBJS_DETECTED - if history: - self.history = history - else: - self.history = self.mem.STATE_HISTORY - - def store(self, data): - if not self.mem: - rospy.logerr("Trying to store data to a nonexistent MIDCA object.") - - #TODO: Code should handle detecting the following relations (predicates): - #block: ['on', 'clear'] diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py deleted file mode 100644 index daf9612f..00000000 --- a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py +++ /dev/null @@ -1,503 +0,0 @@ -from midca import rosrun, plans -from midca import midcatime -import traceback -from midca.examples.homography import * -import math -import copy -import numpy as np - - -try: - from geometry_msgs.msg import PointStamped - from geometry_msgs.msg import Point - from midca.examples import ObjectDetector - from std_msgs.msg import String - from scipy.spatial import distance -except: - pass #if ROS is not installed, an error message will already have been generated. - - -END_COLOR_CODE = '\033[0m' -NOT_STARTED = 0 -NS_COLOR_CODE = END_COLOR_CODE -IN_PROGRESS = 1 -IP_COLOR_CODE = '\033[92m' -COMPLETE = 2 -C_COLOR_CODE = '\033[94m' -FAILED = 3 -F_COLOR_CODE = '\033[91m' -FEEDBACK_KEY = "code" -CMD_ID_KEY = "cmd_id" - -LOC_TOPIC = "loc" -RAISE_TOPIC = "raise" - -#set this to change output for all asynch actions. -verbose = 2 - -MAX_SIGHTING_LAG = 3.0 -MAX_SIGHTING_WAIT = 5.0 - -def allowed_sighting_lag(objectID): - ''' - returns how long ago an object can have been seen before MIDCA stops considering its - location known - ''' - return MAX_SIGHTING_LAG - -def allowed_sighting_wait(objectID): - ''' - returns the amount of midcatime MIDCA should wait to see an object before giving up. - ''' - return MAX_SIGHTING_WAIT - -''' -''' - -def get_asynch_action(midcaAction): - raise ArgumentException("midca action " + str(midcaAction) + " does not translate to a \ - valid asynchronous action.") - -def asynch_plan(mem, midcaPlan): - ''' - returns an asynchronous plan that corresponds to the given MIDCA plan. - ''' - actions = [] - goals = midcaPlan.goals - for midcaAction in midcaPlan.actions: - if midcaAction[0] == "block_until_seen": - actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) - elif midcaAction[0] == "unstack": - cmdID = rosrun.next_id() - actions.append(unstack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - ['loc'], cmdID)) - elif midcaAction[0] == "pickup": - cmdID = rosrun.next_id() - actions.append(pickup(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - ['loc'], cmdID)) - elif midcaAction[0] == "putdown": - cmdID = rosrun.next_id() - actions.append(putdown(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - ['loc'], cmdID)) - elif midcaAction[0] == "stack": - cmdID = rosrun.next_id() - actions.append(stack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - ['raise'], cmdID)) - else: - if verbose >= 1: - print "MIDCA action", midcaAction, "does not correspond to an asynch", - "action. MIDCA will skip this action" - return AsynchPlan(actions, goals) - - -class AsynchPlan(plans.Plan): - - ''' - subclass of MIDCA Plan class that uses asynchronous actions. - ''' - - def finished(self): - ''' - overrides plan.finished(). Declares a plan complete if all its actions report - complete or failed. - ''' - for action in self.actions: - if action.status != COMPLETE and action.status != FAILED: - return False - return True - - @property - def status(self): - ''' - property that returns the plan's status. This can be NOT_STARTED, IN_PROGRESS, - FAILED, or COMPLETE. If any action fails, the plan is considered to have failed. - The plan is complete when all actions are complete. - ''' - status = COMPLETE - for action in self.actions: - if action.status == FAILED: - return FAILED - elif action.status == NOT_STARTED and status == COMPLETE: - status = NOT_STARTED - elif action.status == IN_PROGRESS: - status = IN_PROGRESS - return status - - def __str__(self): - s = "" - for action in self.actions: - if action.status == NOT_STARTED: - s += NS_COLOR_CODE - elif action.status == IN_PROGRESS: - s += IP_COLOR_CODE - elif action.status == FAILED: - s += F_COLOR_CODE - elif action.status == COMPLETE: - s += C_COLOR_CODE - - s += str(action) + " " - return s[:-1] + END_COLOR_CODE - -class AsynchAction: - - nextID = 0 - - def __init__(self, mem, midcaAction, executeFunc, isComplete, blocks): - self.status = NOT_STARTED - self.mem = mem - self.midcaAction = midcaAction - self.executeFunc = executeFunc - self.isComplete = isComplete - self.blocks = blocks - self.startTime = None - self.id = AsynchAction.nextID - AsynchAction.nextID += 1 - - def execute(self): - if not self.startTime: - self.startTime = midcatime.now() - self.status = IN_PROGRESS - if not self.executeFunc: - return - try: - self.executeFunc(self.mem, self.midcaAction, self.status) - except: - if verbose >= 2: - print "Error executing action", self, ":\n", traceback.format_exc(), - "\n\nAction assumed to be failed" - self.status = FAILED - - def check_complete(self): - if not self.startTime: - self.startTime = midcatime.now() - if not self.check_complete: - return - try: - complete = self.isComplete(self.mem, self.midcaAction, self.status) - if verbose >= 2 and not complete: - print "Action", self, "not complete." - if verbose >= 1 and complete: - print "Action", self, "complete." - if complete: - self.status = COMPLETE - return complete - except: - if verbose >= 1: - print "Error checking completion status for action", self, " - Assuming \ - failure:\n", traceback.format_exc() - self.status = FAILED - - def ros_msg(self, topic, d): - ''' - arg d should be a dictionary that contains the key/value pairs to be sent. - ''' - sent = rosrun.send_msg(topic, rosrun.dict_as_msg) - if not sent: - if verbose >= 1: - print "Unable to send msg; ", d, "on topic", topic, " Action", self, - "assumed failed." - self.status = FAILED - - def __str__(self): - return str(self.midcaAction) - -def get_last_position(mem, objectOrID): - state = mem.get(mem.STATE) - positions = state.all_pos(objectOrID) - if not positions: - return None - else: - for state_pos in reversed(positions): - if state_pos.position: - return (state_pos.position) - return None - -def get_last_location(mem, objectOrID): - world = mem.get(mem.STATE) - sightings = world.all_sightings(objectOrID) - if not sightings: - return None - else: - for detectionEvent in reversed(sightings): - if detectionEvent.loc: - return (detectionEvent.loc, detectionEvent.time) - return None - - - - -class AwaitCurrentLocation(AsynchAction): - - ''' - Action that blocks until there is a current (within last maxAllowedLag seconds) - observation of the object's location. - ''' - - def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration): - self.objectOrID = objectOrID - self.maxAllowedLag = maxAllowedLag - self.maxDuration = maxDuration - executeAction = None - completionCheck = lambda mem, midcaAction, status: self.completion_check() - AsynchAction.__init__(self, mem, midcaAction, executeAction, - completionCheck, True) - - def completion_check(self): - t = midcatime.now() - if t - self.startTime > self.maxDuration: - if verbose >= 1: - print "max midcatime exceeded for action:", self, "- changing status to failed." - self.status = FAILED - return False - lastLocReport = get_last_location(self.mem, self.objectOrID) - if not lastLocReport: - return False - return t - lastLocReport[1] <= self.maxAllowedLag - - -class unstack(AsynchAction): - - def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, - msgID): - self.objectOrID = objectOrID - self.maxAllowedLag = maxAllowedLag - self.maxDuration = maxDuration - self.lastCheck = 0.0 - self.topics = topics - self.complete = False - self.msgID = msgID - # TODO: fill in formats for each topic - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} - self.topicFormats = {'loc': {},} - - executeAction = lambda mem, midcaAction, status: self.send_point() - completionCheck = lambda mem, midcaAction, status: self.check_confirmation() - AsynchAction.__init__(self, mem, midcaAction, executeAction, - completionCheck, True) - - - - def send_topic(self): - - for topic in self.topics: - # Handle - self.msgDict = topicFormats[topic] - - print self.msgDict - - print "trying to send" - print topic - - sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) - if not sent: - if verbose >= 1: - print "Fail" - self.status = FAILED - - def check_confirmation(self): - checkTime = self.lastCheck - self.lastCheck = midcatime.now() - feedback = self.mem.get(self.mem.FEEDBACK) - if not feedback: - return False - for item in reversed(feedback): - #if all items have been checked, either in this check or previous, return - if item['received_at'] - checkTime < 0: - return False - #else see if item is a completion or failure message with id == self.msgID - if item[CMD_ID_KEY] == self.msgID: - if item[FEEDBACK_KEY] == COMPLETE: - return True - elif item[FEEDBACK_KEY] == FAILED: - self.status = FAILED - if verbose >= 1: - print "MIDCA received feedback that action", self, "has failed" - return False - return False - -class pickup(AsynchAction): - - def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, - msgID): - self.objectOrID = objectOrID - self.maxAllowedLag = maxAllowedLag - self.maxDuration = maxDuration - self.lastCheck = 0.0 - self.topics = topics - self.complete = False - self.msgID = msgID - # TODO: fill in formats for each topic - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} - self.topicFormats = {'loc': {},} - - executeAction = lambda mem, midcaAction, status: self.send_point() - completionCheck = lambda mem, midcaAction, status: self.check_confirmation() - AsynchAction.__init__(self, mem, midcaAction, executeAction, - completionCheck, True) - - - - def send_topic(self): - - for topic in self.topics: - # Handle - self.msgDict = topicFormats[topic] - - print self.msgDict - - print "trying to send" - print topic - - sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) - if not sent: - if verbose >= 1: - print "Fail" - self.status = FAILED - - def check_confirmation(self): - checkTime = self.lastCheck - self.lastCheck = midcatime.now() - feedback = self.mem.get(self.mem.FEEDBACK) - if not feedback: - return False - for item in reversed(feedback): - #if all items have been checked, either in this check or previous, return - if item['received_at'] - checkTime < 0: - return False - #else see if item is a completion or failure message with id == self.msgID - if item[CMD_ID_KEY] == self.msgID: - if item[FEEDBACK_KEY] == COMPLETE: - return True - elif item[FEEDBACK_KEY] == FAILED: - self.status = FAILED - if verbose >= 1: - print "MIDCA received feedback that action", self, "has failed" - return False - return False - -class putdown(AsynchAction): - - def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, - msgID): - self.objectOrID = objectOrID - self.maxAllowedLag = maxAllowedLag - self.maxDuration = maxDuration - self.lastCheck = 0.0 - self.topics = topics - self.complete = False - self.msgID = msgID - # TODO: fill in formats for each topic - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} - self.topicFormats = {'loc': {},} - - executeAction = lambda mem, midcaAction, status: self.send_point() - completionCheck = lambda mem, midcaAction, status: self.check_confirmation() - AsynchAction.__init__(self, mem, midcaAction, executeAction, - completionCheck, True) - - - - def send_topic(self): - - for topic in self.topics: - # Handle - self.msgDict = topicFormats[topic] - - print self.msgDict - - print "trying to send" - print topic - - sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) - if not sent: - if verbose >= 1: - print "Fail" - self.status = FAILED - - def check_confirmation(self): - checkTime = self.lastCheck - self.lastCheck = midcatime.now() - feedback = self.mem.get(self.mem.FEEDBACK) - if not feedback: - return False - for item in reversed(feedback): - #if all items have been checked, either in this check or previous, return - if item['received_at'] - checkTime < 0: - return False - #else see if item is a completion or failure message with id == self.msgID - if item[CMD_ID_KEY] == self.msgID: - if item[FEEDBACK_KEY] == COMPLETE: - return True - elif item[FEEDBACK_KEY] == FAILED: - self.status = FAILED - if verbose >= 1: - print "MIDCA received feedback that action", self, "has failed" - return False - return False - -class stack(AsynchAction): - - def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, - msgID): - self.objectOrID = objectOrID - self.maxAllowedLag = maxAllowedLag - self.maxDuration = maxDuration - self.lastCheck = 0.0 - self.topics = topics - self.complete = False - self.msgID = msgID - # TODO: fill in formats for each topic - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} - self.topicFormats = {'raise': {},} - - executeAction = lambda mem, midcaAction, status: self.send_point() - completionCheck = lambda mem, midcaAction, status: self.check_confirmation() - AsynchAction.__init__(self, mem, midcaAction, executeAction, - completionCheck, True) - - - - def send_topic(self): - - for topic in self.topics: - # Handle - self.msgDict = topicFormats[topic] - - print self.msgDict - - print "trying to send" - print topic - - sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) - if not sent: - if verbose >= 1: - print "Fail" - self.status = FAILED - - def check_confirmation(self): - checkTime = self.lastCheck - self.lastCheck = midcatime.now() - feedback = self.mem.get(self.mem.FEEDBACK) - if not feedback: - return False - for item in reversed(feedback): - #if all items have been checked, either in this check or previous, return - if item['received_at'] - checkTime < 0: - return False - #else see if item is a completion or failure message with id == self.msgID - if item[CMD_ID_KEY] == self.msgID: - if item[FEEDBACK_KEY] == COMPLETE: - return True - elif item[FEEDBACK_KEY] == FAILED: - self.status = FAILED - if verbose >= 1: - print "MIDCA received feedback that action", self, "has failed" - return False - return False - - diff --git a/midca/domains/minecraft/minecraft.cfg b/midca/domains/minecraft/minecraft.cfg index 612120f1..2b0406a8 100644 --- a/midca/domains/minecraft/minecraft.cfg +++ b/midca/domains/minecraft/minecraft.cfg @@ -1,3 +1,4 @@ +middleware,mOOSE type,mob,entity type,item,entity type,block,item diff --git a/midca/domains/minecraft/ros/minecraftDetectors.cpp b/midca/domains/minecraft/ros/minecraftDetectors.cpp index edcb7065..507134cf 100644 --- a/midca/domains/minecraft/ros/minecraftDetectors.cpp +++ b/midca/domains/minecraft/ros/minecraftDetectors.cpp @@ -85,9 +85,9 @@ std::string detect_grass() int main(int argc, char** argv) { - ROS_INFO_STREAM("Starting minecraft/ros/minecraft Entity Detectors node"); + ROS_INFO_STREAM("Starting ../domains/minecraft/ros/minecraft Entity Detectors node"); - ros::init(argc, argv, "minecraft/ros/minecraft_entity_detectors"); + ros::init(argc, argv, "../domains/minecraft/ros/minecraft_entity_detectors"); ros::NodeHandle n; ros::Publisher stone_pub = n.advertise("stone_attr", 1); diff --git a/midca/domains/minecraft/ros/minecraftEntitiesHandler.py b/midca/domains/minecraft/ros/minecraftEntitiesHandler.py index af31ebd4..94c38d42 100644 --- a/midca/domains/minecraft/ros/minecraftEntitiesHandler.py +++ b/midca/domains/minecraft/ros/minecraftEntitiesHandler.py @@ -1,6 +1,6 @@ # https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py -class minecraft/ros/minecraftEntitiesHandler(IncomingMsgHandler): +class minecraftEntitiesHandler(IncomingMsgHandler): ''' class that receives Point messages, where each message indicates that the given object @@ -13,7 +13,7 @@ def __init__(self, topic, midcaObject, memKey = None, history = None): callback = lambda strMsg: self.store(strMsg) msgType = String self.left = None - super(minecraft/ros/minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + super(minecraftEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) #self.objID = objID if memKey: self.memKey = memKey diff --git a/midca/domains/minecraft/ros/minecraft_async.py b/midca/domains/minecraft/ros/minecraft_async.py index dc08d933..5fe2a13a 100644 --- a/midca/domains/minecraft/ros/minecraft_async.py +++ b/midca/domains/minecraft/ros/minecraft_async.py @@ -29,11 +29,11 @@ FEEDBACK_KEY = "code" CMD_ID_KEY = "cmd_id" -AIM_TOPIC = "aim_cmd" -FOOD_TOPIC = "food_cmd" -PICKUP_TOPIC = "pickup_cmd" -POTION_TOPIC = "potion_cmd" -SWING_TOPIC = "swing_cmd" +AIM_TOPIC = "aim" +FOOD_TOPIC = "food" +PICKUP_TOPIC = "pickup" +POTION_TOPIC = "potion" +SWING_TOPIC = "swing" #set this to change output for all asynch actions. verbose = 2 @@ -71,52 +71,31 @@ def asynch_plan(mem, midcaPlan): if midcaAction[0] == "block_until_seen": actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) - elif midcaAction[0] == "point_to": - cmdID = rosrun.next_id() - actions.append(DoPoint(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - POINT_TOPIC, cmdID)) - - elif midcaAction[0] == "reach_to_pickup": - cmdID = rosrun.next_id() - actions.append(DoReach(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "reach_to_unstack": - cmdID = rosrun.next_id() - actions.append(DoUnstack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "grab": - cmdID = rosrun.next_id() - actions.append(DoGrab(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - GRAB_TOPIC, cmdID)) - elif midcaAction[0] == "release": - cmdID = rosrun.next_id() - actions.append(DoRelease(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RELEASE_TOPIC, cmdID)) - elif midcaAction[0] == "raising": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "raising_arm": - cmdID = rosrun.next_id() - actions.append(DoRaise(mem, midcaAction, ' ', - allowed_sighting_lag(' '), allowed_sighting_wait(' '), - RAISE_TOPIC, cmdID)) - elif midcaAction[0] == "putdown": - cmdID = rosrun.next_id() - actions.append(DoPut(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - LOC_TOPIC, cmdID)) - elif midcaAction[0] == "stack": - cmdID = rosrun.next_id() - actions.append(DoStack(mem, midcaAction, midcaAction[1], - allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), - RAISE_TOPIC, cmdID)) + elif midcaAction[0] == "drinkPotion": + cmdID = rosrun.next_id() + actions.append(drinkPotion(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['swing', 'potion'], cmdID)) + elif midcaAction[0] == "breakBlock": + cmdID = rosrun.next_id() + actions.append(breakBlock(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['aim', 'swing', 'pickup'], cmdID)) + elif midcaAction[0] == "useBlock": + cmdID = rosrun.next_id() + actions.append(useBlock(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['aim', 'swing'], cmdID)) + elif midcaAction[0] == "eat": + cmdID = rosrun.next_id() + actions.append(eat(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['swing', 'food'], cmdID)) + elif midcaAction[0] == "placeBlock": + cmdID = rosrun.next_id() + actions.append(placeBlock(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['aim', 'swing'], cmdID)) else: if verbose >= 1: print "MIDCA action", midcaAction, "does not correspond to an asynch", @@ -289,7 +268,7 @@ def completion_check(self): return t - lastLocReport[1] <= self.maxAllowedLag -class DodrinkPotion(AsynchAction): +class drinkPotion(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -301,6 +280,7 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} self.topicFormats = {'swing': {},'potion': {},} executeAction = lambda mem, midcaAction, status: self.send_point() @@ -315,7 +295,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -349,7 +328,7 @@ def check_confirmation(self): return False return False -class DobreakBlock(AsynchAction): +class breakBlock(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -361,6 +340,7 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} self.topicFormats = {'aim': {},'swing': {},'pickup': {},} executeAction = lambda mem, midcaAction, status: self.send_point() @@ -375,7 +355,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -409,7 +388,7 @@ def check_confirmation(self): return False return False -class DouseBlock(AsynchAction): +class useBlock(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -421,6 +400,7 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} self.topicFormats = {'aim': {},'swing': {},} executeAction = lambda mem, midcaAction, status: self.send_point() @@ -435,7 +415,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -469,7 +448,7 @@ def check_confirmation(self): return False return False -class Doeat(AsynchAction): +class eat(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -481,6 +460,7 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} self.topicFormats = {'swing': {},'food': {},} executeAction = lambda mem, midcaAction, status: self.send_point() @@ -495,7 +475,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict @@ -529,7 +508,7 @@ def check_confirmation(self): return False return False -class DoplaceBlock(AsynchAction): +class placeBlock(AsynchAction): def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, msgID): @@ -541,7 +520,8 @@ def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, top self.complete = False self.msgID = msgID # TODO: fill in formats for each topic - self.topicFormats = {'aim': {},'swing': {}} + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'aim': {},'swing': {},} executeAction = lambda mem, midcaAction, status: self.send_point() completionCheck = lambda mem, midcaAction, status: self.check_confirmation() @@ -555,7 +535,6 @@ def send_topic(self): for topic in self.topics: # Handle self.msgDict = topicFormats[topic] - # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} print self.msgDict diff --git a/midca/domains/newMine/__init__.py b/midca/domains/newMine/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/midca/domains/newMine/plan/minecraft.pddl b/midca/domains/newMine/plan/minecraft.pddl new file mode 100644 index 00000000..d81a7ac9 --- /dev/null +++ b/midca/domains/newMine/plan/minecraft.pddl @@ -0,0 +1,180 @@ +(define (domain minecraft-beta) + (:requirements :typing :fluents :existential-preconditions) + (:types + resource - thing + mapgrid + player + ) + + (:types + resource - thing + material - thing + tool - thing + craftgrid + mapgrid + direction + player + monster - thing + weapon - thing + food - thing + potion - thing + Helmet - Armor + chestplates - Armor + ) + + (:predicates + (is-trap ?loc - mapgrid) + (looking-for ?res - resource) + (know-where ?res - resource ?loc - mapgrid) + (player-at ?loc - mapgrid) + (in-shelter) + (look-at ?direction - direction) + (monster-at ?zombie - monster ?loc - mapgrid) + (thing-at-map ?obj - resource ?loc - mapgrid) + (thing-at-loc ?obj - resource ?loc - mapgrid) + (known-loc ?obj - resource) + (placed-thing-at-map ?obj - material ?loc - mapgrid) + (resource-at-craft ?res - thing ?loc - craftgrid) + (craft-empty ?loc - craftgrid) + (connect ?from - mapgrid ?to - mapgrid) + (next-to ?from - direction ?to - direction) + (crafting) + (survive) + (eat ?food - food) + (is-attacked) + (is-trapped) + (is-dead ?player -player) + (is-alive ?player -player) + (head-armed) + (chest-armed) + ) + (:hidden is-trap thing-at-loc is-attacked is-trapped) + + (:functions + (self) - player + (thing-available ?obj - thing) - int + (current-harvest-duration) - int + (current-harvest-location) - int + (duration-need ?tool - tool ?res - resource) - int + (location-id ?loc - mapgrid) - int + (tool-id ?tool - tool) - int + (tool-in-hand) - int + (tool-max-health ?tool - tool) - int + (tool-current-health ?tool - tool) - int + (player-current-health) - int + (furnace-fuel) - int + (current-hunger-value) - int + (food-value ?f -food) - int + ) + + + + ;; ---------------------------------------------------- + (:action move + :parameters (?from - mapgrid ?to - mapgrid) + :precondition + (and + (player-at ?from) + (connect ?from ?to) + + ) + :effect + (and + (player-at ?to) + (not (player-at ?from)) + + ) + ) + ;;----------------------------------------------------- + + (:action event-fall-in-trap + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc arrow_trap ?loc) + + (not (is-trapped)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-trapped) + ) + ) + ;;------------------------------------------------------ + + (:action event-skeleton-attacked + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc skeleton ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map arrow ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + (:action event-monster-explosion + :parameters (?loc1 - mapgrid ?loc - mapgrid) + :precondition + ( and + (player-at ?loc1) + (connect ?loc1 ?loc) + (thing-at-loc monster ?loc) + (not (is-attacked)) + (neq (player-current-health) 0) + + ) + :effect + (and + (decrease (player-current-health) 5) + (thing-at-map monster-remains ?loc1) + (is-attacked) + ) + ) + ;;---------------------------------------------- + + (:action event-die + :parameters (?player -player) + :precondition + ( and + (is-alive ?player) + (eq (player-current-health) 0) + ) + :effect + (and + (is-dead ?player) + ) + ) + + ;;--------------------------------------------- + + (:action event-find + :parameters (?res -resource ?loc -mapgrid ?player-loc -mapgrid) + :precondition + (and + (looking-for ?res) + (connected ?loc ?player-loc) + (thing-at-loc ?res ?loc) + ) + :effect + (and + (know-where ?res ?loc) + ) + + + ) + + +) \ No newline at end of file From ec3965d115347635776a2f2602b8d62ce6335b72 Mon Sep 17 00:00:00 2001 From: Anthony Mitchell Date: Sat, 24 Apr 2021 19:47:03 -0400 Subject: [PATCH 23/23] removed testing domains and add ROS subdirectory --- midca/api/Midca_Domain_API.py | 2 - .../coloredBlocksworld/coloredBlocksworld.cfg | 2 +- .../ros/coloredBlocksworldDetectors.cpp | 40 ++ .../ros/coloredBlocksworldEntitiesHandler.py | 32 ++ .../ros/coloredBlocksworld_async.py | 503 ++++++++++++++++++ midca/domains/newMine/__init__.py | 0 midca/domains/newMine/plan/minecraft.pddl | 180 ------- 7 files changed, 576 insertions(+), 183 deletions(-) create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py create mode 100644 midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py delete mode 100644 midca/domains/newMine/__init__.py delete mode 100644 midca/domains/newMine/plan/minecraft.pddl diff --git a/midca/api/Midca_Domain_API.py b/midca/api/Midca_Domain_API.py index 68203f9d..183d6ab9 100644 --- a/midca/api/Midca_Domain_API.py +++ b/midca/api/Midca_Domain_API.py @@ -309,8 +309,6 @@ def modifyAsync(filename): domainPath = domainPath.split('/')[0] +'/'+ domainPath.split('/')[1] +'/'+ domainPath.split('/')[2] # remove .cfg from this path - print(middleware) - if middleware == "UNDEFINED": print("Error: no middleware defined") elif middleware == "ros": diff --git a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg index cfc3f7d2..aa74a97c 100644 --- a/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg +++ b/midca/domains/coloredBlocksworld/coloredBlocksworld.cfg @@ -1,4 +1,4 @@ -middleware,moOSe +middleware,ROS type,block,entity attribute,block,color attribute,block,x diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp new file mode 100644 index 00000000..25dd0927 --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldDetectors.cpp @@ -0,0 +1,40 @@ +/********************************************************************* + * + * + * For example, consider using PointCloudLab + * (https://github.com/COLAB2/baxter_pcl/blob/master/src/detect_objects.cpp) + * + * + *********************************************************************/ + +#include + + +std::string detect_block() +{ + //TODO: create block_attr string with the following attributes: + //['color', 'z', 'y', 'x'] + + return block_attr; +} + + +int main(int argc, char** argv) +{ + ROS_INFO_STREAM("Starting ../domains/coloredBlocksworld/ros/coloredBlocksworld Entity Detectors node"); + + ros::init(argc, argv, "../domains/coloredBlocksworld/ros/coloredBlocksworld_entity_detectors"); + ros::NodeHandle n; + + ros::Publisher block_pub = n.advertise("block_attr", 1); + + while (ros::ok()) + { + block_pub.publish(block_attr); + + ros::spinOnce(); + } + + ros::spin(); + return 0; +} \ No newline at end of file diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py new file mode 100644 index 00000000..b0c3739f --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworldEntitiesHandler.py @@ -0,0 +1,32 @@ +# https://github.com/COLAB2/midca/blob/c3e4cc9fab5683f44435816d90a7a2eb591c4ce4/midca/rosrun.py + +class coloredBlocksworldEntitiesHandler(IncomingMsgHandler): + + ''' + class that receives Point messages, where each message indicates that the given object + has been identified at that location. Args include the topic to listen to, object id, + and midca object to whose memory observations will be stored. Optionally the memory + key to be stored to can also be specified. + ''' + + def __init__(self, topic, midcaObject, memKey = None, history = None): + callback = lambda strMsg: self.store(strMsg) + msgType = String + self.left = None + super(coloredBlocksworldEntitiesHandler, self).__init__(topic, msgType, callback, midcaObject) + #self.objID = objID + if memKey: + self.memKey = memKey + else: + self.memKey = self.mem.ROS_OBJS_DETECTED + if history: + self.history = history + else: + self.history = self.mem.STATE_HISTORY + + def store(self, data): + if not self.mem: + rospy.logerr("Trying to store data to a nonexistent MIDCA object.") + + #TODO: Code should handle detecting the following relations (predicates): + #block: ['on', 'clear'] diff --git a/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py new file mode 100644 index 00000000..daf9612f --- /dev/null +++ b/midca/domains/coloredBlocksworld/ros/coloredBlocksworld_async.py @@ -0,0 +1,503 @@ +from midca import rosrun, plans +from midca import midcatime +import traceback +from midca.examples.homography import * +import math +import copy +import numpy as np + + +try: + from geometry_msgs.msg import PointStamped + from geometry_msgs.msg import Point + from midca.examples import ObjectDetector + from std_msgs.msg import String + from scipy.spatial import distance +except: + pass #if ROS is not installed, an error message will already have been generated. + + +END_COLOR_CODE = '\033[0m' +NOT_STARTED = 0 +NS_COLOR_CODE = END_COLOR_CODE +IN_PROGRESS = 1 +IP_COLOR_CODE = '\033[92m' +COMPLETE = 2 +C_COLOR_CODE = '\033[94m' +FAILED = 3 +F_COLOR_CODE = '\033[91m' +FEEDBACK_KEY = "code" +CMD_ID_KEY = "cmd_id" + +LOC_TOPIC = "loc" +RAISE_TOPIC = "raise" + +#set this to change output for all asynch actions. +verbose = 2 + +MAX_SIGHTING_LAG = 3.0 +MAX_SIGHTING_WAIT = 5.0 + +def allowed_sighting_lag(objectID): + ''' + returns how long ago an object can have been seen before MIDCA stops considering its + location known + ''' + return MAX_SIGHTING_LAG + +def allowed_sighting_wait(objectID): + ''' + returns the amount of midcatime MIDCA should wait to see an object before giving up. + ''' + return MAX_SIGHTING_WAIT + +''' +''' + +def get_asynch_action(midcaAction): + raise ArgumentException("midca action " + str(midcaAction) + " does not translate to a \ + valid asynchronous action.") + +def asynch_plan(mem, midcaPlan): + ''' + returns an asynchronous plan that corresponds to the given MIDCA plan. + ''' + actions = [] + goals = midcaPlan.goals + for midcaAction in midcaPlan.actions: + if midcaAction[0] == "block_until_seen": + actions.append(AwaitCurrentLocation(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]))) + elif midcaAction[0] == "unstack": + cmdID = rosrun.next_id() + actions.append(unstack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc'], cmdID)) + elif midcaAction[0] == "pickup": + cmdID = rosrun.next_id() + actions.append(pickup(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc'], cmdID)) + elif midcaAction[0] == "putdown": + cmdID = rosrun.next_id() + actions.append(putdown(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['loc'], cmdID)) + elif midcaAction[0] == "stack": + cmdID = rosrun.next_id() + actions.append(stack(mem, midcaAction, midcaAction[1], + allowed_sighting_lag(midcaAction[1]), allowed_sighting_wait(midcaAction[1]), + ['raise'], cmdID)) + else: + if verbose >= 1: + print "MIDCA action", midcaAction, "does not correspond to an asynch", + "action. MIDCA will skip this action" + return AsynchPlan(actions, goals) + + +class AsynchPlan(plans.Plan): + + ''' + subclass of MIDCA Plan class that uses asynchronous actions. + ''' + + def finished(self): + ''' + overrides plan.finished(). Declares a plan complete if all its actions report + complete or failed. + ''' + for action in self.actions: + if action.status != COMPLETE and action.status != FAILED: + return False + return True + + @property + def status(self): + ''' + property that returns the plan's status. This can be NOT_STARTED, IN_PROGRESS, + FAILED, or COMPLETE. If any action fails, the plan is considered to have failed. + The plan is complete when all actions are complete. + ''' + status = COMPLETE + for action in self.actions: + if action.status == FAILED: + return FAILED + elif action.status == NOT_STARTED and status == COMPLETE: + status = NOT_STARTED + elif action.status == IN_PROGRESS: + status = IN_PROGRESS + return status + + def __str__(self): + s = "" + for action in self.actions: + if action.status == NOT_STARTED: + s += NS_COLOR_CODE + elif action.status == IN_PROGRESS: + s += IP_COLOR_CODE + elif action.status == FAILED: + s += F_COLOR_CODE + elif action.status == COMPLETE: + s += C_COLOR_CODE + + s += str(action) + " " + return s[:-1] + END_COLOR_CODE + +class AsynchAction: + + nextID = 0 + + def __init__(self, mem, midcaAction, executeFunc, isComplete, blocks): + self.status = NOT_STARTED + self.mem = mem + self.midcaAction = midcaAction + self.executeFunc = executeFunc + self.isComplete = isComplete + self.blocks = blocks + self.startTime = None + self.id = AsynchAction.nextID + AsynchAction.nextID += 1 + + def execute(self): + if not self.startTime: + self.startTime = midcatime.now() + self.status = IN_PROGRESS + if not self.executeFunc: + return + try: + self.executeFunc(self.mem, self.midcaAction, self.status) + except: + if verbose >= 2: + print "Error executing action", self, ":\n", traceback.format_exc(), + "\n\nAction assumed to be failed" + self.status = FAILED + + def check_complete(self): + if not self.startTime: + self.startTime = midcatime.now() + if not self.check_complete: + return + try: + complete = self.isComplete(self.mem, self.midcaAction, self.status) + if verbose >= 2 and not complete: + print "Action", self, "not complete." + if verbose >= 1 and complete: + print "Action", self, "complete." + if complete: + self.status = COMPLETE + return complete + except: + if verbose >= 1: + print "Error checking completion status for action", self, " - Assuming \ + failure:\n", traceback.format_exc() + self.status = FAILED + + def ros_msg(self, topic, d): + ''' + arg d should be a dictionary that contains the key/value pairs to be sent. + ''' + sent = rosrun.send_msg(topic, rosrun.dict_as_msg) + if not sent: + if verbose >= 1: + print "Unable to send msg; ", d, "on topic", topic, " Action", self, + "assumed failed." + self.status = FAILED + + def __str__(self): + return str(self.midcaAction) + +def get_last_position(mem, objectOrID): + state = mem.get(mem.STATE) + positions = state.all_pos(objectOrID) + if not positions: + return None + else: + for state_pos in reversed(positions): + if state_pos.position: + return (state_pos.position) + return None + +def get_last_location(mem, objectOrID): + world = mem.get(mem.STATE) + sightings = world.all_sightings(objectOrID) + if not sightings: + return None + else: + for detectionEvent in reversed(sightings): + if detectionEvent.loc: + return (detectionEvent.loc, detectionEvent.time) + return None + + + + +class AwaitCurrentLocation(AsynchAction): + + ''' + Action that blocks until there is a current (within last maxAllowedLag seconds) + observation of the object's location. + ''' + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + executeAction = None + completionCheck = lambda mem, midcaAction, status: self.completion_check() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + def completion_check(self): + t = midcatime.now() + if t - self.startTime > self.maxDuration: + if verbose >= 1: + print "max midcatime exceeded for action:", self, "- changing status to failed." + self.status = FAILED + return False + lastLocReport = get_last_location(self.mem, self.objectOrID) + if not lastLocReport: + return False + return t - lastLocReport[1] <= self.maxAllowedLag + + +class unstack(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class pickup(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class putdown(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'loc': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + +class stack(AsynchAction): + + def __init__(self, mem, midcaAction, objectOrID, maxAllowedLag, maxDuration, topics, + msgID): + self.objectOrID = objectOrID + self.maxAllowedLag = maxAllowedLag + self.maxDuration = maxDuration + self.lastCheck = 0.0 + self.topics = topics + self.complete = False + self.msgID = msgID + # TODO: fill in formats for each topic + # Reference {'x': x, 'y': y, 'z': z, 'time': self.startTime, 'cmd_id': self.msgID} + self.topicFormats = {'raise': {},} + + executeAction = lambda mem, midcaAction, status: self.send_point() + completionCheck = lambda mem, midcaAction, status: self.check_confirmation() + AsynchAction.__init__(self, mem, midcaAction, executeAction, + completionCheck, True) + + + + def send_topic(self): + + for topic in self.topics: + # Handle + self.msgDict = topicFormats[topic] + + print self.msgDict + + print "trying to send" + print topic + + sent = rosrun.send_msg(topic, rosrun.dict_as_msg(self.msgDict)) + if not sent: + if verbose >= 1: + print "Fail" + self.status = FAILED + + def check_confirmation(self): + checkTime = self.lastCheck + self.lastCheck = midcatime.now() + feedback = self.mem.get(self.mem.FEEDBACK) + if not feedback: + return False + for item in reversed(feedback): + #if all items have been checked, either in this check or previous, return + if item['received_at'] - checkTime < 0: + return False + #else see if item is a completion or failure message with id == self.msgID + if item[CMD_ID_KEY] == self.msgID: + if item[FEEDBACK_KEY] == COMPLETE: + return True + elif item[FEEDBACK_KEY] == FAILED: + self.status = FAILED + if verbose >= 1: + print "MIDCA received feedback that action", self, "has failed" + return False + return False + + diff --git a/midca/domains/newMine/__init__.py b/midca/domains/newMine/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/midca/domains/newMine/plan/minecraft.pddl b/midca/domains/newMine/plan/minecraft.pddl deleted file mode 100644 index d81a7ac9..00000000 --- a/midca/domains/newMine/plan/minecraft.pddl +++ /dev/null @@ -1,180 +0,0 @@ -(define (domain minecraft-beta) - (:requirements :typing :fluents :existential-preconditions) - (:types - resource - thing - mapgrid - player - ) - - (:types - resource - thing - material - thing - tool - thing - craftgrid - mapgrid - direction - player - monster - thing - weapon - thing - food - thing - potion - thing - Helmet - Armor - chestplates - Armor - ) - - (:predicates - (is-trap ?loc - mapgrid) - (looking-for ?res - resource) - (know-where ?res - resource ?loc - mapgrid) - (player-at ?loc - mapgrid) - (in-shelter) - (look-at ?direction - direction) - (monster-at ?zombie - monster ?loc - mapgrid) - (thing-at-map ?obj - resource ?loc - mapgrid) - (thing-at-loc ?obj - resource ?loc - mapgrid) - (known-loc ?obj - resource) - (placed-thing-at-map ?obj - material ?loc - mapgrid) - (resource-at-craft ?res - thing ?loc - craftgrid) - (craft-empty ?loc - craftgrid) - (connect ?from - mapgrid ?to - mapgrid) - (next-to ?from - direction ?to - direction) - (crafting) - (survive) - (eat ?food - food) - (is-attacked) - (is-trapped) - (is-dead ?player -player) - (is-alive ?player -player) - (head-armed) - (chest-armed) - ) - (:hidden is-trap thing-at-loc is-attacked is-trapped) - - (:functions - (self) - player - (thing-available ?obj - thing) - int - (current-harvest-duration) - int - (current-harvest-location) - int - (duration-need ?tool - tool ?res - resource) - int - (location-id ?loc - mapgrid) - int - (tool-id ?tool - tool) - int - (tool-in-hand) - int - (tool-max-health ?tool - tool) - int - (tool-current-health ?tool - tool) - int - (player-current-health) - int - (furnace-fuel) - int - (current-hunger-value) - int - (food-value ?f -food) - int - ) - - - - ;; ---------------------------------------------------- - (:action move - :parameters (?from - mapgrid ?to - mapgrid) - :precondition - (and - (player-at ?from) - (connect ?from ?to) - - ) - :effect - (and - (player-at ?to) - (not (player-at ?from)) - - ) - ) - ;;----------------------------------------------------- - - (:action event-fall-in-trap - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc arrow_trap ?loc) - - (not (is-trapped)) - (neq (player-current-health) 0) - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map arrow ?loc1) - (is-trapped) - ) - ) - ;;------------------------------------------------------ - - (:action event-skeleton-attacked - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc skeleton ?loc) - (not (is-attacked)) - (neq (player-current-health) 0) - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map arrow ?loc1) - (is-attacked) - ) - ) - ;;---------------------------------------------- - (:action event-monster-explosion - :parameters (?loc1 - mapgrid ?loc - mapgrid) - :precondition - ( and - (player-at ?loc1) - (connect ?loc1 ?loc) - (thing-at-loc monster ?loc) - (not (is-attacked)) - (neq (player-current-health) 0) - - ) - :effect - (and - (decrease (player-current-health) 5) - (thing-at-map monster-remains ?loc1) - (is-attacked) - ) - ) - ;;---------------------------------------------- - - (:action event-die - :parameters (?player -player) - :precondition - ( and - (is-alive ?player) - (eq (player-current-health) 0) - ) - :effect - (and - (is-dead ?player) - ) - ) - - ;;--------------------------------------------- - - (:action event-find - :parameters (?res -resource ?loc -mapgrid ?player-loc -mapgrid) - :precondition - (and - (looking-for ?res) - (connected ?loc ?player-loc) - (thing-at-loc ?res ?loc) - ) - :effect - (and - (know-where ?res ?loc) - ) - - - ) - - -) \ No newline at end of file