Module seaModels
[hide private]
[frames] | no frames]

Source Code for Module seaModels

  1  ################################################################################## 
  2  # Copyright (c) 2012, Daniel Urieli, Peter Stone 
  3  # University of Texas at Austin 
  4  # All right reserved 
  5  #  
  6  # Based On: 
  7  #  
  8  # Copyright (c) 2000-2003, Jelle Kok, University of Amsterdam 
  9  # All rights reserved. 
 10  #  
 11  # Redistribution and use in source and binary forms, with or without 
 12  # modification, are permitted provided that the following conditions are met: 
 13  #  
 14  # 1. Redistributions of source code must retain the above copyright notice, this 
 15  # list of conditions and the following disclaimer. 
 16  #  
 17  # 2. Redistributions in binary form must reproduce the above copyright notice, 
 18  # this list of conditions and the following disclaimer in the documentation 
 19  # and/or other materials provided with the distribution. 
 20  #  
 21  # 3. Neither the name of the University of Amsterdam nor the names of its 
 22  # contributors may be used to endorse or promote products derived from this 
 23  # software without specific prior written permission. 
 24  #  
 25  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 26  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 27  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 28  # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 29  # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 30  # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 31  # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 32  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 33  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 34  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 35  ################################################################################## 
 36   
 37   
 38   
 39  import numpy 
 40  from numpy import * 
 41  import random 
 42   
