Jump to content
IGNORED

Minimal Apollo lunar lander simulation in console basic WIP


Recommended Posts

I've been having some fun developing a simulation of the Apollo 11 landing on the Moon in console basic. It's been lots of fun reducing the complexity of the moon landing so it can be run on the TI99 in basic. I'm not sure if it's a little crazy but it's been interesting learning about the technical side of the landing.

 

The simulated lander on the TI has it's own very simple autopilot, not based on the Apollo guidance computer in any way. It simply controls the simulated lander so it meets specified vertical and horizontal velocities at specific altitudes using basic equations of motion, i.e. at the level of velocity=acceleration*time.

 

The simulation starts from an altitude of about 15 km (50000 ft) where the lander brakes at 100% thrust. Then at an altitude of about 2.2 km (7500 ft) the lander pitches up so the crew can view the landing site. The landing phase starts at an altitude of 150 m (500 ft) and this is where in the real landing the crew can manually pilot the lander if needed.

 

In the YouTube video I've linked below the simulation starts from the approach phase which starts at 2.2 km (7500 km). The video demonstrates switching between the different views, i.e. from a remote camera flying alongside the lander and from a camera looking out of the LEM window at the landing site.

 

https://youtu.be/EJnK9hYMVfw

 

The simulation can also be played as a game where the player takes on the role of steering the lander from an altitude of 15 km (15000 ft) based on pitch and thrust information displayed by the autopilot. This is not demonstrated in the video as it's still a work in progress but I don't think there's much more to do.

 

  • Like 9
Link to comment
Share on other sites

19 hours ago, arcadeshopper said:

you should turn off the 'made for kids' it doesn't do what you think, it actually restricts your video from being put in play lists etc..

 

Thanks for noticing that! It's turned off now.

 

19 hours ago, TI_Ken said:

Minimal? That looks great! It actually had a good depth of field. A few years ago I was thinking a "view from the cockpit" type lunar lander but never did anything with it.

 

Thanks, I'm glad to hear the view from the lander looks realistic! The 3D effect is calculated using basic trigonometry and projecting the horizon and landing area onto the pilot's window, i.e. the computer screen. The landing area is supposed to be a 200 by 200 m square.

  • Like 1
Link to comment
Share on other sites

My kind of program. Nicely done. Getting the computer to make the necessary thrust corrections in real time and still achieve a safe landing is harder than it looks. I might want to replicate that idea in Pascal :)

  • Like 2
Link to comment
Share on other sites

2 hours ago, Vorticon said:

My kind of program. Nicely done. Getting the computer to make the necessary thrust corrections in real time and still achieve a safe landing is harder than it looks. I might want to replicate that idea in Pascal :)

Thanks for the compliment! I would like to see what can be done in Pascal. Sound like fun! 😀

 

Yeah, there was quite a bit of trial and error trying to get it all working properly. I think the algorithms are fairly robust now. The trickiest part was the braking phase because of issues to do with the high initial speed. This phase is not shown in the video because it's several minutes long and not much is happening. Although you do need to pay attention to what the autopilot is telling you when flying it manually.

 

I'll post the code in a few days time once I've documented how the autopilot works. Then I'll update the code if I get feeback from people on the gameplay side of things.  

  • Like 3
Link to comment
Share on other sites

Posted (edited)

Here's some documentation on the algorithms and the graphics for the simulation. Hope it makes sense. I've also included the code for the YouTube version of the simulation and also the latest version of the simulation using more realistic orbital equations. The attached zips are the Classic99 disk versions. The documentation is for the YouTube version of the simulation (LEM_YT.zip).

 

btw the game side of the simulation is not working at the moment so I haven't included any documentation for it. I'll probably return to this next month.

 

Keys for the simulation

 

1 Remote camera view
2 Window view
3 Headings for displayed data
4 Horizon distance
5 Distance travelled
6 Range to go
9 Time elapsed  (only available in new simulation with orbital equations)
0 Fuel remaining in percent (only available in new version with orbital equations)

 

Version in the YouTube video

Spoiler

