Update 15.02.2018: siehe Das Kochbuchartikel für einen einfacheren Weg
Update 10. April 2018: siehe Bryan's Skript für einen modernen Ansatz
Frühe Erinnerung
Als ich fast drei Jahre alt war, ließ mich mein Vater, W4FNB, SK, im Funkraum herumhängen, während er dem Signal von lauschte Sputnik .Ich erinnere mich, dass er erklärte, wie die Doppler-Verschiebung es erforderte, dass er die Stimmung auf dem kontinuierlich anpasste Hammarlund Empfänger HQ-129X , und wie wichtig es für den Empfänger war, sich mehrere Stunden aufzuwärmen, um die internen Oszillatoren des Radios zu stabilisieren.Ich glaube, er hat auch versucht, mir etwas am Himmel zu zeigen, aber es sollte noch vier Jahre dauern, bis die Schulkrankenschwester merkte, wie dringend ich eine Brille brauchte.Klänge von den ersten Satelliten
Neuerdings
Der Internationale Raumstation befindet sich seit 1998 oder 2000 im Orbit. Dieser Beitrag stellte JSL vor, um den aktuellen Standort der ISS abzurufen und ihn auf einer Karte darzustellen, die aus einem anderen NASA-Bild erstellt wurde.Ich habe die JSL ein wenig angepasst und ein Video gemacht, das ein paar Tage mit 90-minütigen Umlaufbahnen in weniger als einer Minute zeigt.
Ein paar Verbesserungen, aber ziemlich ähnlich.Ich habe die Dateinamen durcheinander gebracht, indem ich die führenden Nullen nicht ausgefüllt habe Mixer erwartet; Ich habe JSL verwendet, um die Dateien umzubenennen.
// code repaired 15feb2018, requires JMP 11 or later
// trimmed down JSON parser (go get the real one, there is more support for tables)
/*
* JSL JSON Parser, Xan Gregg, 2014-12-29
* pattern matching speedup, Craige Hales, 2015-01-01
*/
New Namespace( "JSON" );
JSON:Char Escape = Function( {c},
Match( c, "\!"", "\!"", "b", "\!u0008", "f", "\!u000C", "n", "\!u000A", "r", "\!u000D", "t", "\!u0009", c )
);
JSON:Unicode Escape = Function( {u},
u = "\!"\!\!u" || u || "\!"";
Parse( u );
);
JSON:Pattern Name = "\!"" // leading quotation mark
+ Pat Test(
value = "";
1;
) // init string accumulator
+ Pat Repeat(
(Pat Break( "\!\\!"" ) >> temp + Pat Test(
value ||= temp;
1;
)) // run of characters that are not \ or "
| ("\u" + Pat Len( 4 ) >> temp + Pat Test(
value ||= JSON:Unicode Escape( temp );
1;
)) // \uXXXX
| ("\" + Pat Len( 1 ) >> temp + Pat Test(
value ||= JSON:Char Escape( temp );
1;
)) // \", for example...embedded quotation mark
) + "\!""; // trailing quotation mark
JSON:Pattern Number = Pat Span( "0123456789-+eE." ) >> temp + Pat Test(
value = Num( temp );
1;
);
JSON:PatternParse = Pat Pos( 0 ) + Pat Repeat(
Pat Pos( /* remember how far we parsed for error message */ ) >> failpos// /* comment out this line for a little more speed */+pattest(if(tickseconds()-lasttime>1,lasttime=tickseconds();wait(0));1)
+ Pat Fence( /* fence off previously parsed text...ain't no going back */ ) + (Pat Regex( "\s*" ) // ignore whitespace
| JSON:Pattern Name | (":" + Pat Test(
key = value;
1;
)) | JSON:Pattern Number | ("true" + Pat Test(
value = 1;
1;
)) | ("false" + Pat Test(
value = 0;
1;
)) | ("null" + Pat Test(
value = .;
1;
)) | ("[" + Pat Test(
Insert Into( stack, {{}}, 1 );
value = Empty();
1;
)) | ("{" + Pat Test(
Insert Into( stack, Associative Array(), 1 );
value = Empty();
Insert Into( keys, key, 1 );
1;
)) | ("]" + Pat Test(
If( !Is Empty( value ),
Insert Into( stack[1], value, 1 /*needs reverse later*/ )
);
value = stack[1];
value = Reverse( value );
Remove From( stack, 1 );
1;
)) | ("}" + Pat Test(
If( !Is Empty( value ),
stack[1][key] = value
);
value = stack[1];
Remove From( stack, 1 );
key = keys[1];
Remove From( keys, 1 );
1;
)) | ("," + Pat Test(
If( Is List( stack[1] ),
Insert Into( stack[1], value, 1 /*needs reverse later*/ ),
stack[1][key] = value
);
value = Empty();
1;
)))
) + Pat R Pos( 0 );
JSON:jsonParse = Function( {json},
{stack = {}, keys = {}, key = "", value = Empty(), temp = 0, totalLen = Length( json ), failpos = 0},
If( !Try( Pat Match( json, JSON:PatternParse ), 0 ),
Throw( "unrecognized JSON at " || Char( failpos ) )
);
value;
);
// end namespace
lat = J( 3600, 1, . ); // trail of previous points, you can make it longer
lon = J( N Rows( lat ), 1, . );
idx = 1;
cur = idx;
error = "";
time = "";
dir = "D:\directory\ISS\m";
seq = 0;
/* open-notify.org (Thanks!) returns JSON data like this:
{
"iss_position": {
"latitude": 24.94415308475734,
"longitude": 116.70173230986174
},
"message": "success",
"timestamp": 1462990726
}
*/
updateLatLon = Function( {},
{where = Try(
loadtextfile( "http://api.open-notify.org/iss-now.json?" || Char( Random Integer( 1, 1e6 ) ) )
//Open( "http://api.open-notify.org/iss-now.json?" || Char( Random Integer( 1, 1e6 ) ) )
, "" ), // fetch a JSON string
locationData = JSON:jsonParse( where ) // use XAN's parser
},
If( !Is Empty( locationData ) & locationData["message"] == "success",
error = ""; // clear any previous message
lat[idx] = Num( locationData["iss_position"]["latitude"] ); // get the two numbers
lon[idx] = Num( locationData["iss_position"]["longitude"] ); // used in the script below to plot a point
time = locationData["timestamp"]; // unix time, not JMP time
time = Format( 1jan1970 + time, /*"ddMonyyyyh:m:s"*/ "yyyy-mm-ddThh:mm:ss" ) || " GMT";
cur = idx;
idx++;
If( idx > N Rows( lat ),
idx = 1
);
,
error = "no location data available"
);
Try(
g << inval;
Wait( 1 );
seq++;
g[framebox( 1 )] << savepicture( dir || Char( seq ) || ".png", "png" );
); // if the map exists, update it.
Schedule( 28, updateLatLon() ); // schedule this function to run again. it would be rude to ask for updates much faster than this.
);
updateLatLon(); // bootstrap call, then it calls itself every 30 seconds
earthLight = Open( "http://eoimages.gsfc.nasa.gov/images/imagerecords/55000/55167/earth_lights_lrg.jpg", "jpg" );
{width, height} = earthLight << size; // need the ratio for the frame size...
New Window( "NASA's Night Light Map",
g = Graph Box(
framesize( width / 2, height / 2 ),
X Scale( -180, 180 ),
Y Scale( -90, 90 ),
Text Color( "white" );
Text( {0, -50}, error );
Text( {-150, -88}, time );
Text( {-179, 80}, "International Space Station" );
Text( RightJustified, {160, -88}, "http://visibleearth.nasa.gov" ); // credits
Text( {-50, -88}, "http://open-notify.org/Open-Notify-API/ISS-Location-Now/" ); // credits
//Marker Size( 2 ); Marker( Combine States( Color State( "RED" ), Marker State( 12 ) ), lon, lat ); // space station trail
//Marker Size( 4 ); Marker( Combine States( Color State( "RED" ), Marker State( 12 ) ), {lon[cur], lat[cur]} ); // head
bright = N Rows( lon );
Marker Size( 4 );
For( i = cur, i >= 1, i--,
Marker( Combine States( Color State( RGB Color( bright / N Rows( lon ), 0.1, 0.1 ) ), Marker State( 12 ) ), {lon[i], lat[i]} );
bright--;
Marker Size( 2 );
);
For( i = N Rows( lon ), i > cur, i--,
Marker( Combine States( Color State( RGB Color( bright / N Rows( lon ), 0.1, 0.1 ) ), Marker State( 12 ) ), {lon[i], lat[i]} );
bright--;
);
)
);
frameBox = g[framebox( 1 )]; // the framebox, in the graphbox, is just inside the axes
frameBox << Background Map( Boundaries( "World" ) ); // add boundaries first; they wind up on top of the next bitmap...
g[axisbox( 1 )] << Scale( "Linear" ) << remove axis label; // the geo coordinates were set when the map was added, but
g[axisbox( 2 )] << Scale( "Linear" ) << remove axis label; // we need linear coords to line up the map...
frameBox << AddImage( Image( earthLight ), bounds( Left( -180 ), Right( 180 ), top( 90 ), bottom( -90 ) ) ); // -180..180 seems correct
imgSeg = frameBox << FindSeg( PictSeg( 1 ) ); // the most recently added one is first
imgSeg << lock( 1 ); // and lock it so mouse won't move it by mistake
frameBox << xaxis( show major ticks( false ), show minor ticks( false ), show labels( false ) );
frameBox << yaxis( show major ticks( false ), show minor ticks( false ), show labels( false ) );