-
isaac sim ddpg solution of cartpole problemAI 2024. 4. 16. 21:50
isaac sim에 입문하는 용도로 제격인 주제인 거 같다.
https://github.com/akswnd98/cartpole_train
isaac sim 인터페이스
우선 isaac sim simulator와 python 코드로 대화하는 방법에 대해 알아보자.
다음과 같은 방법으로 cartpole들을 원하는 위치에 원하는 개수 만큼 생성할 수 있다.
def generate_cartpoles (cartpole_origin_positions: np.ndarray[np.ndarray[np.float32]]): assets_root_path = 'omniverse://localhost/NVIDIA/Assets/Isaac/2023.1.1/' cartpole_usd_path = os.path.join(assets_root_path, 'Isaac/Robots/Cartpole/cartpole.usd') add_reference_to_stage(cartpole_usd_path, '/World/Cartpole_0') Articulation(prim_path='/World/Cartpole_0', name='cartpole') cloner = Cloner() cloner.filter_collisions('/physicsScene', '/World', list(map(lambda x: '/World/Cartpole_{}'.format(x), list(range(0, cartpole_origin_positions.shape[0]))))) target_paths = cloner.generate_paths("/World/Cartpole", cartpole_origin_positions.shape[0]) cloner.clone(source_prim_path="/World/Cartpole_0", prim_paths=target_paths, positions=cartpole_origin_positions) cartpoles = ArticulationView('/World/Cartpole_*', 'cartpole_view') return cartpoles
omniverse nucleus를 local에 설치하면 "omniverse://localhost/NVIDIA/Assets/Isaac/2023.1.1/" 이런 경로에 다양한 usd 파일 (asset 파일)들이 저장된다. 그 곳에 cartpole.usd가 있다.
따라서 omniverse에서 기본적으로 제공하는 cartpole asset을 사용한다.
다음과 같은 방법으로 cartpole의 joint들을 조작할 수 있다.
참고로 cartpole.usd에는 joint 0와 joint 1이 있는데 joint 0는 직동 joint이고 joint 1은 회전 joint이다.
self.env['cartpoles'] 는 위의 generate_cartpoles의 리턴 값에 해당한다.
self.env['cartpoles'].set_joint_positions(positions=np.concatenate([np.zeros((self.env['xn'] * self.env['yn'], 1), dtype=np.float32), np.random.normal(size=(self.env['xn'] * self.env['yn'], 1)) * np.pi / 6], axis=1), joint_indices=[0, 1]) self.env['cartpoles'].set_joint_velocities(velocities=np.concatenate([np.zeros((self.env['xn'] * self.env['yn'], 1), dtype=np.float32), np.zeros((self.env['xn'] * self.env['yn'], 1), dtype=np.float32)], axis=1), joint_indices=[0, 1])
다음과 같이 isaac sim 환경에 action을 반영하기도 하고
self.cartpoles.set_joint_efforts(efforts=np.reshape(a, (-1, 1)) * 5, joint_indices=np.repeat(0, a.shape[0]))
또 다음과 같이 joint들의 상태 값들을 읽어올 수도 있다.
cur_joint_positions = self.cartpoles.get_joint_positions(joint_indices=[0, 1]) cur_joint_velocities = self.cartpoles.get_joint_velocities(joint_indices=[0, 1])
ddpg를 구현할 때 고려해야 할 것들
ddpg의 원리는 다음의 블로그들을 참고하자.
https://ropiens.tistory.com/96
이 cartpole 예제의 실구현에서 고려해야할 몇 가지 사항들에 대해 짚어 보자면,
1. network의 발산을 막기위한 replay buffer와 target network의 soft update
2. exploration을 위한 noise for action
3. done의 구현 (게임이 종료된 이후의 데이터들에 대한 처리)
4. 적당한 reward 구현
이 있다.
1. 데이터 발생 즉시 그 데이터로 학습을 시켜버리면 network가 데이터를 시간 순서에 종속적으로 학습을 해버리는 문제가 있는 모양이다. 이런 방식을 online 이라고 한다.
보통 어떤 상황에서도 즉각즉각 응답을 잘 내길 바랄 것이므로 offline으로 학습을 진행.
그리기 위해 replay buffer를 사용.
그 buffer에서 random으로 뽑아와서 학습시키는 방법을 사용한다.
또한 학습도중에 critic network의 변화가 너무 심하여 잘 수렴하지 않는 문제가 발생할 수 있는 모양이다.
따라서 target network는 학습의 결과를 천천히 추종하도록 low pass filter를 적용하여 업데이트를 시켜주는 모양이다.
그 것이 soft update이다.
2. overestimation bias 즉 network가 특정 액션에 대해 과대평가를 하는 바람에 local minimum에 빠져버리는 문제가 발생할 수 있는 거 같다.
따라서 exploration을 위해 action에 noise를 추가해준다.
ddpg의 논문 저자는 ou process라고 다소 어려운 random process를 이용한 noise 결정을 제안했는데,
그냥 적당한 normal noise로도 cartpole 예제 정도에는 충분한 거 같다.
3. done직전의 마지막 action의 target q value는 다음 step이 남아 있는 action의 target q value와는 산출 방식이 조금 다르다.
4. 본인의 경우에는 3가지 reward를 줬다. cartpole의 위치나 각도가 game over인 경우 -1, 그렇지 않는 경우는 모두 일단 +0.1, 거기에 원점으로 부터 cartpole이 멀어진 거리에 따라 negative 보상
이렇게 했더니 다음 정도의 결과가 나왔다.
'AI' 카테고리의 다른 글
우분투에서 anaconda init 후에 자동 activate 막는 법 (0) 2024.06.29 파이썬 버전 여러 개 사용하는 방법 (0) 2024.06.24 NLP 입문자를 위한 text 전처리 (0) 2023.04.26 AI할 때 수치 안정성 (0) 2023.04.25 tensorflow custom gradient (0) 2023.04.25