Unity/Unity ML-Agents

[Robotics Lab] AMR Articulation Body ML-Agents 학습

pnltoen 2023. 5. 14.
반응형

AMR_Articulation Body

Unity Technologies


서론

 

기존 구현한 환경과 조금 다르지만 전반적인 내용 및 구동 메커니즘은 동일합니다 (Spin Turn + Target Velocity)

다만 팀원이 올려주신 Jetbot으로 파일 바꾸고 시작함.

 

Unity Articulation Body AMR 로봇 제어 구현에 관련 코드 설명까지 올려놓았으니 이 글을 읽기전 해당 글을 확인해주시길 바랍니다.

 

본 글의 목적은 로봇 및 본인 도메인을 잘 알고 계시지만 환경 구성에 어려움을 겪으시는 분들에게 도움을 드리기 위해 작성하였습니다.

 

사전 개념

 

Closed surface

 

특히 Spline의 경우 Convex를 하셨을 경우 눈에 보이는 영역만 있다고 생각하실 수 있습니다. 하지만 유니티는 Unity 5 이후로 non-convex collider를 지원하지 않음으로 위와 같이 설정했을 경우 closed되어 있다는 것을 알고 있어야 합니다.

 

 

보상 함수

 

강화학습은 보상이 최대가 되도록 학습합니다. 따라서 보상 함수가 잘못되있는 경우 엔지니어의 설계 의도와는 다른 결과가 나타날 수 있습니다.

 

개선 사항

 

보상함수 수정 #1

 

    private void OnTriggerStay(Collider coll)
    {
        if (coll.CompareTag("Spline"))
        {
            Debug.Log("Stayed!");
            AddReward(0.001f);
        }
    }

 

Spline 구역 안에 있을 때 보상을 받도록 수정함. 기존 OnactionRecived에서 스텝마다 보상을 주는 방법을 해봤는데 추후 기술할 제자리 spin turn으로 삭제하였음. 

 

 

        _mag = _jetbot.velocity.magnitude;
        AddReward(0.1f * _mag);

 

속도의 크기를 이용, 최대 속도로 움직일 경우 보상을 더 많이 받도록 즉 빠르게 트랙을 돌 수 있도록 설정 함.

이 경우 문제가 발생하였는데 제자리에서 Spin Turn만 하는 현상이 발생함 -> 가장 단순하게 보상을 최대화 할 수 있는 방법이라고 학습 

 

이 경우를 막기위해 Collider 및 속도를 수정함 

 

Collider 크기 수정

Trigger 형태의 Collider를 다음과 같이 전면부로 수정하였음.

 

 

이 경우 제자리에서 턴을 할 경우 Spline을 넘어가는 구간이 생기면서 학습이 종료됨.

 

 

 

여기서 학습의 종료 조건인 EndEpisode()를 호출하는 경우는 다음과 같다.

 

    private void OnTriggerExit(Collider coll)
    {
        if (coll.CompareTag("Spline"))
        {
            Debug.Log("Exited!");
            SetReward(-1f);
            EndEpisode();
        }
    }

 

    private void OnTriggerEnter(Collider coll)
    {
        if (coll.CompareTag("Spline_exit"))
        {
            Debug.Log("Hitted Boundary lines");
            SetReward(-1f);
            EndEpisode();
        }      
    }

 

    void _End()
    {
        if (_jetbot.transform.position.y <= -5f)
        {
            SetReward(-1);
            EndEpisode();
        }
    }

 

에이전트의 비열한 Spin Turn으로 보상 받는 방법을 막았으니... 어느정도 학습을 될 것으로 예상했음. 따라서 이 부분에서는 환경의 버그를 없애는 것에 초점을 맞춤.

 

OnepisodeBegin

 

초기화 하는 부분임 EndEpisode 또는 interrupted시 호출 된다. Articulation Body는 이 부분을 특히 잘 봐줘야 하는데 rigid body는 오브젝트를 초기화 하는 방법이 쉽지만 이거는 조금 다르다.

 

--> 누군가 Scene을 초기화 하는 방법을 생각할 수 있으나 비동기는 렉이 안걸리는 대신 학습이 오래걸리고 동기는 렉이 걸림. 그리고 무엇보다 한 화면에서 학습되는 전체 과정을 보고 싶었음.

 

    private void _agentReset()
    {
        Vector3 re = _respawn.transform.position;
        _jetbot.TeleportRoot(re, Quaternion.Euler(0, 180, 0)); //Articulation 추가
        _jetbot.velocity = Vector3.zero;
        _jetbot.angularVelocity = Vector3.zero;
        Debug.Log("Reset!");
    }

 

유니티 에디터에서 다른 물리엔진을 써본 사람은 알겠지만... Play시 Inspector 창에서 Drag & Drop이 안되는 경우가 있다. 가장 생각나는 예시로는 Mujoco SDK...? 아무튼 Articulation Body도 마찬가지로 Translate 및 transform 재정의가 안되는데 이 때 TeleportRoot를 통해 해줘야함. 

 

+) 잊지 말고 물리력 초기화해주자 안하면... 쉽게 표현하면 외력(이전 에피소드에서 남은 힘)이 작용되서 학습에 노이즈가 된다.

 

관측

 

    public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(transform.rotation.x);
        sensor.AddObservation(transform.rotation.y);
        sensor.AddObservation(transform.rotation.z);
        sensor.AddObservation(L_Rot); //L 입력 값
        sensor.AddObservation(R_Rot); //R 입력 값
        sensor.AddObservation(_mag); // Jetbot 속도 벡터의 크기
    }

 

관측은 단순하게 진행함. 추 후 OpenCV로 관측할거기 때문에 RayCast는 쓰지 않음. Vector observation은 위와 같이 했고 이미지는 아래와 같이 설정했다.

 

 

바로 앞 라인만 보이면 될 것 같아서 Far를 2로 설정하고 Near를 0.01로 설정했음.

 

 

이런 식으로 보인다 84x84로 설정하고 Game view에서 Simple 렌더도 확인해봄 -> 문제 없음 충분히 학습 가능할 것으로 판단함.

 

병렬(?) 학습

 

 

너무 오랜만이라 에디터에서 계속 수정하기 위해 --num-envs를 못썻고 top view에서 한눈에 보고 싶어서 경기장 하나에 Jetbot 여러개 복붙함.

 

 

카메라 렌더에서 Jetbot 렌더 안하게 해줌 서로의 카메라가 노이즈 생기는 것을 방지.

마찬가지로 물리 간섭 없애줌.

 

 

하이퍼 파라미터 튜닝

 

쏘 간단한 환경이라... 경험상 했는데 한번에 됐다 야호~ 확실히 예전에 Drone Delivery Challenge 그리고 Gdori X ML-Agents 한게 큰 도움이 됐음. 대략 감이와서 그대로 했다.

 

behaviors:
  My behavior:
    trainer_type: ppo
    hyperparameters:
      batch_size: 16
      buffer_size: 320
      learning_rate: 0.0005
      beta: 0.03
      epsilon: 0.2
      lambd: 0.99
      num_epoch: 2
      learning_rate_schedule: linear
    network_settings:
      normalize: true
      hidden_units: 16
      num_layers: 2
      vis_encode_type: simple
    reward_signals:
      extrinsic:
        gamma: 0.995
        strength: 1.0
    keep_checkpoints: 30
    max_steps: 20000000
    time_horizon: 64
    summary_freq: 50000

 

결론

 

20분 20만번 정도에 학습이 완료됐다.

 

칙칙폭폭 기차놀이~

반응형

댓글