UAVTopologyComponent.java 13.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

21
package de.tud.kom.p2psim.impl.topology.component;
22

23
import java.util.LinkedList;
24
25
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
26
import de.tud.kom.p2psim.api.energy.Battery;
27
28
import de.tud.kom.p2psim.api.energy.ComponentType;
import de.tud.kom.p2psim.api.energy.EnergyModel;
29
import de.tud.kom.p2psim.api.network.SimNetInterface;
30
import de.tud.kom.p2psim.api.topology.Topology;
31
import de.tud.kom.p2psim.api.topology.TopologyComponent;
32
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
33
import de.tud.kom.p2psim.api.topology.movement.SimUAVLocationActuator;
34
35
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
36
import de.tud.kom.p2psim.impl.energy.RechargeableBattery;
37
import de.tud.kom.p2psim.impl.energy.components.ActuatorComponent;
38
39
import de.tud.kom.p2psim.impl.energy.models.AbstractEnergyModel;
import de.tud.kom.p2psim.impl.topology.placement.UAVBasePlacement;
40
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
41
import de.tudarmstadt.maki.simonstrator.api.Monitor;
42
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
43
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
Julian Zobel's avatar
Julian Zobel committed
44
import de.tudarmstadt.maki.simonstrator.api.component.overlay.OverlayComponent;
45
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
46
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
Julian Zobel's avatar
Julian Zobel committed
47
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.BaseConnectionCallback;
48
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.BatteryReplacementCallback;
49
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback;
Julian Zobel's avatar
Julian Zobel committed
50
import de.tudarmstadt.maki.simonstrator.api.uavsupport.communication.UAVToBaseInterface;
51

Julian Zobel's avatar
Julian Zobel committed
52
/**
Julian Zobel's avatar
Julian Zobel committed
53
 * Topology component extension providing a broader topology functionality for UAVs
Julian Zobel's avatar
Julian Zobel committed
54
55
56
57
 * 
 * @author Julian Zobel
 * @version 1.0, 06.09.2018
 */
58
public class UAVTopologyComponent extends AbstractTopologyComponent implements SimUAVLocationActuator {
59
	
Julian Zobel's avatar
Julian Zobel committed
60
	public enum UAVstate {OFFLINE, BASE_CONNECTION, BASE_CONNECTION_READY, ACTION, RETURN, CRASHED}
61
	
62
	private UAVMovementModel movement;
63
	
64
65
	private OverlayComponent uavOverlayComponent;
	
Julian Zobel's avatar
Julian Zobel committed
66
67
	protected PositionVector direction;
	
68
	private ActuatorComponent actuator;
69
70
	private RechargeableBattery battery;
	
71
	private UAVstate state = UAVstate.OFFLINE;
72
	private PositionVector baseLocation;
Julian Zobel's avatar
Julian Zobel committed
73
	
Julian Zobel's avatar
Julian Zobel committed
74
75
	private UAVToBaseInterface controllerInterface;
	
76
77
78
79
80
81
82
83
84
	/**
	 * Create a TopologyComponent for the current host.
	 *
	 * @param host
	 * @param topology
	 * @param movementModel
	 */
	public UAVTopologyComponent(SimHost host, Topology topology,
			MovementModel movementModel, PlacementModel placementModel, boolean registerAsInformationProviderInSiS) {
85
		super(host, topology, movementModel, placementModel, registerAsInformationProviderInSiS);		
Julian Zobel's avatar
Julian Zobel committed
86
		direction = new PositionVector(0,-1,0);				
87
88
	}

89
90
91
92
93
94
	@Override
	public void initialize() {		
		super.initialize();
		
		try {
			actuator = getHost().getComponent(EnergyModel.class)
95
					.getComponent(ComponentType.ACTUATOR, ActuatorComponent.class);	
96
			movement.setMotorControl(actuator);
97
98
99
100
101
		} catch (ComponentNotAvailableException e) {
			System.err.println("No Acutator Energy Component was found!");
		}
		
		try {
102
			battery = (RechargeableBattery) getHost().getComponent(AbstractEnergyModel.class).getBattery();
103
104
105
106
				
		} catch (ComponentNotAvailableException e) {
			System.err.println("No Battery Component was found!");
		}
107
		
Julian Zobel's avatar
Julian Zobel committed
108
		// retrieve base location
Julian Zobel's avatar
Julian Zobel committed
109
110
		baseLocation = UAVBasePlacement.base.position.clone();	
		
111
112
	}
	
Julian Zobel's avatar
Julian Zobel committed
113
	private void setState(UAVstate newState) {
114
		this.state = newState;
115
116
		
		// TODO analyzer
117
118
119
		if(Monitor.hasAnalyzer(UAVStatisticAnalyzer.class)) {
			Monitor.getOrNull(UAVStatisticAnalyzer.class).uavSwitchedStates(this, newState);
		}
120
	}
121
			
122
123
124
	public void setUAVComponent(OverlayComponent uavOverlayComponent) {
		this.uavOverlayComponent = uavOverlayComponent;
	}
125
	
126
127
128
129
	public OverlayComponent getUAVComponent() {
		return uavOverlayComponent;
	}

130
131
	@Override
	public double getMinMovementSpeed() {
132
		return movement.getHorizontalMinVelocity();
133
134
135
136
	}

