Á¤¼ºÈÆ
    10Àå) ÀÚÀ²ÁÖÇàÂ÷¸¦ À§ÇÑ AI
°­È­ÇнÀ ½Ç½À (ÀÚÀ²ÁÖÇàÂ÷).pdf [1030 KB]   ÀÚÀ²ÁÖÇà ¿¹Á¦ ½ÇÇà°á°ú.mp4 [5382 KB]  



deep_q_learning.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# AI for Autonomous Vehicles - Build a Self-Driving Car
 
# Importing the libraries
 
import os
import random
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
 
# Creating the architecture of the Neural Network
 
class Network(nn.Module):
    
    def __init__(self, input_size, nb_action):
        super(Network, self).__init__()
        self.input_size = input_size
        self.nb_action = nb_action
        self.fc1 = nn.Linear(input_size, 30)
        self.fc2 = nn.Linear(30, nb_action)
    
    def forward(self, state):
        x = F.relu(self.fc1(state))
        q_values = self.fc2(x)
        return q_values
 
# Implementing Experience Replay
 
class ReplayMemory(object):
    
    def __init__(self, capacity):
        self.capacity = capacity
        self.memory = []
    
    def push(self, event):
        self.memory.append(event)
        if len(self.memory) > self.capacity:
            del self.memory[0]
    
    def sample(self, batch_size):
        samples = zip(*random.sample(self.memory, batch_size))
        return map(lambda x: Variable(torch.cat(x, 0)), samples)
 
# Implementing Deep Q-Learning
 
class Dqn(object):
    
    def __init__(self, input_size, nb_action, gamma):
        self.gamma = gamma
        self.model = Network(input_size, nb_action)
        self.memory = ReplayMemory(capacity = 100000)
        self.optimizer = optim.Adam(params = self.model.parameters())
        self.last_state = torch.Tensor(input_size).unsqueeze(0)
        self.last_action = 0
        self.last_reward = 0
    
    def select_action(self, state):
        probs = F.softmax(self.model(Variable(state))*100)
        action = probs.multinomial(len(probs))
        return action.data[0,0]
    
    def learn(self, batch_states, batch_actions, batch_rewards, batch_next_states):
        batch_outputs = self.model(batch_states).gather(1, batch_actions.unsqueeze(1)).squeeze(1)
        batch_next_outputs = self.model(batch_next_states).detach().max(1)[0]
        batch_targets = batch_rewards + self.gamma * batch_next_outputs
        td_loss = F.smooth_l1_loss(batch_outputs, batch_targets)
        self.optimizer.zero_grad()
        td_loss.backward()
        self.optimizer.step()
    
    def update(self, new_state, new_reward):
        new_state = torch.Tensor(new_state).float().unsqueeze(0)
        self.memory.push((self.last_state, torch.LongTensor([int(self.last_action)]), torch.Tensor([self.last_reward]), new_state))
        new_action = self.select_action(new_state)
        if len(self.memory.memory) > 100:
            batch_states, batch_actions, batch_rewards, batch_next_states = self.memory.sample(100)
            self.learn(batch_states, batch_actions, batch_rewards, batch_next_states)
        self.last_state = new_state
        self.last_action = new_action
        self.last_reward = new_reward
        return new_action
    
    def save(self):
        torch.save({'state_dict'self.model.state_dict(),
                    'optimizer' : self.optimizer.state_dict(),
                   }, 'last_brain.pth')
    
    def load(self):
        if os.path.isfile('last_brain.pth'):
            print("=> loading checkpoint... ")
            checkpoint = torch.load('last_brain.pth')
            self.model.load_state_dict(checkpoint['state_dict'])
            self.optimizer.load_state_dict(checkpoint['optimizer'])
            print("done !")
        else:
            print("no checkpoint found...")
cs


map.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# AI for Autonomous Vehicles - Build a Self-Driving Car
 
# Building the Environment
 
# Importing the libraries
import numpy as np
from random import random, randint
import time
 
# Importing the Kivy packages
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line
from kivy.config import Config
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
 
# Importing the Dqn object from our AI in deep_q_learning.py
from deep_q_learning import Dqn
 
# Adding this line if we don't want the right click to put a red point
Config.set('input''mouse''mouse,multitouch_on_demand')
 
