00001 /********************************************************************* 00002 * 00003 * Software License Agreement (BSD License) 00004 * 00005 * Copyright (c) 2010, ISR University of Coimbra. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the ISR University of Coimbra nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * Author: Gonçalo Cabrita and Pedro Sousa on 03/01/2010 00036 *********************************************************************/ 00037 #include <string.h> 00038 #include <stdio.h> 00039 #include <math.h> 00040 00041 #include "PSSources.h" 00042 00043 // ***************************************************************************** 00044 // Constructor. 00045 plumesim::PSGaussian::PSGaussian() 00046 { 00047 this->changesOverTime = true; 00048 00049 this->startPoint.px = 0.0; 00050 this->startPoint.py = 0.0; 00051 this->startPoint.pz = 0.0; 00052 00053 this->arenaRect.startPoint.px = 0.0; 00054 this->arenaRect.startPoint.py = 0.0; 00055 this->arenaRect.endPoint.px = 0.0; 00056 this->arenaRect.endPoint.py = 0.0; 00057 00058 this->cellSize = 0.1; 00059 this->diffX = 0.2; 00060 this->diffY = 0.005; 00061 this->radius = 0.1; 00062 this->maxPointsPerCell = 10; 00063 } 00064 00065 // ***************************************************************************** 00066 // Destructor. 00067 plumesim::PSGaussian::~PSGaussian() 00068 { 00069 // Clean up... 00070 } 00071 00072 // ***************************************************************************** 00073 // Setup routine. 00074 int plumesim::PSGaussian::setup() 00075 { 00076 int i, j; 00077 00078 if(!plumePoints.empty()) plumePoints.clear(); 00079 if(!frame.empty()) frame.clear(); 00080 00081 int numXpoints = (this->arenaRect.endPoint.px - this->arenaRect.startPoint.px)/this->cellSize; 00082 int numYpoints = (this->arenaRect.endPoint.py - this->arenaRect.startPoint.py)/this->cellSize; 00083 00084 for(i=0 ; i<numXpoints ; i++) 00085 { 00086 for(j=0 ; j<numYpoints ; j++) 00087 { 00088 PSFramePoint frameCell; 00089 frameCell.point.px = startPoint.px + this->cellSize*i; 00090 frameCell.point.py = startPoint.py + this->cellSize*j; 00091 frameCell.point.pz = 0.0; 00092 00093 frameCell.odor.chemical = 0.0; // Start value 00094 frameCell.odor.windDirection = 0.0; // rad 00095 frameCell.odor.windSpeed = 0.5; // m/s 00096 00097 this->frame.push_back(frameCell); 00098 } 00099 } 00100 t = 1; 00101 this->isPlaying = true; 00102 00103 return 0; 00104 } 00105 00106 // ***************************************************************************** 00107 // Cleanup routine. 00108 int plumesim::PSGaussian::cleanup() 00109 { 00110 plumePoints.clear(); 00111 frame.clear(); 00112 return 0; 00113 } 00114 00115 // ***************************************************************************** 00116 // Generate points. 00117 int plumesim::PSGaussian::generatePoints() 00118 { 00119 PSFramePoint * frameCell; 00120 int pointsCount; 00121 int j; 00122 00123 if(!plumePoints.empty()) plumePoints.clear(); 00124 00125 for(int i=0 ; i<this->frame.size() ; i++) 00126 { 00127 frameCell = &this->frame[i]; 00128 00129 frameCell->odor.chemical = 100.0/(4*M_PI*sqrt(this->diffX)*sqrt(this->diffY)*t)*exp(-(((frameCell->point.px - this->startPoint.px)*(frameCell->point.px - this->startPoint.px)/this->diffX)+((frameCell->point.py - this->startPoint.py)*(frameCell->point.py - this->startPoint.py)/this->diffY))/(4*t)); 00130 00131 pointsCount = round(maxPointsPerCell * frameCell->odor.chemical/100.0); 00132 for(j=0 ; j<pointsCount ; j++) 00133 { 00134 PSPoint3d point; 00135 point.px = frameCell->point.px + cellSize * randomNormal(); 00136 point.py = frameCell->point.py + cellSize * randomNormal(); 00137 // TODO: Complete for full 3D support! 00138 point.pz = 0.0; 00139 this->plumePoints.push_back(point); 00140 } 00141 } 00142 t++; 00143 if(t > 25) t = 20; 00144 //isPlaying = false; 00145 00146 return(0); 00147 } 00148 00149 // ***************************************************************************** 00150 // Sends the chemical reading for a given position. 00151 int plumesim::PSGaussian::getChemicalReading(PSPoint3d * point, PSOdorData * odor_data) 00152 { 00153 double distance; 00154 double minDistance = cellSize; 00155 00156 odor_data->chemical = 0.0; 00157 odor_data->windSpeed = 0.0; 00158 odor_data->windDirection = 0.0; 00159 00160 PSFramePoint * framePoint; 00161 for(int i=0 ; i<this->frame.size() ; i++) 00162 { 00163 framePoint = &this->frame[i]; 00164 00165 distance = sqrt((point->px - framePoint->point.px)*(point->px - framePoint->point.px) + (point->py - framePoint->point.py)*(point->py - framePoint->point.py) + (point->pz - framePoint->point.pz)*(point->pz - framePoint->point.pz)); 00166 if(distance < minDistance) 00167 { 00168 odor_data->chemical = framePoint->odor.chemical; 00169 odor_data->windSpeed = framePoint->odor.windSpeed; 00170 odor_data->windDirection = framePoint->odor.windDirection; 00171 00172 minDistance = distance; 00173 } 00174 } 00175 return(0); 00176 } 00177 00178 // EOF 00179