43 -class Sea:
44 """ 45 This is a base class for the sea model. 46 Different sea models can implement it, 47 and together with the ships states, they compose the world state. 48 """ 49 50 # TODO: add a temporal model of changes to wind, waterCurrents, waves, and obstacles map
51 - def __init__(self, wind, waterCurrents, waves, obstacles):
52 """ 53 Initialize the sea model. 54 55 @type wind: Wind 56 @param wind: the Wind model 57 58 @type waterCurrents: WaterCurrents 59 @param waterCurrents: the water currents model 60 61 @type waves: Waves 62 @param waves: the waves model 63 64 @type obstacles: Obstacles 65 @param obstacles: the sea obstacles model 66 """ 67 68 #print 'Creating sea model' 69 self.wind = wind 70 self.waterCurrents = waterCurrents 71 self.waves = waves 72 self.obstacles = obstacles
73
74 - def __str__(self):
75 res = "\nSea:\n" 76 for member, value in vars(self).items(): 77 res += " " + member + "=" + str(value) 78 res += "\n" 79 return res
80 81 82 83 84 ################################################### 85 # This part defines the wind base class # 86 # and some concrete class examples # 87 ###################################################
88 -class Wind:
89 """ 90 This is a base class for wind models. 91 A wind is a mapping from location to a (2D) direction vector. 92 """ 93
94 - def __init__(self):
95 print 'Creating wind model'
96
97 - def getSpeedVectorInLocation(self, x, y):
98 "Given a location, returns the wind vector in it" 99 abstract
100 101 102
103 -class StaticConstantWind(Wind):
104 """ 105 This class implements a wind that is constant in every point, 106 and never changes. 107 """ 108
109 - def __init__(self, directionX, directionY):
110 "parameters define the constant wind direction vector" 111 self.directionX = directionX 112 self.directionY = directionY
113
114 - def __str__(self):
115 res = "\nStaticConstantWind:" 116 for member, value in vars(self).items(): 117 res += " " + member + "=" + str(value) 118 res += "\n" 119 return res
120
121 - def getSpeedVectorInLocation(self, x, y):
122 "Given a location, returns the wind vector in it" 123 return numpy.array( [self.directionX, self.directionY] )
124 125 126 127 128 ################################################### 129 # This part defines the water-currents base class # 130 # and some concrete class examples # 131 ###################################################
132 -class WaterCurrents:
133 """ 134 This is a base class for water-currents models. 135 A water-current is a mapping from location to a (2D) direction vector. 136 """ 137
138 - def __init__(self):
139 print 'Creating water-current model'
140
141 - def getSpeedVectorInLocation(self, x, y):
142 "Given a location, returns the water-current vector in it" 143 abstract
144
145 -class StaticConstantWaterCurrents(WaterCurrents):
146 """ 147 This class implements a water-current that is constant in every point, 148 and never changes. 149 """ 150
151 - def __init__(self, directionX, directionY):
152 "parameters define the constant water-current direction vector" 153 self.directionX = directionX 154 self.directionY = directionY
155
156 - def __str__(self):
157 res = "\nStaticConstantWaterCurrents:" 158 for member, value in vars(self).items(): 159 res += " " + member + "=" + str(value) 160 res += "\n" 161 return res
162
163 - def getSpeedVectorInLocation(self, x, y):
164 "Given a location, returns the wind vector in it" 165 return numpy.array( [self.directionX, self.directionY] )
166 167
168 -class StripeWaterCurrents(WaterCurrents):
169 """ 170 This class implements a water-current that is constant and never changes, 171 except one vertical stripe (with top and bottom part) 172 that has different conditions. 173 """ 174
175 - def __init__(self, waterDirectionX, waterDirectionY, 176 stripeXStart, stripeXEnd, 177 stripeYmiddle, 178 stripeTopWaterDirectionX, stripeTopWaterDirectionY, 179 stripeBottomWaterDirectionX, stripeBottomWaterDirectionY):
180 "parameters define the constant water-current direction vector" 181 self.waterDirectionX = waterDirectionX 182 self.waterDirectionY = waterDirectionY 183 self.stripeXStart = stripeXStart 184 self.stripeXEnd = stripeXEnd 185 self.stripeYmiddle = stripeYmiddle 186 self.stripeTopWaterDirectionX = stripeTopWaterDirectionX 187 self.stripeTopWaterDirectionY = stripeTopWaterDirectionY 188 self.stripeBottomWaterDirectionX = stripeBottomWaterDirectionX 189 self.stripeBottomWaterDirectionY = stripeBottomWaterDirectionY
190 191
192 - def __str__(self):
193 res = "\nStripeWaterCurrents:" 194 for member, value in vars(self).items(): 195 res += " " + member + "=" + str(value) 196 res += "\n" 197 return res
198
199 - def getSpeedVectorInLocation(self, x, y):
200 "Given a location, returns the wind vector in it" 201 if(x < self.stripeXStart or x > self.stripeXEnd): 202 # outside the stripe 203 return numpy.array( [self.waterDirectionX, self.waterDirectionY] ) 204 elif( y > self.stripeYmiddle ): 205 return numpy.array( [self.stripeTopWaterDirectionX, self.stripeTopWaterDirectionY] ) 206 else: 207 return numpy.array( [self.stripeBottomWaterDirectionX, self.stripeBottomWaterDirectionY] )
208
209 -class IslandWaterCurrents(WaterCurrents):
210 """ 211 Hard coded values For the Island example. 212 We have a few islands, and two areas of strong currents 213 between them. 214 """ 215 # TODO: make this class more general?
216 - def __init__(self, points):
217 self.points = points 218 219 b = self.points 220 221 # First area of rough weather 222 b5 = numpy.array(b[5]) 223 b34 = numpy.array(b[34]) 224 b3 = numpy.array(b[3]) 225 226 tmp = b34 - b5 227 self.bay1Line = tmp * 1.0 / linalg.norm(tmp) 228 229 # normalize and compute the normal for this line and intercept 230 self.normalBay1Line = numpy.array([self.bay1Line[1], -self.bay1Line[0]]) 231 232 # Computed border values for bay1 233 self.border1VerticalValueTop = dot(self.normalBay1Line, b5) 234 self.border1VerticalValueBottom = dot(self.normalBay1Line, b3) 235 self.border1VerticalValueMiddle = (self.border1VerticalValueTop + 236 self.border1VerticalValueBottom) * 1.0 / 2 237 self.border1HorizonalValueTop = dot(self.bay1Line, b34) + 50 238 self.border1HorizonalValueBottom = dot(self.bay1Line, b5) - 50 239 self.border1HorizonalValueMiddle = (self.border1HorizonalValueTop + 240 self.border1HorizonalValueBottom) * 1.0 / 2 241 242 243 # Second area of rough water 244 b25 = numpy.array(b[25]) 245 b24 = numpy.array(b[24]) 246 b13 = numpy.array(b[13]) 247 b14 = numpy.array(b[14]) 248 249 tmp = b25 - b24 250 self.bay2Line = tmp * 1.0 / linalg.norm(tmp) 251 252 # normalize and compute the normal for this line and intercept 253 self.normalBay2Line = numpy.array([self.bay2Line[1], -self.bay2Line[0]]) 254 255 # Computed "top-bottom" border values for bay1 256 self.border2VerticalValueTop = dot(self.normalBay2Line, b24) + 50 257 self.border2VerticalValueBottom = dot(self.normalBay2Line, b13) - 50 258 self.border2VerticalValueMiddle = (self.border2VerticalValueTop + 259 self.border2VerticalValueBottom) * 1.0 / 2 260 self.border2HorizonalValueTop = dot(self.bay2Line, b25) 261 self.border2HorizonalValueBottom = dot(self.bay2Line, b14) 262 self.border2HorizonalValueMiddle = (self.border2HorizonalValueTop + 263 self.border2HorizonalValueBottom) * 1.0 / 2
264
265 - def __str__(self):
266 res = "\nIslandWaterCurrents:" 267 for member, value in vars(self).items(): 268 res += " " + member + "=" + str(value) 269 res += "\n" 270 return res
271
272 - def getSpeedVectorInLocation(self, x, y):
273 # If in bay 1 - hard to cross 274 p = numpy.array((x,y)) 275 dot1 = dot(p, self.normalBay1Line) 276 dot2 = dot(p, self.bay1Line) 277 inSideBay1 = ((self.border1VerticalValueBottom <= dot1 <= self.border1VerticalValueTop) and 278 (self.border1HorizonalValueBottom <= dot2 <= self.border1HorizonalValueTop)) 279 if inSideBay1: 280 return self.bay1Line * 8 281 282 dot1 = dot(p, self.normalBay2Line) 283 dot2 = dot(p, self.bay2Line) 284 inSideBay2 = (self.border2VerticalValueBottom <= dot1 <= self.border2VerticalValueTop and 285 self.border2HorizonalValueBottom <= dot2 <= self.border2HorizonalValueTop) 286 if inSideBay2: 287 return self.normalBay2Line * -8 288 289 # other wise, random mild current 290 waterSpeed = random.weibullvariate(1,2) 291 waterDirection = random.randint(0,360) 292 return numpy.array( waterSpeed * cos(radians(waterDirection)), waterSpeed * sin(radians(waterDirection)) )
293
294 -class VerticalWaterCurrents(WaterCurrents):
295 """ 296 Defines north->south or south->north currents. 297 Was used for the AAAI 11 experiments. 298 """ 299
300 - def __init__(self, regionsAndCurrentsList):
301 """ 302 @type regionsAndCurrentsList: list of 3-tuples 303 @param regionsAndCurrentsList: a list of 3-tuples, each defines a stripe: (minX, maxX, currentValue), where currentValue is signed to account for direction. 304 """ 305 self.regionsAndCurrentsList = regionsAndCurrentsList
306
307 - def getSpeedVectorInLocation(self, x, y):
308 """ 309 Check stripe and return corresponding current. 310 """ 311 for p1, p2, current in self.regionsAndCurrentsList: 312 x1 = p1[0] 313 x2 = p2[0] 314 if x1 <= x <= x2: 315 # vertical normal multiplied by the current value 316 return current * numpy.array([0,1]) 317 return numpy.array([0, 0])
318 319
320 - def __str__(self):
321 res = "\nVerticalWaterCurrents:" 322 for member, value in vars(self).items(): 323 res += " " + member + "=" + str(value) 324 res += "\n" 325 return res
326 327 328 329 330 331 332 333 ################################################### 334 # This part defines the waves base class # 335 # and some concrete class examples # 336 # We don't yet have a good waves model so we just # 337 # ignore it. # 338 ###################################################
339 -class Waves:
340 """ 341 This is a base class for wave models. 342 Currently, we assume that waves just have a direction vector 343 in each location. We ignore the wave height, and the fact 344 that is has some period, and averaging everything out, 345 to assume a direction vector in each (x,y) point. 346 """ 347
348 - def __init__(self):
349 print 'Creating water-current model'
350
351 - def getSpeedVectorInLocation(self, x, y):
352 "Given a location, returns the avg speed vector, for this location" 353 abstract
354
355 -class StaticConstantWaves(Waves):
356 """ 357 This class implements waves that are constant in every point, 358 and never change. 359 """ 360
361 - def __init__(self, directionX, directionY):
362 "Parameters define the constant wave speed vector" 363 self.directionX = directionX 364 self.directionY = directionY
365
366 - def __str__(self):
367 res = "\nStaticConstantWaves:" 368 for member, value in vars(self).items(): 369 res += " " + member + "=" + str(value) 370 res += "\n" 371 return res
372
373 - def getSpeedVectorInLocation(self, x, y):
374 "Given a location, returns the wave vector in it" 375 return numpy.array( [self.directionX, self.directionY] )
376 377 378 379 380 ################################################### 381 # This part defines Obstacles in the sea # 382 ###################################################
383 -class Obstacle:
384 """ 385 An obstacle in the sea. Currently an obstacle is just a 386 straight line. This class support general polygon but, 387 for now we only want line composed of 2 points. It is 388 possible to construct complex obstacles just from 389 straight lines. 390 391 Therfore, for now IGNORE the following: 392 [Currently implemented 393 as a list of points, where connecting each two 394 consecutive points by line defines the obstacle's 395 shape. The first point should be equal to the last one.] 396 """
397 - def __init__(self, points):
398 """ 399 @type points: a list of (x,y) tuples 400 @param points: a list of points - connecting each consecutive pair of points by line defines the obstacle's shape. 401 """ 402 self.points = points 403 # if points[0] != points[-1]: 404 # raise Exception("First point of an obstacle should be equal to the last point") 405 if len(points) != 2: 406 raise Exception("We currently support only straight line obstacles (though this could easily be changed)")
407
408 - def __str__(self):
409 res = "\nObstacle:" 410 # for member, value in vars(self).items(): 411 # res += " " + member + "=" + str(value) 412 for p in self.points: 413 res += " " + str(point) 414 res += "\n" 415 return res
416
417 - def getBorder(self):
418 """ 419 @rtype: tuple 420 @return: a list of points defining the shape of the obstacle 421 """ 422 return self.points
423 424 425
426 -class Obstacles:
427 """ 428 This class models the obstacles part of the sea. 429 """
430 - def __init__(self, obstacleList):
431 """ 432 Initialize the set of obstacles. 433 434 @type obstacleList: a list of Obstacle. 435 @param obstacleList: a list of obstacles. 436 """ 437 print 'Creating obstacles model' 438 self.obstacles = obstacleList
439
440 - def getObstaclesList(self):
441 return self.obstacles
442
443 - def __str__(self):
444 res = "\nObstacles:" 445 # for member, value in vars(self).items(): 446 # res += " " + member + "=" + str(value) 447 for o in self.obstacles: 448 res += str(o) 449 res += "\n" 450 return res
451