SocialGroupMovementModel.java 16.6 KB
Newer Older
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.modularosm;

23
import java.util.LinkedHashMap;
24
25
26
import java.util.LinkedHashSet;

import de.tud.kom.p2psim.api.scenario.ConfigurationException;
27
import de.tud.kom.p2psim.api.topology.Topology;
28
29
30
31
32
33
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounter.IGroupEncounterBehavior;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming.IGroupFormingBehavior;
Julian Zobel's avatar
wip    
Julian Zobel committed
34
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
35
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
36
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
37
import de.tud.kom.p2psim.impl.util.Either;
38
import de.tudarmstadt.maki.simonstrator.api.Binder;
39
import de.tudarmstadt.maki.simonstrator.api.Event;
40
import de.tudarmstadt.maki.simonstrator.api.Monitor;
41
import de.tudarmstadt.maki.simonstrator.api.Time;
42
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
43
44
45
46
47
48
49
50

/**
 * 
 * @author Julian Zobel
 * @version 1.0, 28.01.2020
 */
public class SocialGroupMovementModel extends ModularMovementModel {

51
52
53
	private final double MEETING_POINT_DISTANCE = 5;
	private final double LEADER_GROUP_DISTANCE = 10;
	
54
55
56
	protected MovementGroupContainer groupContainer;
	protected IGroupFormingBehavior groupFormingBehavior;
	protected IGroupEncounterBehavior groupEncounterBehavior;
57
58
	
	protected IAttractionAssigmentStrategy groupAttractionAssignment;
59
		
60
	
61
	private LinkedHashSet<SimLocationActuator> singleHosts = new LinkedHashSet<SimLocationActuator>();
62
	private int numberOfSingleHosts;
63
64
		
	
65
66
67
	