100 CALL CLEAR
110 PRINT "   LUNAR MODULE PILOT"
120 PRINT "   ******************":::
130 PRINT "1. VERTICAL DESCENT"
140 PRINT "   50 METRES ALTITUDE"::
150 PRINT "2. LANDING"
160 PRINT "   150 METRES ALTITUDE"::
170 PRINT "3. APPROACH"
180 PRINT "   2200 METRES ALTITUDE"::
190 PRINT "4. BRAKING"
200 PRINT "   16000 METRES ALTITUDE"::
210 PRINT
220 INPUT "STARTING PHASE?":A
230 CALL CHAR(96,"000000FFFF000000")
240 CALL CHAR(128,"0001193C3C190100")
250 CALL CHAR(129,"0000193D3C180204")
260 CALL CHAR(130,"0000183D3D18000C")
270 CALL CHAR(131,"0000183C3D190018")
280 CALL CHAR(132,"0000183C3C190230")
290 CALL CHAR(133,"0000183C3C180066")
300 CALL CHAR(134,"0000183C3C98400C")
310 CALL CHAR(135,"0000183CBC980018")
320 CALL CHAR(136,"000018BCBC180030")
330 CALL CHAR(137,"000098BC3C184020")
340 CALL CHAR(138,"0080983C3C988000")
350 CALL CHAR(144,"000000000000AAFF")
360 CALL CHAR(145,"000000000000CCFF")
370 CALL CHAR(146,"00000000002277FF")
380 CALL CHAR(147,"0000000010387CFF")
390 CALL CHAR(148,"00000000183C7EFF")
400 CALL CHAR(149,"0000183C7EFFFFFF")
410 CALL CHAR(152,"0000000010000000")
420 CALL CHAR(153,"0000001818000000")
430 CALL CHAR(154,"0000182424180000")
440 CALL CHAR(155,"003C424242423C00")
450 CALL CHAR(156,"3C4281818181423C")
460 CALL CHAR(157,"7E8181818181817E")
470 A$(8)="00000000000000FF"
480 A$(7)="000000000000FF"
490 A$(6)="0000000000FF"
500 A$(5)="00000000FF"
510 A$(4)="000000FF"
520 A$(3)="0000FF"
530 A$(2)="00FF"
540 A$(1)="FF"
550 B$(8)="FE"
560 B$(7)="FD"
570 B$(6)="FB"
580 B$(5)="F7"
590 B$(4)="EF"
600 B$(3)="DF"
610 B$(2)="BF"
620 B$(1)="7F"
630 PI=4*ATN(1)
640 DEF ASIN(X)=ATN(X/SQR(1-X*X))
650 GM=7.3E+22*6.6743E-11
660 ASCF=2376
670 DESF=8248
680 ASCM=2445
690 DESM=2034
700 DRYM=ASCM+DESM+ASCF
710 MAXT=43903.0*1.6
720 DISP=311.0
730 THRU=1.0*MAXT
740 VELX=1695.0
750 VELZ=-2.0
760 ALTI=14078.0+2000.0
770 DIST=0
780 RANG0=337030
790 ANGL=-9.0
800 LUNG=1.60
810 EARG=9.81
820 DT=1
830 TI=0
840 X=1
850 IF A=3 THEN 860 ELSE 930
860 DESF=1961
870 VELX=157
880 VELZ=-44
890 ALTI=2274
900 DIST=330748+200
910 ANGL=-29
920 THRU=26245
930 IF A=2 THEN 940 ELSE 1010
940 DESF=1320
950 VELX=19
960 VELZ=-5
970 ALTI=153
980 DIST=336567
990 ANGL=-81
1000 THRU=17211
1010 IF A=1 THEN 1020 ELSE 1090
1020 DESF=1195
1030 VELX=1.8
1040 VELZ=-2.9
1050 ALTI=50.2
1060 DIST=336811
1070 ANGL=-79
1080 THRU=13240
1090 TOTM=ASCF+DESF+ASCM+DESM
1100 ACCX=0.0
1110 LAND_FLAG=0
1120 LANDED=0
1130 RADI=1737400.0+ALTI
1140 ANGV=VELX/RADI
1150 ANGX=0.0
1160 RAD=2.0*PI/360.0
1170 IF LANDED=1 THEN 2350
1180 FLAG=-(ALTI<7509)-(ALTI<2209)-(ALTI<156)-(ALTI<61)
1190 REM  14000 M TO 7509 M
1200 IF FLAG<>0 THEN 1330
1210 IF TI>26 THEN 1250
1220 THRU=0.1*MAXT
1230 ANGL=0
1240 GOTO 1330
1250 THRU=MAXT
1260 TARG=7509
1270 TARV=32
1280 TARH=ALTI-TARG
1290 N=(0.5*VELZ^2-0.5*TARV^2+1.6*TARH)/(THRU*TARH/TOTM)
1300 N=-N*(N<1)-0.99999999*(N>=1)
1310 ANGL=-ASIN(N)*360/(2*PI)
1320 REM  7509 M TO 2290 M
1330 IF FLAG<>1 THEN 1460
1340 TARG=2209
1350 TARV=44
1360 TARH=ALTI-TARG
1370 N=(0.5*VELZ^2-0.5*TARV^2+1.6*TARH)/(THRU*TARH/TOTM)
1380 N=-N*(N<1)-0.99999999*(N>=1)
1390 ANGL=-ASIN(N)*360/(2*PI)
1400 SHOR=VELX-ACCX*(ALTI-TARG)/VELZ
1410 IF SHOR>154.0 THEN 1420 ELSE 1430
1420 THRU=THRU+1000.0
1430 IF SHOR<=154.0 THEN 1440 ELSE 1460
1440 THRU=THRU-1000.0
1450 REM  2209 M TO 156 M
1460 IF FLAG<>2 THEN 1620
1470 TARG=156
1480 TARV=5
1490 TARH=ALTI-TARG
1500 DECE=(-TARV^2+VELZ^2)/(2.0*TARH)+1.6
1510 N=-(DECE/(MAXT/TOTM))/SIN(ANGL*RAD)
1520 THRU=N*MAXT
1530 TVER=-(ALTI-156.0)/VELZ
1540 SHOR=VELX+ACCX*TVER
1550 IF SHOR>20.0 THEN 1560 ELSE 1570
1560 ANGL=ANGL+1
1570 IF SHOR<20.0 THEN 1580 ELSE 1590
1580 ANGL=ANGL-1
1590 IF ANGL>-30.0 THEN 1600 ELSE 1620
1600 ANGL=-30.0
1610 REM  156 M TO 60 M
1620 IF FLAG<>3 THEN 1800
1630 IF HOVE=0 THEN 1660
1640 N=-(TOTM*1.6/MAXT)/SIN(ANGL*RAD)
1650 GOTO 1800
1660 TARG=60
1670 TARV=3
1680 TARH=ALTI-TARG
1690 DECE=(-TARV^2+VELZ^2)/(2.0*TARH)+1.6
1700 N=-(DECE/(MAXT/TOTM))/SIN(ANGL*RAD)
1710 THRU=N*MAXT
1720 TVER=-(ALTI-60.0)/VELZ
1730 SHOR=VELX+ACCX*TVER
1740 IF SHOR>3.0 THEN 1750 ELSE 1760
1750 ANGL=ANGL+5
1760 IF SHOR<3.0 THEN 1770 ELSE 1780
1770 ANGL=ANGL-5
1780 IF ANGL>-30.0 THEN 1790 ELSE 1800
1790 ANGL=-30.0
1800 IF FLAG<>4 THEN 1960
1810 IF HOVE=0 THEN 1840
1820 N=-(TOTM*1.6/MAXT)/SIN(ANGL*RAD)
1830 GOTO 2170
1840 TARV=2.0
1850 TARH=ALTI
1860 N=(0.5*VELZ^2.0-0.5*TARV^2.0+1.6*TARH)/(MAXT*TARH/TOTM)
1870 THRU=N*MAXT
1880 TVER=-ALTI/VELZ
1890 SHOR=VELX+ACCX*TVER
1900 IF SHOR>3.0 THEN 1910 ELSE 1920
1910 ANGL=ANGL+1.0
1920 IF SHOR<3.0 THEN 1930 ELSE 1940
1930 ANGL=ANGL-1
1940 IF ANGL>-30.0 THEN 1950 ELSE 1960
1950 ANGL=-30.0
1960 REM  CALL CLEAR
1970 REM  PERC=THRU*100/MAXT
1980 REM  PRINT "AP PITCH THRUST: ";INT(ANGL);INT(PERC);
1990 IF K3<>49 THEN 2030
2000 CALL HCHAR(4,16,128-ANGL*5/90)
2010 IF YPOS>24 THEN 2070
2020 CALL HCHAR(YPOS,1,42,32)
2030 REM  IF K3<>50 THEN 1940     
2040 REM  IF (HWIN>=1.0)*(HWIN<=23)THEN 1920 ELSE 1940
2050 REM  CALL HCHAR(HWIN,1,144+5*(1-ALTI/2290),32)
2060 REM  CALL HCHAR(HWIN,16,152+5*(1-LDIS/2290))
2070 IF GAME=0 THEN 2170
2080 IF (K=32)*(AP<3)THEN 2120
2090 ANGL=PITC
2100 THRU=THRO
2110 GOTO 2170
2120 PITC=ANGL
2130 THRO=THRU
2140 AP=AP+1
2150 CALL SCREEN(3)
2160 CALL SCREEN(4)
2170 ANGF=-ATN(VELZ/VELX)*57.3
2180 ANGF=-ATN(VELZ/VELX)*57.3
2190 DESF=DESF-THRU*DT/(DISP*EARG)
2200 TOTM=DRYM+DESF
2210 ACCL=THRU/TOTM
2220 ACCX=-COS(ANGL/57.3)*ACCL
2230 ACCZ=SIN(ANGL/57.3)*ACCL
2240 ALTI=ALTI+VELZ*DT
2250 VELZ=VELZ-1.6*DT
2260 VELZ=VELZ-ACCZ*DT
2270 IF HOVE=0 THEN 2290
2280 VELZ=VELZ0
2290 VELX=VELX+ACCX*DT
2300 DIST=DIST+VELX*DT
2310 PERC=THRU*100/MAXT
2320 IF (ALTI<0.0)*(LANDED=0)THEN 2330 ELSE 2350
2330 LANDED=1
2340 ALTI=0.0
2350 CALL CLEAR
2360 CALL KEY(0,K,S)
2370 IF S=0 THEN 2850
2380 IF K=56 THEN 2390 ELSE 2450
2390 GAME=-(GAME=0)
2400 IF GAME=0 THEN 2410 ELSE 2430
2410 PRINT "MANUAL OFF";
2420 GOTO 3030
2430 PRINT "MANUAL CONTROL";
2440 GOTO 3030
2450 IF (K=ASC("Q"))+(K=ASC("A"))THEN 2460 ELSE 2480
2460 PITC=PITC-5*((K=ASC("Q"))-(K=ASC("A")))
2470 GOTO 2500
2480 IF (K=ASC("W"))+(K=ASC("S"))THEN 2490 ELSE 2540
2490 PITC=PITC-((K=ASC("W"))-(K=ASC("S")))
2500 ANGL=PITC
2510 CALL SCREEN(3)
2520 CALL SCREEN(4)
2530 GOTO 3410
2540 IF (K=ASC("O"))+(K=ASC("L"))THEN 2550 ELSE 2570
2550 THRO=THRO-702.5*((K=ASC("O"))-(K=ASC("L")))
2560 GOTO 2590
2570 IF (K=ASC("I"))+(K=ASC("K"))THEN 2580 ELSE 2630
2580 THRO=THRO-7024.5*((K=ASC("I"))-(K=ASC("K")))
2590 THRU=THRO
2600 CALL SCREEN(3)
2610 CALL SCREEN(4)
2620 GOTO 3410
2630 IF K=55 THEN 2640 ELSE 2760
2640 IF HOVE=0 THEN 2650 ELSE 2700
2650 INPUT "DESCENT RATE:":VELZ0
2660 VELZ=VELZ0
2670 PRINT "AUTOPILOT OFF";
2680 HOVE=1
2690 GOTO 2720
2700 PRINT "AUTOPILOT ON";
2710 HOVE=0
2720 FOR DELAY=1 TO 200
2730 NEXT DELAY
2740 CALL CLEAR
2750 GOTO 3420
2760 IF (K=49)+(K=50)THEN 2770 ELSE 2810
2770 IF (P2=1)*(K<>K3)THEN 2790
2780 P2=-(P2=0)
2790 K3=K*P2
2800 GOTO 2850
2810 IF (K>=52)*(K<=58)THEN 2820 ELSE 2850
2820 IF (P=1)*(K<>K2)THEN 2840
2830 P=-(P=0)
2840 K2=K*P
2850 IF (K2>0)+(K3>0)THEN 2860 ELSE 3410
2860 IF K2=51 THEN 2870 ELSE 2880
2870 PRINT " HORIZON:";INT(SQR(ALTI)*1864);
2880 IF K2=52 THEN 2890 ELSE 2990
2890 T1$=SEG$("ALTITUDE",1,LEN(STR$(INT(ABS(ALTI))))+1)
2900 T2$=SEG$("HVEL    ",1,LEN(STR$(INT(ABS(VELX))))+1)
2910 T3$=SEG$("VVEL    ",1,LEN(STR$(INT(ABS(VELZ))))+1)
2920 T4$=SEG$("PITCH   ",1,LEN(STR$(INT(ABS(ANGL))))+1)
2930 T5$=SEG$("THRUST  ",1,LEN(STR$(INT(ABS(THRU)))))
2940 P3=-(P3=0)
2950 IF P3=0 THEN 2960 ELSE 2980
2960 PRINT " "&T1$&" "&T2$&" "&T3$&" "&T4$&" "&T5$;
2970 GOTO 2990
2980 PRINT INT(ALTI);INT(VELX);INT(VELZ);INT(ANGL);INT(PERC);
2990 IF K2=53 THEN 3000 ELSE 3010
3000 PRINT " DISTANCE:";INT(DIST);
3010 IF K2=54 THEN 3020 ELSE 3030
3020 PRINT " RANGE:";INT(RANG0-DIST);
3030 IF K3=49 THEN 3040 ELSE 3190
3040 YP=ALTI*20/150
3050 YPOS=5+INT(YP)
3060 X=16
3070 CALL HCHAR(4,16,128-ANGL*5/90)
3080 IF ALTI>150 THEN 3180
3090 FINE=INT((YP-INT(YP))*8)+1
3100 TOGO=RANG0-DIST
3110 XI=INT(TOGO-INT(TOGO/8)*8)+1
3120 PAD$=SEG$("0000000000000000",1,FINE*2-2)&B$(XI)
3130 CALL HCHAR(YPOS,1,42,32)
3140 CALL CHAR(42,A$(FINE))
3150 IF ABS(RANG0-DIST)<120 THEN 3160 ELSE 3180
3160 CALL CHAR(43,PAD$)
3170 CALL HCHAR(YPOS,(RANG0-DIST)/8+16,43)
3180 IF P=1 THEN 3420 ELSE 3410
3190 IF K3=50 THEN 3200 ELSE 3420
3200 TOGO=RANG0-DIST
3210 ANGW=ATN(SQR(ALTI)/1864.1)+(90+ANGL)/57.3
3220 HWIN=(TAN(ANGW)*0.5+0.2)*24
3230 IF (HWIN>=1.0)*(HWIN<=23)THEN 3240 ELSE 3260
3240 CALL HCHAR(HWIN,1,144+5*(1-ALTI/2290),32)
3250 ANGW=ATN(ALTI/(RANG0-DIST))+(90+ANGL)/57.3
3260 HWIN=(TAN(ANGW)*0.5+0.2)*24
3270 ANGW2=ATN(ALTI/(TOGO+200))+(90+ANGL)/57.3
3280 HWIN2=(TAN(ANGW2)*0.5+0.2)*24
3290 IF (HWIN>=1.0)*(HWIN<=23)THEN 3300 ELSE 3400
3300 REM  LDIS=SQR(ALTI^2+(RANG0-DIST)^2)
3310 REM  CALL HCHAR(HWIN,16,152+5*(1-LDIS/2290))
3320 W1=INT(3000/TOGO)
3330 W2=INT(3000/(TOGO+200))
3340 IF (W1-W2)=1 THEN 3350 ELSE 3360
3350 W2=W2-1
3360 IF (W1-W2)=0 THEN 3370 ELSE 3380
3370 W1=W1+2
3380 CALL HCHAR(HWIN,16-W1/2,96,W1)
3390 CALL HCHAR(HWIN2,16-W2/2,96,W2)
3400 IF P=1 THEN 3420
3410 PRINT INT(ALTI);INT(VELX);INT(VELZ);INT(ANGL);INT(PERC);
3420 TI=TI+DT
3430 GOTO 1170

 

 

