00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <iostream>
00030 #include <time.h>
00031 #include <numeric>
00032 #include <boost/bind.hpp>
00033 #include <boost/thread.hpp>
00034 #include <boost/foreach.hpp>
00035 #include <boost/lambda/lambda.hpp>
00036 #include <boost/date_time.hpp>
00037 #include <ros/ros.h>
00038
00039 #include <sensor_msgs/LaserScan.h>
00040 #include <geometry_msgs/Twist.h>
00041
00042 #include "Wandering.h"
00043
00044 using namespace std;
00045
00046 #define foreach BOOST_FOREACH
00047
00048 ros::Subscriber laserSub;
00049 ros::Publisher velocityPub;
00050 ros::NodeHandle* node;
00051
00052 void publishVelocity(double linear, double angular) {
00053 geometry_msgs::Twist velocity;
00054 velocity.linear.x = linear;
00055 velocity.angular.z = angular;
00056
00057 for (int i = 0; i < 10; i++)
00058 velocityPub.publish(velocity);
00059 }
00060
00067 bool preemptiveWait(double ms, decision_making::EventQueue& queue) {
00068 for (int i = 0; i < 100 && !queue.isTerminated(); i++)
00069 boost::this_thread::sleep(boost::posix_time::milliseconds(ms / 100.0));
00070
00071 return queue.isTerminated();
00072 }
00073
00080 bool preemptiveWait(double minMs, double maxMs, decision_making::EventQueue& queue) {
00081 double msToWait = ((double)rand() / (double)RAND_MAX) * (maxMs - minMs) + minMs;
00082 return preemptiveWait(msToWait, queue);
00083 }
00084
00085 double getAverage(int centerRange, int rangeSize, const sensor_msgs::LaserScan::Ptr& scan) {
00086 double sum = std::accumulate(scan->ranges.begin() + centerRange - rangeSize / 2.0,
00087 scan->ranges.begin() + centerRange + rangeSize / 2.0, 0.0);
00088
00089 return sum / (double)rangeSize;
00090 }
00091
00092 int countRanges(const sensor_msgs::LaserScan::Ptr& scan, int center, int range, double lessThan) {
00093 return std::count_if(scan->ranges.begin() + center - range / 2.0,
00094 scan->ranges.begin() + center + range / 2.0,
00095 bind2nd(less<double>(), lessThan));
00096 }
00097
00098 void onLaserScan(const sensor_msgs::LaserScan::Ptr scan, EventQueue* q) {
00099 int countFrontRange = countRanges(scan, scan->ranges.size() / 2, 100, 0.5);
00100 int countRightRange = countRanges(scan, (scan->ranges.size() / 6) * 1, 50, 0.5);
00101 int countLeftRange = countRanges(scan, (scan->ranges.size() / 6) * 5, 50, 0.5);
00102
00103 bool front = false;
00104 bool left = false;
00105 bool right = false;
00106
00107 if (countFrontRange > 5) {
00108 front = true;
00109 q->riseEvent("/FRONT_OBSTACLE");
00110 }
00111
00112 if (countLeftRange > 3) {
00113 left = true;
00114 q->riseEvent("/LEFT_OBSTACLE");
00115 }
00116
00117 if (countRightRange > 3) {
00118 right = true;
00119 q->riseEvent("/RIGHT_OBSTACLE");
00120 }
00121
00122 if (front && right)
00123 q->riseEvent("/FRONT_AND_RIGHT_OBSTACLE");
00124
00125 if (front && left)
00126 q->riseEvent("/FRONT_AND_LEFT_OBSTACLE");
00127 }
00128
00129 decision_making::TaskResult stopRobot(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00130 publishVelocity(0, 0);
00131 return decision_making::TaskResult::SUCCESS();
00132 }
00133
00134 decision_making::TaskResult turnRight(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00135 publishVelocity(0, -2);
00136
00137 if (preemptiveWait(500, 1000, e))
00138 return decision_making::TaskResult::TERMINATED();
00139
00140 e.raiseEvent("/TIMEOUT_TURN");
00141 return decision_making::TaskResult::SUCCESS();
00142 }
00143
00144 decision_making::TaskResult turnLeft(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00145 publishVelocity(0, 2);
00146
00147 if (preemptiveWait(500, 1000, e))
00148 return decision_making::TaskResult::TERMINATED();
00149
00150 e.raiseEvent("/TIMEOUT_TURN");
00151 return decision_making::TaskResult::SUCCESS();
00152 }
00153
00154 decision_making::TaskResult turnRandom(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00155 bool turnRight = rand() % 2;
00156 publishVelocity(0, (turnRight * -2 + 1) * 2);
00157
00158 ROS_INFO("Turning randomly");
00159
00160 if (preemptiveWait(500, 2500, e))
00161 return decision_making::TaskResult::TERMINATED();
00162
00163 e.raiseEvent("/TIMEOUT_TURN");
00164 return decision_making::TaskResult::SUCCESS();
00165 }
00166
00167 decision_making::TaskResult drive(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00168 publishVelocity(0.75, 0);
00169
00170 if (preemptiveWait(9000, 20000, e))
00171 return decision_making::TaskResult::TERMINATED();
00172
00173 e.raiseEvent("/TIMEOUT_DRIVE");
00174 return decision_making::TaskResult::SUCCESS();
00175 }
00176
00177 decision_making::TaskResult driveBackward(std::string, const decision_making::FSMCallContext& c, decision_making::EventQueue& e) {
00178 publishVelocity(-0.75, 0);
00179
00180 if (preemptiveWait(1000, 2000, e))
00181 return decision_making::TaskResult::TERMINATED();
00182
00183 e.raiseEvent("/TIMEOUT_BACKWARD");
00184 return decision_making::TaskResult::SUCCESS();
00185 }
00186
00187 int main(int argc, char **argv) {
00188 ros::init(argc, argv, "wandering_node");
00189 ros_decision_making_init(argc, argv);
00190
00191 ROS_INFO("Preparing wandering...");
00192
00193 boost::posix_time::ptime epoch(boost::posix_time::min_date_time);
00194 boost::posix_time::ptime now(boost::posix_time::microsec_clock::local_time());
00195 unsigned int seed = (now - epoch).total_nanoseconds();
00196 srand(seed);
00197 node = new ros::NodeHandle();
00198
00199 RosEventQueue* q = new RosEventQueue();
00200 laserSub = node->subscribe<void>("/scan", 10,
00201 boost::function<void(const sensor_msgs::LaserScan::Ptr)>(boost::bind(onLaserScan, _1, q)));
00202
00203 velocityPub = node->advertise<geometry_msgs::Twist>("/cmd_vel", 10, false);
00204
00205 LocalTasks::registrate("TurnRight", turnRight);
00206 LocalTasks::registrate("TurnLeft", turnLeft);
00207 LocalTasks::registrate("TurnRandom", turnRandom);
00208 LocalTasks::registrate("Drive", drive);
00209 LocalTasks::registrate("DriveBackward", driveBackward);
00210 LocalTasks::registrate("StopRobot", stopRobot);
00211
00212 ros::AsyncSpinner spinner(1);
00213 spinner.start();
00214 ROS_INFO("Spinner started");
00215 FsmWandering(NULL, q, "Wandering");
00216
00217 delete node;
00218 return 0;
00219 }