Beginner Question: Europa quits after an initial condition is processed

54 views
Skip to first unread message

Christian Dreher

unread,
Jan 13, 2016, 12:18:33 PM1/13/16
to europa-users
Hello.

I am new to EUROPA and I wanted to model the following: 

I have a robot arm (class: Arm) and a workspace (class: Workspace).
On the workspace, I have 3 objects: First, an object slide container (class: ObjectSlideContainer) and two boxes with a lid (LidBox)

The workflow should be the following. First, the arm should fill the object slide container with object slides (this is not modeled explecitely, its basically just a "fill" method)
After that, the first lidbox should be opened. Then the object slides in the object slide container should be prepared by dipping the container into the first lidbox (there is a fluid in it)
Then, the second lidbox should be opened and the object slide container should be dipped into it.
After that, I want the arm to clean up: close the lidbox, and empty the object slide container.
For this, I developed the following code:

Model NDDL file:

class ObjectSlideContainer extends Timeline
{
predicate full {} // The full and empty predicates show if the object slide container holds object slides or not
predicate empty {}
predicate preparation1pending {} // "preparation 1" is the first process of dipping the object slide container into the first lidbox
predicate preparation1done {} // This shows that "preparation 1" was done
predicate preparation2pending {} // "preparation 2" is basically the same as "preparation 1", but the object slide container should be dipped into the second lidbox
predicate preparation2done {} // This shows that "preparation 2" was done
}

class LidBox extends Timeline
{
predicate opened {} // Predicates to indicate whether a lidbox is opened or closed
predicate closed {}
}

class Workspace extends Timeline
{
LidBox _lidbox_1;
LidBox _lidbox_2;
ObjectSlideContainer _osc;

Workspace(LidBox lidbox_1, LidBox lidbox_2, ObjectSlideContainer osc)
{
_lidbox_1 = lidbox_1;
_lidbox_2 = lidbox_2;
_osc = osc;
}
}

class Arm extends Timeline
{
predicate pending {} // This indicates, that the goal was not achieved yet
predicate done {} // This indicates, that the goal was achieved

Workspace _workspace;

Arm(Workspace workspace)
{
_workspace = workspace;
}

action goalAchieved { duration=1; }
action fill_osc { duration=1; }
action empty_osc { duration=1; }
action prepare_oss_1 { duration=1; }
action prepare_oss_2 { duration=1; }
action open_lidbox_1 { duration=1; }
action close_lidbox_1 { duration=1; }
action open_lidbox_2 { duration=1; }
action close_lidbox_2 { duration=1; }
}

Arm::goalAchieved
{
// This is what needs to be done to achieve the goal: preparation 1 and preparation 2 needs to be done, both lidboxes need to be closed and the object slide container should be empty

met_by (condition object.pending);
contained_by (condition object._workspace._osc.preparation1done);
contained_by (condition object._workspace._osc.preparation2done);
contained_by (condition object._workspace._lidbox_1.closed);
contained_by (condition object._workspace._lidbox_2.closed);
contained_by (condition object._workspace._osc.empty);
meets (effect object.done);
}

Arm::fill_osc
{
// This fills the object slide container

met_by (condition object._workspace._osc.empty);
meets (effect object._workspace._osc.full);
}

Arm::empty_osc
{
// This empties the object slide container

met_by (condition object._workspace._osc.full);
meets (effect object._workspace._osc.empty);
}

Arm::prepare_oss_1
{
// This is the process of "preparation 1"

met_by (condition object._workspace._osc.preparation1pending);
contained_by (condition object._workspace._lidbox_1.opened);
contained_by (condition object._workspace._osc.full);
meets (effect object._workspace._osc.preparation1done);
}

Arm::prepare_oss_2
{
// This is the process of "preparation 2"

met_by (condition object._workspace._osc.preparation2pending);
contained_by (condition object._workspace._osc.preparation1done);
contained_by (condition object._workspace._lidbox_2.opened);
contained_by (condition object._workspace._osc.full);
meets (effect object._workspace._osc.preparation2done);
}

Arm::open_lidbox_1
{
// Open lidbox 1

met_by (condition object._workspace._lidbox_1.closed);
meets (effect object._workspace._lidbox_1.opened);
}

Arm::close_lidbox_1
{
// Close lidbox 1

met_by (condition object._workspace._lidbox_1.opened);
meets (effect object._workspace._lidbox_1.closed);
}

