Source code for udaan.models.mujoco.quadrotor_comparison
import copy
import numpy as np
from scipy.spatial.transform import Rotation as sp_rot
from ...manif import SO3, TSO3
from ...utils.logging import get_logger
from .. import base
from ..quadrotor import QuadrotorBase
from . import MujocoModel
_logger = get_logger(__name__)
[docs]
class QuadrotorComparison(base.BaseModel):
[docs]
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Actual plant model.
self.plant = QuadrotorBase()
self.reference = QuadrotorBase()
# mujoco model param handling
self._mjMdl = None
self._mj_quad_index = None
self._mj_payload_index = None
self._mj_cable_index = None
self._attitude_zoh = kwargs["attitude_zoh"] if "attitude_zoh" in kwargs else False
self.render = kwargs["render"] if "render" in kwargs else False
filename = kwargs["filename"] if "filename" in kwargs else "quadrotor_comparison.xml"
self._mjDt = 1.0 / 500.0
self._step_iter = int(self.sim_timestep / self._mjDt)
self._nFrames = 1
if self._attitude_zoh:
self._step_iter, self._nFrames = self._nFrames, self._step_iter
# loading mujoco model
self._mjMdl = MujocoModel(filename, render=self.render)
self._plant_body_index = 1
self._reference_body_index = 2
self._plant_ctrl_index = 0
self._reference_ctrl_index = 4
# read inertial parameters from mujoco model
self.plant.mass = copy.deepcopy(self._mjMdl.model.body_mass[self._plant_body_index])
self.plant.inertia = copy.deepcopy(self._mjMdl.model.body_inertia[self._plant_body_index])
self.reference.mass = copy.deepcopy(self._mjMdl.model.body_mass[self._reference_body_index])
self.reference.inertia = copy.deepcopy(
self._mjMdl.model.body_inertia[self._reference_body_index]
)
# reinitialize controllers after loading mujoco model & params
self.plant._init_default_controllers()
self.reference._init_default_controllers()
if self.verbose:
_logger.info("Mujoco model loaded")
return
[docs]
def set_mass(self, m, plant=True):
if plant:
self.plant.mass = m
self._mjMdl.model.body_mass[self._plant_body_index] = m
else:
self.reference.mass = m
self._mjMdl.model.body_mass[self._reference_body_index] = m
return
[docs]
def set_inertia(self, I, plant=True):
if I.ndim == 2:
I = np.diag(I)
if plant:
self.plant.inertia = I
self._mjMdl.model.body_inertia[self._plant_body_index] = I
else:
self.reference.inertia = I
self._mjMdl.model.body_inertia[self._reference_body_index] = I
return
[docs]
def reset(self, **kwargs):
self.t = 0.0
self.plant.state.reset()
self.reference.state.reset()
k = ["position", "velocity", "orientation", "angular_velocity"]
for key in k:
if key in kwargs:
setattr(self.plant.state, key, kwargs[key])
setattr(self.reference.state, key, kwargs[key])
self._mjMdl.reset()
# Set plant position
self._mjMdl.data.qpos[:3] = self.plant.state.position
self._mjMdl.data.qvel[:3] = self.plant.state.velocity
qQ = sp_rot.from_matrix(np.asarray(self.plant.state.orientation)).as_quat()
self._mjMdl.data.qpos[3:7] = np.array([qQ[3], qQ[0], qQ[1], qQ[2]])
self._mjMdl.data.qvel[3:6] = np.asarray(self.plant.state.angular_velocity)
# Set reference position
self._mjMdl.data.qpos[7:10] = self.reference.state.position
self._mjMdl.data.qvel[6:9] = self.reference.state.velocity
qQ = sp_rot.from_matrix(np.asarray(self.reference.state.orientation)).as_quat()
self._mjMdl.data.qpos[10:14] = np.array([qQ[3], qQ[0], qQ[1], qQ[2]])
self._mjMdl.data.qvel[9:12] = np.asarray(self.reference.state.angular_velocity)
self._query_latest_state()
return
def _query_latest_state(self):
self.t = copy.deepcopy(self._mjMdl.data.time)
pos = copy.deepcopy(self._mjMdl.data.qpos[:3])
q = copy.deepcopy(self._mjMdl.data.qpos[3:7])
vel = copy.deepcopy(self._mjMdl.data.qvel[:3])
ang_vel = copy.deepcopy(self._mjMdl.data.qvel[3:6])
self.plant.state.position = np.array(pos)
self.plant.state.velocity = np.array(vel)
self.plant.state.orientation = SO3(self._mjMdl._quat2rot(q))
self.plant.state.angular_velocity = TSO3(ang_vel)
pos2 = copy.deepcopy(self._mjMdl.data.qpos[7:10])
q2 = copy.deepcopy(self._mjMdl.data.qpos[10:14])
vel2 = copy.deepcopy(self._mjMdl.data.qvel[6:9])
ang_vel2 = copy.deepcopy(self._mjMdl.data.qvel[9:12])
self.reference.state.position = np.array(pos2)
self.reference.state.velocity = np.array(vel2)
self.reference.state.orientation = SO3(self._mjMdl._quat2rot(q2))
self.reference.state.angular_velocity = TSO3(ang_vel2)
return
[docs]
def step(self, u):
for _ in range(self._step_iter):
u_plant = u[0:4]
u_reference = u[4:8]
# set control
self._mjMdl.data.ctrl[self._plant_ctrl_index : self._plant_ctrl_index + 4] = u_plant
self._mjMdl.data.ctrl[self._reference_ctrl_index : self._reference_ctrl_index + 4] = (
u_reference
)
# mujoco simulation
self._mjMdl._step_mujoco_simulation(self._nFrames)
# update state
self._query_latest_state()
return
[docs]
def add_reference_marker(self, x, label="xQd"):
self._mjMdl.add_marker_at(x, size=[0.01, 0.01, 0.01], label=label)
return