Source code for prt_rl.model_based.models.dynamics.pendulum
"""Pendulum dynamics model for physics-based simulation."""
import torch
[docs]
class PendulumDynamics:
"""
Physics-based dynamics model for a simple pendulum system.
This class implements the equations of motion for a simple pendulum with
torque control. The dynamics are based on the physical parameters of the
pendulum (mass, length, gravity) and use Euler integration for time stepping.
Note: Assumes zero theta corresponds to the pendulum straight up, and positive theta / torque is counterclockwise.
Attributes:
g (float): Gravitational acceleration constant (m/s²). Defaults to 10.0.
l (float): Length of the pendulum (m).
m (float): Mass of the pendulum bob (kg).
dt (float): Time step for Euler integration (s).
"""
[docs]
def __init__(
self,
g: float = 10.0,
l: float = 1.0,
m: float = 1.0,
dt: float = 0.05
) -> None:
"""
Initialize the pendulum dynamics model.
Args:
g: Gravitational acceleration constant in m/s². Defaults to 10.0.
l: Length of the pendulum in meters. Defaults to 1.0.
m: Mass of the pendulum bob in kg. Defaults to 1.0.
dt: Time step for Euler integration in seconds. Defaults to 0.05.
"""
self.g = g
self.l = l
self.m = m
self.dt = dt
[docs]
def step(
self,
theta: torch.Tensor,
thetad: torch.Tensor,
tau: torch.Tensor
) -> torch.Tensor:
"""
Perform one time step of the pendulum dynamics using Euler integration.
Args:
theta: Pendulum angle in radians. Shape: [B, 1] where B is batch size.
thetad: Pendulum angular velocity in rad/s. Shape: [B, 1].
tau: Applied torque in N⋅m. Shape: [B, 1].
Returns:
Next state [theta, thetad] after one time step. Shape: [B, 2].
"""
xdot = self.derivative(theta, thetad, tau) # [B, 2]
x = torch.cat([theta, thetad], dim=-1)
x_next = x + xdot * self.dt
return x_next
[docs]
def derivative(
self,
theta: torch.Tensor,
thetad: torch.Tensor,
tau: torch.Tensor
) -> torch.Tensor:
"""
Compute the time derivatives of the pendulum state.
Uses the equations of motion for a simple pendulum with torque input:
θ̈ = (3g)/(2l) * sin(θ) + 3/(ml²) * τ
Args:
theta: Pendulum angle in radians. Shape: [B, 1] where B is batch size.
thetad: Pendulum angular velocity in rad/s. Shape: [B, 1].
tau: Applied torque in N⋅m. Shape: [B, 1].
Returns:
Time derivatives [θ̇, θ̈]. Shape: [B, 2].
"""
thetadd = (3 * self.g / (2 * self.l) * torch.sin(theta) + 3 / (self.m * self.l**2) * tau)
return thetadd