Newton Simulator¶
Fast, differentiable physics simulator with a new physics engine optimized for robot learning.
Overview¶
Newton features a new, purpose-built physics engine designed for machine learning with:
- Blazing fast GPU-accelerated physics
- Differentiable simulation
- Simple API - minimal boilerplate
- Massive parallelization (100,000+ envs)
- PyTorch integration
Installation¶
Quick Start¶
import newton
import torch
# Create environment
env = newton.make("FrankaReach-v0", num_envs=4096, device="cuda")
# Reset
obs = env.reset()
# Run
for _ in range(1000):
actions = torch.randn(4096, env.action_dim, device="cuda")
obs, rewards, dones, info = env.step(actions)
print(f"Steps per second: {env.fps}")
Built-in Environments¶
# Available environments
envs = newton.list_envs()
# Manipulation
env = newton.make("FrankaReach-v0")
env = newton.make("FrankaPickAndPlace-v0")
# Locomotion
env = newton.make("AntWalk-v0")
env = newton.make("HumanoidWalk-v0")
# Classic control
env = newton.make("Cartpole-v0")
env = newton.make("Pendulum-v0")
Custom Environments¶
import newton
from newton.envs import BaseEnv
class MyRobotEnv(BaseEnv):
def __init__(self, num_envs=1024, device="cuda"):
super().__init__(num_envs, device)
# Define observation and action spaces
self.obs_dim = 10
self.action_dim = 4
# Load robot
self.robot = newton.load_urdf("robot.urdf", num_instances=num_envs)
def reset(self):
# Reset robot state
self.robot.set_joint_positions(torch.zeros(self.num_envs, 7))
return self.get_observations()
def step(self, actions):
# Apply actions
self.robot.set_joint_torques(actions)
# Step physics
newton.step()
# Compute rewards and observations
obs = self.get_observations()
rewards = self.compute_rewards()
dones = self.check_termination()
return obs, rewards, dones, {}
def get_observations(self):
return torch.cat([
self.robot.get_joint_positions(),
self.robot.get_joint_velocities()
], dim=-1)
def compute_rewards(self):
# Implement reward logic
pass
Differentiable Simulation¶
import torch
# Create environment
env = newton.make("FrankaReach-v0", num_envs=1, device="cuda")
# Get initial state
state = env.reset()
# Optimize actions via gradient descent
actions = torch.randn(100, env.action_dim, device="cuda", requires_grad=True)
optimizer = torch.optim.Adam([actions], lr=0.01)
for iteration in range(100):
state = env.reset()
total_reward = 0
for t in range(100):
state, reward, done, info = env.step(actions[t])
total_reward += reward
# Backprop through entire trajectory
loss = -total_reward
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"Iteration {iteration}: Reward = {total_reward.item()}")
Physics Configuration¶
env = newton.make(
"FrankaReach-v0",
num_envs=4096,
physics_dt=1/120, # Physics timestep
control_dt=1/30, # Control frequency
gravity=[0, 0, -9.81],
solver_iterations=4, # Solver accuracy
enable_ccd=True # Continuous collision detection
)
Domain Randomization¶
class RandomizedEnv(newton.BaseEnv):
def reset(self):
# Randomize physics parameters
self.robot.set_mass(
torch.rand(self.num_envs, 1) * 2.0 + 1.0 # 1-3 kg
)
self.robot.set_friction(
torch.rand(self.num_envs, 1) * 0.5 + 0.5 # 0.5-1.0
)
# Randomize initial state
init_q = torch.randn(self.num_envs, 7) * 0.1
self.robot.set_joint_positions(init_q)
return self.get_observations()
Sensors¶
# Add camera
camera = newton.Camera(
resolution=(640, 480),
fov=60,
position=[2, 0, 1],
target=[0, 0, 0]
)
# Get RGB image
rgb = camera.get_image() # (num_envs, 3, 480, 640)
# Get depth
depth = camera.get_depth() # (num_envs, 1, 480, 640)
Performance Benchmarks¶
| Environment | Envs | GPU | Steps/sec |
|---|---|---|---|
| FrankaReach | 4096 | RTX 3090 | 50,000 |
| FrankaReach | 4096 | A100 | 100,000 |
| AntWalk | 16384 | A100 | 200,000 |
Integration with RL Libraries¶
Stable-Baselines3¶
import newton
from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import DummyVecEnv
# Wrap Newton env for SB3
class NewtonEnvWrapper:
def __init__(self, env_name, num_envs):
self.env = newton.make(env_name, num_envs=num_envs)
def reset(self):
return self.env.reset().cpu().numpy()
def step(self, actions):
actions_tensor = torch.tensor(actions).to(self.env.device)
obs, rewards, dones, info = self.env.step(actions_tensor)
return obs.cpu().numpy(), rewards.cpu().numpy(), dones.cpu().numpy(), info
# Train
env = NewtonEnvWrapper("FrankaReach-v0", num_envs=4096)
model = PPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=10_000_000)
Custom Training Loop¶
import torch
env = newton.make("FrankaReach-v0", num_envs=4096)
policy = PolicyNetwork()
optimizer = torch.optim.Adam(policy.parameters())
obs = env.reset()
for step in range(1_000_000):
# Get actions
actions = policy(obs)
# Step environment
next_obs, rewards, dones, info = env.step(actions)
# Compute loss and update
loss = compute_ppo_loss(obs, actions, rewards, next_obs, dones)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# Reset done environments
if dones.any():
next_obs[dones] = env.reset_indexed(dones.nonzero())
obs = next_obs
Advantages¶
| Feature | Newton | IsaacLab | IsaacSim |
|---|---|---|---|
| Setup Time | 5 min | 30 min | 2 hours |
| Learning Curve | Easy | Medium | Hard |
| Max Parallel Envs | 100,000+ | 10,000+ | 1,000 |
| Differentiable | Yes | No | No |
| Graphics | Basic | Good | Photorealistic |
Use Cases¶
Best for:¶
- Fast RL prototyping
- Trajectory optimization
- Model-based RL
- Large-scale parallel training
- Gradient-based planning
Not ideal for:¶
- Photorealistic rendering
- Complex sensor simulation
- Digital twins
- Visual perception research
Next Steps¶
- IsaacLab - More features, slightly slower
- Comparison - Detailed comparison
- RL Training - Training guide