SimpleMulticopterMovement.java 7.71 KB
Newer Older
Julian Zobel's avatar
Julian Zobel committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * 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/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.movement.aerial;

23

Julian Zobel's avatar
Julian Zobel committed
24
25
26
27
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
28
29
import de.tud.kom.p2psim.impl.energy.components.ActuatorComponent;
import de.tud.kom.p2psim.impl.energy.components.StatefulActuatorComponent;
Julian Zobel's avatar
Julian Zobel committed
30
31
32
33
34
35
import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback;

/**
36
37
38
 * Local movement for UAVs. 
 * This simple movement logic uses straight forward movement with the set speed (up to a max).
 * Energy consumption is based on state actuators.
Julian Zobel's avatar
Julian Zobel committed
39
40
 * 
 * @author Julian Zobel
41
 * @version 1.1, 14.01.2020
Julian Zobel's avatar
Julian Zobel committed
42
43
44
 */
public class SimpleMulticopterMovement implements UAVMovementModel  {

45
	private UAVTopologyComponent topologyComponent;	
46
47
	private double velocity;	
	private double targetVelocity;
Julian Zobel's avatar
Julian Zobel committed
48
	
49
50
	private double maximumHorizontalVelocity;
	private double maximumVerticalVelocity;
Julian Zobel's avatar
Julian Zobel committed
51
	
52
53
54
55
	// TODO currently not used
	private double minimumHorizontalVelocity;
	private double minimumVerticalVelocity;
	
Julian Zobel's avatar
Julian Zobel committed
56
	private LinkedList<PositionVector> route = new LinkedList<>();
57
	private Map<PositionVector, ReachedLocationCallback> locationCallbacks = new LinkedHashMap<>();  
58
		
59
	private StatefulActuatorComponent motor;
60
		
61
	public SimpleMulticopterMovement(UAVTopologyComponent topologyComponent, double maximumHorizontalVelocity, 
62
			double maximumVerticalVelocity, double minimumHorizontalVelocity, double minimumVerticalVelocity) {
63
64
65
		this.topologyComponent = topologyComponent;		
		this.maximumHorizontalVelocity = maximumHorizontalVelocity;
		this.maximumVerticalVelocity = maximumVerticalVelocity;
66
67
		this.minimumHorizontalVelocity = minimumHorizontalVelocity;
		this.minimumVerticalVelocity = minimumVerticalVelocity;
68
	}	
Julian Zobel's avatar
Julian Zobel committed
69
70
71
	
	@Override
	public void move(long timeBetweenMovementOperations) {
72
				
73
74
75
		if(motor.isOn() && !route.isEmpty()) {		
		
			PositionVector currentPosition = topologyComponent.getRealPosition();
Julian Zobel's avatar
Julian Zobel committed
76
			
77
78
79
			PositionVector targetPosition = route.getFirst();
			Double distanceToTargetPosition = targetPosition.distanceTo(currentPosition);
							
Julian Zobel's avatar
Julian Zobel committed
80
			// If target point is reached within a 1 meter margin, we remove that point from the list 
81
			if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < velocity)
Julian Zobel's avatar
Julian Zobel committed
82
			{						
83
				route.removeFirst();
Julian Zobel's avatar
Julian Zobel committed
84
				
85
				topologyComponent.updateCurrentLocation(targetPosition); // triggers energy consumption for last distance
86
				velocity = 0;
87
88
89
				motor.useActuator(0);
				locationReached(targetPosition);
				return;
Julian Zobel's avatar
Julian Zobel committed
90
			}
91
92
93
			
			double timefactor = timeBetweenMovementOperations / Time.SECOND;
			
94
			velocity = Math.min(distanceToTargetPosition, targetVelocity);					
95
96
97
98
						
			PositionVector direction = new PositionVector(targetPosition);
			direction.subtract(currentPosition);
			direction.normalize();
99
			direction.multiplyScalar(velocity * timefactor);
Julian Zobel's avatar
Julian Zobel committed
100

101
102
			PositionVector newPosition = new PositionVector(currentPosition);
			newPosition.add(direction);		
Julian Zobel's avatar
Julian Zobel committed
103
			
104
105
			motor.useActuator(1);
			topologyComponent.updateCurrentLocation(newPosition);					
Julian Zobel's avatar
Julian Zobel committed
106
		}
Julian Zobel's avatar
Bugfix    
Julian Zobel committed
107
108
		else if(motor.isOn()) {
			
109
			if(velocity != 0) {
Julian Zobel's avatar
Bugfix    
Julian Zobel committed
110
111
112
113
114
115
				throw new UnsupportedOperationException("no route but speed not 0?");
			}
			
			PositionVector position = new PositionVector(topologyComponent.getRealPosition());	
			
			if(position.getAltitude() == 0) {
116
				motor.turnOff();
Julian Zobel's avatar
Bugfix    
Julian Zobel committed
117
118
			}
			else {
119
				motor.useActuator(0);
Julian Zobel's avatar
Bugfix    
Julian Zobel committed
120
121
			}
		}
Julian Zobel's avatar
Julian Zobel committed
122
123
124
	}
		
	@Override
