00001 #include "CallSimulatedElevator.h" 00002 00003 #include <boost/foreach.hpp> 00004 00005 #include "bwi_kr_execution/CurrentStateQuery.h" 00006 #include "bwi_msgs/DoorHandlerInterface.h" 00007 00008 #include "ActionFactory.h" 00009 #include "../StaticFacts.h" 00010 00011 #include "bwi_kr_execution/UpdateFluents.h" 00012 00013 #include "ros/console.h" 00014 #include "ros/ros.h" 00015 00016 namespace bwi_krexec { 00017 00018 CallSimulatedElevator::CallSimulatedElevator() : 00019 done(false), 00020 failed(false), 00021 requestSent(false) {} 00022 00023 void CallSimulatedElevator::run() { 00024 00025 if (!requestSent) { 00026 00027 // Get the doors for this elevator. 00028 doors.clear(); 00029 std::list<actasp::AspAtom> static_facts = StaticFacts::staticFacts(); 00030 BOOST_FOREACH(const actasp::AspAtom fact, static_facts) { 00031 if (fact.getName() == "elevhasdoor") { 00032 std::vector<std::string> params = fact.getParameters(); 00033 if (params[0] == elevator) { 00034 doors.push_back(params[1]); 00035 } 00036 } 00037 } 00038 00039 if (doors.size() == 0) { 00040 ROS_ERROR_STREAM("Unable to retrieve doors for elevator " << elevator << ". Cannot complete action!"); 00041 done = true; 00042 failed = true; 00043 } else { 00044 00045 ros::NodeHandle n; 00046 ros::ServiceClient doorClient = n.serviceClient<bwi_msgs::DoorHandlerInterface> ("/update_doors"); 00047 doorClient.waitForExistence(); 00048 00049 bwi_msgs::DoorHandlerInterface dhi; 00050 00051 selectedDoor = doors[rand() % doors.size()]; 00052 dhi.request.all_doors = false; 00053 dhi.request.door = selectedDoor; 00054 dhi.request.open = true; 00055 dhi.request.open_timeout = 45.0f; 00056 00057 doorClient.call(dhi); 00058 00059 requestSent = true; 00060 } 00061 } else if (!done) { 00062 00063 // The door may not be visible to the robot in simulation. Force state update. 00064 ros::NodeHandle n; 00065 ros::ServiceClient krClient = n.serviceClient<bwi_kr_execution::UpdateFluents> ( "update_fluents" ); 00066 krClient.waitForExistence(); 00067 bwi_kr_execution::UpdateFluents uf; 00068 bwi_kr_execution::AspFluent open_door; 00069 open_door.name = "open"; 00070 open_door.variables.push_back(selectedDoor); 00071 uf.request.fluents.push_back(open_door); 00072 00073 /* TODO: Remove this hack. Also, pretend you're facing the door that opened. This way it's shorter to use the open elevator. */ 00074 bwi_kr_execution::AspFluent facing_door; 00075 facing_door.name = "facing"; 00076 facing_door.variables.push_back(selectedDoor); 00077 uf.request.fluents.push_back(facing_door); 00078 00079 krClient.call(uf); 00080 00081 done = true; 00082 } 00083 00084 } 00085 00086 bool CallSimulatedElevator::hasFinished() const { 00087 return done; 00088 } 00089 00090 bool CallSimulatedElevator::hasFailed() const { 00091 return failed; 00092 } 00093 00094 actasp::Action *CallSimulatedElevator::cloneAndInit(const actasp::AspFluent & fluent) const { 00095 CallSimulatedElevator *other = new CallSimulatedElevator(); 00096 other->elevator = fluent.getParameters().at(0); 00097 other->going_up = fluent.getParameters().at(1) == "up"; //throws an exception if the parameter doesn't exist 00098 return other; 00099 } 00100 00101 std::vector<std::string> CallSimulatedElevator::getParameters() const { 00102 std::vector<std::string> params; 00103 params.reserve(2); 00104 params.push_back(elevator); 00105 params.push_back(going_up? "up" : "down"); 00106 return params; 00107 } 00108 00109 //if you want the action to be available only in simulation, or only 00110 //on the robot, use the constructor that also takes a boolean. 00111 ActionFactory callSimulatedElevator(new CallSimulatedElevator(), true); 00112 00113 }