Source code for udaan.models.base.s2_pendulum

import numpy as np

from ... import manif
from ..base import BaseModel


[docs] class S2Pendulum(BaseModel): """Pendulum model with attitude on S2. State: attitude (S2 unit vector, 3), angular_velocity (3) -> n_state=6, n_action=3 """
[docs] class State:
[docs] def __init__(self): self.attitude = manif.S2(np.array([0.0, 0.0, -1.0])) self.angular_velocity = np.zeros(3) return
[docs] def reset(self): self.attitude = manif.S2(np.array([0.0, 0.0, -1.0])) self.angular_velocity = np.zeros(3) return
[docs] def __init__(self, **kwargs): super().__init__(**kwargs) self._n_state = 6 self._n_action = 3 self.mass = 0.1 self.length = 1.0 self.state = S2Pendulum.State() self._parse_args(**kwargs) return
def _zoh(self, torque): """Zero-order hold integration on S2.""" dt = self.sim_timestep q = self.state.attitude om = self.state.angular_velocity # S2 geodesic update for attitude self.state.attitude = q.step(om * dt) # angular velocity update dom = -(self._g / self.length) * np.cross(self.state.attitude, self._e3) + torque / ( self.mass * self.length**2 ) self.state.angular_velocity = om + dom * dt
[docs] def step(self, action): self._zoh(action) self.t += self.sim_timestep
[docs] def reset(self, **kwargs): self.t = 0.0 self.state.reset() if "attitude" in kwargs: self.state.attitude = manif.S2(kwargs["attitude"]) if "angular_velocity" in kwargs: self.state.angular_velocity = kwargs["angular_velocity"] return
[docs] def get_rand_init_state(self, rand=True): if rand: rng = np.random.default_rng() phi = -np.pi + 2 * np.pi * rng.standard_normal(1) th = np.pi * rng.random(1) init_att = manif.S2.from_spherical(phi[0], th[0]) else: init_att = manif.S2(np.array([1.0, 0.0, 0.0])) return {"attitude": init_att, "angular_velocity": np.zeros(3)}