125
126
	public void setTargetVelocity(double v_pref) {
		this.targetVelocity = v_pref;		
Julian Zobel's avatar
Julian Zobel committed
127
128
129
	}
	
	@Override
130
131
	public double getCurrentVelocity() {
		return velocity;
Julian Zobel's avatar
Julian Zobel committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
	}

	/**
	 * Trigger the callback function, if there is a valid callback 
	 * 
	 * @param position
	 */
	private void locationReached(PositionVector position) {
		if(locationCallbacks.containsKey(position)) {
			locationCallbacks.get(position).reachedLocation();
		}
	}
	
	@Override
	public void setTargetLocation(PositionVector target,
			ReachedLocationCallback reachedLocationCallback) {
		route.clear();
		route.add(target);
		if(reachedLocationCallback != null)
			locationCallbacks.put(target, reachedLocationCallback);
		
	}

	@Override
	public void setTargetLocationRoute(LinkedList<PositionVector> route,
			ReachedLocationCallback reachedLocationCallback) {
		this.route.clear();
		this.route.addAll(route);
		if(reachedLocationCallback != null)
			locationCallbacks.put(route.getLast(), reachedLocationCallback);
	}

	@Override
	public void addTargetLocation(PositionVector target,
			ReachedLocationCallback reachedLocationCallback) {
		route.add(target);
		if(reachedLocationCallback != null)
			locationCallbacks.put(target, reachedLocationCallback);
	}

	@Override
	public LinkedList<PositionVector> getTargetLocations() {
		
		LinkedList<PositionVector> copy = new LinkedList<>();
		for (PositionVector pv : route) {
			copy.add(pv.clone());		
		}
		
		return copy;
	}

	@Override
	public void removeTargetLocations() {
		route.clear();
		locationCallbacks.clear();
	}

189
	@Override
190
191
192
	public double estimatePowerConsumptionWatt(double velocity) {
		
		double wattage = 0;
193
194
		
		if(velocity == 0) {
195
			wattage = motor.estimateEnergyConsumptionWatt(0);
196
		}
197
198
		else { 		
			wattage = motor.estimateEnergyConsumptionWatt(1.0);
199
200
		}
		
201
		return wattage;
202
	}
203
204
205
206
207
208
209

	@Override
	public void setMotorControl(ActuatorComponent motor) {
		this.motor = (StatefulActuatorComponent) motor;
	}

	@Override
210
211
	public double getVerticalAscentMaxVelocity() {
		return maximumVerticalVelocity;
212
213
214
	}

	@Override
215
216
	public double getHorizontalMaxVelocity() {
		return maximumHorizontalVelocity;
217
	}
218
	
219
	@Override	
220
	public double getHorizontalMinVelocity() {
221
222
		return 0;
	}
223
224
225
226
227
228
229
230
	
	/**
	 * Factory for this movement model
	 * 
	 * @author Julian Zobel
	 * @version 1.0, 14.01.2020
	 */
	public static class Factory implements AerialMovementModelFactory {
231
232
233
234
235
236
237
238
239
240
241
242
243
		
		private double maximumHorizontalVelocity = 15;
		
		public void setMaximumHorizontalVelocity(double maximumHorizontalVelocity) {
			this.maximumHorizontalVelocity = maximumHorizontalVelocity;
		}

		private double maximumVerticalVelocity = 5;		
		
		public void setMaximumVerticalVelocity(double maximumVerticalVelocity) {
			this.maximumVerticalVelocity = maximumVerticalVelocity;
		}
		
244
245
246
247
248
249
250
251
252
253
254
255
		private double minimumHorizontalVelocity = 15;
		
		public void setMinimumHorizontalVelocity(double minimumHorizontalVelocity) {
			this.minimumHorizontalVelocity = minimumHorizontalVelocity;
		}
		
		private double minimumVerticalVelocity = 5;		
		
		public void setMinimumVerticalVelocity(double minimumVerticalVelocity) {
			this.minimumVerticalVelocity = minimumVerticalVelocity;
		}
		
256
		public UAVMovementModel createComponent(UAVTopologyComponent topologyComponent) {
257
258
			return new SimpleMulticopterMovement(topologyComponent, maximumHorizontalVelocity, 
					maximumVerticalVelocity, minimumHorizontalVelocity, minimumVerticalVelocity);
259
		}			
260
	}
261
262
263
264
265

	@Override
	public double estimateOptimalSpeed() {
		return maximumHorizontalVelocity;
	}
Julian Zobel's avatar
Julian Zobel committed
266
}