졸업 논문을 쓰기 위해 AirSim 자율주행 시뮬레이션을 강화학습을 사용하여 어떻게 구현하였는지 알아보고자 한다.
상세한 내용은 아래 링크를 참고하자.
https://microsoft.github.io/AirSim/reinforcement_learning/
목차
1. Introduction
아래 내용은 AirSim API와 OpenAI gym, 그리고 RL 알고리즘의 baseline을 활용하여 DQN을 어떻게 구현하였는지에 대한 내용이다.
우선 아래 링크에서 stable-baseline3를 다운받아두자.
https://github.com/DLR-RM/stable-baselines3
참고로, 해당 개발 내용은 현재에도 진행중인 개발이다. 아래에 소개된 framework는 확장되고, 발전시킬 수 있는 내용이다.
1) Gym wrapper
AirSim을 gym 환경으로 사용하려면, AirSim에 맞게 'step', '_get_obs', '_compute_reward', 'reset' 등의 base 메소드들을 확장하거나 재구현해야 한다.
차와 드론에 관한 예제에 쓰인 샘플 environment는 다음 경로에 있다.
PythonClient/reinforcement_learning/airgym/envs/*_env.py
이 예제는 아래 링크의 release와 같은 AirSimNeighborhood 환경에서 동작한다.
https://github.com/Microsoft/AirSim/releases
2. RL with Car
Source Code들은 아래 깃허브를 참조하자.
https://github.com/Microsoft/AirSim/tree/master/PythonClient/reinforcement_learning
1) 이미지 변환
먼저, 시뮬레이션으로부터 얻은 이미지를 적절한 형태로 transform 해야한다.
Ego camera로부터 depth image를 어떻게 얻고, 네트워크에 84 × 84 input으로 어떻게 변환하는지 알아보자.
(해당 코드는 다른 센서 modality나 센서 input으로 바꿀 수 있고, 당연히 그에 따라 적절히 코드를 수정해야 할 것이다.)
responses = client.simGetImages([ImageRequest(0, AirSimImageType.DepthPerspective, True, False)])
current_state = transform_input(responses)
2) Agent가 행할 수 있는 Action 정의
'interpret_action' 함수를 통해 Agent가 할 수 있는 Action을 정의해준다. 그 Action은 다음과 같이 6가지이다.
- Brake
- Straight with throttle
- Full-left with throttle
- Full-right with throttle
- Half-left with throttle
- Half-right with throttle
def interpret_action(action):
car_controls.brake = 0
car_controls.throttle = 1
if action == 0:
car_controls.throttle = 0
car_controls.brake = 1
elif action == 1:
car_controls.steering = 0
elif action == 2:
car_controls.steering = 0.5
elif action == 3:
car_controls.steering = -0.5
elif action == 4:
car_controls.steering = 0.25
else:
car_controls.steering = -0.25
return car_controls
3) Reward Function 정의
다음으로 '_compute_reward' 함수로 reward function을 정의한다. 이는 차가 얼마나 빠른지, center line으로부터 얼마나 떨어져 있는지에 대한 convex combination으로 정의된다.
이에 따라 Agent는 빠르면서 차선의 중앙에 있으면 높은 reward를 받게 된다.
def _compute_reward(car_state):
MAX_SPEED = 300
MIN_SPEED = 10
thresh_dist = 3.5
beta = 3
z = 0
pts = [np.array([0, -1, z]), np.array([130, -1, z]), np.array([130, 125, z]),
np.array([0, 125, z]), np.array([0, -1, z]), np.array([130, -1, z]),
np.array([130, -128, z]), np.array([0, -128, z]), np.array([0, -1, z])]
pd = car_state.position
car_pt = np.array(list(pd.values()))
dist = 10000000
for i in range(0, len(pts) - 1):
dist = min(dist, np.linalg.norm(np.cross((car_pt - pts[i]), (car_pt -
pts[i + 1]))) / np.linalg.norm(pts[i] - pts[i + 1]))
# print(dist)
if dist > thresh_dist:
reward = -3
else:
reward_dist = (math.exp(-beta * dist) - 0.5)
reward_speed = (((car_state.speed - MIN_SPEED) / (MAX_SPEED - MIN_SPEED)) - 0.5)
reward = reward_dist + reward_speed
return reward
이후에 reward 계산 함수는 충돌 등에 의해 에피소드가 끝나는지 또한 결정한다.
차의 속도를 계속 관찰하고, threshold보다 작게 되면 에피소드는 끝나게 된다.
done = 0
if reward < -1:
done = 1
if car_controls.brake == 0:
if car_state.speed <= 5:
done = 1
return done
4) Main Loop
이제 main loop에서 이미지를 얻고, 현재 Policy에 따라 취할 Action을 계산하고, Reward를 받는 등의 과정을 진행한다.
에피소드가 끝나게 되면 'reset()'함수로 차량을 처음 state로 되돌린다.
client.reset()
client.enableApiControl(True)
client.armDisarm(True)
car_control = intercept_action(1) // Reset position and drive straight for one second
client.setCarControls(car_control)
time.sleep(1)
5) DQN Training Loop
gym wrapper가 'car_env.py' 파일 내에서 정의되면 DQN 학습 loop를 실행하기 위해 stable-baselines3를 사용하게 된다.
DQN training은 'dqn_car.py' 파일에서 보이는 바와 같이 다음과 같다.
model = DQN(
"CnnPolicy",
env,
learning_rate=0.00025,
verbose=1,
batch_size=32,
train_freq=4,
target_update_interval=10000,
learning_starts=200000,
buffer_size=500000,
max_grad_norm=10,
exploration_fraction=0.1,
exploration_final_eps=0.01,
device="cuda",
tensorboard_log="./tb_logs/",
)
Training 환경과 Evaluation 환경('dqn_car.py'파일의 'EvalCallback')을 정의할 수 있다.
Evaluation 환경은 training 환경과는 다른 termination 조건과 scene 설정을 가질 수 있다.
결론적으로 'model.learn()'함수는 DQN training loop를 시작하도록 하며, 이는 stable-baselines3로부터 사용 가능한 PPO, A3C 등의 실행과 비슷하다.
'dqn_car.py'파일을 실행시키기 전에 시뮬레이션을 실행시켜야 한다. 아래 video는 DQN training 처음 몇몇 에피소드를 보여준다.
https://www.youtube.com/watch?v=fv-oFPAqSZ4
최근댓글