Arm::open_lidbox_2
{
// Open lidbox 2

met_by (condition object._workspace._lidbox_2.closed);
meets (effect object._workspace._lidbox_2.opened);
}

Arm::close_lidbox_2
{
// Close lidbox 2

met_by (condition object._workspace._lidbox_2.opened);
meets (effect object._workspace._lidbox_2.closed);
}


Initial state NDDL file:

#include "SymbolicPlanning-model.nddl"

LidBox lidbox_1 = new LidBox();
LidBox lidbox_2 = new LidBox();

ObjectSlideContainer osc = new ObjectSlideContainer();

Workspace workspace = new Workspace(lidbox_1, lidbox_2, osc);

Arm arm = new Arm(workspace);

close();

fact(lidbox_1.closed initCon1); // Initial condition for "lidbox 1 is closed"
eq(initCon1.start, 0);

fact(lidbox_2.closed initCon2); // Initial condition for "lidbox 2 is closed"
eq(initCon2.start, 0);

fact(osc.empty initCon3); // Initial condition for "object slide container is empty"
eq(initCon3.start, 0);

fact(osc.preparation1pending initCon4); // Initial condition for "preparation 1 process is still pending"
eq(initCon4.start, 0);

fact(osc.preparation2pending initCon5); // Initial condition for "preparation 2 process is still pending"
eq(initCon5.start, 0);

fact(arm.pending initCon6); // Initial condition for "the overall goal was not achieved"
eq(initCon6.start, 0);

goal(arm.done goal1);
lt(0, goal1.start);
lt(goal1.start, 10000);



Whenever I try to run EUROPA, it just quits after processing the 4th initial condition. On the picture you can also see that the open decisions count just drops to 0 after the 7th step.



I would highly appreciate every hint to solve this problem. If something is unclear, excuse me and give me the chance to explain it once more.

Since I am new to EUROPA, I think that the mistake is quite trivial, but anyway, I just can't get it to work.


Thanks in advance for any help

Christian Dreher

Christian Dreher

unread,
Jan 13, 2016, 3:43:47 PM1/13/16
to europa-users
I got a tip that all predicates in a class extending Timeline are mutual exclusive. That was my error in first place. But unfortunately, it is still not finding any plan. Here is my updated code:

Initial state NDDL file:

Changes:

-Updated goals such that the ones with lower numbers precede the ones with higher values (goal1 before goal2 etc...)
-p1 and p2 are Process classes which only hold the predicates for one process (pending, processing, done)
-oscs is the state of the ObjectSlideContainer (full, filling, empty, emptying)

#include "SymbolicPlanning-model.nddl"

LidBox lidbox_1 = new LidBox();
LidBox lidbox_2 = new LidBox();
PreparationProcess p1 = new PreparationProcess();
PreparationProcess p2 = new PreparationProcess();
ObjectSlideContainerState oscs = new ObjectSlideContainerState();
ObjectSlideContainer osc = new ObjectSlideContainer(oscs, p1, p2);
Workspace workspace = new Workspace(lidbox_1, lidbox_2, osc);
Arm arm = new Arm(workspace);

close();

fact(lidbox_1.closed initCon1);
eq(initCon1.start, 0);

fact(lidbox_2.closed initCon2);
eq(initCon2.start, 0);

fact(oscs.empty initCon3);
eq(initCon3.start, 0);

fact(p1.pending initCon4);
eq(initCon4.start, 0);

fact(p2.pending initCon5);
eq(initCon5.start, 0);

goal(p1.done goal1);
lt(0, goal1.start);
lt(goal1.end, 10000);

goal(p2.done goal2);
lt(goal1.end, goal2.start);
lt(goal2.end, 10000);

goal(lidbox_1.closed goal3);
lt(goal2.end, goal3.start);
lt(goal3.start, 10000);

goal(lidbox_2.closed goal4);
lt(goal3.end, goal4.start);
lt(goal4.end, 10000);

goal(oscs.empty goal5);
lt(goal4.end, goal5.start);
lt(goal5.end, 10000);


Here is the model NDDL file:

Changes:

-Outsourced predicates of each process into dedicated class
-Removed "extends Timeline" where it is not neccessary

class ObjectSlideContainerState extends Timeline
{
predicate full {}
predicate filling {}
predicate empty {}
predicate emptying {}
}

class PreparationProcess extends Timeline
{
predicate pending {}
predicate processing {}
predicate done {}
}