New version using orbital equations of motion

Spoiler

100 CALL CLEAR
101 CALL SCREEN(2)
102 FOR I=1 TO 12
103 CALL COLOR(I,16,1)
104 NEXT I
110 PRINT "   LUNAR MODULE PILOT"
120 PRINT "   ******************":::
130 PRINT "1. VERTICAL DESCENT"
140 PRINT "   50 METRES ALTITUDE"::
150 PRINT "2. LANDING"
160 PRINT "   150 METRES ALTITUDE"::
170 PRINT "3. APPROACH"
180 PRINT "   2200 METRES ALTITUDE"::
181 PRINT "4. THROTTLE RECOVERY"
182 PRINT "   7500 METRES ALTITUDE"::
190 PRINT "5. BRAKING"
200 PRINT "   15000 METRES ALTITUDE"::
210 PRINT
219 INPUT "START AT:":A
220 CALL CLEAR
221 CALL SCREEN(2)
222 FOR I=1 TO 8
223 CALL COLOR(I,4,1)
224 NEXT I
225 CALL COLOR(9,16,1)
226 CALL COLOR(13,11,1)
227 CALL COLOR(14,11,1)
228 CALL COLOR(15,15,1)
230 CALL CHAR(96,"000000FFFF000000")
240 CALL CHAR(128,"0001193C3C190100")
250 CALL CHAR(129,"0000193D3C180204")
260 CALL CHAR(130,"0000183D3D18000C")
270 CALL CHAR(131,"0000183C3D190018")
280 CALL CHAR(132,"0000183C3C190230")
290 CALL CHAR(133,"0000183C3C180066")
300 CALL CHAR(134,"0000183C3C98400C")
310 CALL CHAR(135,"0000183CBC980018")
320 CALL CHAR(136,"000018BCBC180030")
330 CALL CHAR(137,"000098BC3C184020")
340 CALL CHAR(138,"0080983C3C988000")
350 CALL CHAR(144,"000000000000AAFF")
360 CALL CHAR(145,"000000000000CCFF")
370 CALL CHAR(146,"00000000002277FF")
380 CALL CHAR(147,"0000000010387CFF")
390 CALL CHAR(148,"00000000183C7EFF")
400 CALL CHAR(149,"0000183C7EFFFFFF")
410 CALL CHAR(152,"0000000010000000")
420 CALL CHAR(153,"0000001818000000")
430 CALL CHAR(154,"0000182424180000")
440 CALL CHAR(155,"003C424242423C00")
450 CALL CHAR(156,"3C4281818181423C")
460 CALL CHAR(157,"7E8181818181817E")
470 A$(8)="00000000000000FF"
480 A$(7)="000000000000FF"
490 A$(6)="0000000000FF"
500 A$(5)="00000000FF"
510 A$(4)="000000FF"
520 A$(3)="0000FF"
530 A$(2)="00FF"
540 A$(1)="FF"
550 B$(8)="FE"
560 B$(7)="FD"
570 B$(6)="FB"
580 B$(5)="F7"
590 B$(4)="EF"
600 B$(3)="DF"
610 B$(2)="BF"
620 B$(1)="7F"
630 PI=4*ATN(1)
640 DEF ASIN(X)=ATN(X/SQR(1-X*X))
650 GM=7.3E+22*6.6743E-11
660 ASCF=2376
670 DESF=8248
680 ASCM=2445
690 DESM=2034
700 DRYM=ASCM+DESM+ASCF
710 MAXT=43903
720 DISP=311
730 THRU=1.0*MAXT
731 THRO=1
732 PITC=1
740 VELX=1695.0
750 VELZ=-2.0
760 ALTI=14078
770 DIST=0
780 RANG0=489170
790 ANGL=-9.0
800 LUNG=1.60
810 EARG=9.81
815 RADI=1737400.0+ALTI
820 DT=1
830 TI=0
840 X=1
850 IF A=4 THEN 860 ELSE 921
860 DESF=2453
870 VELX=270
880 VELZ=-32
890 ALTI=7511
900 DIST=454707
910 ANGL=-18
920 THRU=43903
921 IF A=3 THEN 922 ELSE 930
922 DESF=1961
923 VELX=157
924 VELZ=-44
925 ALTI=2274
926 DIST=483088
927 ANGL=-29
928 THRU=26245
930 IF A=2 THEN 940 ELSE 1010
940 DESF=1320
950 VELX=19
960 VELZ=-5
970 ALTI=153
980 DIST=488907
990 ANGL=-81
1000 THRU=17211
1010 IF A=1 THEN 1020 ELSE 1090
1020 DESF=1195
1030 VELX=1.8
1040 VELZ=-2.9
1050 ALTI=50.2
1060 DIST=489170
1070 ANGL=-79
1080 THRU=13240
1090 TOTM=ASCF+DESF+ASCM+DESM
1100 ACCX=0.0
1110 LAND_FLAG=0
1120 LANDED=0
1130 RADI=1737400.0+ALTI
1140 ANGV=VELX/RADI
1150 ANGX=0.0
1151 RADI_OLD=RADI
1152 ANGX_OLD=ANGX
1153 VELZ_OLD=VELZ
1154 ANGV_OLD=ANGV
1160 RAD=2.0*PI/360.0
1170 IF LANDED=1 THEN 2350
1180 FLAG=-(ALTI<7509)-(ALTI<2209)-(ALTI<156)-(ALTI<61)
1190 REM   14000 M TO 7509 M      
1200 IF FLAG<>0 THEN 1330
1210 IF TI>26 THEN 1250
1220 THRU=0.1*MAXT
1230 ANGL=0
1240 GOTO 1330
1250 THRU=MAXT
1260 TARG=7509
1270 TARV=32
1280 TARH=ALTI-TARG
1285 MOOG=-(RADI*ANGV^2.0-GM/RADI^2.0)
1290 N=(0.5*VELZ^2-0.5*TARV^2+MOOG*TARH)/(THRU*TARH/TOTM)
1300 N=-N*(N<1)-0.99999999*(N>=1)
1310 ANGL=-ASIN(N)*360/(2*PI)
1320 REM   7509 M TO 2290 M  
1330 IF FLAG<>1 THEN 1460
1340 TARG=2209
1350 TARV=44
1360 TARH=ALTI-TARG
1365 MOOG=-(RADI*ANGV^2.0-GM/RADI^2.0)
1370 N=(0.5*VELZ^2-0.5*TARV^2+MOOG*TARH)/(THRU*TARH/TOTM)
1380 N=-N*(N<1)-0.99999999*(N>=1)
1390 ANGL=-ASIN(N)*360/(2*PI)
1400 SHOR=VELX-ACCX*(ALTI-TARG)/VELZ
1410 IF SHOR>154.0 THEN 1420 ELSE 1430
1420 THRU=THRU+1000.0
1430 IF SHOR<=154.0 THEN 1440 ELSE 1460
1440 THRU=THRU-1000.0
1450 REM   2209 M TO 156 M  
1460 IF FLAG<>2 THEN 1620
1470 TARG=156
1480 TARV=5
1490 TARH=ALTI-TARG
1500 DECE=(-TARV^2+VELZ^2)/(2.0*TARH)+1.6
1510 N=-(DECE/(MAXT/TOTM))/SIN(ANGL*RAD)
1520 THRU=N*MAXT
1530 TVER=-(ALTI-156.0)/VELZ
1540 SHOR=VELX+ACCX*TVER
1550 IF SHOR>20.0 THEN 1560 ELSE 1570
1560 ANGL=ANGL+1
1570 IF SHOR<20.0 THEN 1580 ELSE 1590
1580 ANGL=ANGL-1
1590 IF ANGL>-30.0 THEN 1600 ELSE 1620
1600 ANGL=-30.0
1610 REM   156 M TO 60 M  
1620 IF FLAG<>3 THEN 1800
1630 IF HOVE=0 THEN 1660
1640 N=-(TOTM*1.6/MAXT)/SIN(ANGL*RAD)
1650 GOTO 1800
1660 TARG=60
1670 TARV=3
1680 TARH=ALTI-TARG
1690 DECE=(-TARV^2+VELZ^2)/(2.0*TARH)+1.6
1700 N=-(DECE/(MAXT/TOTM))/SIN(ANGL*RAD)
1710 THRU=N*MAXT
1720 TVER=-(ALTI-60.0)/VELZ
1730 SHOR=VELX+ACCX*TVER
1740 IF SHOR>3.0 THEN 1750 ELSE 1760
1750 ANGL=ANGL+5
1760 IF SHOR<3.0 THEN 1770 ELSE 1780
1770 ANGL=ANGL-5
1780 IF ANGL>-30.0 THEN 1790 ELSE 1800
1790 ANGL=-30.0
1800 IF FLAG<>4 THEN 1960
1810 IF HOVE=0 THEN 1840
1820 N=-(TOTM*1.6/MAXT)/SIN(ANGL*RAD)
1830 GOTO 2170
1840 TARV=2.0
1850 TARH=ALTI
1860 N=(0.5*VELZ^2.0-0.5*TARV^2.0+1.6*TARH)/(MAXT*TARH/TOTM)
1870 THRU=N*MAXT
1880 TVER=-ALTI/VELZ
1890 SHOR=VELX+ACCX*TVER
1900 IF SHOR>3.0 THEN 1910 ELSE 1920
1910 ANGL=ANGL+1.0
1920 IF SHOR<3.0 THEN 1930 ELSE 1940
1930 ANGL=ANGL-1
1940 IF ANGL>-30.0 THEN 1950 ELSE 1960
1950 ANGL=-30.0
1960 IF GAME=0 THEN 2170
1961 CALL CLEAR
1970 PERC=THRU*100/MAXT
1980 PRINT "AP PITCH THRUST: ";INT(ANGL);INT(PERC);
1990 IF K3<>49 THEN 2030
2000 CALL HCHAR(4,16,128-ANGL*5/90)
2010 IF YPOS>24 THEN 2070
2020 CALL HCHAR(YPOS,1,42,32)
2030 REM   IF K3<>50 THEN 1940      
2040 REM   IF (HWIN>=1.0)*(HWIN<=23)THEN 1920 ELSE 1940  
2050 REM   CALL HCHAR(HWIN,1,144+5*(1-ALTI/2290),32)  
2060 REM   CALL HCHAR(HWIN,16,152+5*(1-LDIS/2290))  
2070 REM  IF GAME=0 THEN 2170     
2080 IF (K=32)*(AP<10)THEN 2120
2090 ANGL=PITC
2100 THRU=THRO
2110 GOTO 2170
2120 PITC=ANGL
2130 THRO=THRU
2140 AP=AP+1
2150 CALL SOUND(100,300,0)
2160 CALL SOUND(100,500,0)
2165 CALL SOUND(100,700,0)
2170 ANGF=-ATN(VELZ/VELX)*57.3
2180 ANGF=-ATN(VELZ/VELX)*57.3
2190 DESF=DESF-THRU*DT/(DISP*EARG)
2200 TOTM=DRYM+DESF
2210 ACCL=THRU/TOTM
2220 ACCX=-COS(ANGL/57.3)*ACCL
2230 ACCZ=SIN(ANGL/57.3)*ACCL
2240 RADI=RADI_OLD+VELZ_OLD*DT
2250 VELZ=VELZ_OLD+(RADI_OLD*ANGV_OLD^2.0-(GM/(RADI_OLD^2.0)))*DT
2260 IF HOVE=0 THEN 2280
2270 VELZ=VELZ0
2280 ANGV=ANGV_OLD-(2.0*VELZ_OLD*ANGV_OLD/RADI_OLD)*DT
2290 VELX=ANGV*RADI
2300 ALTI=RADI-1737400.0
2310 DIST=DIST+VELX*DT
2311 VELZ=VELZ-ACCZ*DT
2312 ANGV=ANGV+ACCX*DT/RADI
2313 RADI_OLD=RADI
2314 ANGX_OLD=ANGX
2315 VELZ_OLD=VELZ
2316 ANGV_OLD=ANGV
2317 PERC=THRU*100/MAXT
2320 IF (ALTI<0.0)*(LANDED=0)THEN 2330 ELSE 2350
2330 LANDED=1
2340 ALTI=0.0
2350 CALL CLEAR
2360 CALL KEY(0,K,S)
2370 IF S=0 THEN 2850
2380 IF K=56 THEN 2390 ELSE 2450
2390 CALL SOUND(100,1000,0)
2391 GAME=-(GAME=0)
2400 IF GAME=0 THEN 2410 ELSE 2430
2410 PRINT "GAME MODE OFF";
2420 GOTO 3030
2430 PRINT "GAME MODE ON";
2440 GOTO 3030
2450 IF (K=ASC("Q"))+(K=ASC("A"))THEN 2460 ELSE 2480
2460 PITC=PITC-5*((K=ASC("Q"))-(K=ASC("A")))
2470 GOTO 2500
2480 IF (K=ASC("W"))+(K=ASC("S"))THEN 2490 ELSE 2540
2490 PITC=PITC-((K=ASC("W"))-(K=ASC("S")))
2500 ANGL=PITC
2510 CALL SOUND(100,500,15)
2530 GOTO 3410
2540 IF (K=ASC("O"))+(K=ASC("L"))THEN 2550 ELSE 2570
2550 THRO=THRO-439*((K=ASC("O"))-(K=ASC("L")))
2560 GOTO 2590
2570 IF (K=ASC("I"))+(K=ASC("K"))THEN 2580 ELSE 2630
2580 THRO=THRO-4390.3*((K=ASC("I"))-(K=ASC("K")))
2590 THRU=THRO
2600 CALL SOUND(100,500,15)
2620 GOTO 3410
2630 IF K=55 THEN 2640 ELSE 2760
2640 IF HOVE=0 THEN 2650 ELSE 2700
2650 INPUT "DESCENT RATE:":VELZ0
2660 VELZ=VELZ0
2670 PRINT "MANUAL CONTROL";
2680 HOVE=1
2690 GOTO 2720
2700 PRINT "MANUAL CONTROL OFF";
2710 HOVE=0
2720 FOR DELAY=1 TO 200
2730 NEXT DELAY
2740 CALL CLEAR
2750 GOTO 3420
2760 IF (K=49)+(K=50)THEN 2770 ELSE 2810
2770 IF (P2=1)*(K<>K3)THEN 2790
2780 P2=-(P2=0)
2790 K3=K*P2
2800 GOTO 2850
2810 IF (K>=48)*(K<=58)THEN 2820 ELSE 2850
2820 CALL SOUND(100,500,0)
2821 CALL SOUND(100,1000,0)
2822 IF (P=1)*(K<>K2)THEN 2840
2830 P=-(P=0)
2840 K2=K*P
2850 IF (K2>0)+(K3>0)THEN 2860 ELSE 3410
2860 IF K2=51 THEN 2870 ELSE 2880
2870 PRINT " HORIZON:";INT(SQR(ALTI)*1864);
2880 IF K2=52 THEN 2890 ELSE 2990
2890 T1$=SEG$("ALTITUDE",1,LEN(STR$(INT(ABS(ALTI))))+1)
2900 T2$=SEG$("HVEL    ",1,LEN(STR$(INT(ABS(VELX))))+1)
2910 T3$=SEG$("VVEL    ",1,LEN(STR$(INT(ABS(VELZ))))+1)
2920 T4$=SEG$("PITCH   ",1,LEN(STR$(INT(ABS(ANGL))))+1)
2930 T5$=SEG$("THRUST  ",1,LEN(STR$(INT(ABS(THRU)))))
2940 P3=-(P3=0)
2950 IF P3=0 THEN 2960 ELSE 2980
2960 PRINT " "&T1$&" "&T2$&" "&T3$&" "&T4$&" "&T5$;
2970 GOTO 2990
2980 PRINT INT(ALTI);INT(VELX);INT(VELZ);INT(ANGL);INT(PERC);
2990 IF K2=53 THEN 3000 ELSE 3010
3000 PRINT " DISTANCE:";INT(DIST);
3010 IF K2=54 THEN 3020 ELSE 3021
3020 PRINT " RANGE:";INT(RANG0-DIST);
3021 IF K2=57 THEN 3022 ELSE 3023
3022 PRINT " TIME:";TI;
3023 IF K2=48 THEN 3024 ELSE 3030
3024 PRINT " FUEL:";INT(DESF*100/8248);
3030 IF K3=49 THEN 3040 ELSE 3190
3040 YP=ALTI*20/150
3050 YPOS=5+INT(YP)
3060 X=16
3070 CALL HCHAR(4,16,128-ANGL*5/90)
3080 IF ALTI>150 THEN 3180
3090 FINE=INT((YP-INT(YP))*8)+1
3100 TOGO=RANG0-DIST
3110 XI=INT(TOGO-INT(TOGO/8)*8)+1
3120 PAD$=SEG$("0000000000000000",1,FINE*2-2)&B$(XI)
3130 CALL HCHAR(YPOS,1,42,32)
3140 CALL CHAR(42,A$(FINE))
3150 IF ABS(RANG0-DIST)<120 THEN 3160 ELSE 3180
3160 CALL CHAR(43,PAD$)
3170 CALL HCHAR(YPOS,(RANG0-DIST)/8+16,43)
3180 IF P=1 THEN 3420 ELSE 3410
3190 IF K3=50 THEN 3200 ELSE 3420
3200 TOGO=RANG0-DIST
3210 ANGW=ATN(SQR(ALTI)/1864.1)+(90+ANGL)/57.3
3220 HWIN=(TAN(ANGW)*0.5+0.2)*24
3230 IF (HWIN>=1.0)*(HWIN<=23)THEN 3235 ELSE 3245
3235 CH=144+5*(1-ALTI/2290)
3236 CH=-CH*(CH>=144)-144*(CH<144)
3240 CALL HCHAR(HWIN,1,CH,32)
3245 IF ABS(TOGO)>1864.1*SQR(ALTI)THEN 3400
3250 ANGW=ATN(ALTI/(RANG0-DIST))+(90+ANGL)/57.3
3260 HWIN=(TAN(ANGW)*0.5+0.2)*24
3270 ANGW2=ATN(ALTI/(TOGO+200))+(90+ANGL)/57.3
3280 HWIN2=(TAN(ANGW2)*0.5+0.2)*24
3290 IF (HWIN>=1.0)*(HWIN<=23)THEN 3295 ELSE 3400
3295 IF (HWIN2>=1.0)*(HWIN2<=23)THEN 3300 ELSE 3400
3300 REM   LDIS=SQR(ALTI^2+(RANG0-DIST)^2)  
3310 REM   CALL HCHAR(HWIN,16,152+5*(1-LDIS/2290))  
3320 W1=ABS(INT(3000/TOGO))
3330 W2=ABS(INT(3000/(TOGO+200)))
3340 IF (W1-W2)=1 THEN 3350 ELSE 3360
3350 W2=W2-1
3360 IF (W1-W2)=0 THEN 3370 ELSE 3380
3370 W1=W1+2
3380 CALL HCHAR(HWIN,16-W1/2,96,W1)
3390 CALL HCHAR(HWIN2,16-W2/2,96,W2)
3400 IF P=1 THEN 3420
3410 PRINT INT(ALTI);INT(VELX);INT(VELZ);INT(ANGL);INT(PERC);
3420 TI=TI+DT
3430 GOTO 1170

 

 