	@Override
	public void initialize() {
68
		
69
		if (!initialized) {
70
			
71
72
73
74
75
76
77
78
79
80
81
			groupContainer = MovementGroupContainer.getInstance();
			groupFormingBehavior.initialize(this);
			groupEncounterBehavior.initialize(this);
			
			// Choose single hosts
			if(numberOfSingleHosts > 0) {
				do {
					singleHosts.add(getRandomActuator());
				} while(singleHosts.size() < numberOfSingleHosts);
			}
			
82
83
84
85
86
87
88
			if (modelVisualisation == null) {
				modelVisualisation = new ModularMovementModelViz(this);
			}
			VisualizationInjector.injectComponent(modelVisualisation);
			if (mapVisualization != null) {
				VisualizationInjector.injectComponent(mapVisualization);
			}
89
90
91
92
			if (attractionPointViz != null) {
				System.out.println("insert AP viz");
				VisualizationInjector.injectComponent(attractionPointViz);
			}
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

			checkConfiguration();

			// setWayPointModel
			localMovementStrategy.setObstacleModel(Binder
					.getComponentOrNull(Topology.class).getObstacleModel());
			localMovementStrategy.setWaypointModel(Binder
					.getComponentOrNull(Topology.class).getWaypointModel());

			/*
			 * Scale depending on calculation interval, if interval != 1 Second.
			 */
			localMovementStrategy
					.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
			
			attractionAssigment.addAttractionAssignmentListener(this);
Julian Zobel's avatar
Julian Zobel committed
109
			attractionAssigment.setAttractionProvider(attractionProvider);
110

111
112
113
			groupAttractionAssignment.addAttractionAssignmentListener(this);
			groupAttractionAssignment.setAttractionProvider(attractionProvider);
			
114
115
116
			// This adds the mobile hosts (smartphones/users) to the transition
			// strategy
			for (SimLocationActuator ms : moveableHosts) {
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
				if(singleHosts.contains(ms)) {
					attractionAssigment.addComponent(ms);
					
					if(placeNodesAtAP) {
						IAttractionPoint assignment = attractionAssigment.getAssignment(ms);
						ms.updateCurrentLocation(this.addOffset(new PositionVector(assignment),
								(assignment.hasRadius() ? Math.max(assignment.getRadius(), 25.0) : 25.0)));	
						attractionAssigment.updateTargetAttractionPoint(ms, assignment);
					}		
				}
				else {
					groupAttractionAssignment.addComponent(ms);
					
					if(placeNodesAtAP) {
						IAttractionPoint assignment = groupAttractionAssignment.getAssignment(ms);
						ms.updateCurrentLocation(this.addOffset(new PositionVector(assignment),
								(assignment.hasRadius() ? Math.max(assignment.getRadius(), 25.0) : 25.0)));	
						groupAttractionAssignment.updateTargetAttractionPoint(ms, assignment);
					}		
				}
//				//attractionAssigment.addComponent(ms);
//				if(placeNodesAtAP) {
//					IAttractionPoint assignment = attractionAssigment.getAssignment(ms);
//					ms.updateCurrentLocation(this.addOffset(new PositionVector(assignment),
//							(assignment.hasRadius() ? Math.max(assignment.getRadius(), 25.0) : 25.0)));	
//					attractionAssigment.updateTargetAttractionPoint(ms, assignment);
//				}								
144
			}
145
						
146
147
			setTimeBetweenMoveOperations(timeBetweenMoveOperation);

148
149
			// Inform analyzer of resolved movement
			if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {			
150
				Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAllNodeInitializationCompleted(moveableHosts);
151
152
			}
			
153
154
155
156
			// initial move
			move();

			initialized = true;
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
	/**
	 * Returns a random SimLocationActuator component from the set of moveable hosts.
	 * 
	 * @return SimLocationActuator
	 */
	private SimLocationActuator getRandomActuator() {
		
		int index = rand.nextInt(moveableHosts.size());
		int i = 0;
		for(SimLocationActuator actuator : moveableHosts) {
			if(i == index) {
				return actuator;
			}
			i++;
		}

		return null;
	}
	
	/**
	 * The movement model. 
	 * 1) Updates the number of hosts within each attraction point.
	 * 2) Creates and deletes groups, if necessary.
	 * 3) Applies encounter action to meeting groups.
	 * 4) Moves the hosts using doGroupMovement, movement style depends on role of the host (Leader, Participant, Single)
	 */
	@Override
Julian Zobel's avatar
wip    
Julian Zobel committed
188
	protected void move() {	
189
				
190
191
192
		// Check POIs if groups can be created. Delete groups, if destination reached.
		groupFormingBehavior.manageGroups();
		
193
194
		// Checks if groups encounter each other and applies a specified action to these groups.		
		groupEncounterBehavior.handleEncounters();
195
196
	
		/*	
197
198
		 * Moves all nodes according to definition in group movement method
		 */
199
200
		for (SimLocationActuator host : moveableHosts) {
			assert currentTargets.containsKey(host);
201
						
202
			// Single Host Movement
203
204
205
206
			if(singleHosts.contains(host)) {			
				super.doLocalMovement(host, currentTargets.get(host));
			}
			else if( !groupContainer.isGroupMember(host)) {
207
208
209
210
211
212
213
214
				doLocalMovement(host, currentTargets.get(host));
			}
			else if(groupContainer.isGroupMember(host)){
				doGroupMovement(host, currentTargets.get(host));
			}
			else {
				throw new UnsupportedOperationException("SimLocationActuator " + host + " is neither in a group nor a single node");
			}
215
216
	
			// TODO maybe remodel the group movement to do a whole group?
217
			
218
		}
219
220
		
	
221
222
223
		// TODO Move each group
		
		
224
225
226
		Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, EVENT_MOVE);
	}
		
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
	@Override
	protected void doLocalMovement(SimLocationActuator ms, PositionVector destination) {
		Either<PositionVector, Boolean> either = localMovementStrategy.nextPosition(ms, destination);
		
		if (either.hasLeft()) {
			ms.updateCurrentLocation(either.getLeft());
			if(!checkBoundaries(ms.getRealPosition())) {
				System.err.println("Social Group Movement Model: Host moved outside of simulated area!");
			}				
		} 
		else {
			groupAttractionAssignment.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
		}
	}

	
243
244
245
246
247
248
249
250
251
252
253
	/**
	 * Applies movement of the host according to different circumstances:
	 * 
	 * Towards Destination: Host is not a group member || Group has met at meeting point successfully.
	 * Towards MeetingPoint: Host if group member and has not reached meeting point yet.
	 * No movement: Host reached meeting point, but still waits for group members to arrive.
	 * 
	 * @param SimLocationActuator The host to move.
	 * @param PositionVector Destination of the host.
	 */
	protected void doGroupMovement(SimLocationActuator host, PositionVector destination) {
254
255
256
257
		// This host is a member of a group, thus...
		SocialMovementGroup group = groupContainer.getGroupOfHost(host);	
		
		// if the group is currently gathering at a meeting point...
258
		if(movesToGroupMeetingPoint(host)) {
259
			// if this host has already arrived at the group meeting point..
260
			if(hostIsAtMeetingPoint(host)) {
261
262
263
264
				// ... and if the whole group is also at the meeting point...					
				if(groupGatheredAtMeetingPoint(group)) {				
					// remove the meeting point and thus, start moving towards the actual destination								
					group.setMeetingPoint(null);
265
				}
266
267
268
269
270
271
272
				// ... but the group is not gathered at the meeting point, do nothing and wait for the rest.
				else {								
					// inform analyzer of waiting group members
					if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {						
						Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onMemberWaitAtMeetingPoint(group, host);											
					}					
				}				
273
			}
274
275
			// if the host has not reached the group meeting point, move towards it.
			else {				
276
277
				PositionVector mp = groupContainer.getGroupOfHost(host).getMeetingPoint();
				doLocalMovement(host, mp);
278
279
280
281
282
				
				// inform analyzer group member moves to meeting point
				if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {						
					Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onMoveToMeetingPoint(group, host);								
				}
283
284
			}
		}
285
		// ... but if the group is currently on their way to the destination
286
		else {
287
			// the leader does a local movement
288
			if(groupContainer.isLeader(host)) {
Julian Zobel's avatar
Julian Zobel committed
289
				if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) {		
290
291
292
					// inform analyzer of movement to attraction point
					if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {						
						Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMovesToAttractionPoint(group);			
Julian Zobel's avatar
Julian Zobel committed
293
294
					}	
					
295
296
297
298
299
300
301
302
303
304
305
306
307
308
					doLocalMovement(host, destination);		
					
					PositionVector leaderPos = host.getRealPosition();					
					LinkedHashSet<SimLocationActuator> groupMembers = groupContainer.getGroupMembers(host);
					groupMembers.remove(host); // remove leader
									
					for (SimLocationActuator groupMember : groupMembers) {
						// Assign small offset to the host depending on the leaders position.						
						PositionVector offset = new PositionVector(rand.nextDouble() * LEADER_GROUP_DISTANCE, rand.nextDouble() * LEADER_GROUP_DISTANCE);
						PositionVector newPos = leaderPos.plus(offset);
					
						// Update location of host, which will be around the leaders location.
						groupMember.updateCurrentLocation(newPos);
					}
309
310
311
312
313
314
				}
				else {
					// inform analyzer of waiting group
					if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {						
						Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupWait(group);
					}		
315
316
317
				}
			}
		}
318
		
319
320
	}
	
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
	@Override
	public void changeTargetLocation(SimLocationActuator actuator, IAttractionPoint ap) {
		if(singleHosts.contains(actuator)) {
			attractionAssigment.updateTargetAttractionPoint(actuator, ap);
		}
		else {
			groupAttractionAssignment.updateTargetAttractionPoint(actuator, ap);
		}
				
	}	
	
