rl-seminar

๐Ÿ“ƒ ์‚ฌ์ „ ์ค€๋น„

  1. Anaconda ์„ค์น˜
  2. git ์„ค์น˜
  3. ์‹ค์Šต ์ž๋ฃŒ ์ปดํ“จํ„ฐ์— ๋‹ค์šด + https://github.com/kwonnahyun0625/go1_ws ๋ ˆํฌ ๋‹ค์šด

โœจ ๋ชฉํ‘œ โœจ

์‹ฌ์ธต ๊ฐ•ํ™”ํ•™์Šต ๊ธฐ๋ฐ˜ ์‚ฌ์กฑ ๋ณดํ–‰ ๋กœ๋ด‡ ์ œ์–ด์˜ ๊ฒฝํ—˜์„ ์Œ“๊ณ , Isaac gym์„ ์ด์šฉํ•œ ๊ฐ•ํ™”ํ•™์Šต ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์นœํ•ด์ง€๊ธฐ ๐Ÿ˜€

๐Ÿ To do list

์‹ค์Šต1. legged gym ๊ธฐ๋ฐ˜ ๊ฐ•ํ™”ํ•™์Šต ํ™˜๊ฒฝ ์„ค์น˜ํ•˜๊ธฐ
์‹ค์Šต2. action, reward, observation ์ˆ˜์ •ํ•ด๋ณด๊ธฐ
์‹ค์Šต3. ์ƒˆ๋กœ์šด ๋กœ๋ด‡์„ ์ด์šฉํ•œ ๊ฐ•ํ™”ํ•™์Šต
์‹ค์Šต4. Walk These Ways
์‹ค์Šต5. legged gymํ•™์Šต ํ™˜๊ฒฝ์— adaptation module ์ถ”๊ฐ€ํ•ด์„œ ์†๋„ ์ถ”์ •๊ธฐ ๋งŒ๋“ค๊ธฐ
์‹ค์Šต6. ํ•™์Šต ๋ชจ๋ธ์˜ sim to real(sim)์„ ์œ„ํ•œ lcm ์‹ค์Šต
์‹ค์Šต7. wtw์˜ deploy์ฝ”๋“œ์™€ ๊ฐ€์ œ๋ณด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ด์šฉํ•œ sim to simํ™˜๊ฒฝ ๋งŒ๋“ค๊ธฐ

๐Ÿ”ด ์‹ค์Šต1. legged gym ๊ธฐ๋ฐ˜ ๊ฐ•ํ™”ํ•™์Šต ํ™˜๊ฒฝ ์„ค์น˜ํ•˜๊ธฐ

## ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ ๋ฐ pytorch์„ค์น˜
>> conda create -n seminar python=3.8
>> conda activate seminar
>> pip3 install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html

## isaac gym ์„ค์น˜
>> cd isaacgym/python/
>> pip install -e .

## isaac gym ์„ค์น˜ ํ…Œ์ŠคํŠธ
>> cd examples/
>> python 1080_balls_of_solitude.py

## rsl_rl install
>> git clone https://github.com/leggedrobotics/rsl_rl.git
>> cd rsl_rl && git checkout v1.0.2 && pip install -e .

## legged_gym install
>> git clone https://github.com/leggedrobotics/legged_gym.git
>> cd legged_gym && pip install -e .

## train & play
>> cd legged_gym/scripts/
>> python train.py --task=anymal_c_flat
>> python play.py --task=anymal_c_flat
## error

์˜ค๋ฅ˜#1 ModuleNotFoundError: No module named 'tensorboard'
ํ•ด๊ฒฐ >> pip install tensorboard

์˜ค๋ฅ˜#2 AttributeError: module 'distutils' has no attribute 'version'
ํ•ด๊ฒฐ >> pip install future
    >> pip install --upgrade torch
    
์˜ค๋ฅ˜#3 The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
ํ•ด๊ฒฐ >> pip install "numpy<1.24"

์˜ค๋ฅ˜#4 AttributeError: module 'numpy' has no attribute 'float'.
ํ•ด๊ฒฐ >> pip install "numpy<1.24"

์˜ค๋ฅ˜#5 The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
ํ•ด๊ฒฐ >> pip install "numpy<1.24"

์˜ค๋ฅ˜#6 RuntimeError: Ninja is required to load C++ extensions
ํ•ด๊ฒฐ >> wget https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip
    >> sudo unzip ninja-linux.zip -d /usr/local/bin/
    >> sudo update-alternatives --install /usr/bin/ninja ninja /usr/local/bin/ninja 1 --force  
    
์˜ค๋ฅ˜#7 RuntimeError: nvrtc: error: invalid value for --gpu-architecture (-arch) 
ํ•ด๊ฒฐ >> pip3 uninstall torch torchvision torchaudio
    >> pip3 install torch torchvision torchaudio -f https://download.pytorch.org/whl/cu123/torch_stable.html

