-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added simulation for fixed directional antenna
- Loading branch information
1 parent
6e53646
commit 77d76e4
Showing
4 changed files
with
341 additions
and
1 deletion.
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
src/test/java/ru/r2cloud/simulation/FixedDirectionalAntennaTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package ru.r2cloud.simulation; | ||
|
||
import java.io.BufferedWriter; | ||
import java.io.File; | ||
import java.io.FileWriter; | ||
import java.io.InputStream; | ||
import java.nio.file.FileSystems; | ||
import java.text.SimpleDateFormat; | ||
import java.util.Date; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.TimeZone; | ||
import java.util.UUID; | ||
|
||
import org.orekit.propagation.analytical.tle.TLEPropagator; | ||
|
||
import com.eclipsesource.json.JsonArray; | ||
import com.eclipsesource.json.JsonObject; | ||
import com.eclipsesource.json.WriterConfig; | ||
|
||
import ru.r2cloud.CelestrakServer; | ||
import ru.r2cloud.FixedClock; | ||
import ru.r2cloud.TestUtil; | ||
import ru.r2cloud.it.util.BaseTest; | ||
import ru.r2cloud.model.AntennaConfiguration; | ||
import ru.r2cloud.model.AntennaType; | ||
import ru.r2cloud.model.SatPass; | ||
import ru.r2cloud.model.Tle; | ||
import ru.r2cloud.predict.PredictOreKit; | ||
import ru.r2cloud.rotctrld.Position; | ||
import ru.r2cloud.tle.CelestrakClient; | ||
import ru.r2cloud.util.Configuration; | ||
|
||
public class FixedDirectionalAntennaTest { | ||
|
||
public static void main(String[] args) throws Exception { | ||
|
||
AntennaConfiguration antenna = new AntennaConfiguration(); | ||
antenna.setType(AntennaType.FIXED_DIRECTIONAL); | ||
antenna.setAzimuth(34); | ||
antenna.setElevation(55.0); | ||
antenna.setBeamwidth(45); | ||
Configuration config; | ||
File userSettingsLocation = new File("target/.r2cloud-" + UUID.randomUUID().toString()); | ||
try (InputStream is = BaseTest.class.getClassLoader().getResourceAsStream("config-dev.properties")) { | ||
config = new Configuration(is, userSettingsLocation.getAbsolutePath(), "config-common-test.properties", FileSystems.getDefault()); | ||
} | ||
config.setProperty("locaiton.lat", "51.49"); | ||
config.setProperty("locaiton.lon", "0.01"); | ||
config.setProperty("scheduler.orekit.path", "./src/test/resources/data/orekit-data"); | ||
|
||
CelestrakServer celestrak = new CelestrakServer(); | ||
celestrak.start(); | ||
celestrak.mockResponse(TestUtil.loadExpected("tle-2020-09-27.txt")); | ||
config.setList("tle.urls", celestrak.getUrls()); | ||
|
||
PredictOreKit predict = new PredictOreKit(config); | ||
|
||
SimpleDateFormat sdf = createFormatter(); | ||
long current = sdf.parse("2022-07-19 18:47:32").getTime(); | ||
|
||
CelestrakClient client = new CelestrakClient(config, new FixedClock(current)); | ||
|
||
Map<String, Tle> tles = client.downloadTle(); | ||
|
||
int maxOutput = 50; | ||
int currentOutput = 0; | ||
|
||
JsonArray ds = new JsonArray(); | ||
for (Tle cur : tles.values()) { | ||
TLEPropagator propagator = TLEPropagator.selectExtrapolator(new org.orekit.propagation.analytical.tle.TLE(cur.getRaw()[1], cur.getRaw()[2])); | ||
List<SatPass> schedule = predict.calculateSchedule(antenna, new Date(current), propagator); | ||
for (SatPass curPass : schedule) { | ||
// capture 4 minutes min | ||
long length = curPass.getEndMillis() - curPass.getStartMillis(); | ||
if (length < 4 * 60 * 1000) { | ||
continue; | ||
} | ||
ds.add(output(curPass, predict, propagator, currentOutput)); | ||
|
||
currentOutput++; | ||
if (currentOutput >= maxOutput) { | ||
break; | ||
} | ||
} | ||
if (currentOutput >= maxOutput) { | ||
break; | ||
} | ||
} | ||
|
||
File output = new File("target" + File.separator + "fixedDirectional"); | ||
if (!output.exists() && !output.mkdirs()) { | ||
System.out.println("can't create output directory"); | ||
System.exit(1); | ||
} | ||
|
||
TestUtil.copy("fixedDirectional/index.html", new File(output, "index.html")); | ||
TestUtil.copy("fixedDirectional/AzElChart.js", new File(output, "AzElChart.js")); | ||
|
||
try (BufferedWriter w = new BufferedWriter(new FileWriter(new File(output, "Data.js")))) { | ||
w.append("const dses = ").append(ds.toString(WriterConfig.PRETTY_PRINT)).append(";"); | ||
} | ||
|
||
System.out.println("Results written to " + output.getAbsolutePath()); | ||
|
||
System.exit(0); | ||
|
||
} | ||
|
||
private static JsonObject output(SatPass pass, PredictOreKit predict, TLEPropagator tle, int index) throws Exception { | ||
JsonArray points = new JsonArray(); | ||
for (long i = pass.getStartMillis(); i < pass.getEndMillis(); i += 1000) { | ||
Position pos = predict.getSatellitePosition(i, predict.getPosition(), tle); | ||
JsonObject cur = new JsonObject(); | ||
cur.add("x", pos.getAzimuth()); | ||
cur.add("y", pos.getElevation()); | ||
cur.add("time", i); | ||
points.add(cur); | ||
} | ||
JsonObject ds = new JsonObject(); | ||
ds.add("label", "data " + index); | ||
ds.add("data", points); | ||
ds.add("borderColor", generateColor(Integer.hashCode((int) (index + pass.getStartMillis())))); | ||
ds.add("borderWidth", 1); | ||
return ds; | ||
} | ||
|
||
private static String generateColor(int hash) { | ||
StringBuilder result = new StringBuilder(); | ||
result.append("#"); | ||
for (int i = 0; i < 3; i++) { | ||
int cur = (hash >> (i * 8)) & 0xFF; | ||
String color = "00" + Integer.toHexString(cur); | ||
result.append(color.substring(color.length() - 2)); | ||
} | ||
return result.toString(); | ||
} | ||
|
||
private static SimpleDateFormat createFormatter() { | ||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
sdf.setTimeZone(TimeZone.getTimeZone("GMT")); | ||
return sdf; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
const data = { | ||
labels: ['0', '45', '90', '135', '180', '225', '270', '315'], | ||
datasets: dses | ||
}; | ||
|
||
const options = { | ||
elements: { | ||
point: { | ||
radius: 0, | ||
hitRadius: 10, | ||
hoverRadius: 4, | ||
hoverBorderWidth: 3 | ||
} | ||
}, | ||
animation: { | ||
duration: 0 | ||
}, | ||
scale: { | ||
type: 'myScale', | ||
angleLines: { | ||
display: true | ||
}, | ||
gridLines: { | ||
circular: true | ||
}, | ||
ticks: { | ||
display: false, | ||
beginAtZero: true, | ||
max: 90, | ||
min: 0 | ||
} | ||
}, | ||
legend: { | ||
display: false | ||
}, | ||
tooltips: { | ||
displayColors: false, | ||
callbacks: { | ||
title: function(tooltipItem, data) { | ||
return data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index].time; | ||
//console.log(tooltipItem) | ||
//return ''; | ||
}, | ||
label: function(tooltipItem, data) { | ||
let item = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; | ||
return [ | ||
"AZ: " + item.x, | ||
"EL: " + item.y | ||
]; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
Chart.defaults.derivedRadar= Chart.defaults.radar; | ||
|
||
var custom = Chart.controllers.radar.extend({ | ||
update: function(reset) { | ||
var me = this; | ||
var meta = me.getMeta(); | ||
var line = meta.dataset; | ||
var points = meta.data || []; | ||
var scale = me.chart.scale; | ||
var config = me._config; | ||
var i, ilen; | ||
|
||
// Compatibility: If the properties are defined with only the old name, use those values | ||
if (config.tension !== undefined && config.lineTension === undefined) { | ||
config.lineTension = config.tension; | ||
} | ||
|
||
// Utility | ||
line._scale = scale; | ||
line._datasetIndex = me.index; | ||
// Data | ||
line._children = points; | ||
line._loop = false; | ||
// Model | ||
line._model = me._resolveDatasetElementOptions(line); | ||
|
||
line.pivot(); | ||
|
||
// Update Points | ||
for (i = 0, ilen = points.length; i < ilen; ++i) { | ||
me.updateElement(points[i], i, reset); | ||
} | ||
|
||
// Update bezier control points | ||
me.updateBezierControlPoints(); | ||
|
||
// Now pivot the point for animation | ||
for (i = 0, ilen = points.length; i < ilen; ++i) { | ||
points[i].pivot(); | ||
} | ||
} | ||
}); | ||
Chart.controllers.derivedRadar = custom; | ||
|
||
let MyScale = Chart.scaleService.getScaleConstructor('radialLinear').extend({ | ||
getPointPositionForValue: function(index, value) { | ||
var me = this; | ||
var scalingFactor = me.drawingArea / (me.max - me.min); | ||
return { | ||
y: scalingFactor * Math.cos(value.x * Math.PI / 180.0) * (value.y - 90) + me.yCenter, | ||
x: scalingFactor * Math.sin(value.x * Math.PI / 180.0) * (90 - value.y) + me.xCenter | ||
}; | ||
}, | ||
getDistanceFromCenterForValue: function(value) { | ||
var me = this; | ||
// Take into account half font size + the yPadding of the top value | ||
var scalingFactor = me.drawingArea / (me.max - me.min); | ||
if (me.options.ticks.reverse) { | ||
return (me.max - value) * scalingFactor; | ||
} | ||
return (value - me.min) * scalingFactor; | ||
} | ||
}); | ||
Chart.scaleService.registerScaleType('myScale', MyScale, { | ||
display: true, | ||
|
||
// Boolean - Whether to animate scaling the chart from the centre | ||
animate: false, | ||
position: 'chartArea', | ||
|
||
angleLines: { | ||
display: true, | ||
color: 'rgba(0,0,0,0.1)', | ||
lineWidth: 1, | ||
borderDash: [], | ||
borderDashOffset: 0.0 | ||
}, | ||
|
||
gridLines: { | ||
circular: false | ||
}, | ||
|
||
// label settings | ||
ticks: { | ||
// Boolean - Show a backdrop to the scale label | ||
showLabelBackdrop: true, | ||
|
||
// String - The colour of the label backdrop | ||
backdropColor: 'rgba(255,255,255,0.75)', | ||
|
||
// Number - The backdrop padding above & below the label in pixels | ||
backdropPaddingY: 2, | ||
|
||
// Number - The backdrop padding to the side of the label in pixels | ||
backdropPaddingX: 2 | ||
|
||
}, | ||
|
||
pointLabels: { | ||
// Boolean - if true, show point labels | ||
display: true, | ||
|
||
// Number - Point label font size in pixels | ||
fontSize: 10, | ||
|
||
// Function - Used to convert point labels | ||
callback: function(label) { | ||
return label; | ||
} | ||
} | ||
}); | ||
|
||
// Get the canvas element | ||
const ctx = document.getElementById('radarChart').getContext('2d'); | ||
|
||
// Create the radar chart | ||
const radarChart = new Chart(ctx, { | ||
type: 'derivedRadar', | ||
data: data, | ||
options: options | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script> | ||
<title>Radar Chart</title> | ||
</head> | ||
<body> | ||
<div style="width: 360px; height: 360px"> | ||
<canvas id="radarChart" width="360" height="360"></canvas> | ||
</div> | ||
<script src="Data.js"></script> | ||
<script src="AzElChart.js"></script> | ||
</body> | ||
</html> |