	@Override
	public double getMaxMovementSpeed() {
137
		return movement.getHorizontalMaxVelocity();
138
139
140
141
	}

	@Override
	public double getMovementSpeed() {
142
		return movement.getCurrentVelocity();
143
144
145
146
	}

	@Override
	public void setMovementSpeed(double speed) {
147
		movement.setTargetVelocity(speed);
148
149
150
	}

	@Override
151
	public boolean isActive() {
152
		if(actuator.isOn()) {
153
			return true;
154
		} else {
155
156
157
158
159
			if(state == UAVstate.ACTION || state == UAVstate.RETURN) {
				this.deactivate();
			}
			return false;
		}
160
161
162
	}

	@Override
163
164
	public boolean activate() {		
		if(actuator.turnOn()) {
165
			this.setState(UAVstate.ACTION);			
166
167
168
169
170
			return true;
		}
		else {
			return false;
		}
171
172
173
174
	}

	@Override
	public boolean deactivate() {
175
		actuator.turnOff();
176
				
177
		if(this.position.getAltitude() != 0) {
178
179
180
181
			this.setState(UAVstate.CRASHED);
			PositionVector l = getCurrentLocation();
			l.setAltitude(0);
			this.updateCurrentLocation(l);
182
183
			uavOverlayComponent.shutdown();	
			shutdownCommunication();
184
			
185
186
			Monitor.log(this.getClass(), Level.WARN, "[UAVTopologyComponent] UAV " + getUAVComponent().getHost().getId() + " crashed at " + getRealPosition(), "");
			
187
188
189
		} else {
			this.setState(UAVstate.OFFLINE);				
		}				
190
		
191
		return true;
192
193
194
	}

	@Override
195
196
	public PositionVector getCurrentLocation() {
		return position.clone();
197
198
199
	}

	@Override
200
	public double getCurrentBatteryLevel() {
201
		return battery.getCurrentPercentage();
202
	}
203
204
205
	
	@Override
	public double getCurrentBatteryEnergy() {
206
		return battery.getCurrentEnergy();
207
	}
208

209
210
211
	public RechargeableBattery getBattery() {
		return battery;
	}
212
	
213
214
215
216
217
	@Override
	public double getMaximumBatteryCapacity() {
		return battery.getMaximumEnergy();
	}
	
218
219
220
221
222
	@Override
	public UAVMovementModel getUAVMovement() {
		return movement;
	}

Julian Zobel's avatar
Julian Zobel committed
223
224
	@Override
	public void setUAVMovement(UAVMovementModel uavMovement) {
225
		this.movement = uavMovement;		
Julian Zobel's avatar
Julian Zobel committed
226
	}
227

228
	@Override
229
	public Set<IAttractionPoint> getAllAttractionPoints() {
230
231
232
233
234
235
		throw new UnsupportedOperationException();
	}

	@Override
	public void setTargetLocation(PositionVector targetLocation,
			ReachedLocationCallback cb) {
Julian Zobel's avatar
Julian Zobel committed
236
237
		if(!isActive()) return;
		
238
239
240
241
242
243
		movement.setTargetLocation(new PositionVector(targetLocation), cb);		
	}

	@Override
	public void addTargetLocation(PositionVector targetLocation,
			ReachedLocationCallback cb) {
Julian Zobel's avatar
Julian Zobel committed
244
245
		if(!isActive()) return;
		
246
247
248
249
250
251
		movement.addTargetLocation(new PositionVector(targetLocation), cb);
	}