๐Ÿ”Ž ์ฐธ๊ณ ์ž๋ฃŒ

  1. legged gym repo : https://github.com/leggedrobotics/legged_gym
  2. rsl_rl gym repo : https://github.com/leggedrobotics/rsl_rl

๐ŸŸ  ์‹ค์Šต2. action, reward, observation ์ˆ˜์ •ํ•ด๋ณด๊ธฐ

๐ŸŸก ์‹ค์Šต3. ์ƒˆ๋กœ์šด ๋กœ๋ด‡์„ ์ด์šฉํ•œ ๊ฐ•ํ™”ํ•™์Šต

๐ŸŸข ์‹ค์Šต4. Walk These Ways

## ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ ๋ฐ pytorch์„ค์น˜
>> conda create -n seminar2 python=3.8
>> conda activate seminar2
>> pip3 install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html

## isaac gym ์„ค์น˜
>> cd isaacgym/python/
>> pip install -e .

## isaac gym ์„ค์น˜ ํ…Œ์ŠคํŠธ
>> cd examples/
>> python 1080_balls_of_solitude.py

## walk-these-ways install
>> git clone https://github.com/Improbable-AI/walk-these-ways.git
>> pip install -e .

## train & play
>> cd scripts/
>> python train.py 
>> python play.py 
## error

์˜ค๋ฅ˜#1 RuntimeError: nvrtc: error: invalid value for --gpu-architecture (-arch) 
ํ•ด๊ฒฐ >> pip3 uninstall torch torchvision torchaudio
    >> pip3 install torch torchvision torchaudio -f https://download.pytorch.org/whl/cu123/torch_stable.html

๐Ÿ”ต ์‹ค์Šต5. legged gymํ•™์Šต ํ™˜๊ฒฝ์— adaptation module ์ถ”๊ฐ€ํ•ด์„œ ์†๋„ ์ถ”์ •๊ธฐ ๋งŒ๋“ค๊ธฐ

1๏ธโƒฃ legged_gym ์ˆ˜์ •

โ—พ legged_robot.py

## def compute_observations 
self.obs_buf = torch.cat((  #self.base_lin_vel * self.obs_scales.lin_vel,
                            #self.base_ang_vel  * self.obs_scales.ang_vel,
                            self.projected_gravity,
                            self.commands[:, :3] * self.commands_scale,
                            (self.dof_pos - self.default_dof_pos) * self.obs_scales.dof_pos,
                            self.dof_vel * self.obs_scales.dof_vel,
                            self.actions
                            ),dim=-1)
##############################################################################
self.privileged_obs_buf = torch.empty(self.num_envs, 0).to(self.device)
self.privileged_obs_buf = torch.cat((self.obs_buf,
                                     self.base_lin_vel * self.obs_scales.lin_vel,
                                     self.base_ang_vel  * self.obs_scales.ang_vel ),dim=-1)

## def _get_noise_scale_vec
noise_vec[0:3] = noise_scales.gravity * noise_level
noise_vec[3:6] = 0. # commands
noise_vec[6:18] = noise_scales.dof_pos * noise_level * self.obs_scales.dof_pos
noise_vec[18:30] = noise_scales.dof_vel * noise_level * self.obs_scales.dof_vel
noise_vec[30:42] = 0. # previous actions

โ—พ anymal_c_flat_config.py

## class env( AnymalCRoughCfg.env ):
num_observations = 42
num_privileged_obs = 48

2๏ธโƒฃ rsl_rl ์ˆ˜์ •

โ—พ actor_critic.py

## def __init__
# Adaptation module
adaptation_module_branch_hidden_dims = [256, 128]
num_latent = 6
mlp_input_dim_a = num_actor_obs + num_latent

adaptation_module_layers = []
adaptation_module_layers.append(nn.Linear(num_actor_obs, adaptation_module_branch_hidden_dims[0]))
adaptation_module_layers.append(activation)
for l in range(len(adaptation_module_branch_hidden_dims)):
    if l == len(adaptation_module_branch_hidden_dims) - 1:
        adaptation_module_layers.append(
            nn.Linear(adaptation_module_branch_hidden_dims[l], num_latent))
    else:
        adaptation_module_layers.append(
            nn.Linear(adaptation_module_branch_hidden_dims[l],
                      adaptation_module_branch_hidden_dims[l + 1]))
        adaptation_module_layers.append(activation)
self.adaptation_module = nn.Sequential(*adaptation_module_layers)
print(f"Adaptation Module: {self.adaptation_module}")

## def update_distribution
latent = self.adaptation_module(observations)
mean = self.actor(torch.cat((observations, latent), dim=-1))

## def act_inference
latent = self.adaptation_module(observations)
actions_mean = self.actor(torch.cat((observations, latent), dim=-1))

โ—พ ppo.py

## def __init__
self.adaptation_module_optimizer = optim.Adam(self.actor_critic.parameters(), lr=learning_rate)

## def update
mean_adaptation_module_loss = 0
##############################################################################
# Adaptation module gradient step
adaptation_pred = self.actor_critic.adaptation_module(obs_batch)
with torch.no_grad():
    adaptation_target = critic_obs_batch[:, 42:48]
