CARLA를 윈도우에 설치해보자!(그리고 수료하자!)
Coursera 자율주행 전문화코스 첫번째 강좌 Introduction to self-driving cars 의 마지막 주차이자 수료 과제인 CARLA 프로그래밍을 위해 윈도우에 Carla를 설치해보겠습니다.
원래는 우분투에 설치해야되는데 저의 할아버지 우분투 노트북(중3~대3 까지 쓴ㅠㅠ)에서는 돌아가지 않을 것 같고 맥에서는 안된다길래 학교 실습실 윈도우에 깔아보려고 합니다. 알고보니 우리학교 실습실에는 리눅스가 센토스만 있고 우분투 깔아도 되냐고 물어보니까 안된다고 하더라고요...
그래서 시작한 윈도우에 CARLA설치하기!(그리고 수료하기!)
*구체적인 것은 CARLA setup for Windows 공식 문서를 참고해주세요!
HW : 여러가지 스펙 요구사항이 있었지만 저에겐 어차피 실습실 컴퓨터밖에 답이 없었기 때문에 그냥 했습니다.
Software : CARLA 시뮬레이터 다운로드 받아서 압출 풀고 시작함
윈도우7 64bit 이상
2000~2002 방화벽 포트 접근 가능
OpenGL 3.3 이상, DirectX10 이상 → CARLA 바이너리 불러올 때 알아서 됨
Python : 3.6.x (***매우중요)
실습실 컴이라 Python 깔려있는 줄 알고 넘어갔다가 다시 돌아옴...꼭 확인하세요!
>python —version
>python -m pip —version
> python -m pip install -r C:\(위치)\CarlaSimulator\requirements.txt--user
Default Map 으로 시뮬레이터를 로딩하기
>CarlaUE4.exe -windowed -carla-no-networking
‘-windowed’ 는 전체화면모드 해제
중간에 DirectX 를 깔지 물어보는데 깔아주시면 됩니다.
완료!
A,S,D,W 로 차량을 움직일 수 있고 Q로 기어 바꿈. P는 파일럿모드
Coursera 과제에 사용할 맵으로 로딩해봅시다.
>CarlaUE4.exe /Game/Maps/RaceTrack -windowed -carla-server -benchmark -fps=20
여기서 waypoints 는 이미 txt파일로 만들어져있고 이것이 과제예시파일에서 callback 함수로 구현이 되어있다. 종방향, 횡방향 제어기만 설계하면 된다!
나는 2021년 창작자동차대회 자율주행부문에서 횡방향 제어 알고리즘을 구현했고 2022-1학기에 청강하는 시스템모델링제어에서 PID를 배웠으므로 이 두 개를 구현해보도록 하겠다(Coursera에서도 이론을 배웠다!!!). 스탠리는 차량 앞축을 기준으로, PID는 뒷축을 기준으로 에러값을 계산하며 lookahead distance 없이 가장 가까운 포인트를 기준으로 에러값을 계산하여 에러에 따라 휠을 더 많이 꺾는다. waypoints txt에 포함된 속도값이 22kph 수준이므로 purepursuit 으로도 충분히 정확한 추종이 가능할 것이라고 생각하여 purepursuit&PID 로 구현하였다.
#!/usr/bin/env python3
"""
2D Controller Class to be used for the CARLA waypoint follower demo.
"""
import cutils
import numpy as np
import math
class Controller2D(object):
def __init__(self, waypoints):
self.vars = cutils.CUtils()
self._current_x = 0
self._current_y = 0
self._current_yaw = 0
self._current_speed = 0
self._desired_speed = 0
self._current_frame = 0
self._current_timestamp = 0
self._start_control_loop = False
self._set_throttle = 0
self._set_brake = 0
self._set_steer = 0
self._waypoints = waypoints
self._conv_rad_to_steer = 180.0 / 70.0 / np.pi
self._pi = np.pi
self._2pi = 2.0 * np.pi
def update_values(self, x, y, yaw, speed, timestamp, frame):
self._current_x = x
self._current_y = y
self._current_yaw = yaw
self._current_speed = speed
self._current_timestamp = timestamp
self._current_frame = frame
if self._current_frame:
self._start_control_loop = True
def update_desired_speed(self):
min_idx = 0
min_dist = float("inf")
desired_speed = 0
for i in range(len(self._waypoints)):
dist = np.linalg.norm(np.array([
self._waypoints[i][0] - self._current_x,
self._waypoints[i][1] - self._current_y]))
if dist < min_dist:
min_dist = dist
min_idx = i
if min_idx < len(self._waypoints)-1:
desired_speed = self._waypoints[min_idx][2]
else:
desired_speed = self._waypoints[-1][2]
self._desired_speed = desired_speed
def update_waypoints(self, new_waypoints):
self._waypoints = new_waypoints
def get_commands(self):
return self._set_throttle, self._set_steer, self._set_brake
def set_throttle(self, input_throttle):
# Clamp the throttle command to valid bounds
throttle = np.fmax(np.fmin(input_throttle, 1.0), 0.0)
self._set_throttle = throttle
def set_steer(self, input_steer_in_rad):
# Covnert radians to [-1, 1]
input_steer = self._conv_rad_to_steer * input_steer_in_rad
# Clamp the steering command to valid bounds
steer = np.fmax(np.fmin(input_steer, 1.0), -1.0)
self._set_steer = steer
def set_brake(self, input_brake):
# Clamp the steering command to valid bounds
brake = np.fmax(np.fmin(input_brake, 1.0), 0.0)
self._set_brake = brake
def update_controls(self):
# RETRIEVE SIMULATOR FEEDBACK
x = self._current_x #meter
y = self._current_y #meter
yaw = self._current_yaw #radian
v = self._current_speed #m/s
self.update_desired_speed()
v_desired = self._desired_speed #m/s
t = self._current_timestamp
waypoints = self._waypoints #x, y, v
throttle_output = 0 # 0~1
steer_output = 0 #-1.22~1.22(rad)
brake_output = 0 #0~1
# MODULE 7: DECLARE USAGE VARIABLES HERE
self.vars.create_var('v_prev', 0.0) #velocity
self.vars.create_var('t_prev', 0.0) #dt = t_prev-t
self.vars.create_var('e_prev', 0.0) #Error : v_desired-v
self.vars.create_var('e_iprev', 0.0) #integral Error
self.vars.create_var('o_tprev', 0.0) #throttle output
self.vars.create_var('o_sprev', 0.0) #steer output
# Skip the first frame to store previous values properly
if self._start_control_loop:
# MODULE 7: IMPLEMENTATION OF LONGITUDINAL CONTROLLER HERE
# PID Controller
K_p = 1.0
K_i = 0.1
K_d = 0.01
dt = t-self.vars.t_prev
throttle_output = 0
brake_output = 0
e_v = v_desired - v
i_v = self.vars.e_iprev + e_v*dt
d_v = (e_v - self.vars.e_prev) / dt
accel = K_p * e_v + K_i*i_v + K_d * d_v
if(accel >0):
throttle_output = (np.tanh(accel) + 1)/2
if(throttle_output - self.vars.o_tprev > 0.1):
throttle_output = self.vars.o_tprev + 0.1
else:
throttle_output = 0
# MODULE 7: IMPLEMENTATION OF LATERAL CONTROLLER HERE
# PurePursuit
steer_output = 0
L = 2.7 #meter - Ford Mustang Wheelbase
min_ld = 10 #meter
K_pld = 0.8
x_desired = x-L*np.cos(yaw)/2
y_desired = y-L*np.sin(yaw)/2
l_d = max(min_ld, v*K_pld)
for i in waypoints:
dist = np.sqrt((i[0] - x_desired)**2 + (i[1] - y_desired)**2)
if(dist>l_d):
target = i
break
else:
target = waypoints[0]
alpha = math.atan2(target[1] - y_desired, target[0]-x_desired)-yaw
delta = math.atan2(2*L*np.sin(alpha)/l_d)
steer_output = delta
# SET CONTROLS OUTPUT
self.set_throttle(throttle_output) # in percent (0 to 1)
self.set_steer(steer_output) # in rad (-1.22 to 1.22)
self.set_brake(brake_output) # in percent (0 to 1)
self.vars.v_prev = v # Store forward speed to be used in next step
self.vars.t_prev = t
self.vars.e_prev = v_desired-v
self.vars.e_iprev = i_v
self.vars.o_tprev = throttle_output
self.vars.o_sprev = steer_output
이 코드를 저장하고 시뮬레이터를 실행시킨 다음 cmd창을 하나 더 열어서 module_7.py(waypoint 추종 및 제어 코드 launch) 를 실행시킨다!
상당히 잘 나온다. 속도를 22kph에서 25kph까지 올렸는데도 잘 된다. (잘된다 = 추종한 waypoints 저장하여 비교해보았을 때 100% 일치) 하지만 한 50kph이상 올려버리면 다이나믹모델이 달라지므로 스탠리나 MPC모델로 제어를 해야할 것 같다.
3월부터 시작한 Introductiont to Self-Driving Cars 강의를 수료하였다. 다음주부터는 상태 예측과 위치측위 강좌로 바로 들어간다...와아아아...와ㅏ...행복해...
'실무->입문수업' 순서로 진행되었는데,
오히려 좋았다. 왜냐면 배우면서 '그 땐 노가다로 삼중 for문 돌려가면서 튜닝했는데, 역시 이론이 중요하다...'는 것을 깨달았기 때문이다. 그리고 그것에서 멈추지 않고 과제로 코딩하고 시뮬레이터도 돌려보았기 때문에 오히려 좋아...(ㅋㅋㅋ)
다음주부터 상태예측과 위치측위 강좌로 적장의 목을 베고... 돌아오겠다. 내일도 화이팅
시뮬레이션 중에 특정 부분에서 지속적으로 프로그램이 종료 되고
ERROR: (localhost:2001) failed to read data: [WinError 10054] 현재 연결은 원격 호스트에 의해 강제로 끊겼습니다
ERROR: (localhost:2000) failed to connect: [WinError 10061] 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다
ERROR: (localhost:2000) failed to connect: [WinError 10061] 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다
ERROR: (localhost:2000) failed to connect: [WinError 10061] 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다
이러한 에러가 발생하는데 혹시 이 문제에 대해서 아시는거 있으신가요..