TI_LEM_graphics.pdf LEM_YT.zip LEM_ORB.zip

TI_LEM_algorithms.pdf

Edited by tibasic
  • Like 2
Link to comment
Share on other sites

The layout and graphics look very nice! I guess your original idea was a first person version of an arcade lunar lander game. Is that right? This sounds like an interesting and novel idea. 

 

You're welcome to use or adapt the graphics from my program. It's the reason I documented it in the pdf. It's also for my own future reference. I'm not planning to polish the graphics in my program any more so there might be opportunities there for others to do something better.

 

I don't think I'd have time for any collaborations though.

 

 

Edited by tibasic
  • Like 1
Link to comment
Share on other sites

16 hours ago, SteveB said:

I just added "uses CRT;" and it compiled with Freepascal / Lazarus for Windows 64bit ... that's what I call portable code!

LANDER.exe 76 kB · 2 downloads

The game is character-based with no embedded Z80 code or CP/M-specific features and the code is pretty standard, so that's not too surprising. I'll have to check it out on my PC 😄

  • Like 1
Link to comment
Share on other sites

So in looking at the descent algorithm by @tibasic, I see that it's broken down into separate stages with specific target altitudes and velocities for each based on actual NASA specs which is very helpful. And now with orbital mechanics included to account for centrifugal force at orbital speeds! It's like Kerbal Space Program saying it's too complicated for that wimpy 40 year old computer, and @tibasic going "hold my beer..." 😁

Now for an even greater challenge, can we come up with a general autopilot algorithm that can handle variable gravity (obviously within the thrust and fuel limits of the LEM engines) without a landing profile and targeting an arbitrary landing zone? My original C version (manual control only) had these variable features, which when you think about it it's amazing how the human brain can process all this complicated information subliminally (no one is running motion equations on the fly in their heads) to achieve a soft landing under the most challenging situations. Neil Armstrong did just that when he took manual control of the LEM in the last few seconds to re-direct the LEM to a safe landing zone. 

  • Like 3
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...