selection_indices = torch.linspace(0, adaptation_pred.shape[1]-1, steps=adaptation_pred.shape[1], dtype=torch.long)
adaptation_loss = F.mse_loss(adaptation_pred[:, selection_indices], adaptation_target[:, selection_indices])
self.adaptation_module_optimizer.zero_grad()
adaptation_loss.backward()
self.adaptation_module_optimizer.step()
mean_adaptation_module_loss += adaptation_loss.item()
##############################################################################
import torch.nn.functional as F
##############################################################################
mean_adaptation_module_loss /= num_updates
##############################################################################
return mean_value_loss, mean_surrogate_loss, mean_adaptation_module_loss

โ—พ on_policy_runner.py

## def learn
mean_value_loss, mean_surrogate_loss, mean_adaptation_module_loss = self.alg.update()

## def log
self.writer.add_scalar('Loss/adaptation_module', locs['mean_adaptation_module_loss'], locs['it'])
##############################################################################
f"""{'adaptation_module loss:':>{pad}} {locs['mean_adaptation_module_loss']:.4f}\n"""
##############################################################################
f"""{'adaptation_module loss:':>{pad}} {locs['mean_adaptation_module_loss']:.4f}\n""" 

๐ŸŸฃ ์‹ค์Šต6. ํ•™์Šต ๋ชจ๋ธ์˜ sim to real(sim)์„ ์œ„ํ•œ lcm ์‹ค์Šต

๐Ÿ“Œ lcm ํŒจํ‚ค์ง€ ์„ค์น˜

>> sudo apt-get install liblcm-dev

>> pip3 install lcm

>> git clone https://github.com/lcm-proj/lcm.git
>> cd lcm
>> mkdir build
>> cd build
>> cmake ..
>> make
>> sudo make install

๐Ÿ“Œ ๋ฐ์ดํ„ฐํƒ€์ž… ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ

# For Python
>> lcm-gen -p test.lcm

# For C++
>> lcm-gen -x test.lcm 

โœ๏ธ server.py

import lcm
from test_lcm_type import test_t
import time

def main():
    lc = lcm.LCM()
    msg = test_t()
    msg.timestamp = int(time.time() * 1e6)
    msg.d = 11.2
    msg.str = "hi"

    while True:
        lc.publish("EXAMPLE_CHANNEL", msg.encode())
        time.sleep(1)

if __name__ == "__main__":
    main()

โœ๏ธ client.cpp

#include <lcm/lcm-cpp.hpp>
#include "test_lcm_type/test_t.hpp"
#include <iostream>

class Handler {
public:
    void handleMessage(const lcm::ReceiveBuffer* rbuf,
                       const std::string& chan, 
                       const example_lcm_type::test_t* msg) {
        std::cout << "Received message on channel " << chan << std::endl;
        std::cout << "  timestamp = " << msg->timestamp << std::endl;
        std::cout << "  d      = " << msg->d << std::endl;
        std::cout << "  str      = " << msg->str << std::endl;
    }
};

int main(int argc, char** argv) {
    lcm::LCM lcm;
    if (!lcm.good()) return 1;
    Handler handlerObject;
    lcm.subscribe("EXAMPLE_CHANNEL", &Handler::handleMessage, &handlerObject);

    while (0 == lcm.handle());
    return 0;
}
## cppํŒŒ์ผ ์ปดํŒŒ์ผ
>> g++ -o cpp_lcm_client client.cpp -llcm

## python ์„œ๋ฒ„ ์‹คํ–‰
>> python server.py

## cpp ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰
>> ./cpp_lcm_client 

๐Ÿ”Ž ์ฐธ๊ณ ์ž๋ฃŒ

  1. Python๊ณผ C++ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๋ฐฉ๋ฒ• 2๊ฐ€์ง€ โ€“ LCM์„ ํ†ตํ•œ ํ”„๋กœ๊ทธ๋žจ๊ฐ„ ํ†ต์‹  : https://phd.korean-engineer.com/coding/python_cpp_lcm/

๐ŸŸค ์‹ค์Šต7. wtw์˜ deploy์ฝ”๋“œ์™€ ๊ฐ€์ œ๋ณด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ด์šฉํ•œ sim to sim ์‹ค์Šต

## ModuleNotFoundError: No module named 'lcm'
>> pip3 install lcm


## ModuleNotFoundError: No module named 'cv2'
>> python3 -m pip install opencv-python

## Errors     << go1_controller:cmake /home/kwon/1225/go1_ws/logs/go1_controller/build.cmake.000.log   
CMake Error at /opt/ros/noetic/share/catkin/cmake/catkinConfig.cmake:83 (find_package):
  Could not find a package configuration file provided by "geometry_msgs"
  with any of the following names:
>> sudo apt update
>> sudo apt install ros-noetic-geometry-msgs
>> source /opt/ros/noetic/setup.bash