1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 from math import *
40
41 from perceptModels import *
42
43
44
45
47 """
48 Interface for the perception system of a ship.
49 """
50
52 """
53 An abstract function, that defines an interface for perception.
54 Its input is the full world state, and its output is a list
55 of percepts that the ships senses, based on the current world
56 state.
57 """
58 abstract
59
60
62 "Percepts the complete state of the world"
63
68
69
70
71
72
73
74
76 """
77 This class describes a general ship.
78 A ship has:
79 - Perception capability
80 - A set of legal actions that can be applied to it, through its interface functions.
81 - An internal state (currently the state of it's actuators)
82 that is controlled through the set of legal actions.
83 - Functions that describes its response to the environment, and depends on its
84 physical properties.
85
86 Any implementation of any of the above part can be plugged-in, allowing
87 to mix different combinations of capabilities into a ship.
88
89 A ship's external state, which is its coordinates, velocity, orientation
90 and so on, is not part of the ship itself, but part of the environment,
91 and is part of the world state.
92 """
93
94
95
96 - def __init__(self, perceptionModule = CompleteStatePerceptionModule(),
97 initialEngineSpeed = 0,
98 initialSteering = 0,
99 maxSpeed = 40,
100 minSpeed = -10,
101 maxSteering = 90,
102 minSteering = -90,
103 mass = 1000,
104
105 length = 12):
106
107 self.perception = perceptionModule
108 self.engineSpeed = initialEngineSpeed
109 self.steering = initialSteering
110 self.maxSpeed = maxSpeed
111 self.minSpeed = minSpeed
112 self.maxSteering = maxSteering
113 self.minSteering = minSteering
114 self.mass = mass
115 self.length = length
116
118 res = "\nShip:"
119 for member, value in vars(self).items():
120 res += " " + member + "=" + str(value)
121 return res
122
123
124
125
126
127
129 """
130 We view the ship as receiving a full world state
131 and then "filtering" it to only the percepts it is
132 able to process. Philosophically, we could view
133 the world that way: we are only able to process
134 part of the complete information that surrounds us.
135 """
136 return self.perception.getListOfPercepts(fullState)
137
139 """
140 Change the internal state of a ship as a result of an action
141 that was chosen by the ship agent.
142 The 'action' argument can be a (possibly empty) composite action,
143 and in general is a list of pairs of the form (methodname, args),
144 such that self.methodname(args) is executed for each pair.
145 """
146 for a in action.primitiveActions:
147 getattr(self, a.functionName) (*a.args)
148
149
150
151
152
153
155 if steering < self.minSteering or steering > self.maxSteering:
156 print '-W- steering is out of range, action has no affect'
157 return
158 print '-W- steering is out of range, fix that'
159 self.steering = steering
160
161
163 if speed < self.minSpeed or speed > self.maxSpeed:
164 print '-W- speed is out of range, action has no affect'
165 return
166 print '-W- speed is out of range, fix that'
167 self.engineSpeed = speed
168
170 """Stop the ship.
171 This function might need to be changed because it will not always be
172 correct that setting everything to 0 will stop it
173 """
174 self.setSteering(0)
175 self.setEngineSpeed(0)
176
177
178
179
180
181
183 """
184 Computing the forward force applied on the ship based on the engine and the drag forces.
185 """
186 forwardDragConstant = 100.0
187
188 engineForce = self.engineSpeed * 50.0
189
190 dragForce = -shipSpeed * abs(shipSpeed) * forwardDragConstant
191
192 return engineForce + dragForce
193
195 """Computing the steering force based on the, the speed, the drag and so on."""
196
197 const = 1.5
198 angularDragConst = 0.5
199 rudderForce = sin(radians(self.steering)) * shipSpeed * const
200
201 dragForce = -shipAngularSpeed * abs(shipAngularSpeed) * angularDragConst
202
203 return rudderForce + dragForce
204
206 return forwardForce / self.mass
207
209 """
210 Assuming mass is spread homogenously.
211 Using formulas from http://rockpile.phys.virginia.edu/arch16.pdf
212 that relates angular acceleration to torque.
213 """
214 radius = self.length / 2.0
215 return degrees( steeringForce / ( 1 / 12.0 * self.mass * radius) )
216
218 """
219 Compute a ship's response to the environment conditions.
220
221 @type windVector: NumPy vector
222 @param windVector: vector of the wind in the ship's location
223
224 @type currentVector: a numpy vector
225 @param currentVector: vector of the current in the ship's location
226
227 @type orient: float
228 @param orient: The ship's orientation (part of determining the response)
229
230 @rtype: NumPy vector
231 @return: An (x, y) offset of the ship, as a numpy vector
232 """
233
234 windConstant = 0.01
235 currentConstant = 0.1
236 return windConstant * windVector + currentConstant * currentVector
237