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 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #define NODE_VERSION 1.00
00038 
00039 #include <unistd.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042 #include <math.h>
00043 
00044 #include <ros/ros.h>
00045 #include <boost/thread/mutex.hpp>
00046 #include <boost/thread/thread.hpp>
00047 #include <visualization_msgs/Marker.h>
00048 #include <nav_msgs/Odometry.h>
00049 
00050 #include "plumesim/ReadPlumeSim.h"
00051 
00052 
00053 #include "utils/PSSources.h"
00054 
00055 using namespace plumesim;
00056 
00057 class PlumeSim
00058 {
00059         
00060         public:
00068         PlumeSim();
00070 
00073         ~PlumeSim();
00074 
00083         bool ReadPlumeSim(plumesim::ReadPlumeSim::Request  &req, plumesim::ReadPlumeSim::Response &res);
00084         
00092         void UpdatePlume();
00093 
00101         double getFrequency();
00102         
00103         private:
00104         
00105         PSSource * source;
00106         
00107         ros::NodeHandle n;
00108         ros::Publisher marker_pub;
00109         ros::ServiceServer service;
00110 
00111         visualization_msgs::Marker points;
00112         
00113         std::string global_frame_id;
00114         
00115         double freq;
00116         
00117         double plume_color_r, plume_color_g, plume_color_b, plume_color_a;
00118         
00119         std::string plume_ns;
00120         int plume_id;
00121 };
00122 
00123 
00124 
00125 PlumeSim::PlumeSim() : n("~")
00126 {               
00127         ROS_INFO("PlumeSim for ROS %.2f", NODE_VERSION);
00128         
00129         marker_pub = n.advertise<visualization_msgs::Marker>("plumesim_markers", 10);
00130         service = n.advertiseService("read_plumesim", &PlumeSim::ReadPlumeSim, this);
00131         
00132         
00133         if(!n.hasParam("type"))
00134         {
00135                 ROS_FATAL("No type of simulation was defined!");
00136                 ROS_BREAK();
00137         }
00138         std::string type;
00139         n.getParam("type", type);
00140         
00141         if(type.compare("meadering") == 0)
00142         {
00143                 source = new PSMeadering();
00144                 PSMeadering * meandering = dynamic_cast<PSMeadering*>(source);          
00145                 
00146                 n.param("releasepoint/x", meandering->startPoint.px, 0.0);
00147                 n.param("releasepoint/y", meandering->startPoint.py, 0.0);
00148                 n.param("releasepoint/z", meandering->startPoint.pz, 0.0);
00149                 n.param("arena/start/x", meandering->arenaRect.startPoint.px, 0.0);
00150                 n.param("arena/start/y", meandering->arenaRect.startPoint.py, 0.0);
00151                 n.param("arena/end/x", meandering->arenaRect.endPoint.px, 0.0);
00152                 n.param("arena/end/y", meandering->arenaRect.endPoint.py, 0.0);
00153                 n.param("number_of_points", meandering->numOfPlumePoints, 100);
00154                 n.param("release_rate", meandering->releaseRate, 10.0);
00155                 n.param("dispersion_coeficient", meandering->dispersionCoeficient, 0.06);
00156                 n.param("radius", meandering->radius, 0.1);
00157         }
00158         else if(type.compare("gaussian") == 0)
00159         {
00160                 source = new PSGaussian();
00161                 PSGaussian * gaussian = dynamic_cast<PSGaussian*>(source);
00162                 
00163                 n.getParam("releasepoint/x", gaussian->startPoint.px);
00164                 n.getParam("releasepoint/y", gaussian->startPoint.py);
00165                 n.getParam("releasepoint/z", gaussian->startPoint.pz);
00166                 n.getParam("arena/start/x", gaussian->arenaRect.startPoint.px);
00167                 n.getParam("arena/start/y", gaussian->arenaRect.startPoint.py);
00168                 n.getParam("arena/end/x", gaussian->arenaRect.endPoint.px);
00169                 n.getParam("arena/end/y", gaussian->arenaRect.endPoint.py);
00170                 n.getParam("cell_size", gaussian->cellSize);
00171                 n.getParam("diffx", gaussian->diffX);
00172                 n.getParam("diffy", gaussian->diffY);
00173                 n.getParam("radius", gaussian->radius);
00174                 n.getParam("max_points_per_cell", gaussian->maxPointsPerCell);
00175         }
00176         else if(type.compare("fluent") == 0)
00177         {
00178                 source = new PSFluent();
00179                 PSFluent * fluent = dynamic_cast<PSFluent*>(source);
00180                 
00181                 n.getParam("max_points_per_cell", fluent->maxPointsPerCell);
00182                 n.getParam("file_name", fluent->fileName);
00183                 n.getParam("num_of_frames", fluent->numOfFrames);
00184                 n.getParam("cell_size", fluent->cellSize);
00185                 n.getParam("max_concentration", fluent->maxOdorValue);
00186         }
00187         else if(type.compare("pslog") == 0)
00188         {
00189                 source = new PSLog();
00190                 PSLog * log = dynamic_cast<PSLog*>(source);
00191                 
00192                 n.getParam("max_points_per_cell", log->maxPointsPerCell);
00193                 n.getParam("file_name", log->logFilePath);
00194         }
00195         else
00196         {
00197                 ROS_FATAL("The type of simulation selected is not defined!");
00198                 ROS_BREAK();
00199         }
00200         
00201         n.param<std::string>("global_frame_id", global_frame_id, "map");
00202         
00203         
00204         n.param("color/r", this->plume_color_r, 1.0);
00205         n.param("color/g", this->plume_color_g, 0.0);
00206         n.param("color/b", this->plume_color_b, 0.0);
00207         n.param("color/a", this->plume_color_a, 0.9);
00208         
00209         
00210         plume_ns = "plume";
00211         n.getParam("ns", plume_ns);
00212         n.param("id", plume_id, 0);
00213         
00214         
00215         n.param("frequency", freq, 1.0);
00216         
00217         if(source->setup() == -1)
00218         {
00219                 ROS_FATAL("Failed to setup the plume!");
00220                 ROS_BREAK();
00221         }
00222         ROS_INFO("Plume setup is complete.");
00223 
00224         
00225         points.header.frame_id = global_frame_id;
00226         points.header.stamp = ros::Time::now();
00227         points.action = visualization_msgs::Marker::ADD;
00228         points.ns = this->plume_ns;
00229         points.id = this->plume_id;
00230         points.pose.orientation.w = 1.0;
00231         points.type = visualization_msgs::Marker::SPHERE_LIST;
00232         
00233         
00234         points.scale.x = 0.06;
00235         points.scale.y = 0.06;
00236         points.scale.z = 0.06;
00237         
00238         points.color.r = this->plume_color_r;
00239         points.color.g = this->plume_color_g;
00240         points.color.b = this->plume_color_b;
00241         points.color.a = this->plume_color_a;
00242 }
00243 
00244 
00245 
00246 PlumeSim::~PlumeSim()
00247 {
00248         source->cleanup();
00249         delete source;
00250 }
00251 
00252 
00253 
00254 void PlumeSim::UpdatePlume()
00255 {       
00256         if(this->source->IsPlaying())
00257         {
00258                 if(this->source->generatePoints() == -1)
00259                 {
00260                         ROS_ERROR("Unable to generate a new plume!");
00261                 }
00262                 else
00263                 {
00264                         points.header.stamp = ros::Time::now();
00265                         points.points.clear();
00266                         
00267                         for(int i=0 ; i<source->plumePoints.size() ; i++)
00268                         {
00269                                 geometry_msgs::Point p;
00270                                 p.x = source->plumePoints[i].px;
00271                                 p.y = source->plumePoints[i].py;
00272                                 
00273                                 p.z = 0.2;
00274                                 points.points.push_back(p);
00275                         }
00276                 }
00277         }
00278         
00279         marker_pub.publish(points);
00280 }
00281 
00282 
00283 
00284 double PlumeSim::getFrequency()
00285 {
00286         return this->freq;
00287 }
00288 
00289 
00290 
00291 bool PlumeSim::ReadPlumeSim(plumesim::ReadPlumeSim::Request  &req, plumesim::ReadPlumeSim::Response &res)
00292 {
00293         PSOdorData odor_data;
00294         PSPoint3d point;
00295         
00296         point.px = req.odom.pose.pose.position.x;
00297         point.py = req.odom.pose.pose.position.y;
00298         point.pz = req.odom.pose.pose.position.z;
00299         
00300         source->getChemicalReading(&point, &odor_data);
00301         
00302         res.nostril.header.frame_id = req.odom.header.frame_id;
00303         res.nostril.header.stamp = ros::Time::now();
00304         res.nostril.sensor_model = "PlumeSim";
00305         res.nostril.reading = odor_data.chemical;
00306         res.nostril.max_reading = 1.0;
00307         res.nostril.min_reading = 0.0;
00308 
00309         
00310 
00311         return true;
00312 }
00313 
00314 
00315 
00316 
00317 int main(int argc, char** argv)
00318 {
00319         ros::init(argc, argv, "plumesim");
00320 
00321         PlumeSim * plumesim_node = new PlumeSim();
00322         
00323         boost::thread t = boost::thread::thread(boost::bind(&ros::spin));
00324 
00325         ros::Rate r(plumesim_node->getFrequency());
00326         while(ros::ok())
00327         {
00328         plumesim_node->UpdatePlume();
00329         r.sleep();
00330     }
00331         t.join();
00332 
00333         delete plumesim_node;
00334 
00335         exit(0);
00336 }
00337 
00338 
00339