Wandering.cpp
Go to the documentation of this file.
00001 /*
00002  * Filename: Wandering.cpp
00003  *   Author: Igor Makhtes
00004  *     Date: Dec 16, 2013
00005  *
00006  * The MIT License (MIT)
00007  *
00008  * Copyright (c) 2013 Cogniteam Ltd.
00009  *
00010  * Permission is hereby granted, free of charge, to any person obtaining a copy
00011  * of this software and associated documentation files (the "Software"), to deal
00012  * in the Software without restriction, including without limitation the rights
00013  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00014  * copies of the Software, and to permit persons to whom the Software is
00015  * furnished to do so, subject to the following conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be included in
00018  * all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00023  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00024  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00026  * THE SOFTWARE.
00027  */
00028 
00029 #include <iostream>
00030 
00031 #include <boost/bind.hpp>
00032 #include <boost/thread.hpp>
00033 #include <boost/foreach.hpp>
00034 
00035 #include <ros/ros.h>
00036 #include <random_numbers/random_numbers.h>
00037 #include <sensor_msgs/LaserScan.h>
00038 #include <geometry_msgs/Twist.h>
00039 
00040 #include <decision_making/FSM.h>
00041 #include <decision_making/ROSTask.h>
00042 #include <decision_making/DecisionMaking.h>
00043 
00044 using namespace std;
00045 using namespace decision_making;
00046 
00047 #define foreach BOOST_FOREACH
00048 
00049 /*************************************************************************************************
00050 *** Variables
00051 **************************************************************************************************/
00052 
00053 random_numbers::RandomNumberGenerator _randomizer;
00054 ros::Publisher _velocityPublisher;
00055 
00056 /*************************************************************************************************
00057 *** Final state machine
00058 **************************************************************************************************/
00059 
00060 FSM(Wandering)
00061 {
00062     FSM_STATES
00063     {
00064         Drive,
00065         Turn,
00066         Pause
00067     }
00068     FSM_START(Turn)
00069     FSM_BGN
00070     {
00071         FSM_STATE(Turn)
00072         {
00073             FSM_CALL_TASK(Turn)
00074 
00075             FSM_TRANSITIONS
00076             {
00077                 FSM_ON_EVENT(/TURN_TIMEOUT, FSM_NEXT(Drive))
00078                 FSM_ON_EVENT(/PAUSE, FSM_NEXT(Pause))
00079             }
00080         }
00081         FSM_STATE(Drive)
00082         {
00083             FSM_CALL_TASK(Drive)
00084 
00085             FSM_TRANSITIONS
00086             {
00087                 FSM_ON_EVENT(/DRIVE_TIMEOUT, FSM_NEXT(Turn))
00088                 FSM_ON_EVENT(/OBSTACLE, FSM_NEXT(Turn))
00089                 FSM_ON_EVENT(/PAUSE, FSM_NEXT(Pause))
00090             }
00091         }
00092         FSM_STATE(Pause)
00093         {
00094             FSM_CALL_TASK(Pause)
00095 
00096             FSM_TRANSITIONS
00097             {
00098                 FSM_ON_EVENT(/RESUME, FSM_NEXT(Turn))
00099             }
00100         }
00101     }
00102     FSM_END
00103 }
00104 
00105 /*************************************************************************************************
00106 *** ROS Subscriptions
00107 **************************************************************************************************/
00108 
00109 void onLaserScanMessage(const sensor_msgs::LaserScan::Ptr laserScanMessage, RosEventQueue* eventQueue) {
00110     double frontRange = laserScanMessage->ranges[laserScanMessage->ranges.size() / 2];
00111 
00112     if (frontRange < 0.5) {
00113         eventQueue->riseEvent("/OBSTACLE");
00114     }
00115 }
00116 
00117 
00118 /*************************************************************************************************
00119 *** Task implementations
00120 **************************************************************************************************/
00121 
00122 decision_making::TaskResult driveTask(string name, const FSMCallContext& context, EventQueue& eventQueue) {
00123     ROS_INFO("Driving...");
00124 
00125     double timeToDriveMs = _randomizer.uniformInteger(4000, 8000);
00126 
00127     geometry_msgs::Twist forwardMessage;
00128     forwardMessage.linear.x = 2;
00129     _velocityPublisher.publish(forwardMessage);
00130 
00134     for (int i = 0; i < 100; ++i) {
00135         if (eventQueue.isTerminated()) {
00136             ROS_INFO("Obstacle!");
00137             return TaskResult::TERMINATED();
00138         }
00139 
00140         boost::this_thread::sleep(boost::posix_time::milliseconds(timeToDriveMs / 100.0));
00141     }
00142 
00143     eventQueue.riseEvent("/DRIVE_TIMEOUT");
00144     return TaskResult::SUCCESS();
00145 }
00146 
00147 decision_making::TaskResult turnTask(string name, const FSMCallContext& context, EventQueue& eventQueue) {
00148     ROS_INFO("Turning...");
00149 
00150     bool turnRight = _randomizer.uniformInteger(0, 1);
00151     int timeToTurnMs = _randomizer.uniformInteger(2000, 4000);
00152 
00153     geometry_msgs::Twist turnMessage;
00154     turnMessage.angular.z = 2 * (turnRight ? 1 : -1);
00155     _velocityPublisher.publish(turnMessage);
00156 
00157     boost::this_thread::sleep(boost::posix_time::milliseconds(timeToTurnMs));
00158 
00159     eventQueue.riseEvent("/TURN_TIMEOUT");
00160     return decision_making::TaskResult::SUCCESS();
00161 }
00162 
00163 decision_making::TaskResult pauseTask(string name, const FSMCallContext& context, EventQueue& eventQueue) {
00164     ROS_INFO("Pausing...");
00165 
00166     geometry_msgs::Twist stopMessage;
00167     _velocityPublisher.publish(stopMessage);
00168 
00169     return decision_making::TaskResult::SUCCESS();
00170 }
00171 
00172 /*************************************************************************************************
00173 *** The Main
00174 **************************************************************************************************/
00175 
00176 int main(int argc, char **argv) {
00180     ros::init(argc, argv, "wandering");
00181     ros_decision_making_init(argc, argv);
00182     ros::NodeHandle nodeHandle;
00183     RosEventQueue eventQueue;
00184 
00188     LocalTasks::registrate("Drive", driveTask);
00189     LocalTasks::registrate("Turn", turnTask);
00190     LocalTasks::registrate("Pause", pauseTask);
00191 
00196     ros::Subscriber laserSubscriber = nodeHandle.subscribe<void>("/pioneer_1/scan_raw", 1,
00197                 boost::function<void(const sensor_msgs::LaserScan::Ptr)>(boost::bind(onLaserScanMessage, _1, &eventQueue)));
00198 
00199     _velocityPublisher = nodeHandle.advertise<geometry_msgs::Twist>("/pioneer_1/cmd_vel", 100, false);
00200 
00204     ros::AsyncSpinner spinner(1);
00205     spinner.start();
00206 
00210     ROS_INFO("Starting wandering machine...");
00211     FsmWandering(NULL, &eventQueue);
00212 
00216         return 0;
00217 }


decision_making_examples
Author(s):
autogenerated on Wed Aug 26 2015 11:17:01