11"""Defines simple task for training a joystick walking policy for K-Bot."""
22
3- import asyncio
43import functools
54import math
65from dataclasses import dataclass
6+ from pathlib import Path
77from typing import Self , TypedDict
88
99import attrs
10- import distrax
1110import equinox as eqx
1211import jax
1312import jax .numpy as jnp
1716import optax
1817import xax
1918from jaxtyping import Array , PRNGKeyArray , PyTree
19+ from kscale .web .gen .api import RobotURDFMetadataOutput
2020
2121import ksim
2222
@@ -900,8 +900,11 @@ def __init__(
900900 self .ctrl_dt = ctrl_dt
901901
902902 def forward (
903- self , obs_n : Array , carry : Array | tuple [tuple [Array , ...], ...], lpf_params : ksim .LowPassFilterParams
904- ) -> tuple [distrax .Distribution , tuple [tuple [Array , ...], ...], ksim .LowPassFilterParams ]:
903+ self ,
904+ obs_n : Array ,
905+ carry : Array | tuple [tuple [Array , ...], ...],
906+ lpf_params : ksim .LowPassFilterParams ,
907+ ) -> tuple [xax .Distribution , tuple [tuple [Array , ...], ...], ksim .LowPassFilterParams ]:
905908 x_n = self .input_proj (obs_n )
906909 out_carries = []
907910 for i , rnn in enumerate (self .rnns ):
@@ -925,7 +928,7 @@ def forward(
925928 mean_n , lpf_params = ksim .lowpass_one_pole (mean_n , self .ctrl_dt , self .cutoff_frequency , lpf_params )
926929
927930 # Create diagonal gaussian distribution
928- dist_n = distrax . MultivariateNormalDiag ( loc = mean_n , scale_diag = std_n )
931+ dist_n = xax . Normal ( loc_n = mean_n , scale_n = std_n )
929932
930933 return dist_n , tuple (out_carries ), lpf_params
931934
@@ -936,7 +939,7 @@ class Critic(eqx.Module):
936939 input_proj : eqx .nn .Linear
937940 rnns : tuple [eqx .nn .LSTMCell , ...]
938941 output_proj : eqx .nn .Linear
939- num_inputs : int = eqx .static_field ()
942+ num_inputs : int = eqx .field ()
940943
941944 def __init__ (
942945 self ,
@@ -1065,12 +1068,18 @@ def get_optimizer(self) -> optax.GradientTransformation:
10651068 else :
10661069 return optax .chain (optax .adamw (learning_rate = cosine_schedule , weight_decay = self .config .adam_weight_decay ))
10671070
1071+ @property
1072+ def data_root_dir (self ) -> Path :
1073+ return Path (__file__ ).parent / "robot" / "kbot-headless"
1074+
10681075 def get_mujoco_model (self ) -> mujoco .MjModel :
1069- mjcf_path = asyncio . run ( ksim . get_mujoco_model_path ( "robot/kbot-headless" , name = "robot" ))
1076+ mjcf_path = self . data_root_dir / "robot.mjcf"
10701077 return mujoco_scenes .mjcf .load_mjmodel (mjcf_path , scene = "sine" )
10711078
10721079 def get_mujoco_model_metadata (self , mj_model : mujoco .MjModel ) -> ksim .Metadata :
1073- metadata = asyncio .run (ksim .get_mujoco_model_metadata ("robot/kbot-headless" ))
1080+ metadata_path = self .data_root_dir / "metadata.json"
1081+ with open (metadata_path , "r" ) as f :
1082+ metadata = RobotURDFMetadataOutput .model_validate_json (f .read ())
10741083 if metadata .joint_name_to_metadata is None :
10751084 raise ValueError ("Joint metadata is not available" )
10761085 if metadata .actuator_type_to_metadata is None :
@@ -1343,7 +1352,7 @@ def run_actor(
13431352 commands : xax .FrozenDict [str , Array ],
13441353 carry : tuple [tuple [Array , ...], ...],
13451354 lpf_params : ksim .LowPassFilterParams ,
1346- ) -> tuple [distrax .Distribution , tuple [tuple [Array , ...], ...], ksim .LowPassFilterParams ]:
1355+ ) -> tuple [xax .Distribution , tuple [tuple [Array , ...], ...], ksim .LowPassFilterParams ]:
13471356 # joint_pos_n = observations["noisy_joint_position"]
13481357 joint_pos_n = observations ["noisy_biased_joint_position" ]
13491358 joint_vel_n = observations ["noisy_joint_velocity" ]
0 commit comments