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

Source Code for Module seaModels

  1  ################################################################################## 
  2  # Copyright (c) 2010, 2011, 2012, 2013, 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 - def __init__(self, points):
216 self.points = points 217 218 b = self.points 219 220 # First area of rough weather 221 b5 = numpy.array(b[5]) 222 b34 = numpy.array(b[34]) 223 b3 = numpy.array(b[3]) 224 225 tmp = b34 - b5 226 self.bay1Line = tmp * 1.0 / linalg.norm(tmp) 227 228 # normalize and compute the normal for this line and intercept 229 self.normalBay1Line = numpy.array([self.bay1Line[1], -self.bay1Line[0]]) 230 231 # Computed border values for bay1 232 self.border1VerticalValueTop = dot(self.normalBay1Line, b5) 233 self.border1VerticalValueBottom = dot(self.normalBay1Line, b3) 234 self.border1VerticalValueMiddle = (self.border1VerticalValueTop + 235 self.border1VerticalValueBottom) * 1.0 / 2 236 self.border1HorizonalValueTop = dot(self.bay1Line, b34) + 50 237 self.border1HorizonalValueBottom = dot(self.bay1Line, b5) - 50 238 self.border1HorizonalValueMiddle = (self.border1HorizonalValueTop + 239 self.border1HorizonalValueBottom) * 1.0 / 2 240 241 242 # Second area of rough water 243 b25 = numpy.array(b[25]) 244 b24 = numpy.array(b[24]) 245 b13 = numpy.array(b[13]) 246 b14 = numpy.array(b[14]) 247 248 tmp = b25 - b24 249 self.bay2Line = tmp * 1.0 / linalg.norm(tmp) 250 251 # normalize and compute the normal for this line and intercept 252 self.normalBay2Line = numpy.array([self.bay2Line[1], -self.bay2Line[0]]) 253 254 # Computed "top-bottom" border values for bay1 255 self.border2VerticalValueTop = dot(self.normalBay2Line, b24) + 50 256 self.border2VerticalValueBottom = dot(self.normalBay2Line, b13) - 50 257 self.border2VerticalValueMiddle = (self.border2VerticalValueTop + 258 self.border2VerticalValueBottom) * 1.0 / 2 259 self.border2HorizonalValueTop = dot(self.bay2Line, b25) 260 self.border2HorizonalValueBottom = dot(self.bay2Line, b14) 261 self.border2HorizonalValueMiddle = (self.border2HorizonalValueTop + 262 self.border2HorizonalValueBottom) * 1.0 / 2
263
264 - def __str__(self):
265 res = "\nIslandWaterCurrents:" 266 for member, value in vars(self).items(): 267 res += " " + member + "=" + str(value) 268 res += "\n" 269 return res
270
271 - def getSpeedVectorInLocation(self, x, y):
272 # If in bay 1 - hard to cross 273 p = numpy.array((x,y)) 274 dot1 = dot(p, self.normalBay1Line) 275 dot2 = dot(p, self.bay1Line) 276 inSideBay1 = ((self.border1VerticalValueBottom <= dot1 <= self.border1VerticalValueTop) and 277 (self.border1HorizonalValueBottom <= dot2 <= self.border1HorizonalValueTop)) 278 if inSideBay1: 279 return self.bay1Line * 8 280 281 dot1 = dot(p, self.normalBay2Line) 282 dot2 = dot(p, self.bay2Line) 283 inSideBay2 = (self.border2VerticalValueBottom <= dot1 <= self.border2VerticalValueTop and 284 self.border2HorizonalValueBottom <= dot2 <= self.border2HorizonalValueTop) 285 if inSideBay2: 286 return self.normalBay2Line * -8 287 288 # other wise, random mild current 289 waterSpeed = random.weibullvariate(1,2) 290 waterDirection = random.randint(0,360) 291 return numpy.array( waterSpeed * cos(radians(waterDirection)), waterSpeed * sin(radians(waterDirection)) )
292
293 -class VerticalWaterCurrents(WaterCurrents):
294 """ 295 Defines north->south or south->north currents. 296 Was used for the AAAI 11 experiments. 297 """ 298
299 - def __init__(self, regionsAndCurrentsList):
300 """ 301 @type regionsAndCurrentsList: list of 3-tuples 302 @param regionsAndCurrentsList: a list of 3-tuples, each defines a stripe: (minX, maxX, currentValue), where currentValue is signed to account for direction. 303 """ 304 self.regionsAndCurrentsList = regionsAndCurrentsList
305
306 - def getSpeedVectorInLocation(self, x, y):
307 """ 308 Check stripe and return corresponding current. 309 """ 310 for p1, p2, current in self.regionsAndCurrentsList: 311 x1 = p1[0] 312 x2 = p2[0] 313 if x1 <= x <= x2: 314 # vertical normal multiplied by the current value 315 return current * numpy.array([0,1]) 316 return numpy.array([0, 0])
317 318
319 - def __str__(self):
320 res = "\nVerticalWaterCurrents:" 321 for member, value in vars(self).items(): 322 res += " " + member + "=" + str(value) 323 res += "\n" 324 return res
325 326 327 328 329 330 331 332 ################################################### 333 # This part defines the waves base class # 334 # and some concrete class examples # 335 # We don't yet have a good waves model so we just # 336 # ignore it. # 337 ###################################################
338 -class Waves:
339 """ 340 This is a base class for wave models. 341 Currently, we assume that waves just have a direction vector 342 in each location. We ignore the wave height, and the fact 343 that is has some period, and averaging everything out, 344 to assume a direction vector in each (x,y) point. 345 """ 346
347 - def __init__(self):
348 print 'Creating water-current model'
349
350 - def getSpeedVectorInLocation(self, x, y):
351 "Given a location, returns the avg speed vector, for this location" 352 abstract
353
354 -class StaticConstantWaves(Waves):
355 """ 356 This class implements waves that are constant in every point, 357 and never change. 358 """ 359
360 - def __init__(self, directionX, directionY):
361 "Parameters define the constant wave speed vector" 362 self.directionX = directionX 363 self.directionY = directionY
364
365 - def __str__(self):
366 res = "\nStaticConstantWaves:" 367 for member, value in vars(self).items(): 368 res += " " + member + "=" + str(value) 369 res += "\n" 370 return res
371
372 - def getSpeedVectorInLocation(self, x, y):
373 "Given a location, returns the wave vector in it" 374 return numpy.array( [self.directionX, self.directionY] )
375 376 377 378 379 ################################################### 380 # This part defines Obstacles in the sea # 381 ###################################################
382 -class Obstacle:
383 """ 384 An obstacle in the sea. Currently an obstacle is just a 385 straight line. This class support general polygon but, 386 for now we only want line composed of 2 points. It is 387 possible to construct complex obstacles just from 388 straight lines. 389 390 Therfore, for now IGNORE the following: 391 [Currently implemented 392 as a list of points, where connecting each two 393 consecutive points by line defines the obstacle's 394 shape. The first point should be equal to the last one.] 395 """
396 - def __init__(self, points):
397 """ 398 @type points: a list of (x,y) tuples 399 @param points: a list of points - connecting each consecutive pair of points by line defines the obstacle's shape. 400 """ 401 self.points = points 402 # if points[0] != points[-1]: 403 # raise Exception("First point of an obstacle should be equal to the last point") 404 if len(points) != 2: 405 raise Exception("We currently support only straight line obstacles (though this could easily be changed)")
406
407 - def __str__(self):
408 res = "\nObstacle:" 409 # for member, value in vars(self).items(): 410 # res += " " + member + "=" + str(value) 411 for p in self.points: 412 res += " " + str(point) 413 res += "\n" 414 return res
415
416 - def getBorder(self):
417 """ 418 @rtype: tuple 419 @return: a list of points defining the shape of the obstacle 420 """ 421 return self.points
422 423 424
425 -class Obstacles:
426 """ 427 This class models the obstacles part of the sea. 428 """
429 - def __init__(self, obstacleList):
430 """ 431 Initialize the set of obstacles. 432 433 @type obstacleList: a list of Obstacle. 434 @param obstacleList: a list of obstacles. 435 """ 436 print 'Creating obstacles model' 437 self.obstacles = obstacleList
438
439 - def getObstaclesList(self):
440 return self.obstacles
441
442 - def __str__(self):
443 res = "\nObstacles:" 444 # for member, value in vars(self).items(): 445 # res += " " + member + "=" + str(value) 446 for o in self.obstacles: 447 res += str(o) 448 res += "\n" 449 return res
450