Skip to content

Commit 7a15e38

Browse files
committed
added links for lander
1 parent 3716950 commit 7a15e38

21 files changed

+1413
-8
lines changed

assets/styles/components/misc.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
pre {
2020
margin: 5px;
21+
border-bottom-right-radius: 18px;
22+
2123
& > code {
2224
padding: 10px !important;
2325
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import pygame
2+
from pygame.math import Vector3
3+
from OpenGL.GL import *
4+
from OpenGL.GLU import *
5+
import numpy as np
6+
7+
class LunarLander:
8+
def __init__(self):
9+
self.position = Vector3(0, 10, 0)
10+
self.velocity = Vector3(0, 0, 0)
11+
self.acceleration = Vector3(0, -1.62, 0) # Moon's gravity
12+
self.fuel = 1000.0
13+
self.thrust = Vector3(0, 0, 0)
14+
15+
def update(self, dt):
16+
self.velocity += (self.acceleration + self.thrust) * dt
17+
self.position += self.velocity * dt
18+
self.fuel -= self.thrust.length() * dt
19+
20+
def apply_thrust(self, thrust_vector):
21+
if self.fuel > 0:
22+
self.thrust = thrust_vector
23+
else:
24+
self.thrust = Vector3(0, 0, 0)
25+
26+
class Terrain:
27+
def __init__(self, size, resolution):
28+
self.size = size
29+
self.resolution = resolution
30+
self.heights = np.random.uniform(0, 1, (resolution, resolution))
31+
# Apply some smoothing here for more realistic terrain
32+
33+
def draw_cube():
34+
vertices = [
35+
( 0.5, 0.5, 0.5), (-0.5, 0.5, 0.5), (-0.5, -0.5, 0.5), ( 0.5, -0.5, 0.5),
36+
( 0.5, 0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), ( 0.5, -0.5, -0.5)
37+
]
38+
39+
edges = [
40+
(0,1), (1,2), (2,3), (3,0),
41+
(4,5), (5,6), (6,7), (7,4),
42+
(0,4), (1,5), (2,6), (3,7)
43+
]
44+
45+
glBegin(GL_LINES)
46+
for edge in edges:
47+
for vertex in edge:
48+
glVertex3fv(vertices[vertex])
49+
glEnd()
50+
51+
def draw_lander(lander):
52+
glPushMatrix()
53+
glTranslatef(lander.position.x, lander.position.y, lander.position.z)
54+
glColor3f(1, 1, 1)
55+
draw_cube()
56+
glPopMatrix()
57+
58+
def draw_terrain(terrain):
59+
glBegin(GL_TRIANGLES)
60+
for i in range(terrain.resolution - 1):
61+
for j in range(terrain.resolution - 1):
62+
x1, z1 = i * terrain.size / terrain.resolution, j * terrain.size / terrain.resolution
63+
x2, z2 = (i + 1) * terrain.size / terrain.resolution, (j + 1) * terrain.size / terrain.resolution
64+
y11, y12, y21, y22 = (terrain.heights[i,j], terrain.heights[i,j+1],
65+
terrain.heights[i+1,j], terrain.heights[i+1,j+1])
66+
67+
glColor3f(0.5, 0.5, 0.5)
68+
glVertex3f(x1, y11, z1)
69+
glVertex3f(x1, y12, z2)
70+
glVertex3f(x2, y22, z2)
71+
72+
glVertex3f(x1, y11, z1)
73+
glVertex3f(x2, y22, z2)
74+
glVertex3f(x2, y21, z1)
75+
glEnd()
76+
77+
def main():
78+
pygame.init()
79+
display = (800, 600)
80+
pygame.display.set_mode(display, pygame.DOUBLEBUF | pygame.OPENGL)
81+
82+
gluPerspective(45, (display[0] / display[1]), 0.1, 50.0)
83+
glTranslatef(0.0, 0.0, -20)
84+
85+
lander = LunarLander()
86+
terrain = Terrain(20, 50)
87+
88+
clock = pygame.time.Clock()
89+
90+
while True:
91+
for event in pygame.event.get():
92+
if event.type == pygame.QUIT:
93+
pygame.quit()
94+
quit()
95+
96+
keys = pygame.key.get_pressed()
97+
thrust = Vector3(0, 0, 0)
98+
if keys[pygame.K_UP]:
99+
thrust.y = 100
100+
print(thrust)
101+
if keys[pygame.K_LEFT]:
102+
thrust.x = -1.0
103+
print(thrust)
104+
if keys[pygame.K_RIGHT]:
105+
thrust.x = 1.0
106+
107+
lander.apply_thrust(thrust)
108+
lander.update(0.01)
109+
110+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
111+
112+
draw_terrain(terrain)
113+
draw_lander(lander)
114+
115+
pygame.display.flip()
116+
clock.tick(60)
117+
118+
if __name__ == "__main__":
119+
main()
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import gymnasium as gym
2+
import numpy as np
3+
import torch
4+
import torch.nn as nn
5+
import torch.optim as optim
6+
from collections import deque
7+
import random
8+
9+
10+
class DQN(nn.Module):
11+
def __init__(self, state_size, action_size):
12+
super(DQN, self).__init__()
13+
self.fc1 = nn.Linear(state_size, 64)
14+
self.fc2 = nn.Linear(64, 64)
15+
self.fc3 = nn.Linear(64, action_size)
16+
17+
def forward(self, x):
18+
x = torch.relu(self.fc1(x))
19+
x = torch.relu(self.fc2(x))
20+
return self.fc3(x)
21+
22+
23+
class DQNAgent:
24+
def __init__(self, state_size, action_size):
25+
self.state_size = state_size
26+
self.action_size = action_size
27+
self.memory = deque(maxlen=100000)
28+
self.gamma = 0.99 # discount rate
29+
self.epsilon = 1.0 # exploration rate
30+
self.epsilon_min = 0.01
31+
self.epsilon_decay = 1 - 1e-5
32+
self.learning_rate = 0.002
33+
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
34+
self.model = DQN(state_size, action_size).to(self.device)
35+
self.target_model = DQN(state_size, action_size).to(self.device)
36+
self.optimizer = optim.Adam(self.model.parameters(), lr=self.learning_rate)
37+
self.criterion = nn.MSELoss()
38+
39+
def update_target_model(self):
40+
self.target_model.load_state_dict(self.model.state_dict())
41+
42+
def remember(self, state, action, reward, next_state, done):
43+
self.memory.append((state, action, reward, next_state, done))
44+
45+
def act(self, state):
46+
if np.random.rand() <= self.epsilon:
47+
return random.randrange(self.action_size)
48+
state = torch.FloatTensor(state).unsqueeze(0).to(self.device)
49+
with torch.no_grad():
50+
act_values = self.model(state)
51+
return np.argmax(act_values.cpu().data.numpy())
52+
53+
def replay(self, batch_size):
54+
minibatch = random.sample(self.memory, batch_size)
55+
states, actions, rewards, next_states, dones = zip(*minibatch)
56+
57+
states = torch.FloatTensor(states).to(self.device)
58+
actions = torch.LongTensor(actions).to(self.device)
59+
rewards = torch.FloatTensor(rewards).to(self.device)
60+
next_states = torch.FloatTensor(next_states).to(self.device)
61+
dones = torch.FloatTensor(dones).to(self.device)
62+
63+
current_q_values = self.model(states).gather(1, actions.unsqueeze(1))
64+
next_q_values = self.target_model(next_states).max(1)[0].detach()
65+
target_q_values = rewards + (self.gamma * next_q_values * (1 - dones))
66+
67+
loss = self.criterion(current_q_values, target_q_values.unsqueeze(1))
68+
self.optimizer.zero_grad()
69+
loss.backward()
70+
self.optimizer.step()
71+
72+
if self.epsilon > self.epsilon_min:
73+
self.epsilon *= self.epsilon_decay
74+
75+
def main():
76+
env = gym.make("LunarLander-v2", render_mode='human')
77+
state_size = env.observation_space.shape[0]
78+
action_size = env.action_space.n
79+
agent = DQNAgent(state_size, action_size)
80+
batch_size = 32
81+
episodes = 1000
82+
83+
for episode in range(episodes):
84+
state, _ = env.reset()
85+
score = 0
86+
max_steps = 1000
87+
for time in range(max_steps):
88+
action = agent.act(state)
89+
next_state, reward, done, _, _ = env.step(action)
90+
agent.remember(state, action, reward, next_state, done)
91+
state = next_state
92+
score += reward
93+
if len(agent.memory) > batch_size:
94+
agent.replay(batch_size)
95+
if done:
96+
agent.update_target_model()
97+
break
98+
99+
print(f"Episode: {episode+1}/{episodes}, Score: {score:.2f}, Epsilon: {agent.epsilon:.2f}")
100+
101+
# Render every 50 episodes
102+
if (episode + 1) % 50 == 0:
103+
env.render()
104+
105+
env.close()
106+
# state, _ = env.reset()
107+
# score = 0
108+
# max_steps = 1000
109+
# for time in range(max_steps):
110+
# action = agent.act(state)
111+
# next_state, reward, done, _, _ = env.step(action)
112+
# agent.remember(state, action, reward, next_state, done)
113+
# state = next_state
114+
# score += reward
115+
# if len(agent.memory) > batch_size:
116+
# agent.replay(batch_size)
117+
# if done:
118+
# agent.update_target_model()
119+
# break
120+
# env.render("human")
121+
122+
if __name__ == "__main__":
123+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* https://aayala4.github.io/Lunar-Lander-Python/
2+
* https://github.com/arda-guler/miniLanding3D/tree/master

public/application.48fbd910ec2bdab3c57b60f2698483acf3bb5786ccfa4b11960e2eb1117c6b89.css

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/application.a680ede547917d70647cd9740beaf84d8cfd9c14e5632ad70fc68f05058beef5.css

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)