Compare commits
2 Commits
4761cd3916
...
7d5be6ee31
Author | SHA1 | Date | |
---|---|---|---|
7d5be6ee31 | |||
|
ada569035d |
6
.idea/compiler.xml
Normal file
6
.idea/compiler.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<bytecodeTargetLevel target="1.8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="JavadocGenerationManager">
|
||||||
|
<option name="OUTPUT_DIRECTORY" value="$USER_HOME$/Desktop/TrafficSimDoc" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package de.hems.trafficsim;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
|
||||||
assertEquals("de.hems.trafficsim", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
package de.hems.trafficsim;
|
package de.hems.trafficsim;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@ -9,79 +7,143 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.Observable;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import java.util.Observer;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main user interface class, containing all necessary gui elements and their control flow.
|
||||||
|
*/
|
||||||
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
|
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
|
||||||
|
/**
|
||||||
|
* default value of the number of vehicles on the track
|
||||||
|
*/
|
||||||
public static final int defaultNoOfVehicles = 25;
|
public static final int defaultNoOfVehicles = 25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of the length of the track
|
||||||
|
*/
|
||||||
public static final int defaultTrackLength = 100;
|
public static final int defaultTrackLength = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of brake probability
|
||||||
|
*/
|
||||||
public static final float defaultBrakeProb = 0.3f;
|
public static final float defaultBrakeProb = 0.3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of the maximum velocity of the vehicles
|
||||||
|
*/
|
||||||
public static final float defaultMaxVelocity = 5.0f;
|
public static final float defaultMaxVelocity = 5.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of the delay between two simulation steps
|
||||||
|
*/
|
||||||
public static final int defaultDelay = 0;
|
public static final int defaultDelay = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of the number of vehicles on the track
|
||||||
|
*/
|
||||||
public static final int defaultHistoryLength = 50;
|
public static final int defaultHistoryLength = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default value of the number of vehicles on the track
|
||||||
|
*/
|
||||||
public static final int defaultFrameskip = 0;
|
public static final int defaultFrameskip = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the track to show in the activity
|
||||||
|
*/
|
||||||
protected Track track;
|
protected Track track;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the surface view on which the renderer draws the track history
|
||||||
|
*/
|
||||||
protected TimeRecordView trackView;
|
protected TimeRecordView trackView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the thread which runs the simulation and visualization
|
||||||
|
*/
|
||||||
protected Worker worker;
|
protected Worker worker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the renderer instance drawing the track history
|
||||||
|
*/
|
||||||
protected Renderer renderer;
|
protected Renderer renderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the layout which keeps the surface view
|
||||||
|
*/
|
||||||
protected LinearLayout viewStack;
|
protected LinearLayout viewStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to round a float to a given amount of digits.
|
||||||
|
*
|
||||||
|
* @param number number to round
|
||||||
|
* @param digits amount of digits
|
||||||
|
* @return rounded number
|
||||||
|
*/
|
||||||
|
public static float round(float number, int digits) {
|
||||||
|
float div = (float) Math.pow(10.0f, digits);
|
||||||
|
return Math.round(number * div) / div;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MainActivity
|
||||||
|
*
|
||||||
|
* @param savedInstanceState Bundle with previously saved activity state, otherwise null
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
this.track = new Track(defaultNoOfVehicles, defaultTrackLength, defaultBrakeProb,
|
this.track = new Track(defaultNoOfVehicles, defaultTrackLength, defaultBrakeProb,
|
||||||
defaultMaxVelocity, defaultDelay, defaultHistoryLength);
|
defaultMaxVelocity, defaultDelay, defaultHistoryLength);
|
||||||
this.viewStack = (LinearLayout) findViewById(R.id.trackViewStack);
|
this.viewStack = findViewById(R.id.trackViewStack);
|
||||||
this.trackView = new TimeRecordView(this, track);
|
this.trackView = new TimeRecordView(this, track);
|
||||||
|
|
||||||
viewStack.addView(this.trackView);
|
viewStack.addView(this.trackView);
|
||||||
this.renderer = new Renderer(track, this.trackView.getHolder());
|
this.renderer = new Renderer(track, this.trackView.getHolder());
|
||||||
|
|
||||||
SeekBar trackLengthSeekBar = (SeekBar) findViewById(R.id.trackLengthSeekBar);
|
SeekBar trackLengthSeekBar = findViewById(R.id.trackLengthSeekBar);
|
||||||
trackLengthSeekBar.setOnSeekBarChangeListener(this);
|
trackLengthSeekBar.setOnSeekBarChangeListener(this);
|
||||||
trackLengthSeekBar.setProgress(defaultTrackLength);
|
trackLengthSeekBar.setProgress(defaultTrackLength);
|
||||||
((TextView)(findViewById(R.id.trackLengthTextView))).setText(String.valueOf(defaultTrackLength));
|
((TextView)(findViewById(R.id.trackLengthTextView))).setText(String.valueOf(defaultTrackLength));
|
||||||
|
|
||||||
SeekBar maxVelocitySeekBar = (SeekBar) findViewById(R.id.maxVelocitySeekBar);
|
SeekBar maxVelocitySeekBar = findViewById(R.id.maxVelocitySeekBar);
|
||||||
maxVelocitySeekBar.setOnSeekBarChangeListener(this);
|
maxVelocitySeekBar.setOnSeekBarChangeListener(this);
|
||||||
maxVelocitySeekBar.setProgress((int)defaultMaxVelocity);
|
maxVelocitySeekBar.setProgress((int)defaultMaxVelocity);
|
||||||
((TextView)(findViewById(R.id.maxVeloTextView))).setText(String.valueOf((int)defaultMaxVelocity));
|
((TextView)(findViewById(R.id.maxVeloTextView))).setText(String.valueOf((int)defaultMaxVelocity));
|
||||||
|
|
||||||
SeekBar noOfVehiclesSeekBar = (SeekBar) findViewById(R.id.noOfVehiclesSeekBar);
|
SeekBar noOfVehiclesSeekBar = findViewById(R.id.noOfVehiclesSeekBar);
|
||||||
noOfVehiclesSeekBar.setOnSeekBarChangeListener(this);
|
noOfVehiclesSeekBar.setOnSeekBarChangeListener(this);
|
||||||
noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles);
|
noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles);
|
||||||
((TextView)(findViewById(R.id.noOfVehiclesTextView))).setText(String.valueOf(defaultNoOfVehicles));
|
((TextView)(findViewById(R.id.noOfVehiclesTextView))).setText(String.valueOf(defaultNoOfVehicles));
|
||||||
|
|
||||||
SeekBar brakeProbabilitySeekBar = (SeekBar) findViewById(R.id.brakeProbabilitySeekBar);
|
SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar);
|
||||||
brakeProbabilitySeekBar.setOnSeekBarChangeListener(this);
|
brakeProbabilitySeekBar.setOnSeekBarChangeListener(this);
|
||||||
brakeProbabilitySeekBar.setProgress((int)(defaultBrakeProb*20));
|
brakeProbabilitySeekBar.setProgress((int)(defaultBrakeProb*20));
|
||||||
((TextView)(findViewById(R.id.brakeProbTextView))).setText(String.valueOf(defaultBrakeProb));
|
((TextView)(findViewById(R.id.brakeProbTextView))).setText(String.valueOf(defaultBrakeProb));
|
||||||
|
|
||||||
SeekBar delaySeekBar = (SeekBar)(findViewById(R.id.simDelaySeekBar));
|
SeekBar delaySeekBar = findViewById(R.id.simDelaySeekBar);
|
||||||
delaySeekBar.setOnSeekBarChangeListener(this);
|
delaySeekBar.setOnSeekBarChangeListener(this);
|
||||||
delaySeekBar.setProgress(defaultDelay);
|
delaySeekBar.setProgress(defaultDelay);
|
||||||
((TextView)(findViewById(R.id.simDelayTextView))).setText(String.valueOf(defaultDelay));
|
((TextView) (findViewById(R.id.simDelayTextView))).setText(String.valueOf(defaultDelay));
|
||||||
|
|
||||||
SeekBar frameskipSeekBar = (SeekBar)(findViewById(R.id.frameskipSeekBar));
|
SeekBar frameskipSeekBar = findViewById(R.id.frameskipSeekBar);
|
||||||
frameskipSeekBar.setOnSeekBarChangeListener(this);
|
frameskipSeekBar.setOnSeekBarChangeListener(this);
|
||||||
frameskipSeekBar.setProgress(defaultFrameskip);
|
frameskipSeekBar.setProgress(defaultFrameskip);
|
||||||
((TextView)(findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip));
|
((TextView) (findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip));
|
||||||
|
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float round(float number, int digits) {
|
/**
|
||||||
float div = (float) Math.pow(10.0f, digits);
|
* Updates the statistics view.
|
||||||
return Math.round(number*div)/div;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public void updateStats() {
|
public void updateStats() {
|
||||||
final Track trackRef = this.track;
|
final Track trackRef = this.track;
|
||||||
final TextView lastAvgView = (TextView) findViewById(R.id.avgVeloLastView);
|
final TextView lastAvgView = findViewById(R.id.avgVeloLastView);
|
||||||
final TextView overallAvgView = (TextView) findViewById(R.id.avgVeloOverallView);
|
final TextView overallAvgView = findViewById(R.id.avgVeloOverallView);
|
||||||
final TextView delayedAvgView = (TextView) findViewById(R.id.delayedAvgTextView);
|
final TextView delayedAvgView = findViewById(R.id.delayedAvgTextView);
|
||||||
final TextView stepsView = (TextView) findViewById(R.id.stepsTextView);
|
final TextView stepsView = findViewById(R.id.stepsTextView);
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -93,46 +155,59 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for clicks on the "Step" button.
|
||||||
|
*
|
||||||
|
* @param view the view the event is generated from
|
||||||
|
*/
|
||||||
public void onStepButtonClick(View view) {
|
public void onStepButtonClick(View view) {
|
||||||
this.track.timeElapse();
|
this.track.timeElapse();
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
this.renderer.draw();
|
this.renderer.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for clicks on the "Play" button.
|
||||||
|
*
|
||||||
|
* @param view the view the event is generated from
|
||||||
|
*/
|
||||||
public void onPlayButtonClick(View view) {
|
public void onPlayButtonClick(View view) {
|
||||||
Button playButton = (Button) findViewById(R.id.playButton);
|
Button playButton = findViewById(R.id.playButton);
|
||||||
playButton.setEnabled(false);
|
playButton.setEnabled(false);
|
||||||
Button stepButton = (Button) findViewById(R.id.stepButton);
|
Button stepButton = findViewById(R.id.stepButton);
|
||||||
stepButton.setEnabled(false);
|
stepButton.setEnabled(false);
|
||||||
Button stopButton = (Button) findViewById(R.id.stopButton);
|
Button stopButton = findViewById(R.id.stopButton);
|
||||||
stopButton.setEnabled(true);
|
stopButton.setEnabled(true);
|
||||||
Button clearButton = (Button) findViewById(R.id.clearButton);
|
Button clearButton = findViewById(R.id.clearButton);
|
||||||
clearButton.setEnabled(false);
|
clearButton.setEnabled(false);
|
||||||
|
|
||||||
int frameskip = ((SeekBar)(findViewById(R.id.frameskipSeekBar))).getProgress();
|
int frameskip = ((SeekBar) (findViewById(R.id.frameskipSeekBar))).getProgress();
|
||||||
this.worker = new Worker(track, this, renderer, frameskip);
|
this.worker = new Worker(track, this, renderer, frameskip);
|
||||||
this.worker.start();
|
this.worker.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for clicks on the "Stop" button.
|
||||||
|
*
|
||||||
|
* @param view the view the event is generated from
|
||||||
|
*/
|
||||||
public void onStopButtonClick(View view) {
|
public void onStopButtonClick(View view) {
|
||||||
Button playButton = (Button) findViewById(R.id.playButton);
|
Button playButton = findViewById(R.id.playButton);
|
||||||
playButton.setEnabled(true);
|
playButton.setEnabled(true);
|
||||||
Button stepButton = (Button) findViewById(R.id.stepButton);
|
Button stepButton = findViewById(R.id.stepButton);
|
||||||
stepButton.setEnabled(true);
|
stepButton.setEnabled(true);
|
||||||
Button stopButton = (Button) findViewById(R.id.stopButton);
|
Button stopButton = findViewById(R.id.stopButton);
|
||||||
stopButton.setEnabled(false);
|
stopButton.setEnabled(false);
|
||||||
Button clearButton = (Button) findViewById(R.id.clearButton);
|
Button clearButton = findViewById(R.id.clearButton);
|
||||||
clearButton.setEnabled(true);
|
clearButton.setEnabled(true);
|
||||||
|
|
||||||
this.worker.setStop(true);
|
this.stopWorker();
|
||||||
try {
|
|
||||||
this.worker.join();
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
this.worker = null;
|
this.worker = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the current worker thread.
|
||||||
|
*/
|
||||||
protected void stopWorker() {
|
protected void stopWorker() {
|
||||||
this.worker.setStop(true);
|
this.worker.setStop(true);
|
||||||
try {
|
try {
|
||||||
@ -142,15 +217,20 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
this.worker = null;
|
this.worker = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for clicks on the "Stop" button.
|
||||||
|
*
|
||||||
|
* @param view the view the event is generated from
|
||||||
|
*/
|
||||||
public void onClearButtonClick(View view) {
|
public void onClearButtonClick(View view) {
|
||||||
if (this.worker != null) { // There was a simulation running
|
if (this.worker != null) { // There was a simulation running
|
||||||
this.stopWorker();
|
this.stopWorker();
|
||||||
}
|
}
|
||||||
Button playButton = (Button) findViewById(R.id.playButton);
|
Button playButton = findViewById(R.id.playButton);
|
||||||
playButton.setEnabled(true);
|
playButton.setEnabled(true);
|
||||||
Button stepButton = (Button) findViewById(R.id.stepButton);
|
Button stepButton = findViewById(R.id.stepButton);
|
||||||
stepButton.setEnabled(true);
|
stepButton.setEnabled(true);
|
||||||
Button stopButton = (Button) findViewById(R.id.stopButton);
|
Button stopButton = findViewById(R.id.stopButton);
|
||||||
stopButton.setEnabled(false);
|
stopButton.setEnabled(false);
|
||||||
this.updateTrack();
|
this.updateTrack();
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
@ -158,24 +238,28 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new track with the current settings. This methods restarts the simulation it
|
||||||
|
* it was running before.
|
||||||
|
*/
|
||||||
protected void updateTrack() {
|
protected void updateTrack() {
|
||||||
int newTrackLength = ((SeekBar)(findViewById(R.id.trackLengthSeekBar))).getProgress();
|
int newTrackLength = ((SeekBar) (findViewById(R.id.trackLengthSeekBar))).getProgress();
|
||||||
SeekBar noOfVehiclesSeekBar = (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar));
|
SeekBar noOfVehiclesSeekBar = findViewById(R.id.noOfVehiclesSeekBar);
|
||||||
int newNoOfVehicles = noOfVehiclesSeekBar.getProgress();
|
int newNoOfVehicles = noOfVehiclesSeekBar.getProgress();
|
||||||
if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length!
|
if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length!
|
||||||
newNoOfVehicles = (int) newTrackLength;
|
newNoOfVehicles = newTrackLength;
|
||||||
noOfVehiclesSeekBar.setProgress(newNoOfVehicles);
|
noOfVehiclesSeekBar.setProgress(newNoOfVehicles);
|
||||||
|
|
||||||
}
|
}
|
||||||
TextView noOfVehiclesTextView = (TextView)(findViewById(R.id.noOfVehiclesTextView));
|
TextView noOfVehiclesTextView = findViewById(R.id.noOfVehiclesTextView);
|
||||||
noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles));
|
noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles));
|
||||||
|
|
||||||
TextView trackLengthTextView = (TextView)(findViewById(R.id.trackLengthTextView));
|
TextView trackLengthTextView = findViewById(R.id.trackLengthTextView);
|
||||||
trackLengthTextView.setText(String.valueOf(newTrackLength));
|
trackLengthTextView.setText(String.valueOf(newTrackLength));
|
||||||
|
|
||||||
float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress();
|
float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress();
|
||||||
SeekBar brakeProbabilitySeekBar = (SeekBar) findViewById(R.id.brakeProbabilitySeekBar);
|
SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar);
|
||||||
float newBrakeProb = (float)brakeProbabilitySeekBar.getProgress()
|
float newBrakeProb = (float) brakeProbabilitySeekBar.getProgress()
|
||||||
/ (float)brakeProbabilitySeekBar.getMax();
|
/ (float)brakeProbabilitySeekBar.getMax();
|
||||||
|
|
||||||
int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress();
|
int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress();
|
||||||
@ -186,7 +270,8 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
this.worker.setStop(true);
|
this.worker.setStop(true);
|
||||||
try {
|
try {
|
||||||
this.worker.join();
|
this.worker.join();
|
||||||
} catch (InterruptedException ex) { }
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity,
|
this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity,
|
||||||
@ -199,27 +284,34 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for changes on the seek bars.
|
||||||
|
*
|
||||||
|
* @param seekBar the seek bar changed
|
||||||
|
* @param progress the new progress value of the seek bar
|
||||||
|
* @param fromUser flag if the event is the result of an user action
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
if (seekBar == (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar))) {
|
if (seekBar == findViewById(R.id.noOfVehiclesSeekBar)) {
|
||||||
this.updateTrack();
|
this.updateTrack();
|
||||||
} else if (seekBar == (SeekBar)(findViewById(R.id.brakeProbabilitySeekBar))) {
|
} else if (seekBar == findViewById(R.id.brakeProbabilitySeekBar)) {
|
||||||
float newBrakeProb = (float)seekBar.getProgress() / (float)seekBar.getMax();
|
float newBrakeProb = (float) seekBar.getProgress() / (float) seekBar.getMax();
|
||||||
this.track.setBrakeProb(newBrakeProb);
|
this.track.setBrakeProb(newBrakeProb);
|
||||||
TextView newBrakeProbTextView = (TextView)(findViewById(R.id.brakeProbTextView));
|
TextView newBrakeProbTextView = findViewById(R.id.brakeProbTextView);
|
||||||
newBrakeProbTextView.setText(String.valueOf((newBrakeProb)));
|
newBrakeProbTextView.setText(String.valueOf((newBrakeProb)));
|
||||||
} else if (seekBar == (SeekBar)(findViewById(R.id.maxVelocitySeekBar))) {
|
} else if (seekBar == findViewById(R.id.maxVelocitySeekBar)) {
|
||||||
this.track.setMaxVelocity(seekBar.getProgress());
|
this.track.setMaxVelocity(seekBar.getProgress());
|
||||||
TextView tv = (TextView)(findViewById(R.id.maxVeloTextView));
|
TextView tv = findViewById(R.id.maxVeloTextView);
|
||||||
tv.setText(String.valueOf(progress));
|
tv.setText(String.valueOf(progress));
|
||||||
} else if (seekBar == (SeekBar)(findViewById(R.id.trackLengthSeekBar))) {
|
} else if (seekBar == findViewById(R.id.trackLengthSeekBar)) {
|
||||||
this.updateTrack();
|
this.updateTrack();
|
||||||
} else if (seekBar == (SeekBar)(findViewById(R.id.simDelaySeekBar))) {
|
} else if (seekBar == findViewById(R.id.simDelaySeekBar)) {
|
||||||
TextView tv = (TextView)(findViewById(R.id.simDelayTextView));
|
TextView tv = findViewById(R.id.simDelayTextView);
|
||||||
tv.setText(String.valueOf(seekBar.getProgress()));
|
tv.setText(String.valueOf(seekBar.getProgress()));
|
||||||
this.track.setWaitTime(seekBar.getProgress());
|
this.track.setWaitTime(seekBar.getProgress());
|
||||||
} else if (seekBar == (SeekBar)(findViewById(R.id.frameskipSeekBar))) {
|
} else if (seekBar == findViewById(R.id.frameskipSeekBar)) {
|
||||||
TextView tv = (TextView)(findViewById(R.id.frameSkipTextView));
|
TextView tv = findViewById(R.id.frameSkipTextView);
|
||||||
tv.setText(String.valueOf(seekBar.getProgress()));
|
tv.setText(String.valueOf(seekBar.getProgress()));
|
||||||
if (this.worker != null) {
|
if (this.worker != null) {
|
||||||
this.worker.setFrameskip(seekBar.getProgress());
|
this.worker.setFrameskip(seekBar.getProgress());
|
||||||
@ -227,11 +319,21 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for beginning touch events on a seek bar.
|
||||||
|
*
|
||||||
|
* @param seekBar the seek bar touched
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for ending touch events on a seek bar.
|
||||||
|
*
|
||||||
|
* @param seekBar the seek bar touched
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
|
@ -9,25 +9,73 @@ import android.view.SurfaceHolder;
|
|||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interface class rendering the track history on a SurfaceView.
|
||||||
|
*/
|
||||||
public class Renderer {
|
public class Renderer {
|
||||||
private List<VehicleTimeRecord> stepRecords;
|
/**
|
||||||
|
* the track to render
|
||||||
|
*/
|
||||||
protected Track track;
|
protected Track track;
|
||||||
|
/**
|
||||||
|
* width of a rectangle representing one vehicle
|
||||||
|
*/
|
||||||
protected int pixelPerVehicle;
|
protected int pixelPerVehicle;
|
||||||
|
/**
|
||||||
|
* height of a rectangle representing one vehicle
|
||||||
|
*/
|
||||||
protected int pixelPerLine;
|
protected int pixelPerLine;
|
||||||
|
/**
|
||||||
|
* amount of pixels per track position which are lost by rounding
|
||||||
|
*/
|
||||||
protected float tooShortPerTrackLength;
|
protected float tooShortPerTrackLength;
|
||||||
|
/**
|
||||||
|
* amount of pixels per height which are lost by rounding
|
||||||
|
*/
|
||||||
protected float tooShortPerHeight;
|
protected float tooShortPerHeight;
|
||||||
|
/**
|
||||||
|
* Paint instance of the renderer
|
||||||
|
*/
|
||||||
protected Paint paint;
|
protected Paint paint;
|
||||||
|
/**
|
||||||
|
* holder of the surface the renderer draws to
|
||||||
|
*/
|
||||||
protected SurfaceHolder holder;
|
protected SurfaceHolder holder;
|
||||||
protected Canvas canvas;
|
/**
|
||||||
|
* width of the surface to draw to
|
||||||
|
*/
|
||||||
protected int width;
|
protected int width;
|
||||||
|
/**
|
||||||
|
* height of the surface to draw to
|
||||||
|
*/
|
||||||
protected int height;
|
protected int height;
|
||||||
|
/**
|
||||||
|
* temporary reference to the time records of one simulation step
|
||||||
|
*/
|
||||||
|
private List<VehicleTimeRecord> stepRecords;
|
||||||
|
/**
|
||||||
|
* temporary reference to the canvas to draw to
|
||||||
|
*/
|
||||||
|
private Canvas canvas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constuctor for a Renderer.
|
||||||
|
*
|
||||||
|
* @param track the track to render
|
||||||
|
* @param holder the holder of the surface to draw to
|
||||||
|
*/
|
||||||
public Renderer(Track track, SurfaceHolder holder) {
|
public Renderer(Track track, SurfaceHolder holder) {
|
||||||
this.track = track;
|
this.track = track;
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
this.paint = new Paint();
|
this.paint = new Paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the dimension information of the renderer.
|
||||||
|
*
|
||||||
|
* @param width the width of the SurfaceView
|
||||||
|
* @param height the height of the SurfaceView
|
||||||
|
*/
|
||||||
public void setSize(int width, int height) {
|
public void setSize(int width, int height) {
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
this.pixelPerVehicle = width / (int) this.track.getTrackLength();
|
this.pixelPerVehicle = width / (int) this.track.getTrackLength();
|
||||||
@ -36,34 +84,50 @@ public class Renderer {
|
|||||||
/ this.track.getTrackLength();
|
/ this.track.getTrackLength();
|
||||||
this.pixelPerLine = height / this.track.getHistoryLength();
|
this.pixelPerLine = height / this.track.getHistoryLength();
|
||||||
this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength())
|
this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength())
|
||||||
/ (float)height;
|
/ (float) height;
|
||||||
System.out.println("Viewport: "+width+"x"+height);
|
System.out.println("Viewport: " + width + "x" + height);
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the track of the Surface.
|
||||||
|
*
|
||||||
|
* @param track the new track to render
|
||||||
|
*/
|
||||||
public void setTrack(Track track) {
|
public void setTrack(Track track) {
|
||||||
this.track = track;
|
this.track = track;
|
||||||
this.setSize(width, height);
|
this.setSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function which calculates a color from the relation between the current speed of a
|
||||||
|
* vehicle and it's maximum speed (from red over yellow to green).
|
||||||
|
*
|
||||||
|
* @param curVelocity current velocity of the vehicle
|
||||||
|
* @param maxVelocity maximum velocity of the vehilce
|
||||||
|
* @return color encoded as Android color integer
|
||||||
|
*/
|
||||||
protected int getColor(float curVelocity, float maxVelocity) {
|
protected int getColor(float curVelocity, float maxVelocity) {
|
||||||
float perc = curVelocity / maxVelocity;
|
float perc = curVelocity / maxVelocity;
|
||||||
perc = 1 - perc;
|
perc = 1 - perc;
|
||||||
if (perc <= 0.5) {
|
if (perc <= 0.5) {
|
||||||
int red = ((int) (2*perc*0xFF)) << 16;
|
int red = ((int) (2 * perc * 0xFF)) << 16;
|
||||||
int green = 0xFF << 8;
|
int green = 0xFF << 8;
|
||||||
int blue = 0;
|
int blue = 0;
|
||||||
return 0xff000000 | red | green | blue;
|
return 0xff000000 | red | green | blue;
|
||||||
} else {
|
} else {
|
||||||
int red = 0xFF << 16;
|
int red = 0xFF << 16;
|
||||||
int green = ((int)(0xFF-0xFF*(perc-0.5)*2)) << 8;
|
int green = ((int) (0xFF - 0xFF * (perc - 0.5) * 2)) << 8;
|
||||||
int blue = 0;
|
int blue = 0;
|
||||||
return 0xff000000 | red | green | blue;
|
return 0xff000000 | red | green | blue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the current state of the track history to the Surface.
|
||||||
|
*/
|
||||||
protected void draw() {
|
protected void draw() {
|
||||||
try {
|
try {
|
||||||
if (this.pixelPerVehicle == 0) {
|
if (this.pixelPerVehicle == 0) {
|
||||||
@ -79,7 +143,7 @@ public class Renderer {
|
|||||||
int vCompensateStart = 0;
|
int vCompensateStart = 0;
|
||||||
int vCompensateEnd = 0;
|
int vCompensateEnd = 0;
|
||||||
canvas.drawColor(Color.BLACK);
|
canvas.drawColor(Color.BLACK);
|
||||||
for (int curStepIdx = this.track.getVtrList().size()-1;curStepIdx >= 0;
|
for (int curStepIdx = this.track.getVtrList().size()-1; curStepIdx >= 0;
|
||||||
curStepIdx--) {
|
curStepIdx--) {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
package de.hems.trafficsim;
|
package de.hems.trafficsim;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.text.Layout;
|
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import java.util.ConcurrentModificationException;
|
/**
|
||||||
import java.util.List;
|
* A Surface View which servers as a stage for a renderer.
|
||||||
|
*/
|
||||||
public class TimeRecordView extends SurfaceView {
|
public class TimeRecordView extends SurfaceView {
|
||||||
public TimeRecordView(Context context, Track track) {
|
public TimeRecordView(Context context, Track track) {
|
||||||
super(context);
|
super(context);
|
||||||
this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the size information of the SurfaceView, used by the Android SDK.
|
||||||
|
*
|
||||||
|
* @param w new width
|
||||||
|
* @param h new height
|
||||||
|
* @param oldw old width
|
||||||
|
* @param oldh old height
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
@ -5,42 +5,92 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.LockSupport;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main model class of TrafficSim. Represents a round course containing vehicles.
|
||||||
|
*/
|
||||||
public class Track extends Observable {
|
public class Track extends Observable {
|
||||||
|
/**
|
||||||
|
* list a vehicles on the track
|
||||||
|
*/
|
||||||
protected List<Vehicle> vehicles;
|
protected List<Vehicle> vehicles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of resulting time records of the simulation
|
||||||
|
*/
|
||||||
protected List<List<VehicleTimeRecord>> vtrList;
|
protected List<List<VehicleTimeRecord>> vtrList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* length of the track
|
||||||
|
*/
|
||||||
protected float trackLength;
|
protected float trackLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sum of all vehicle speeds during the simulation, used for average calculation
|
||||||
|
*/
|
||||||
protected float sumAvgMemory;
|
protected float sumAvgMemory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sum of all vehicle speeds during the simulation ignoring the first ten steps,
|
||||||
|
* used for average calculation
|
||||||
|
*/
|
||||||
protected float sumDelAvgMemory;
|
protected float sumDelAvgMemory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* length of the history kept
|
||||||
|
*/
|
||||||
protected int historyLength;
|
protected int historyLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* average over all velocities in the simulation
|
||||||
|
*/
|
||||||
protected float overallAvg;
|
protected float overallAvg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* average over all velocities in the simulation, ignoring the first ten steps
|
||||||
|
*/
|
||||||
protected float delayedAvg;
|
protected float delayedAvg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* average over all velocities in the last step
|
||||||
|
*/
|
||||||
protected float lastAvg;
|
protected float lastAvg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current configured wait time between two simulation steps
|
||||||
|
*/
|
||||||
protected int waitTime;
|
protected int waitTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* currently configured max velocity for all vehicles
|
||||||
|
*/
|
||||||
protected float maxVelocity;
|
protected float maxVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* currently configured brake probability for all vehicles
|
||||||
|
*/
|
||||||
protected float brakeProb;
|
protected float brakeProb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* counter for executed simulation steps
|
||||||
|
*/
|
||||||
protected long steps;
|
protected long steps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* semaphore protecting the vtrlist
|
||||||
|
*/
|
||||||
protected Semaphore listSemaphore;
|
protected Semaphore listSemaphore;
|
||||||
|
|
||||||
public List<List<VehicleTimeRecord>> getVtrList() { return vtrList; }
|
/**
|
||||||
public float getOverallAvg() {
|
* Constructor for a new Track.
|
||||||
return overallAvg;
|
*
|
||||||
}
|
* @param numberVehicles number of vehicles on the Track
|
||||||
public float getLastAvg() {
|
* @param trackLength length of the new Track
|
||||||
return lastAvg;
|
* @param brakeProb probability of a vehicle to suddenly brake without reason
|
||||||
}
|
* @param maxVelocity maxmimum velocity of the vehicles
|
||||||
public float getDelayedAvg() { return delayedAvg; }
|
* @param waitTime time between two simulation steps to slow down the simulation artificially
|
||||||
public List<Vehicle> getVehicles() {
|
* @param historyLength length of the history to keep
|
||||||
return vehicles;
|
*/
|
||||||
}
|
|
||||||
public float getTrackLength() {
|
|
||||||
return trackLength;
|
|
||||||
}
|
|
||||||
public long getSteps() { return steps; }
|
|
||||||
public Semaphore getListSemaphore() { return listSemaphore; }
|
|
||||||
public int getHistoryLength() { return historyLength; }
|
|
||||||
|
|
||||||
public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime, int historyLength) {
|
public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime, int historyLength) {
|
||||||
this.trackLength = trackLength;
|
this.trackLength = trackLength;
|
||||||
this.brakeProb = brakeProb;
|
this.brakeProb = brakeProb;
|
||||||
@ -59,9 +109,96 @@ public class Track extends Observable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Vehicle> createVehiclesList(int numberVehicles){
|
/**
|
||||||
|
* Getter for vtrList
|
||||||
|
*
|
||||||
|
* @return vtrList
|
||||||
|
*/
|
||||||
|
public List<List<VehicleTimeRecord>> getVtrList() {
|
||||||
|
return vtrList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for overallAvg
|
||||||
|
*
|
||||||
|
* @return overallAvg
|
||||||
|
*/
|
||||||
|
public float getOverallAvg() {
|
||||||
|
return overallAvg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for lastAvg
|
||||||
|
*
|
||||||
|
* @return lastAvg
|
||||||
|
*/
|
||||||
|
public float getLastAvg() {
|
||||||
|
return lastAvg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for delayedAvg
|
||||||
|
*
|
||||||
|
* @return delayedAvg
|
||||||
|
*/
|
||||||
|
public float getDelayedAvg() {
|
||||||
|
return delayedAvg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for vehicles
|
||||||
|
*
|
||||||
|
* @return vehicles
|
||||||
|
*/
|
||||||
|
public List<Vehicle> getVehicles() {
|
||||||
|
return vehicles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for trackLength
|
||||||
|
*
|
||||||
|
* @return trackLength
|
||||||
|
*/
|
||||||
|
public float getTrackLength() {
|
||||||
|
return trackLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for steps
|
||||||
|
*
|
||||||
|
* @return steps
|
||||||
|
*/
|
||||||
|
public long getSteps() {
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for listSemaphore
|
||||||
|
*
|
||||||
|
* @return listSemaphore
|
||||||
|
*/
|
||||||
|
public Semaphore getListSemaphore() {
|
||||||
|
return listSemaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for historyLength
|
||||||
|
*
|
||||||
|
* @return historyLength
|
||||||
|
*/
|
||||||
|
public int getHistoryLength() {
|
||||||
|
return historyLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to add vehicles to the Track.
|
||||||
|
*
|
||||||
|
* @param numberVehicles number of vehicles to add
|
||||||
|
* @return filled list with vehicles
|
||||||
|
*/
|
||||||
|
protected List<Vehicle> createVehiclesList(int numberVehicles) {
|
||||||
List<Vehicle> result = new ArrayList<>();
|
List<Vehicle> result = new ArrayList<>();
|
||||||
for(int i=0;i<numberVehicles;i++){
|
for (int i = 0; i < numberVehicles; i++) {
|
||||||
Vehicle vehicle = new Vehicle(i, i, this.maxVelocity, this.brakeProb, this.trackLength);
|
Vehicle vehicle = new Vehicle(i, i, this.maxVelocity, this.brakeProb, this.trackLength);
|
||||||
result.add(vehicle);
|
result.add(vehicle);
|
||||||
}
|
}
|
||||||
@ -69,24 +206,42 @@ public class Track extends Observable {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the wait time of the simulation.
|
||||||
|
*
|
||||||
|
* @param waitTime new wait time in ms
|
||||||
|
*/
|
||||||
public void setWaitTime(int waitTime) {
|
public void setWaitTime(int waitTime) {
|
||||||
this.waitTime = waitTime;
|
this.waitTime = waitTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the brake probability of all vehicles.
|
||||||
|
*
|
||||||
|
* @param brakeProb new brake probability
|
||||||
|
*/
|
||||||
public void setBrakeProb(float brakeProb) {
|
public void setBrakeProb(float brakeProb) {
|
||||||
for (Vehicle v : this.vehicles) {
|
for (Vehicle v : this.vehicles) {
|
||||||
v.setBrakeProb(brakeProb);
|
v.setBrakeProb(brakeProb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the maximum velocity of all vehicles.
|
||||||
|
*
|
||||||
|
* @param maxVelocity new maximum velocity
|
||||||
|
*/
|
||||||
public void setMaxVelocity(float maxVelocity) {
|
public void setMaxVelocity(float maxVelocity) {
|
||||||
for (Vehicle v : this.vehicles) {
|
for (Vehicle v : this.vehicles) {
|
||||||
v.setMaxVelocity(maxVelocity);
|
v.setMaxVelocity(maxVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates on simulation step ahead and then waits for the configured wait time.
|
||||||
|
*/
|
||||||
public void timeElapse() {
|
public void timeElapse() {
|
||||||
for(int i=0; i<vehicles.size();i++) {
|
for (int i = 0; i < vehicles.size(); i++) {
|
||||||
Vehicle v = vehicles.get(i);
|
Vehicle v = vehicles.get(i);
|
||||||
int forerunnerIndex = i + 1;
|
int forerunnerIndex = i + 1;
|
||||||
if (forerunnerIndex >= vehicles.size()) {
|
if (forerunnerIndex >= vehicles.size()) {
|
||||||
@ -94,7 +249,7 @@ public class Track extends Observable {
|
|||||||
}
|
}
|
||||||
Vehicle forerunner = vehicles.get(forerunnerIndex);
|
Vehicle forerunner = vehicles.get(forerunnerIndex);
|
||||||
float distanceForerunner = forerunner.getPosition() - v.getPosition() - 1;
|
float distanceForerunner = forerunner.getPosition() - v.getPosition() - 1;
|
||||||
if(distanceForerunner < 0.0){
|
if (distanceForerunner < 0.0) {
|
||||||
distanceForerunner += this.trackLength;
|
distanceForerunner += this.trackLength;
|
||||||
}
|
}
|
||||||
v.updateVelocity(distanceForerunner);
|
v.updateVelocity(distanceForerunner);
|
||||||
@ -117,25 +272,32 @@ public class Track extends Observable {
|
|||||||
this.listSemaphore.release();
|
this.listSemaphore.release();
|
||||||
|
|
||||||
update_avg();
|
update_avg();
|
||||||
this.setChanged();
|
try {
|
||||||
//this.notifyObservers();
|
|
||||||
this.clearChanged();
|
|
||||||
//LockSupport.parkNanos(1);
|
|
||||||
try {
|
|
||||||
Thread.sleep(waitTime);
|
Thread.sleep(waitTime);
|
||||||
} catch (InterruptedException ex) { }
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float avg_step(int step){
|
/**
|
||||||
|
* Returns the average velocity of the given simulation step.
|
||||||
|
*
|
||||||
|
* @param step index of the step in the history list
|
||||||
|
* @return average velocity
|
||||||
|
*/
|
||||||
|
public float avg_step(int step) {
|
||||||
float sum_step = 0;
|
float sum_step = 0;
|
||||||
for (VehicleTimeRecord r : vtrList.get(step)) {
|
for (VehicleTimeRecord r : vtrList.get(step)) {
|
||||||
sum_step += r.velocity;
|
sum_step += r.velocity;
|
||||||
}
|
}
|
||||||
return sum_step / vehicles.size();
|
return sum_step / vehicles.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void update_avg(){
|
/**
|
||||||
lastAvg = avg_step(vtrList.size()-1);
|
* Utility function which updates the averages values with the results from the last simulation
|
||||||
|
* step.
|
||||||
|
*/
|
||||||
|
protected void update_avg() {
|
||||||
|
lastAvg = avg_step(vtrList.size() - 1);
|
||||||
if (this.steps > 10) {
|
if (this.steps > 10) {
|
||||||
sumDelAvgMemory += lastAvg;
|
sumDelAvgMemory += lastAvg;
|
||||||
delayedAvg = sumDelAvgMemory / (this.steps - 10);
|
delayedAvg = sumDelAvgMemory / (this.steps - 10);
|
||||||
@ -144,13 +306,4 @@ public class Track extends Observable {
|
|||||||
overallAvg = sumAvgMemory / this.steps;
|
overallAvg = sumAvgMemory / this.steps;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float avg_span(int start, int end){
|
|
||||||
float sum_span = 0;
|
|
||||||
for (int i=start; i <end;i++){
|
|
||||||
sum_span += avg_step(i);
|
|
||||||
}
|
|
||||||
return sum_span / (end-start+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,49 @@ package de.hems.trafficsim;
|
|||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model class which represents a vehicle in the simulation.
|
||||||
|
*/
|
||||||
public class Vehicle {
|
public class Vehicle {
|
||||||
|
/**
|
||||||
|
* a number to index the vehicle
|
||||||
|
*/
|
||||||
protected int id;
|
protected int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current position of the vehicle on the track
|
||||||
|
*/
|
||||||
protected float position;
|
protected float position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current velocity of the vehicle
|
||||||
|
*/
|
||||||
protected float curVelocity;
|
protected float curVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* maximum velocity of the vehicle
|
||||||
|
*/
|
||||||
protected float maxVelocity;
|
protected float maxVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* probability of the vehicle to brake without reason
|
||||||
|
*/
|
||||||
protected float brakeProb;
|
protected float brakeProb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* length of the track the vehicle is placed on
|
||||||
|
*/
|
||||||
protected float trackLength;
|
protected float trackLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new vehicle.
|
||||||
|
*
|
||||||
|
* @param id a number to index the vehicle
|
||||||
|
* @param position current position of the vehicle on the track
|
||||||
|
* @param maxVelocity maximum velocity of the vehicle
|
||||||
|
* @param brakeProb probability of the vehicle to brake without reason
|
||||||
|
* @param trackLength length of the track the vehicle is placed on
|
||||||
|
*/
|
||||||
public Vehicle(int id, int position, float maxVelocity, float brakeProb, float trackLength) {
|
public Vehicle(int id, int position, float maxVelocity, float brakeProb, float trackLength) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
@ -21,22 +55,61 @@ public class Vehicle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for position
|
||||||
|
*
|
||||||
|
* @return position
|
||||||
|
*/
|
||||||
public float getPosition() {
|
public float getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for curVelocity
|
||||||
|
*
|
||||||
|
* @return curVelocity
|
||||||
|
*/
|
||||||
public float getCurVelocity() {
|
public float getCurVelocity() {
|
||||||
return curVelocity;
|
return curVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for maxVelocity
|
||||||
|
*
|
||||||
|
* @return maxVelocity
|
||||||
|
*/
|
||||||
public float getMaxVelocity() {
|
public float getMaxVelocity() {
|
||||||
return maxVelocity;
|
return maxVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBrakeProb(float brakeProb) { this.brakeProb = brakeProb; }
|
/**
|
||||||
|
* Setter for maxVelocity
|
||||||
|
*
|
||||||
|
* @return maxVelocity
|
||||||
|
*/
|
||||||
|
public void setMaxVelocity(float maxVelocity) {
|
||||||
|
this.maxVelocity = maxVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
public void setMaxVelocity(float maxVelocity) { this.maxVelocity = maxVelocity; }
|
/**
|
||||||
|
* Setter for brakeProb
|
||||||
|
*
|
||||||
|
* @return brakeProb
|
||||||
|
*/
|
||||||
|
public void setBrakeProb(float brakeProb) {
|
||||||
|
this.brakeProb = brakeProb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the new velocity of the vehicle based on the following rules:
|
||||||
|
* <ol>
|
||||||
|
* <li>Increase by one if the vehicle is slower than it's maximum speed</li>
|
||||||
|
* <li>Random brake by one</li>
|
||||||
|
* <li>Break if the distance to the forerunner is less than it's speed</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param distanceForerunner distance to the forerunner of the vehicle
|
||||||
|
*/
|
||||||
public void updateVelocity(float distanceForerunner) {
|
public void updateVelocity(float distanceForerunner) {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
@ -53,6 +126,9 @@ public class Vehicle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the position of the vehicle according to it's previously calculated speed.
|
||||||
|
*/
|
||||||
public void timeElapse() {
|
public void timeElapse() {
|
||||||
position = (position + curVelocity) % this.trackLength;
|
position = (position + curVelocity) % this.trackLength;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,27 @@
|
|||||||
package de.hems.trafficsim;
|
package de.hems.trafficsim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model class which keeps the previous simulation data for analysis.
|
||||||
|
*/
|
||||||
public class VehicleTimeRecord {
|
public class VehicleTimeRecord {
|
||||||
|
/**
|
||||||
|
* the id of the vehicle it belongs to
|
||||||
|
*/
|
||||||
protected int id;
|
protected int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the position of the vehicle after the last simulation step
|
||||||
|
*/
|
||||||
protected float position;
|
protected float position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the velocity of the vehicle during the last simulation step
|
||||||
|
*/
|
||||||
protected float velocity;
|
protected float velocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the maximum velocity of the vehicle
|
||||||
|
*/
|
||||||
protected float maxVelocity;
|
protected float maxVelocity;
|
||||||
|
|
||||||
public float getMaxVelocity() {
|
public float getMaxVelocity() {
|
||||||
@ -18,6 +36,14 @@ public class VehicleTimeRecord {
|
|||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new VehicleTimeRecord.
|
||||||
|
*
|
||||||
|
* @param id the id of the vehicle it belongs to
|
||||||
|
* @param position the position of the vehicle after the last simulation step
|
||||||
|
* @param velocity the velocity of the vehicle during the last simulation step
|
||||||
|
* @param maxVelocity the maximum velocity of the vehicle
|
||||||
|
*/
|
||||||
public VehicleTimeRecord(int id, float position, float velocity, float maxVelocity) {
|
public VehicleTimeRecord(int id, float position, float velocity, float maxVelocity) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
@ -1,17 +1,46 @@
|
|||||||
package de.hems.trafficsim;
|
package de.hems.trafficsim;
|
||||||
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.view.SurfaceHolder;
|
|
||||||
|
|
||||||
import java.util.ConcurrentModificationException;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculation thread, which runs the simulation itself and also updates the view with a set rate.
|
||||||
|
*/
|
||||||
public class Worker extends Thread {
|
public class Worker extends Thread {
|
||||||
|
/**
|
||||||
|
* the track to simulate
|
||||||
|
*/
|
||||||
protected Track track;
|
protected Track track;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop flag, indicating that the worker shall stop
|
||||||
|
*/
|
||||||
protected boolean stop;
|
protected boolean stop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the MainActivity of the gui
|
||||||
|
*/
|
||||||
protected MainActivity gui;
|
protected MainActivity gui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the Renderer drawing the Track
|
||||||
|
*/
|
||||||
protected Renderer renderer;
|
protected Renderer renderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount of simulation steps between two frames in the view. Zero means
|
||||||
|
* that every simulation step is drawn.
|
||||||
|
*/
|
||||||
protected int frameskip;
|
protected int frameskip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new worker.
|
||||||
|
*
|
||||||
|
* @param track the track to simulate
|
||||||
|
* @param gui the MainActivity of the gui
|
||||||
|
* @param renderer the Renderer drawing the Track
|
||||||
|
* @param frameskip Amount of simulation steps between two frames in the view. Zero means
|
||||||
|
* that every simulation step is drawn
|
||||||
|
*/
|
||||||
public Worker(Track track, MainActivity gui, Renderer renderer, int frameskip) {
|
public Worker(Track track, MainActivity gui, Renderer renderer, int frameskip) {
|
||||||
super();
|
super();
|
||||||
this.track = track;
|
this.track = track;
|
||||||
@ -21,16 +50,28 @@ public class Worker extends Thread {
|
|||||||
this.frameskip = frameskip;
|
this.frameskip = frameskip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag that causes the worker to stop.
|
||||||
|
*
|
||||||
|
* @param stop flag whether the thread shall stop
|
||||||
|
*/
|
||||||
public void setStop(boolean stop) {
|
public void setStop(boolean stop) {
|
||||||
this.stop = stop;
|
this.stop = stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the amount of simulation steps between to view frames.
|
||||||
|
*
|
||||||
|
* @param frames amount of steps
|
||||||
|
*/
|
||||||
public void setFrameskip(int frames) {
|
public void setFrameskip(int frames) {
|
||||||
this.frameskip = frames;
|
this.frameskip = frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFrameskip() { return this.frameskip; }
|
/**
|
||||||
|
* Method which is automatically executed when the thread is started. It alternates between
|
||||||
|
* updating the simulation and drawing a new frame in the view.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Canvas canvas = null;
|
Canvas canvas = null;
|
||||||
@ -40,7 +81,7 @@ public class Worker extends Thread {
|
|||||||
this.gui.updateStats();
|
this.gui.updateStats();
|
||||||
if (i >= this.frameskip) {
|
if (i >= this.frameskip) {
|
||||||
this.renderer.draw();
|
this.renderer.draw();
|
||||||
i=0;
|
i = 0;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package de.hems.trafficsim;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user