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