-
Notifications
You must be signed in to change notification settings - Fork 32
/
CallElevator.cpp
145 lines (117 loc) · 4.62 KB
/
CallElevator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "CallElevator.h"
#include <boost/foreach.hpp>
#include "ActionFactory.h"
#include "plan_execution/StaticFacts.h"
#include "plan_execution/CurrentStateQuery.h"
#include "plan_execution/UpdateFluents.h"
#include "ros/console.h"
#include "ros/ros.h"
namespace bwi_krexec {
CallElevator::CallElevator() :
done(false),
asked(false),
failed(false) {}
struct IsFluentFacing {
bool operator() (const plan_execution::AspFluent& fluent) {
return fluent.name == "facing";
}
};
void CallElevator::run() {
if(!asked && !done) {
std::string direction_text = (going_up) ? "up" : "down";
// Get the doors for this elevator.
std::vector<std::string> doors;
std::list<actasp::AspAtom> static_facts = plan_exec::StaticFacts::staticFacts();
BOOST_FOREACH(const actasp::AspAtom fact, static_facts) {
if (fact.getName() == "elevhasdoor") {
std::vector<std::string> params = fact.getParameters();
if (params[0] == elevator) {
doors.push_back(params[1]);
}
}
}
if (doors.size() == 0) {
ROS_ERROR_STREAM("Unable to retrieve doors for elevator " << elevator << ". Cannot complete action!");
done = true;
failed = true;
} else {
// Figure out which of the doors we're facing.
ros::NodeHandle n;
ros::ServiceClient krClient = n.serviceClient<plan_execution::CurrentStateQuery> ( "current_state_query" );
krClient.waitForExistence();
plan_execution::CurrentStateQuery csq;
krClient.call(csq);
std::vector<plan_execution::AspFluent>::const_iterator facingDoorIt =
find_if(csq.response.answer.fluents.begin(), csq.response.answer.fluents.end(), IsFluentFacing());
if (facingDoorIt == csq.response.answer.fluents.end()) {
ROS_ERROR("CallElevator: Unable to ascertain which elevator door the robot is facing!");
done = true;
failed = true;
} else {
facing_door = facingDoorIt->variables[0];
if (std::find(doors.begin(), doors.end(), facing_door) == doors.end()) {
ROS_ERROR("CallElevator: Unable to ascertain which elevator door the robot is facing!");
done = true;
failed = true;
} else {
// Make sure that this is one of the elevator doors.
std::vector<std::string> door_is_open;
door_is_open.push_back("Door is open");
askToCallElevator.reset(new CallGUI("askToCallElevator",
CallGUI::CHOICE_QUESTION,
"Could you call the elevator to go " + direction_text +
", and then let me know when the door in front of me opens?",
120.0f,
door_is_open));
askToCallElevator->run();
}
}
}
asked = true;
} else if(!done) {
if (askToCallElevator->hasFinished()) {
// Check response to see it's not a timeout.
int response_idx = askToCallElevator->getResponseIndex();
if (response_idx == 0) {
ros::NodeHandle n;
ros::ServiceClient krClient = n.serviceClient<plan_execution::UpdateFluents> ( "update_fluents" );
krClient.waitForExistence();
plan_execution::UpdateFluents uf;
plan_execution::AspFluent open_door;
open_door.name = "open";
open_door.variables.push_back(facing_door);
uf.request.fluents.push_back(open_door);
krClient.call(uf);
CallGUI thanks("thanks", CallGUI::DISPLAY, "Thanks! Would you mind helping me inside the elevator as well?");
thanks.run();
} else {
// A door didn't open in the timeout specified.
failed = true;
}
done = true;
}
}
}
bool CallElevator::hasFinished() const {
return done;
}
bool CallElevator::hasFailed() const {
return failed;
}
actasp::Action *CallElevator::cloneAndInit(const actasp::AspFluent & fluent) const {
CallElevator *other = new CallElevator();
other->elevator = fluent.getParameters().at(0);
other->going_up = fluent.getParameters().at(1) == "up"; //throws an exception if the parameter doesn't exist
return other;
}
std::vector<std::string> CallElevator::getParameters() const {
std::vector<std::string> params;
params.reserve(2);
params.push_back(elevator);
params.push_back(going_up? "up" : "down");
return params;
}
//if you want the action to be available only in simulation, or only
//on the robot, use the constructor that also takes a boolean.
ActionFactory callElevator(new CallElevator(), false);
}