class ObjectSlideContainer
{
ObjectSlideContainerState _oscs;
PreparationProcess _p1;
PreparationProcess _p2;
ObjectSlideContainer(ObjectSlideContainerState oscs, PreparationProcess p1, PreparationProcess p2)
{
_oscs = oscs;
_p1 = p1;
_p2 = p2;
}
}

class LidBox extends Timeline
{
predicate opened {}
predicate opening {}
predicate closed {}
predicate closing {}
}

class Workspace
{
LidBox _lidbox_1;
LidBox _lidbox_2;
ObjectSlideContainer _osc;

Workspace(LidBox lidbox_1, LidBox lidbox_2, ObjectSlideContainer osc)
{
_lidbox_1 = lidbox_1;
_lidbox_2 = lidbox_2;
_osc = osc;
}
}

class Arm
{
Workspace _workspace;

Arm(Workspace workspace)
{
_workspace = workspace;
}

action fill_osc { duration=5; }
action empty_osc { duration=5; }
action prepare_oss_1 { duration=3; }
action prepare_oss_2 { duration=3; }
action open_lidbox_1 { duration=1; }
action close_lidbox_1 { duration=1; }
action open_lidbox_2 { duration=1; }
action close_lidbox_2 { duration=1; }
}

Arm::fill_osc
{
met_by (condition object._workspace._osc._oscs.empty);
equals (effect object._workspace._osc._oscs.filling);
meets (effect object._workspace._osc._oscs.full);
}

Arm::empty_osc
{
met_by (condition object._workspace._osc._oscs.full);
equals (effect object._workspace._osc._oscs.emptying);
meets (effect object._workspace._osc._oscs.empty);
}

Arm::prepare_oss_1
{
met_by (condition object._workspace._osc._p1.pending);
contained_by (condition object._workspace._osc._p2.pending);
contained_by (condition object._workspace._lidbox_1.opened);
contained_by (condition object._workspace._osc._oscs.full);
equals (effect object._workspace._osc._p1.processing);
meets (effect object._workspace._osc._p1.done);
}

Arm::prepare_oss_2
{
met_by (condition object._workspace._osc._p2.pending);
contained_by (condition object._workspace._osc._p1.done);
contained_by (condition object._workspace._lidbox_2.opened);
contained_by (condition object._workspace._osc._oscs.full);
equals (effect object._workspace._osc._p2.processing);
meets (effect object._workspace._osc._p2.done);
}

Arm::open_lidbox_1
{
met_by (condition object._workspace._lidbox_1.closed);
equals (effect object._workspace._lidbox_1.opening);
meets (effect object._workspace._lidbox_1.opened);
}

Arm::close_lidbox_1
{
met_by (condition object._workspace._lidbox_1.opened);
equals (effect object._workspace._lidbox_1.closing);
meets (effect object._workspace._lidbox_1.closed);
}

Arm::open_lidbox_2
{
met_by (condition object._workspace._lidbox_2.closed);
equals (effect object._workspace._lidbox_2.opening);
meets (effect object._workspace._lidbox_2.opened);
}

Arm::close_lidbox_2
{
met_by (condition object._workspace._lidbox_2.opened);
equals (effect object._workspace._lidbox_2.closing);
meets (effect object._workspace._lidbox_2.closed);
}


Here is a screenshot of my results with this code:


Like you can see, it doesn't find a plan. Only the initial states are populated into the table of actions.
While playing with a (trivial) working example, I also discovered, that in the "Solver Open Decisions" window, not only the initial states are listed, but also the goals. The planner then crawls through the tokens (facts and goals).
With my code, only the facts are populated into the table. The goals are missing completely. I just can't find out what I am doing wrong.

I appreciate any help, as I was unable to solve this simple planning task since a week of work :/

Greetings, 
Chris

Frédéric Py

unread,
Jan 13, 2016, 4:16:34 PM1/13/16
to Christian Dreher, europa-users

 

Based on what I see on the graph on open-decisions it seems you have only 5 open decisions at the start of the search (as many as you have fact) when you should have 10 (as many as facts+goals).

 

This  along with fact that the solver instantiate the facts properly suggest that your solver configuration is such that the solver is set to filter out your goals. Re3ason can be multiple for this:

-          Maybe you have filter on your flaw handlers that exclude any goal with no  handler that include them

-          Maybe you have an horizon filter (as I recall “partially contained” filter can be tricky to use) that is such that all your goals with the temporal scope (start=[1,9999], end=[2, 10000]) are excluded as they are not necessarily within your plan scope (just a guess though, it’s been a while since I used Europa default filters)

