2018 年 2 月 15 日更新: 参照これ簡単な方法のためのクックブックアイテム
2018 年 4 月 10 日更新: ブライアンの記事を参照脚本現代的なアプローチのために
初期の記憶
私が 3 歳の頃、私の父、W4FNB、SK は、彼がラジオの信号を聞いている間、私をラジオ室でたむろさせてくれました。スプートニク.彼が、ドップラー シフトのために、どのようにチューニングを継続的に調整する必要があったかを説明したことを覚えています。ハマールランド受信機HQ-129X 、そして受信機がラジオの内部発振器を安定させるために数時間ウォームアップすることがいかに重要であったか。彼も私に空に何かを見せようとしたと思いますが、学校の看護師が私がメガネを必要としていることに気付くまでにさらに4年かかりました.最初の衛星からの音
最近になって
の国際宇宙ステーション1998 年または 2000 年から軌道に乗っています。この郵便受けISS の現在位置を取得し、別の NASA 画像から作成されたマップ上にプロットする JSL を提示しました。私は JSL を少し調整し、1 分足らずで 90 分の軌道を 2 日分表示するビデオを作成しました。
いくつかの改善がありますが、かなり似ています。先頭のゼロを埋めずにファイル名を台無しにしましたブレンダー期待します。 JSL を使用してファイルの名前を変更しました。
// 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 ) );