1 package Steerings;
2
3 import SteeringStuff.SteeringManager;
4 import SteeringStuff.SteeringTools;
5 import SteeringStuff.RefBoolean;
6 import SteeringStuff.ISteering;
7
8 import java.util.List;
9
10 import javax.vecmath.Tuple3d;
11 import javax.vecmath.Vector2d;
12 import javax.vecmath.Vector3d;
13
14 import SteeringProperties.PathFollowingProperties;
15 import SteeringProperties.SteeringProperties;
16 import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
17 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
18 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
19 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange;
21 import cz.cuni.amis.utils.future.FutureStatus;
22
23
24
25
26
27
28 public class PathFollowingSteer implements ISteering {
29
30
31 private UT2004Bot botself;
32
33
34
35 private int repulsiveForce;
36
37 int distanceFromThePath;
38
39 IPathFuture<ILocated> pathFuture;
40
41 List<ILocated> path;
42
43 double regulatingForce;
44
45 private int projection;
46
47 private static int NEARLY_THERE_DISTANCE = 150;
48
49
50 Location previousLocation;
51
52 Location nextLocation;
53
54 int actualIndex;
55
56 double lastDistanceFromNextLocation;
57
58 boolean newPath;
59
60 private static boolean ZERO_DISTANCE = false;
61
62
63
64
65
66
67 public PathFollowingSteer(UT2004Bot bot) {
68 botself = bot;
69 actualIndex = 0;
70 }
71
72
73
74
75 public Vector3d run(Vector3d scaledActualVelocity, RefBoolean wantsToGoFaster, RefBoolean wantsToStop, Location focus) {
76 Vector3d nextVelocity;
77 Vector3d actualVelocity = botself.getVelocity().getVector3d();
78 Location pointHeading;
79 Vector3d pointHeadingToFoot;
80 double distanceFromNextLocation;
81
82 nextVelocity = new Vector3d(0,0,0);
83
84 if (pathFuture == null) {
85 if (SteeringManager.DEBUG) System.out.println("path null");
86 return new Vector3d(0,0,0);
87 }
88
89 if (!newPath && pathFuture.getStatus() != FutureStatus.FUTURE_IS_READY) {
90 if (SteeringManager.DEBUG) System.out.println("path not ready");
91 return new Vector3d(0,0,0);
92 }
93
94 if (newPath && pathFuture.getStatus() == FutureStatus.FUTURE_IS_READY) {
95 setComputedPath();
96 }
97
98 if (path == null) {
99 setComputedPath();
100 }
101
102
103
104 boolean shifted = shiftNextLocation();
105 distanceFromNextLocation = botself.getLocation().getDistance(nextLocation);
106
107
108 if (ZERO_DISTANCE) {
109 if (shifted) {
110
111 if (actualIndex + 1 >= path.size()) {
112
113 if (distanceFromNextLocation <= NEARLY_THERE_DISTANCE) {
114 wantsToStop.setValue(true);
115 if (SteeringManager.DEBUG) System.out.println("We reached the target point of the path.");
116 }
117 return nextVelocity;
118 }
119 }
120 Location botsLoc = botself.getLocation();
121 Vector3d toNextLoc = new Vector3d(nextLocation.x - botsLoc.x, nextLocation.y - botsLoc.y, nextLocation.z - botsLoc.z);
122 toNextLoc.normalize();
123 toNextLoc.scale(repulsiveForce);
124 nextVelocity.add(toNextLoc);
125 return nextVelocity;
126 }
127
128
129 if (!shifted) {
130 if (lastDistanceFromNextLocation < distanceFromNextLocation) {
131 lastDistanceFromNextLocation = distanceFromNextLocation;
132 if (SteeringManager.DEBUG) System.out.println("Jdeme na spatnou stranu!");
133
134
135 Vector3d rightDirectionForce = new Vector3d(nextLocation.x - previousLocation.x, nextLocation.y - previousLocation.y, 0);
136 rightDirectionForce.normalize();
137 if (SteeringManager.DEBUG) System.out.println("Od správného směru jsme se odchýlili o "+rightDirectionForce.angle(botself.getVelocity().getVector3d()));
138 double scale = rightDirectionForce.angle(botself.getVelocity().getVector3d())/Math.PI;
139 rightDirectionForce.scale(repulsiveForce*scale);
140 nextVelocity.add((Tuple3d) rightDirectionForce);
141 wantsToGoFaster.setValue(false);
142 return nextVelocity;
143 } else {
144 lastDistanceFromNextLocation = distanceFromNextLocation;
145 }
146 } else {
147 lastDistanceFromNextLocation = distanceFromNextLocation;
148 if (actualIndex + 1 >= path.size()) {
149
150 if (distanceFromNextLocation <= NEARLY_THERE_DISTANCE) {
151 wantsToStop.setValue(true);
152
153 if (SteeringManager.DEBUG) System.out.println("We reached the target point of the path.");
154 } else {
155 Vector3d botToNextLocation = new Vector3d(nextLocation.x - botself.getLocation().x, nextLocation.y - botself.getLocation().y, nextLocation.z - botself.getLocation().z);
156 botToNextLocation.scale(actualVelocity.length() / botToNextLocation.length());
157 nextVelocity.add((Tuple3d) botToNextLocation);
158 if (SteeringManager.DEBUG) System.out.println("We must go to the target point.");
159 }
160 return nextVelocity;
161 }
162 }
163
164
165 ConfigChange cc = botself.getWorldView().getSingle(ConfigChange.class);
166 double oneTick = cc.getVisionTime();
167
168 double projectionTime = projection * oneTick;
169
170
171 Vector3d shift = new Vector3d(projectionTime * actualVelocity.x, projectionTime * actualVelocity.y, projectionTime * actualVelocity.z);
172
173
174 pointHeading = new Location(botself.getLocation().x + shift.x, botself.getLocation().y + shift.y, botself.getLocation().z + shift.z);
175
176 Vector2d start = new Vector2d(previousLocation.x, previousLocation.y);
177 Vector2d end = new Vector2d(nextLocation.x, nextLocation.y);
178 Vector2d pointP = new Vector2d(pointHeading.x, pointHeading.y);
179
180 Vector2d foot = SteeringTools.getNearestPoint(start, end, pointP, false);
181
182
183 pointHeadingToFoot = new Vector3d(foot.x - pointHeading.getX(), foot.y - pointHeading.getY(), 0);
184
185
186 if (pointHeadingToFoot.length() > distanceFromThePath) {
187 double distOut = pointHeadingToFoot.length() - distanceFromThePath;
188
189
190
191
192
193
194
195
196
197
198 double koefA = distOut / distanceFromThePath;
199 if (koefA > 2) {
200 koefA = 2;
201 }
202 nextVelocity.add(pointHeadingToFoot);
203 nextVelocity.normalize();
204 nextVelocity.scale(koefA * repulsiveForce + 30);
205 if (SteeringManager.DEBUG) System.out.println("STAY IN CORRIDOR!");
206 wantsToGoFaster.setValue(false);
207 } else {
208 wantsToGoFaster.setValue(true);
209 }
210
211 Vector3d regulatingVector = new Vector3d(nextLocation.x - previousLocation.x,nextLocation.y - previousLocation.y,0);
212 regulatingVector.normalize();
213 regulatingVector.scale(regulatingForce);
214 nextVelocity.add((Tuple3d) regulatingVector);
215
216 return nextVelocity;
217 }
218
219 private boolean shiftNextLocation() {
220 if (path == null) return false;
221 if (SteeringManager.DEBUG) System.out.println("vzdalenost od nextLocation "+botself.getLocation().getDistance(nextLocation));
222
223 if (botself.getLocation().getDistance(nextLocation) <= distanceFromThePath || getBehindBorder()) {
224 if (actualIndex + 1 < path.size()) {
225 if (SteeringManager.DEBUG) {
226 System.out.println("Novy navpoint; size " + path.size() + " actual index " + actualIndex);
227 }
228 ILocated help = path.get(actualIndex + 1);
229 if (help == null) {
230 if (SteeringManager.DEBUG) {
231 System.out.println("NULL!!! " + pathFuture.getStatus() + pathFuture.isDone());
232 }
233 } else {
234 actualIndex++;
235 previousLocation = nextLocation;
236 nextLocation = help.getLocation();
237 }
238 }
239 return true;
240 } else {
241 return false;
242 }
243 }
244
245
246 private boolean getBehindBorder() {
247
248 Vector2d startA = new Vector2d(previousLocation.x, previousLocation.y);
249 Vector2d endA = new Vector2d(botself.getLocation().x, botself.getLocation().y);
250 Vector2d directionA = new Vector2d(endA.x - startA.x, endA.y - startA.y);
251
252
253
254 Vector2d startB = new Vector2d(nextLocation.x, nextLocation.y);
255 Vector2d normalDirectionB = new Vector2d(nextLocation.x - previousLocation.x, nextLocation.y - previousLocation.y);
256 Vector2d directionB = new Vector2d(-normalDirectionB.y, normalDirectionB.x);
257
258
259 Vector2d intersection = SteeringTools.getIntersection(startA, directionA, startB, directionB, SteeringTools.LineType.ABSCISSA, SteeringTools.LineType.STRAIGHT_LINE);
260
261 if (SteeringManager.DEBUG) System.out.println("Jsme za hranicí "+(intersection != null)+" průsečík: "+intersection);
262 return (intersection != null);
263 }
264
265
266 private boolean setComputedPath() {
267 List<ILocated> myNewPath = this.pathFuture.get();
268 if (myNewPath == null) {
269 if (SteeringManager.DEBUG) System.out.println("null cesta ");
270 return false;
271 } else if (myNewPath.size() < 1) {
272 if (SteeringManager.DEBUG) System.out.println("kratka cesta " + myNewPath.size());
273 return false;
274 }
275 if (SteeringManager.DEBUG) System.out.println("path received " + myNewPath.size());
276 if (differentNewPath(myNewPath)) {
277 path = myNewPath;
278 actualIndex = getIndexOfNearestILocated();
279 nextLocation = path.get(actualIndex).getLocation();
280 previousLocation = botself.getLocation();
281 lastDistanceFromNextLocation = botself.getLocation().getDistance(nextLocation);
282 }
283 newPath = false;
284 return true;
285 }
286
287 private boolean differentNewPath(List<ILocated> myNewPath) {
288 if (path == null) {
289 return true;
290 } else if (myNewPath == null) {
291 return false;
292 } else if (path.size() != myNewPath.size()) {
293 return true;
294 } else {
295 for(int i = 0; i < path.size(); i++) {
296 ILocated a = path.get(i);
297 ILocated b = myNewPath.get(i);
298 if (!a.equals(b)) {
299 return true;
300 }
301 }
302 return false;
303 }
304 }
305
306
307 private int getIndexOfNearestILocated() {
308 int result = 0;
309 Location botsLocation = botself.getLocation();
310 double dist = botsLocation.getDistance(path.get(0).getLocation());
311 for(int index = 0; index < path.size(); index++) {
312 ILocated il = path.get(index);
313 if (botsLocation.getDistance(il.getLocation()) < dist) {
314 result = index;
315 dist = botsLocation.getDistance(il.getLocation());
316 }
317 }
318 return result;
319 }
320
321 public void setProperties(SteeringProperties newProperties) {
322 this.repulsiveForce = ((PathFollowingProperties)newProperties).getRepulsiveForce();
323 this.distanceFromThePath = ((PathFollowingProperties)newProperties).getDistanceFromThePath();
324 this.pathFuture = ((PathFollowingProperties)newProperties).getPath();
325 this.regulatingForce = ((PathFollowingProperties)newProperties).getRegulatingForce();
326 this.projection = ((PathFollowingProperties)newProperties).getProjection();
327 if (path != null) {
328 newPath = true;
329 } else {
330 newPath = false;
331 }
332 }
333
334 public PathFollowingProperties getProperties() {
335 PathFollowingProperties properties = new PathFollowingProperties();
336 properties.setRepulsiveForce(repulsiveForce);
337 properties.setDistanceFromThePath(distanceFromThePath);
338 properties.setPath(pathFuture);
339 properties.setRegulatingForce(regulatingForce);
340 properties.setProjection(projection);
341 return properties;
342 }
343
344 }
345
346
347
348
349
350