# Introducing last_x and last_y, used to keep the last point in memory when we draw the sand on the map
last_x = 0
last_y = 0
n_points = 0
length = 0
 
# Creating the brain of our AI, the list of actions and the reward variable
brain = Dqn(4,3,0.9)
action2rotation = [0,20,-20]
reward = 0
 
# Initializing the map
first_update = True
def init():
    global sand
    global goal_x
    global goal_y
    global first_update
    sand = np.zeros((longueur,largeur))
    goal_x = 20
    goal_y = largeur - 20
    first_update = False
 
# Initializing the last distance from the car to the goal
last_distance = 0
 
# Creating the car class
 
class Car(Widget):
    
    angle = NumericProperty(0)
    rotation = NumericProperty(0)
    velocity_x = NumericProperty(0)
    velocity_y = NumericProperty(0)
    velocity = ReferenceListProperty(velocity_x, velocity_y)
    sensor1_x = NumericProperty(0)
    sensor1_y = NumericProperty(0)
    sensor1 = ReferenceListProperty(sensor1_x, sensor1_y)
    sensor2_x = NumericProperty(0)
    sensor2_y = NumericProperty(0)
    sensor2 = ReferenceListProperty(sensor2_x, sensor2_y)
    sensor3_x = NumericProperty(0)
    sensor3_y = NumericProperty(0)
    sensor3 = ReferenceListProperty(sensor3_x, sensor3_y)
    signal1 = NumericProperty(0)
    signal2 = NumericProperty(0)
    signal3 = NumericProperty(0)
 
    def move(self, rotation):
        self.pos = Vector(*self.velocity) + self.pos
        self.rotation = rotation
        self.angle = self.angle + self.rotation
        self.sensor1 = Vector(300).rotate(self.angle) + self.pos
        self.sensor2 = Vector(300).rotate((self.angle+30)%360+ self.pos
        self.sensor3 = Vector(300).rotate((self.angle-30)%360+ self.pos
        self.signal1 = int(np.sum(sand[int(self.sensor1_x)-10:int(self.sensor1_x)+10int(self.sensor1_y)-10:int(self.sensor1_y)+10]))/400.
        self.signal2 = int(np.sum(sand[int(self.sensor2_x)-10:int(self.sensor2_x)+10int(self.sensor2_y)-10:int(self.sensor2_y)+10]))/400.
        self.signal3 = int(np.sum(sand[int(self.sensor3_x)-10:int(self.sensor3_x)+10int(self.sensor3_y)-10:int(self.sensor3_y)+10]))/400.
        if self.sensor1_x>longueur-10 or self.sensor1_x<10 or self.sensor1_y>largeur-10 or self.sensor1_y<10:
            self.signal1 = 1.
        if self.sensor2_x>longueur-10 or self.sensor2_x<10 or self.sensor2_y>largeur-10 or self.sensor2_y<10:
            self.signal2 = 1.
        if self.sensor3_x>longueur-10 or self.sensor3_x<10 or self.sensor3_y>largeur-10 or self.sensor3_y<10:
            self.signal3 = 1.
 
class Ball1(Widget):
    pass
class Ball2(Widget):
    pass
class Ball3(Widget):
    pass
 
# Creating the game class
 
class Game(Widget):
 
    car = ObjectProperty(None)
    ball1 = ObjectProperty(None)
    ball2 = ObjectProperty(None)
    ball3 = ObjectProperty(None)
 
    def serve_car(self):
        self.car.center = self.center
        self.car.velocity = Vector(60)
 
    def update(self, dt):
 
        global brain
        global reward
        global last_distance
        global goal_x
        global goal_y
        global longueur
        global largeur
 
        longueur = self.width
        largeur = self.height
        if first_update:
            init()
 
        xx = goal_x - self.car.x
        yy = goal_y - self.car.y
        orientation = Vector(*self.car.velocity).angle((xx,yy))/180.
        state = [orientation, self.car.signal1, self.car.signal2, self.car.signal3]
        action = brain.update(state, reward)
        rotation = action2rotation[action]
        self.car.move(rotation)
        distance = np.sqrt((self.car.x - goal_x)**2 + (self.car.y - goal_y)**2)
        self.ball1.pos = self.car.sensor1
        self.ball2.pos = self.car.sensor2
        self.ball3.pos = self.car.sensor3
 
        if sand[int(self.car.x),int(self.car.y)] > 0:
            self.car.velocity = Vector(10).rotate(self.car.angle)
            reward = -1
        else:
            self.car.velocity = Vector(60).rotate(self.car.angle)
            reward = -0.2
            if distance < last_distance:
                reward = 0.1
 
        if self.car.x < 10:
            self.car.x = 10
            reward = -1
        if self.car.x > self.width - 10:
            self.car.x = self.width - 10
            reward = -1
        if self.car.y < 10:
            self.car.y = 10
            reward = -1
        if self.car.y > self.height - 10:
            self.car.y = self.height - 10
            reward = -1
 
        if distance < 100:
            goal_x = self.width-goal_x
            goal_y = self.height-goal_y
 
        last_distance = distance
 
# Adding the painting tools
 
class MyPaintWidget(Widget):
 
    def on_touch_down(self, touch):
        global length, n_points, last_x, last_y
        with self.canvas:
            Color(0.8,0.7,0)
            d = 10.
            touch.ud['line'= Line(points = (touch.x, touch.y), width = 10)
            last_x = int(touch.x)
            last_y = int(touch.y)
            n_points = 0
            length = 0
            sand[int(touch.x),int(touch.y)] = 1
 
    def on_touch_move(self, touch):
        global length, n_points, last_x, last_y
        if touch.button == 'left':
            touch.ud['line'].points += [touch.x, touch.y]
            x = int(touch.x)
            y = int(touch.y)
            length += np.sqrt(max((x - last_x)**2 + (y - last_y)**22))
            n_points += 1.
            density = n_points/(length)
            touch.ud['line'].width = int(20 * density + 1)
            sand[int(touch.x) - 10 : int(touch.x) + 10int(touch.y) - 10 : int(touch.y) + 10= 1
            last_x = x
            last_y = y
 
# Adding the API Buttons (clear, save and load)
 
class CarApp(App):
 
    def build(self):
        parent = Game()
        parent.serve_car()
        Clock.schedule_interval(parent.update, 1.0/60.0)
        self.painter = MyPaintWidget()
        clearbtn = Button(text = 'clear')
        savebtn = Button(text = 'save', pos = (parent.width, 0))
        loadbtn = Button(text = 'load', pos = (2 * parent.width, 0))
        clearbtn.bind(on_release = self.clear_canvas)
        savebtn.bind(on_release = self.save)
        loadbtn.bind(on_release = self.load)
        parent.add_widget(self.painter)
        parent.add_widget(clearbtn)
        parent.add_widget(savebtn)
        parent.add_widget(loadbtn)
        return parent
 
    def clear_canvas(self, obj):
        global sand
        self.painter.canvas.clear()
        sand = np.zeros((longueur,largeur))
 
    def save(self, obj):
        print("saving brain...")
        brain.save()
 
    def load(self, obj):
        print("loading last saved brain...")
        brain.load()
 
# Running the whole thing
if __name__ == '__main__':
    CarApp().run()
cs


map_commented.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# AI for Autonomous Vehicles - Build a Self-Driving Car
 
# Building the Environment
 
# Importing the libraries
import numpy as np
from random import random, randint
import matplotlib.pyplot as plt
import time
 
# Importing the Kivy packages
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line
from kivy.config import Config
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
 
# Importing the Dqn object from our AI in ia.py
from ai import Dqn
 
# Adding this line if we don't want the right click to put a red point
Config.set('input''mouse''mouse,multitouch_on_demand')
 
# Introducing last_x and last_y, used to keep the last point in memory when we draw the sand on the map
last_x = 0
last_y = 0
n_points = 0 # the total number of points in the last drawing
length = 0 # the length of the last drawing
 
# Creating the brain of our AI, the list of actions and the reward variable
brain = Dqn(4,3,0.9# 4 inputs, 3 actions, gamma = 0.9
action2rotation = [0,20,-20# action = 0 => no rotation, action = 1 => rotate 20 degres, action = 2 => rotate -20 degres
reward = 0 # initializing the reward received after reaching a new state
 
# Initializing the map
first_update = True # using this trick to initialize the map only once
def init():
    global sand # sand is an array that has as many cells as our graphic interface has pixels. Each cell has a one if there is sand, 0 otherwise.
    global goal_x # x-coordinate of the goal (where the car has to go, that is the airport or the downtown)
    global goal_y # y-coordinate of the goal (where the car has to go, that is the airport or the downtown)
    global first_update # map initializer
    sand = np.zeros((longueur,largeur)) # initializing the sand array with only zeros
    goal_x = 20 # the goal to reach is at the upper left of the map (the x-coordinate is 20 and not 0 because the car gets bad reward if it touches the wall)
    goal_y = largeur - 20 # the goal to reach is at the upper left of the map (y-coordinate)
    first_update = False # trick to initialize the map only once
 
# Initializing the last distance from the car to the goal
last_distance = 0
 
# Creating the car class (to understand "NumericProperty" and "ReferenceListProperty", see kivy tutorials: https://kivy.org/docs/tutorials/pong.html)
 
class Car(Widget):
 
    angle = NumericProperty(0# initializing the angle of the car (angle between the x-axis of the map and the axis of the car)
    rotation = NumericProperty(0# initializing the last rotation of the car (after playing the action, the car does a rotation of 0, 20 or -20 degrees)
    velocity_x = NumericProperty(0# initializing the x-coordinate of the velocity vector
    velocity_y = NumericProperty(0# initializing the y-coordinate of the velocity vector
    velocity = ReferenceListProperty(velocity_x, velocity_y) # velocity vector
    sensor1_x = NumericProperty(0# initializing the x-coordinate of the first sensor (the one that looks forward)
    sensor1_y = NumericProperty(0# initializing the y-coordinate of the first sensor (the one that looks forward)
    sensor1 = ReferenceListProperty(sensor1_x, sensor1_y) # first sensor vector
    sensor2_x = NumericProperty(0# initializing the x-coordinate of the second sensor (the one that looks 30 degrees to the left)
    sensor2_y = NumericProperty(0# initializing the y-coordinate of the second sensor (the one that looks 30 degrees to the left)
    sensor2 = ReferenceListProperty(sensor2_x, sensor2_y) # second sensor vector
    sensor3_x = NumericProperty(0# initializing the x-coordinate of the third sensor (the one that looks 30 degrees to the right)
    sensor3_y = NumericProperty(0# initializing the y-coordinate of the third sensor (the one that looks 30 degrees to the right)
    sensor3 = ReferenceListProperty(sensor3_x, sensor3_y) # third sensor vector
    signal1 = NumericProperty(0# initializing the signal received by sensor 1
    signal2 = NumericProperty(0# initializing the signal received by sensor 2
    signal3 = NumericProperty(0# initializing the signal received by sensor 3
 
    def move(self, rotation):
        self.pos = Vector(*self.velocity) + self.pos # updating the position of the car according to its last position and velocity
        self.rotation = rotation # getting the rotation of the car
        self.angle = self.angle + self.rotation # updating the angle
        self.sensor1 = Vector(300).rotate(self.angle) + self.pos # updating the position of sensor 1
        self.sensor2 = Vector(300).rotate((self.angle+30)%360+ self.pos # updating the position of sensor 2
        self.sensor3 = Vector(300).rotate((self.angle-30)%360+ self.pos # updating the position of sensor 3
        self.signal1 = int(np.sum(sand[int(self.sensor1_x)-10:int(self.sensor1_x)+10int(self.sensor1_y)-10:int(self.sensor1_y)+10]))/400. # getting the signal received by sensor 1 (density of sand around sensor 1)
        self.signal2 = int(np.sum(sand[int(self.sensor2_x)-10:int(self.sensor2_x)+10int(self.sensor2_y)-10:int(self.sensor2_y)+10]))/400. # getting the signal received by sensor 2 (density of sand around sensor 2)
        self.signal3 = int(np.sum(sand[int(self.sensor3_x)-10:int(self.sensor3_x)+10int(self.sensor3_y)-10:int(self.sensor3_y)+10]))/400. # getting the signal received by sensor 3 (density of sand around sensor 3)
        if self.sensor1_x > longueur-10 or self.sensor1_x<10 or self.sensor1_y>largeur-10 or self.sensor1_y<10# if sensor 1 is out of the map (the car is facing one edge of the map)
            self.signal1 = 1. # sensor 1 detects full sand
        if self.sensor2_x > longueur-10 or self.sensor2_x<10 or self.sensor2_y>largeur-10 or self.sensor2_y<10# if sensor 2 is out of the map (the car is facing one edge of the map)
            self.signal2 = 1. # sensor 2 detects full sand
        if self.sensor3_x > longueur-10 or self.sensor3_x<10 or self.sensor3_y>largeur-10 or self.sensor3_y<10# if sensor 3 is out of the map (the car is facing one edge of the map)
            self.signal3 = 1. # sensor 3 detects full sand
 
class Ball1(Widget): # sensor 1 (see kivy tutorials: kivy https://kivy.org/docs/tutorials/pong.html)
    pass
class Ball2(Widget): # sensor 2 (see kivy tutorials: kivy https://kivy.org/docs/tutorials/pong.html)
    pass
class Ball3(Widget): # sensor 3 (see kivy tutorials: kivy https://kivy.org/docs/tutorials/pong.html)
    pass
 
# Creating the game class (to understand "ObjectProperty", see kivy tutorials: kivy https://kivy.org/docs/tutorials/pong.html)
 
class Game(Widget):
 
    car = ObjectProperty(None# getting the car object from our kivy file
    ball1 = ObjectProperty(None# getting the sensor 1 object from our kivy file
    ball2 = ObjectProperty(None# getting the sensor 2 object from our kivy file
    ball3 = ObjectProperty(None# getting the sensor 3 object from our kivy file
 
    def serve_car(self): # starting the car when we launch the application
        self.car.center = self.center # the car will start at the center of the map
        self.car.velocity = Vector(60# the car will start to go horizontally to the right with a speed of 6
 
    def update(self, dt): # the big update function that updates everything that needs to be updated at each discrete time t when reaching a new state (getting new signals from the sensors)
 
        global brain # specifying the global variables (the brain of the car, that is our AI)
        global reward # specifying the global variables (the last reward received)
        global last_distance # specifying the global variables (the last distance from the car to the goal)
        global goal_x # specifying the global variables (x-coordinate of the goal)
        global goal_y # specifying the global variables (y-coordinate of the goal)
        global longueur # specifying the global variables (width of the map)
        global largeur # specifying the global variables (height of the map)
 
        longueur = self.width # width of the map (horizontal edge)
        largeur = self.height # height of the map (vertical edge)
        if first_update: # trick to initialize the map only once
            init()
 
        xx = goal_x - self.car.x # difference of x-coordinates between the goal and the car
        yy = goal_y - self.car.y # difference of y-coordinates between the goal and the car
        orientation = Vector(*self.car.velocity).angle((xx,yy))/180. # direction of the car with respect to the goal (if the car is heading perfectly towards the goal, then orientation = 0)
        state = [orientation, self.car.signal1, self.car.signal2, self.car.signal3] # our input state vector, composed of the orientation plus the three signals received by the three sensors
        action = brain.update(state, reward) # updating the weights of the neural network in our ai and playing a new action
        rotation = action2rotation[action] # converting the action played (0, 1 or 2) into the rotation angle (0°, 20° or -20°)
        self.car.move(rotation) # moving the car according to this last rotation angle
        distance = np.sqrt((self.car.x - goal_x)**2 + (self.car.y - goal_y)**2# getting the new distance between the car and the goal right after the car moved
        self.ball1.pos = self.car.sensor1 # updating the position of the first sensor (ball1) right after the car moved
        self.ball2.pos = self.car.sensor2 # updating the position of the second sensor (ball2) right after the car moved
        self.ball3.pos = self.car.sensor3 # updating the position of the third sensor (ball3) right after the car moved
 
        if sand[int(self.car.x),int(self.car.y)] > 0# if the car is on the sand
            self.car.velocity = Vector(10).rotate(self.car.angle) # it is slowed down (speed = 1)
            reward = -1 # and reward = -1
        else# otherwise
            self.car.velocity = Vector(60).rotate(self.car.angle) # it goes to a normal speed (speed = 6)
            reward = -0.2 # and it gets a bad reward of -0.2
            if distance < last_distance: # however if it is getting closer to the goal
                reward = 0.1 # it still gets a slightly positive reward of 0.1
 
        if self.car.x < 10# if the car is in the left edge of the frame
            self.car.x = 10 # it comes back 10 pixels away from the edge
            reward = -1 # and it gets a bad reward of -1
        if self.car.x > self.width-10# if the car is in the right edge of the frame
            self.car.x = self.width-10 # it comes back 10 pixels away from the edge
            reward = -1 # and it gets a bad reward of -1
        if self.car.y < 10# if the car is in the bottom edge of the frame
            self.car.y = 10 # it comes back 10 pixels away from the edge
            reward = -1 # and it gets a bad reward of -1
        if self.car.y > self.height-10# if the car is in the upper edge of the frame
            self.car.y = self.height-10 # it comes back 10 pixels away from the edge
            reward = -1 # and it gets a bad reward of -1
 
        if distance < 100# when the car reaches its goal
            goal_x = self.width - goal_x # the goal becomes the bottom right corner of the map (the downtown), and vice versa (updating of the x-coordinate of the goal)
            goal_y = self.height - goal_y # the goal becomes the bottom right corner of the map (the downtown), and vice versa (updating of the y-coordinate of the goal)
 
        # Updating the last distance from the car to the goal
        last_distance = distance
 
# Painting for graphic interface (see kivy tutorials: https://kivy.org/docs/tutorials/firstwidget.html)
 
class MyPaintWidget(Widget):
 
    def on_touch_down(self, touch): # putting some sand when we do a left click
        global length,n_points,last_x,last_y
        with self.canvas:
            Color(0.8,0.7,0)
            d=10.
            touch.ud['line'= Line(points = (touch.x, touch.y), width = 10)
            last_x = int(touch.x)
            last_y = int(touch.y)
            n_points = 0
            length = 0
            sand[int(touch.x),int(touch.y)] = 1
 
    def on_touch_move(self, touch): # putting some sand when we move the mouse while pressing left
        global length,n_points,last_x,last_y
        if touch.button=='left':
            touch.ud['line'].points += [touch.x, touch.y]
            x = int(touch.x)
            y = int(touch.y)
            length += np.sqrt(max((x - last_x)**2 + (y - last_y)**22))
            n_points += 1.
            density = n_points/(length)
            touch.ud['line'].width = int(20*density + 1)
            sand[int(touch.x) - 10 : int(touch.x) + 10int(touch.y) - 10 : int(touch.y) + 10= 1
            last_x = x
            last_y = y
 
# API and switches interface (see kivy tutorials: https://kivy.org/docs/tutorials/pong.html)
 
class CarApp(App):
 
    def build(self): # building the app
        parent = Game()
        parent.serve_car()
        Clock.schedule_interval(parent.update, 1.0 / 60.0)
        self.painter = MyPaintWidget()
        clearbtn = Button(text='clear')
        savebtn = Button(text='save',pos=(parent.width,0))
        loadbtn = Button(text='load',pos=(2*parent.width,0))
        clearbtn.bind(on_release=self.clear_canvas)
        savebtn.bind(on_release=self.save)
        loadbtn.bind(on_release=self.load)
        parent.add_widget(self.painter)
        parent.add_widget(clearbtn)
        parent.add_widget(savebtn)
        parent.add_widget(loadbtn)
        return parent
 
    def clear_canvas(self, obj): # clear button
        global sand
        self.painter.canvas.clear()
        sand = np.zeros((longueur,largeur))
 
    def save(self, obj): # save button
        print("saving brain...")
        brain.save()
 
    def load(self, obj): # load button
        print("loading last saved brain...")
        brain.load()
 
# Running the app
if __name__ == '__main__':
    CarApp().run()
cs


car.kv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#:kivy 1.0.9
# ref: https://kivy.org/docs/tutorials/pong.html
 
<Car>:
    size: 20, 10
    canvas:
        PushMatrix
        Rotate:
            angle: self.angle
            origin: self.center
        Rectangle:
            pos: self.pos
            size: self.size
        PopMatrix
 
<Ball1>:
    size: 10,10
    canvas:
        Color:
            rgba: 1,0,0,1
        Ellipse:
            pos: self.pos
            size: self.size
<Ball2>:
    size: 10,10
    canvas:
        Color:
            rgba: 0,1,1,1
        Ellipse:
            pos: self.pos
            size: self.size
 
<Ball3>:
    size: 10,10
    canvas:
        Color:
            rgba: 1,1,0,1
        Ellipse:
            pos: self.pos
            size: self.size
 
<Game>:
    car: game_car
    ball1: game_ball1
    ball2: game_ball2
    ball3: game_ball3
 
    Car:
        id: game_car
        center: self.parent.center
    Ball1:
        id: game_ball1
        center: self.parent.center
    Ball2:
        id: game_ball2
        center: self.parent.center
    Ball3:
        id: game_ball3
        center: self.parent.center
cs

 

  µî·ÏÀÏ : 2021-10-30 [02:07] Á¶È¸ : 234 ´Ù¿î : 154   
 
¡â ÀÌÀü±Û13Àå) ½º³×ÀÌÅ© °ÔÀÓ ¸¶½ºÅÍ µÇ±â
¡ä ´ÙÀ½±Û¹Ù´ÚºÎÅÍ ¹è¿ì´Â °­È­ ÇнÀ ÄÚµå (github)
°­È­ÇнÀ ÀÌ·Ð ¹× ½Ç½À(MD) ½Ç½À
¹øÈ£ ¨Ï Á¦ ¸ñ À̸§
¹Ù´ÚºÎÅÍ ¹è¿ì´Â °­È­ ÇнÀ ÄÚµå (github)
°­È­ÇнÀ/½ÉÃþ°­È­ÇнÀ Ư°­ (github)
ÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀ (github)
25 lÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀ (github) Á¤¼ºÈÆ
24 ¦¦❶ 7Àå) ¾ÆŸ¸® ºê·¹ÀÌÅ© ¾Æ¿ô (A3C) Á¤¼ºÈÆ
23 ¦¦❶ 7Àå) ¾ÆŸ¸® ºê·¹ÀÌÅ© ¾Æ¿ô (DQN) Á¤¼ºÈÆ
22 l°­È­ÇнÀ/½ÉÃþ°­È­ÇнÀ Ư°­ (github) Á¤¼ºÈÆ
21 ¦¦❶ 13Àå) ½º³×ÀÌÅ© °ÔÀÓ ¸¶½ºÅÍ µÇ±â Á¤¼ºÈÆ
20 ¦¦❶ 10Àå) ÀÚÀ²ÁÖÇàÂ÷¸¦ À§ÇÑ AI Á¤¼ºÈÆ
19 l¹Ù´ÚºÎÅÍ ¹è¿ì´Â °­È­ ÇнÀ ÄÚµå (github) Á¤¼ºÈÆ
18 ¦¦❶ ÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀÀÌ 5Àå) ÅÙ¼­Ç÷Π2.0°ú ÄÉ¶ó½º Á¤¼ºÈÆ
17    ¦¦❷ ÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀÀÌ 5Àå) ÅÙ¼­Ç÷Π2.0°ú ÄÉ¶ó½º Á¤¼ºÈÆ
16 ¦¦❶ l9Àå) ActorCritic (ch9_ActorCritic.py) Á¤¼ºÈÆ
15    ¦¦❷ 9Àå) Advantage ActorCritic ½Ç½À (ÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀ 6Àå A2C) Á¤¼ºÈÆ
14       ¦¦❸ 9Àå) ¿¬¼ÓÀû ¾×ÅÍ-Å©¸®Æ½ ½Ç½À (ÆÄÀ̽ã°ú Äɶ󽺷Π¹è¿ì´Â °­È­ÇнÀ 6Àå) Á¤¼ºÈÆ
13          ¦¦❹ ¿¬¼ÓÀû ¾×ÅÍ-Å©¸®Æ½ ½ÇÇà ȯ°æ ¹× °á°ú Á¤¼ºÈÆ
12 ¦¦❶ l9Àå) REINFORCE (ch9_REINFORCE.py) Á¤¼ºÈÆ
11 ¦¦❶ l8Àå) DQN (ch8_DQN.py) Á¤¼ºÈÆ

[1][2]