In short your issue seems to be  in the solver.cfg file  and having this would help identify what is the issue here but it really seem that you have a filtering issue on the flaw handlers for your solver (as again the number of open condition in your problem instance should be the number of facts and goals)

 

Regards

-

Frederic Py

Like you can see, it doesn't find a plan. Only the initial states are populated into the table of actions.

I would highly appreciate every hint to solve this problem. If something is unclear, excuse me and give me the chance to explain it once more.

Since I am new to EUROPA, I think that the mistake is quite trivial, but anyway, I just can't get it to work.

 

Thanks in advance for any help

Christian Dreher

--
You received this message because you are subscribed to the Google Groups "europa-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to europa-users...@googlegroups.com.
To post to this group, send email to europa...@googlegroups.com.
Visit this group at https://groups.google.com/group/europa-users.
For more options, visit https://groups.google.com/d/optout.

 

Iatauro, Michael J. (ARC-TI)[QTS, INC]

unread,
Jan 13, 2016, 5:33:25 PM1/13/16
to europa...@googlegroups.com
Pre-note: I see you've sent a second e-mail.  I'm still going to send this one because there might be something useful in it, then read your newer post. 

Christian,

Thank you for your interest in Europa and my apologies for taking so long to get your message out to the group; I had some difficulties with Google's moderation permissions.

What I think I'm seeing in the screenshot you attached is the number of open decisions jumping to six (the middle graph) and the number of decisions in the plan (possibly a better term for that would be the "search depth") dropping from seven to zero.  It looks to me like, at step 7, the Solver is unable to find a valid next choice of any sort, and ends up backing off the entire plan.

I'm still looking at your model and haven't yet had a chance to run it, but a couple of unsatisfiable constraints jump out at me as possible causes.  In Arm::goalAchieved, there are the following three compatibilities:


contained_by (condition object._workspace._osc.preparation1done);
contained_by (condition object._workspace._osc.preparation2done);
contained_by (condition object._workspace._osc.empty);
 
The contained_by relation requires that each of these three predicates overlaps the interval spanned by goalAchieved--they must start before and end after goalAchieved.  However, ObjectSlideContainer is a Timeline, which requires that no two predicates overlap in time. 

The initial state also contains three predicates that have to overlap:


fact(osc.empty initCon3); // Initial condition for "object slide container is empty"
eq(initCon3.start, 0);

fact(osc.preparation1pending initCon4); // Initial condition for "preparation 1 process is still pending"
eq(initCon4.start, 0);

fact(osc.preparation2pending initCon5); // Initial condition for "preparation 2 process is still pending"
eq(initCon5.start, 0);

