00 Robotik RL Zorluğu
Gerçek robot donanımı kırılgandır, yavaştır ve her sıfırlaması insani müdahale gerektirir. Bu kısıtlar robotik RL'yi standart RL'den niteliksel olarak farklı kılar.
Simüle edilmiş ortamlarda milyonlarca adım kolayca toplanabilirken gerçek robotlarda günde birkaç bin adım toplamak bile güçtür. Bunun yanı sıra robotik RL özgü birkaç kritik zorluk daha getirir:
Modern robotik RL neredeyse istisnasız önce simülasyonda eğitim, sonra gerçek donanıma transfer (sim-to-real) prensibini izler. Bu, keşif maliyetini ve donanım riskini dramatik biçimde düşürür.
01 Isaac Gym / Isaac Lab
NVIDIA Isaac Gym, GPU üzerinde binlerce paralel ortam çalıştırarak robotik RL'nin sample efficiency sorununu kökten çözer.
Geleneksel simülatörlerde ortam CPU'da çalışır, sadece RL gradyanları GPU'ya geçer. Isaac Gym ise fizik simülasyonunu doğrudan GPU'da koşturur. Tüm tensörler GPU belleğinde kaldığı için CPU-GPU transferi ortadan kalkar. Sonuç: A100 GPU ile 4.096 paralel Ant ortamı 100.000+ fps hızında çalışır.
# Isaac Lab (Isaac Gym halefi) — Omniverse tabanlı
git clone https://github.com/isaac-sim/IsaacLab.git
cd IsaacLab
./isaaclab.sh --install
# Isaac Gym (eski, hâlâ yaygın kullanım)
# NVIDIA Developer sitesinden indir: developer.nvidia.com/isaac-gym
pip install isaacgym/
pip install -e rl_games/ # RL Games framework
from isaacgym import gymapi, gymtorch
import torch
# Simülatör ve ortam oluştur
gym = gymapi.acquire_gym()
sim = gym.create_sim(
compute_device_id=0,
graphics_device_id=0,
type=gymapi.SIM_PHYSX,
params=gymapi.SimParams())
# Ortam gridi: 64x64 = 4096 paralel ortam
num_envs = 4096
env_lower = gymapi.Vec3(-2.0, -2.0, 0.0)
env_upper = gymapi.Vec3( 2.0, 2.0, 2.0)
envs = []
actors = []
for i in range(num_envs):
env = gym.create_env(sim, env_lower, env_upper, 64)
envs.append(env)
# Tensor API ile GPU üzerinde gözlem al
gym.prepare_sim(sim)
dof_state_tensor = gym.acquire_dof_state_tensor(sim)
dof_states = gymtorch.wrap_tensor(dof_state_tensor)
# dof_states: (num_envs * num_dof, 2) — pos ve vel — GPU'da!
print(f"DOF states shape: {dof_states.shape}, device: {dof_states.device}")
02 MuJoCo ile Locomotion
MuJoCo, Hopper, Ant ve Humanoid gibi klasik locomotion benchmark'larıyla RL algoritmalarının standart test zeminidir.
MuJoCo (Multi-Joint dynamics with Contact), DeepMind tarafından satın alındıktan sonra ücretsiz hale getirildi. Hızlı temas dinamiği simülasyonu ve Gymnasium entegrasyonu sayesinde continuous control RL'nin fiili standardıdır.
import gymnasium as gym
from stable_baselines3 import SAC
from stable_baselines3.common.env_util import make_vec_env
from stable_baselines3.common.callbacks import EvalCallback
# 8 paralel ortam
env = make_vec_env("Ant-v4", n_envs=8)
eval_env = make_vec_env("Ant-v4", n_envs=4)
model = SAC(
"MlpPolicy", env,
learning_rate=3e-4,
batch_size=256,
buffer_size=1_000_000,
learning_starts=10_000,
train_freq=1,
gradient_steps=1,
tau=0.005,
gamma=0.99,
ent_coef="auto",
verbose=1,
tensorboard_log="./tb_ant/"
)
eval_cb = EvalCallback(
eval_env, best_model_save_path="./models/",
eval_freq=50_000, n_eval_episodes=10, deterministic=True)
model.learn(total_timesteps=3_000_000, callback=eval_cb)
model.save("ant_sac")
03 Domain Randomization
Domain randomization, simülasyonu kasıtlı olarak geniş bir parametre aralığında değiştirerek politikayı gerçek dünya varyasyonlarına karşı robust kılar.
Simülasyon ile gerçek dünya arasındaki fark (sim-to-real gap) büyük ölçüde modelleme hataları ve bilinmezlikten kaynaklanır. Domain randomization bu belirsizliği modele bilerek enjekte eder; politika, parametrelerin geniş bir dağılımında çalışmayı öğrenerek gerçek donanıma karşı toleranslı hale gelir.
import gymnasium as gym
import numpy as np
class PhysicsDRWrapper(gym.Wrapper):
"""
Her episode başında MuJoCo fizik parametrelerini rastgele değiştirir.
Politikayı real transfer için robust yapar.
"""
def __init__(self, env,
mass_scale=(0.8, 1.2),
friction_scale=(0.5, 1.5),
damping_scale=(0.8, 1.2)):
super().__init__(env)
self.mass_scale = mass_scale
self.friction_scale = friction_scale
self.damping_scale = damping_scale
self.original_mass = self.env.model.body_mass.copy()
self.original_frict = self.env.model.geom_friction.copy()
self.original_damping = self.env.model.dof_damping.copy()
def reset(self, **kwargs):
obs, info = self.env.reset(**kwargs)
self._randomize()
return obs, info
def _randomize(self):
m = self.env.model
m.body_mass[:] = self.original_mass * np.random.uniform(*self.mass_scale)
m.geom_friction[:] = self.original_frict * np.random.uniform(*self.friction_scale)
m.dof_damping[:] = self.original_damping * np.random.uniform(*self.damping_scale)
# Kullanım
base_env = gym.make("Hopper-v4")
dr_env = PhysicsDRWrapper(base_env)
obs, _ = dr_env.reset()
print("DR ortamı hazır — her episode farklı fizik parametreleri")
04 Sim-to-Real Gap
Sim-to-real gap, simülasyonda mükemmel çalışan politikaların gerçek donanımda neden başarısız olduğunu açıklar.
Sim-to-real gap'in başlıca kaynakları ve teknik çözümleri:
Kumar et al. (2021) tarafından geliştirilen RMA mimarisi sim-to-real'i iki aşamayla çözer: (1) Base policy eğitimi — explicit extrinsics (kütle, sürtünme) ile. (2) Adaptation module — yalnızca geçmiş gözlemlerden extrinsics tahmin eder. Deploy sırasında sadece adaptation module çalışır; explicit fizik parametresi gerekmez.
05 Reward Shaping
Doğru tasarlanmış dense reward, sparse reward'ın verdiği zayıf gradyan sinyalini zenginleştirerek öğrenmeyi dramatik biçimde hızlandırır.
Robotik RL'de en yaygın ödül bileşenleri:
import numpy as np
def pick_place_reward(obs, info,
dist_weight=1.0,
vel_penalty=0.01,
torque_penalty=0.001,
success_bonus=10.0,
success_thresh=0.02):
"""
Pick-and-place görevi için dense + sparse ödül bileşimi.
obs: dict içinde 'ee_pos', 'target_pos', 'ee_vel', 'joint_torques'
"""
ee_pos = obs["ee_pos"] # end-effector konumu
target = obs["target_pos"] # hedef konum
ee_vel = obs["ee_vel"] # end-effector hızı
torques = obs["joint_torques"] # eklem momentleri
dist = np.linalg.norm(ee_pos - target)
r_dist = -dist_weight * dist
r_vel = -vel_penalty * np.linalg.norm(ee_vel) ** 2
r_torq = -torque_penalty * np.linalg.norm(torques) ** 2
r_succ = success_bonus if dist < success_thresh else 0.0
total = r_dist + r_vel + r_torq + r_succ
return total, {
"r_dist": r_dist, "r_vel": r_vel,
"r_torque": r_torq, "r_success": r_succ}
06 SAC ve TD3 — Continuous Control
SAC ve TD3, robotik continuous control için en olgun ve yaygın kullanılan off-policy RL algoritmalarıdır.
SAC (Soft Actor-Critic): Entropi düzenleme terimi ile maximum entropy RL çerçevesinde çalışır. Otomatik entropi katsayısı (ent_coef="auto") hiperparametre arayışını kolaylaştırır. Locomotion ve manipülasyon görevlerinde genellikle en iyi sonucu verir.
TD3 (Twin Delayed DDPG): Overestimation bias'ını iki critic ile düzeltir, delayed policy update ve target policy smoothing ekler. SAC'tan biraz daha kararlıdır; sürekli temas içeren görevlerde avantajlı olabilir.
from stable_baselines3 import SAC, TD3
from stable_baselines3.common.noise import NormalActionNoise
import numpy as np
import gymnasium as gym
env = gym.make("HalfCheetah-v4")
n_actions = env.action_space.shape[0]
# SAC — entropi tabanlı, az hiperparametre
sac = SAC(
"MlpPolicy", env,
learning_rate=3e-4,
buffer_size=1_000_000,
batch_size=256,
ent_coef="auto", # otomatik entropi katsayısı
target_entropy="auto",
verbose=0)
# TD3 — deterministic, action noise gerekli
action_noise = NormalActionNoise(
mean=np.zeros(n_actions),
sigma=0.1 * np.ones(n_actions))
td3 = TD3(
"MlpPolicy", env,
learning_rate=3e-4,
buffer_size=1_000_000,
batch_size=256,
action_noise=action_noise,
policy_delay=2, # actor her 2 critic update'te bir güncellenir
target_policy_noise=0.2,
verbose=0)
# Kısa benchmark karşılaştırması
for name, model in [("SAC", sac), ("TD3", td3)]:
model.learn(total_timesteps=200_000)
print(f"{name} eğitimi tamamlandı")
07 Dexterous Manipulation
İnsan elinin maharetini taklit eden dexterous manipulation, robotik RL'nin en zorlu açık problemleri arasındadır.
Dexterous manipulation — parmaklarla nesne yönlendirme, in-hand rotation, karmaşık kavrama — çok sayıda eklem, yüksek boyutlu eylem uzayı ve kritik temas dinamiği içerir. OpenAI'nin Shadow Hand üzerindeki Dactyl çalışması bu alanda dönüm noktası oldu: domain randomization + LSTM policy + self-play ile insan seviyesi nesne döndürme başarıldı.
(1) Yüksek frekanslı kontrol (100–500 Hz) — temas olayları çok kısadır. (2) İmpedance control + RL hiyerarşisi — low-level compliance kontrolü RL üzerinde. (3) Kapsamlı domain randomization — temas parametreleri en kritik stochasticity kaynağıdır. (4) Uzun horizon history — RNN/Transformer policy geçmiş temas geçmişini kullanır.
08 Pratik: Franka Panda Pick-Place Eğitimi
gymnasium-robotics kütüphanesindeki FetchPickAndPlace ortamında SAC ile eğitim ve HER (Hindsight Experience Replay) uygulaması.
pip install "gymnasium-robotics[mujoco]" stable-baselines3 tensorboard
import gymnasium as gym
import gymnasium_robotics
from stable_baselines3 import SAC, HerReplayBuffer
from stable_baselines3.common.callbacks import EvalCallback
# FetchPickAndPlace: hedef konuma tutma görev
# GoalEnv arayüzü: obs dict içinde 'observation', 'desired_goal', 'achieved_goal'
env = gym.make("FetchPickAndPlace-v2")
eval_env = gym.make("FetchPickAndPlace-v2")
# SAC + HER: sparse reward GoalEnv için ideal kombinasyon
model = SAC(
"MultiInputPolicy",
env,
replay_buffer_class=HerReplayBuffer,
replay_buffer_kwargs={
"n_sampled_goal": 4, # her transition için 4 hindsight goal
"goal_selection_strategy": "future", # gelecek gözlemden hedef
},
learning_rate=1e-3,
buffer_size=1_000_000,
batch_size=256,
ent_coef="auto",
gamma=0.98,
tau=0.005,
verbose=1,
tensorboard_log="./tb_pick_place/"
)
eval_cb = EvalCallback(
eval_env,
best_model_save_path="./models/pick_place/",
eval_freq=20_000,
n_eval_episodes=20,
deterministic=True,
verbose=1
)
print("Eğitim başlıyor: FetchPickAndPlace + SAC + HER")
model.learn(total_timesteps=1_000_000, callback=eval_cb)
model.save("franka_pick_place_sac_her")
print("Model kaydedildi: franka_pick_place_sac_her.zip")
# Değerlendirme
mean_reward = 0.0
for _ in range(50):
obs, _ = eval_env.reset()
done = False
ep_r = 0.0
while not done:
action, _ = model.predict(obs, deterministic=True)
obs, r, done, trunc, _ = eval_env.step(action)
ep_r += r
done = done or trunc
mean_reward += ep_r
print(f"50 ep ortalama ödül: {mean_reward/50:.3f}")
FetchPickAndPlace sparse reward kullanır: yalnızca nesne hedefe ulaşınca +0 (başarı) veya -1 (başarısız) döner. HER olmadan SAC milyonlarca adımda hiç başarı sinyali göremeyebilir. HER, başarısız trajectory'leri geriye dönük "aslında orada durmayı hedefledim" yorumuyla yeniden etiketler; böylece negatif deneyimden de öğrenme mümkün olur.