	@Override
	public void setTargetLocationRoute(LinkedList<PositionVector> route,
			ReachedLocationCallback cb) {
252
		if(!isActive()) return;
253
254
255
256
257
258
259
260
261
262
263
264
265
		LinkedList<PositionVector> positionvectorlist = new LinkedList<>();
		for (Location loc : route) {
			positionvectorlist.add(new PositionVector(loc));
		}
		movement.setTargetLocationRoute(positionvectorlist, cb);
	}

	@Override
	public void removeAllTargetLocations() {
		movement.removeTargetLocations();
	}

	@Override
266
	public void setTargetAttractionPoint(IAttractionPoint targetAttractionPoint) {
267
268
269
270
		throw new UnsupportedOperationException();		
	}

	@Override
271
	public IAttractionPoint getCurrentTargetAttractionPoint() {
272
273
274
275
276
277
278
279
		throw new UnsupportedOperationException();
	}

	@Override
	public LinkedList<PositionVector> getTargetLocations() {
		return movement.getTargetLocations();
	}

280
281
282
	public UAVstate getUAVState() {
		return state;
	}
283
	
284
	private PositionVector getBaseReturnLocation() {
Julian Zobel's avatar
Julian Zobel committed
285
286
287
288
289
290
291
		PositionVector locationOverBase = baseLocation.clone();
		locationOverBase.setAltitude(10);
		
		return locationOverBase;
	}
	
	@Override
292
293
	public void returnToBase(double velocity, ReachedLocationCallback cb) {
		if(!isActive()) return;
Julian Zobel's avatar
Julian Zobel committed
294
		movement.setTargetVelocity(velocity);
295
		movement.setTargetLocation(getBaseReturnLocation(), cb);	
Julian Zobel's avatar
Julian Zobel committed
296
297
	}

298
	@Override
Julian Zobel's avatar
Julian Zobel committed
299
	public boolean landAtBase(BaseConnectionCallback cb) {
300
301
302
		if(!isActive()) return false;
		
		if(isOverBaseLocation()) {
Julian Zobel's avatar
Julian Zobel committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
			this.setState(UAVstate.RETURN);		
			
			ReachedLocationCallback landedCallback = new ReachedLocationCallback() {
				
				@Override
				public void reachedLocation() {
					deactivate();
					connectToBase(cb);				
				}
			};
			
			movement.setTargetVelocity(5);
			movement.setTargetLocation(baseLocation, landedCallback);
			
			return true;
		}
		else return false;
	}	
321
		
Julian Zobel's avatar
Julian Zobel committed
322
323
	@Override
	public boolean startFromBase(ReachedLocationCallback cb) {
324
		if(this.getCurrentLocation().equals(baseLocation)
Julian Zobel's avatar
Julian Zobel committed
325
326
327
328
329
				&& state == UAVstate.BASE_CONNECTION_READY 
				&& activate()) {
			disconnectFromBase();
						
			movement.setTargetVelocity(movement.getVerticalAscentMaxVelocity());
330
			movement.setTargetLocation(getBaseReturnLocation(), cb);
331
			
Julian Zobel's avatar
Julian Zobel committed
332
333
334
			return true;
		}
		else return false;
335
336
		
	}
Julian Zobel's avatar
Julian Zobel committed
337
	
338
339
340
	private boolean isOverBaseLocation() {
		if(this.getCurrentLocation().getX() == baseLocation.getX() 
				&& this.getCurrentLocation().getY() == baseLocation.getY()) {
Julian Zobel's avatar
Julian Zobel committed
341
342
343
344
345
			return true;
		}
		else return false;
	}
	
346
		
Julian Zobel's avatar
Julian Zobel committed
347
	private void batteryReplacement(BatteryReplacementCallback cb) {
348
		
349
		if(state != UAVstate.BASE_CONNECTION) {
350
			throw new UnsupportedOperationException("Cannot recharge if not connected to base!");
351
		}
352
		
Julian Zobel's avatar
Julian Zobel committed
353
354
		this.setState(UAVstate.OFFLINE);
		
355
		BaseTopologyComponent base = UAVBasePlacement.base;
356
		base.getCharger().charge(this, cb);
357
	}
358

Julian Zobel's avatar
Julian Zobel committed
359
	public void setControllerInterface(UAVToBaseInterface controllerInterface) {
Julian Zobel's avatar
Julian Zobel committed
360
361
362
		this.controllerInterface = controllerInterface;			
		this.controllerInterface.setDeploymentArea(topology.getWorldDimensions());
		connectToBase(null);
Julian Zobel's avatar
Julian Zobel committed
363
364
	}

Julian Zobel's avatar
Julian Zobel committed
365
366
367
368
369
370
	/**
	 * Connect to the base and initiate a recharge
	 * 
	 * @param cb
	 */
	private void connectToBase(BaseConnectionCallback cb) {
Julian Zobel's avatar
Julian Zobel committed
371
372
373
		BaseTopologyComponent base = UAVBasePlacement.base;
		base.connectUAVToBase(controllerInterface);	
		
Julian Zobel's avatar
Julian Zobel committed
374
375
376
377
		if(cb != null) {			
			cb.successfulConnection();		
		}
				
378
		this.setState(UAVstate.BASE_CONNECTION);		
379
		shutdownCommunication();
Julian Zobel's avatar
Julian Zobel committed
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
		
		// recharge
		if(battery.getCurrentPercentage() <= 75) {
			batteryReplacement(new BatteryReplacementCallback() {

				@Override
				public void rechargeComplete() {
					setState(UAVstate.BASE_CONNECTION_READY);
					if(cb != null) {
						cb.readyForTakeoff();
					}
				}
			});
		}
		else {
			this.setState(UAVstate.BASE_CONNECTION_READY);		
			if(cb != null) {
				cb.readyForTakeoff();
			}
		}
Julian Zobel's avatar
Julian Zobel committed
400
401
	}

Julian Zobel's avatar
Julian Zobel committed
402
403
	