I think (again, I haven't had a chance to run it) that the temporal network doesn't immediately tell you this initial state is infeasible because facts can be merged, so it takes the Solver a bit to figure it out.

Hopefully more helpful info in my next response!

~MJI

-----------------------------------------
Michael J Iatauro
Software Engineer, IRIS Flight Controller
QTS, Inc.

NASA Ames Research Center
Office: 650-604-0662
Mail stop: 269-2
P.O. Box 1
Moffett Field, CA 94035-0001



January 12, 2016 at 3:25 AM
--
You received this message because you are subscribed to the Google Groups "europa-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to europa-users...@googlegroups.com.
To post to this group, send email to europa...@googlegroups.com.
Visit this group at https://groups.google.com/group/europa-users.
For more options, visit https://groups.google.com/d/optout.

--


Christian Dreher

unread,
Jan 14, 2016, 6:27:40 AM1/14/16
to europa-users, cdreh...@gmail.com
Hello Frédéric and thank you for your help.

This makes sense, yes, but I have no problems when I use the very same setup to run more trivial examples with facts and goals. They are not so much like in the example I am having problems with, but still, nothing is filtered out. 
I have changed nothing from the default EUROPA project, so everything is standard except for the method which shows the actions after the planner is finished (showPlan(); in the beanshell, like in the Light example).
Unfortunately, I was unable to find a file called solver.cfg. In fact, the only two .cfg files in my project are NDDL.cfg and Debug.cfg, like you can see in this screenshot of my eclipse project showing the project tree.


I don't know if the file is in some other location, or was replaced by some code. If so, let me know and I will post everything you need.

Again, thank you so much for your help. I keep reading the docs in parallel, and keep trying stuff. If I find a solution, I will let you know.
...

Christian Dreher

unread,
Jan 14, 2016, 6:39:52 AM1/14/16
to europa-users, michael....@nasa.gov
Hello Michael, and thank you for your help, too.

You don't have to apologize in any way, as I am very grateful that you guys offer help :)

Frédéric already mentioned the problem with the Timeline, and I fixed this in my second post. Although I was not aware of the "contained_by" effect you mentioned. Thank you for pointing that out. I tried to fix the issue you mentioned by replacing all "contained_by" conditions with "before" conditions. According to the docs, this seems to be a less strict rule. Although, nothing changes. It's the exact same result as if I have used "contained_by".

Thank you for clearing up some basics of EUROPA that I obviously have misunderstood and thank you for taking your time and reading my second post, answering to that one, too.
I just wanred to post this in advance, so you know that the "contained_by" issue did not solve the problem of EUROPA being unable to find a plan, although it would not have worked anyway with this problem I guess.

Greetings,
Chris

Christian Dreher

unread,
Jan 14, 2016, 6:48:15 AM1/14/16
to europa-users, michael....@nasa.gov
Oh, I just figured out that with my code from my second post, the contained_by wouldn't harm in any way, since the Timelines are separated into dedicated classes. At least if I now correctly understood how Timelines work. Correct me if I am wrong.
Sorry for posting again, but I didn't came up with this when I was writing my answer to you.

Christian Dreher

unread,
Jan 16, 2016, 7:58:17 AM1/16/16
to europa-users
Hello all,

I now managed to solve the problem, though the solution is very weird. The problem was in the definition of my goals. Before, it looked like this:

goal(p1.done goal1);
lt(0, goal1.start);
lt(goal1.end, 10000);

goal(p2.done goal2);
lt(goal1.end, goal2.start);
lt(goal2.end, 10000);

goal(lidbox_1.closed goal3);
lt(goal2.end, goal3.start);
lt(goal3.start, 10000);

goal(lidbox_2.closed goal4);
lt(goal3.end, goal4.start);
lt(goal4.end, 10000);

goal(oscs.empty goal5);
lt(goal4.end, goal5.start);
lt(goal5.end, 10000);

Like I already told you, I was desperately playing around with values for days. Well, one change a few hours ago made EUROPA find a solution for the problem. This is the new goals definition:

goal(p1.done goal1);
lt(0, goal1.start);
lt(goal1.end, 100);

goal(p2.done goal2);
lt(goal1.end, goal2.start);
lt(goal2.end, 200);

goal(lidbox_1.closed goal3);
lt(goal2.end, goal3.start);
lt(goal3.start, 300);

goal(lidbox_2.closed goal4);
lt(goal3.end, goal4.start);
lt(goal4.end, 400);

goal(oscs.empty goal5);
lt(goal4.end, goal5.start);
lt(goal5.end, 500);

I just changed the end-values down to a smaller number, increasing by 100 for each goal.
I have no idea why it works now, since "finish this goal in 10000 steps" implies "finish this goal in 100 steps". Maybe it is some overflow? If so, I didn't got any exception or anything like this in the console while running EUROPA.

However, I wanted to thank you, Frédéric and Michael, once more for helping me sorting out one issue after the other.

Best regards,
Chris

Christian Dreher

unread,
Jan 16, 2016, 7:59:57 AM1/16/16
to europa-users
Oh, sorry, I meant: "finish this goal in 100 steps" implies "finish this goal in 10000 steps"

Iatauro, Michael J. (ARC-TI)[QTS, INC]

unread,
Jan 25, 2016, 12:52:24 PM1/25/16
to europa...@googlegroups.com
Christian,

I'm glad you solved your problem!  I apologize for not being more of a help.  I'm a little surprised that shortening the time horizon solved the final issue, but I suppose that's probably due to some Solver policy that was causing it to continue to try to fill in the 10000-long timeline.

~MJI

January 16, 2016 at 4:58 AM
--
You received this message because you are subscribed to the Google Groups "europa-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to europa-users...@googlegroups.com.
To post to this group, send email to europa...@googlegroups.com.
Visit this group at https://groups.google.com/group/europa-users.
For more options, visit https://groups.google.com/d/optout.
January 12, 2016 at 3:25 AM
--
You received this message because you are subscribed to the Google Groups "europa-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to europa-users...@googlegroups.com.
To post to this group, send email to europa...@googlegroups.com.
Visit this group at https://groups.google.com/group/europa-users.
For more options, visit https://groups.google.com/d/optout.

--
Reply all
Reply to author
Forward
0 new messages