	@Override
	public IAttractionPoint getTargetLocation(SimLocationActuator actuator) {		
		if(singleHosts.contains(actuator)) {
			return attractionAssigment.getAssignment(actuator);
		}
		else {
			return groupAttractionAssignment.getAssignment(actuator);
		}
	}
	
	
343
344
345
346
347
348
349
350
351
352
353
354
	/* 
	 * =====================================================================================================
	 * === MEETING POINT FUNCTIONS
	 * =====================================================================================================
	 */
	/**
	 * Checks if a host is currently on its way to a meeting point or to its destination.
	 * Returns true if moving towards meeting point, false else.
	 * 
	 * @param SimLocationActuator The host to be checked.
	 * @return Boolean
	 */
355
	private boolean movesToGroupMeetingPoint(SimLocationActuator host) {
356
357
358
359
360
		PositionVector meetingpoint = groupContainer.getGroupOfHost(host).getMeetingPoint();
		
		if(meetingpoint == null) 
			return false;		
		else if(meetingpoint != groupContainer.getGroupOfHost(host).getDestination())
361
			return true;
362
363
		else		
			return false;
364
365
366
367
368
369
370
371
	}

	/**
	 * Returns true, if all group members of a host including the host itself reached the meeting point, false else.
	 * 
	 * @param SimLocationActuator The host to be checked.
	 * @return Boolean
	 */
372
373
374
375
376
	private boolean groupGatheredAtMeetingPoint(SocialMovementGroup group) {
	
		for(SimLocationActuator participant : group.getMembers()) {
			if(!hostIsAtMeetingPoint(participant)) {
				return false;
377
378
			}
		}
379
380
		
		return true;
381
382
383
384
385
386
387
388
389
	}