	private void disconnectFromBase() {
404
405
		startCommunication();
		
Julian Zobel's avatar
Julian Zobel committed
406
		BaseTopologyComponent base = UAVBasePlacement.base;
Julian Zobel's avatar
Julian Zobel committed
407
		base.disconnectUAVFromBase(controllerInterface);		
Julian Zobel's avatar
Julian Zobel committed
408
409
	}

410
411
412
413
	private void shutdownCommunication() {
		for (SimNetInterface net : getHost().getNetworkComponent().getSimNetworkInterfaces()) 
			net.goOffline();
	}
Julian Zobel's avatar
Julian Zobel committed
414

415
416
417
418
	private void startCommunication() {
		for (SimNetInterface net : getHost().getNetworkComponent().getSimNetworkInterfaces()) 
			net.goOnline();
	}
419

Julian Zobel's avatar
Julian Zobel committed
420
421
422
423
424
425
426
427
428
	@Override
	public PositionVector getCurrentDirection() {
		return direction;
	}

	@Override
	public void updateCurrentDirection(PositionVector direction) {
		this.direction.set(direction);
	}
429
	
430
	@Override
431
432
	public double estimatePowerConsumptionWatt(double velocity) {
		return movement.estimatePowerConsumptionWatt(velocity);
433
434
435
	}

	@Override
436
437
438
439
440
441
442
443
444
445
446
	public double estimateFlightDistance(double velocity, double batterylevel, double batterythreshold) {
				
		assert batterylevel > batterythreshold;
		assert batterylevel <= 1.0 && batterylevel >= 0.0;
		assert batterythreshold <= 1.0 && batterythreshold >= 0.0;
		
		double availableEnergy = (battery.getMaximumEnergy() * (batterylevel - batterythreshold)) / Battery.uJconverison; // since battery energy is in uJ, conversion in J is required		
		double powerconsumption = estimatePowerConsumptionWatt(velocity); // J/s (or Watt)				
		double distance = (availableEnergy / powerconsumption) * velocity; // d = (E/P)* v [m]
	
		return distance;
447
	}
448
	
449
450
	@Override
	public PositionVector getBaseLocation() {
451
		return getBaseReturnLocation();
452
453
	}

454
	
455
456
457
458
459
460
461
462
463
464
465
	public static class Factory implements TopologyComponentFactory {

		@Override
		public TopologyComponent createTopologyComponent(SimHost host,
				Topology topology, MovementModel movementModel,
				PlacementModel placementModel,
				boolean registerAsInformationProviderInSiS) {
			return new UAVTopologyComponent(host, topology, movementModel, placementModel, registerAsInformationProviderInSiS);
		}
		
	}
Julian Zobel's avatar
Julian Zobel committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482


	@Override
	public UAVstate getState() {
		return state;
	}

	@Override
	public void updateCurrentLocation(Location location) {		
		super.updateCurrentLocation(location);
		
		if(!actuator.isOn() && (state == UAVstate.ACTION || state == UAVstate.RETURN)) {
			this.deactivate();			
		}
		
	}

483
}