2018년 2월 15일 업데이트: 참조 이것 더 쉬운 방법을 위한 요리책 항목
2018년 4월 10일 업데이트: Bryan's 참조 스크립트 현대적인 접근을 위해
초기 기억
내가 거의 3살이었을 때, 아버지 W4FNB, SK는 내가 라디오 방에서 인공위성 .나는 그가 어떻게 도플러 편이로 인해 계속해서 튜닝을 조정해야 하는지 설명했던 것을 기억합니다. 함말룬드 수화기 HQ-129X , 라디오의 내부 발진기를 안정화하기 위해 수신기가 몇 시간 동안 워밍업하는 것이 얼마나 중요한지.나는 그가 나에게 하늘에 있는 무언가를 보여주려고 했다고 생각하지만, 학교 간호사가 내가 안경이 얼마나 절실히 필요한지 깨닫기까지는 4년이 더 걸릴 것입니다.최초의 위성에서 나는 소리
더 최근
그만큼 국제 우주 정거장 1998년 또는 2000년부터 궤도에 진입했습니다. 이 게시물 JSL은 ISS 현재 위치를 가져오고 다른 NASA 이미지에서 만든 지도에 플롯했습니다.나는 JSL을 약간 조정하고 1분도 안 되는 90분 궤도의 며칠을 보여주는 비디오를 만들었습니다.
몇 가지 개선 사항이 있지만 꽤 비슷합니다.앞에 오는 0을 채우지 않아 파일 이름을 엉망으로 만들었습니다. 블렌더 기대한다; 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 ) );