	/**
	 * Returns true if the host reached its current meeting point, false else.
	 * 
	 * @param SimLocationActuator The host to be checked.
	 * @return Boolean
	 * 
	 */
390
	private boolean hostIsAtMeetingPoint(SimLocationActuator host) {
391
392
393
		PositionVector meetingpoint = groupContainer.getGroupOfHost(host).getMeetingPoint();
	
		if(host.getLastLocation().distanceTo(meetingpoint) <= MEETING_POINT_DISTANCE) 			
394
			return true;
395
396
		else
			return false;
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
	}

	/* 
	 * =====================================================================================================
	 * === MOVEMENT FUNCTIONS
	 * =====================================================================================================
	 */
	

	/**
	 * Host position adapts to leaders position by taking the leader position and adding a small offset
	 * 
	 * @param SimLocationActuator The host to be moved.
	 */
	private void followLeader(SimLocationActuator host) {
		SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader();
413
						
414
415
		// Assign small offset to the host depending on the leaders position.
		PositionVector leaderPos = leader.getRealPosition();
416
		PositionVector offset = new PositionVector(rand.nextDouble() * LEADER_GROUP_DISTANCE, rand.nextDouble() * LEADER_GROUP_DISTANCE);
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
		PositionVector newPos = leaderPos.plus(offset);

		// Update location of host, which will be around the leaders location.
		host.updateCurrentLocation(newPos);
	}


	/* 
	 * =====================================================================================================
	 * === GETTER AND SETTER FUNCTIONS
	 * =====================================================================================================
	 */
	
	public void setGroupFormingBehavior(IGroupFormingBehavior defaultGroupForming) {
		if (defaultGroupForming == null) {
			throw new ConfigurationException(
					"GroupFormingStrategy is missing in ModularMovementModel!");
		}
		this.groupFormingBehavior = defaultGroupForming;
	}

	public void setGroupEncounterBehavior(IGroupEncounterBehavior defaultGroupEncounterBehavior) {
		if (defaultGroupEncounterBehavior == null) {
			throw new ConfigurationException(
					"GroupEncounterStrategy is missing in ModularMovementModel!");
		}
		this.groupEncounterBehavior = defaultGroupEncounterBehavior;
	}

Julian Zobel's avatar
wip    
Julian Zobel committed
446
	public IAttractionAssigmentStrategy getAttractionAssignmentStrategy() {
447
		return this.groupAttractionAssignment;
Julian Zobel's avatar
wip    
Julian Zobel committed
448
449
450
451
	}
	
	public IGroupFormingBehavior getGroupFormingBehavior() {
		return groupFormingBehavior;
452
453
454
455
456
457
458
459
460
461
	}

	public LocalMovementStrategy getMovementStrategy() {
		return localMovementStrategy;
	}
	
	public void setNumberOfSingleHosts(int numberOfSingleHosts) {
		this.numberOfSingleHosts = numberOfSingleHosts;
	}
	
462
	public LinkedHashSet<SimLocationActuator> getSingleHosts(){
463
464
465
		return singleHosts;
	}	

466
	public LinkedHashMap<SimLocationActuator, PositionVector> getCurrentTargets(){
467
468
		return currentTargets;
	}
469
470
471
472
473
474
475
476
477
478
	
	public void setGroupAttractionAssignmentStrategy(IAttractionAssigmentStrategy groupAttractionAssignment) {
		if (groupAttractionAssignment == null) {
			throw new ConfigurationException(
					"IAttractionAssigmentStrategy for Groups is missing in SocialGroupMovementModel!");
		}
		
		this.groupAttractionAssignment = groupAttractionAssignment;
	}

479
}