This repository contains the code for a simulation of a robot named Baloo.
The main class in the code is Baloo, which represents the robot. The Baloo class has methods for setting up the simulation, including setting compiler options, visual settings, and contact settings. It also has methods for creating the robot's body parts and actuators. (see generate_baloo_xml.py for more details on how the robot is created).
The robot is composed of a number of disks, which can be specified when creating a Baloo instance. The robot also has a number of joints, and the height of these joints can be adjusted.
The simulation includes a world plane and a fixed camera view. There is also a box object in the simulation that the robot can interact with.
- Install uv which I use a dependency manager for this project.
- Clone the repository to your local machine.
- Run included install script (
./install.sh) in the root directory of the repository. This will do a few things:- Install the package using
uv(this will also install the dependencies into venv) - Build the C++ plugins for mujoco (one for joint angle estimation and another for the elevator ruckig motion planning). The compiled files are then placed in the mujoco plugin directory.
- Generate the mujoco xml files for the simulation
- Download a precompiled version of mujoco into a
precompileddirectory. This just comes with some useful MuJoCo binaries, like testspeed, which is useful for testing the simulation speed.
- Install the package using
NOTE: This installation has only been tested with Ubuntu 20.04 and Python 3.8. Working on updating deps to include more recent versions.
There are two command line scripts that are installed with the package:
run-baloo-sim: This just pulls up a passive viewer and runs the simulation. It doesn't do anything fancy, but it does allow you to see the robot in action. You can use the arrow keys to move the camera around and the mouse to zoom in and out. This CLI runs baloo_open_loop.py here.generate-baloo-xml: Runs the xml generation script here. The xml file it generates is placed in the assets directory. This is where all of the modeling magic happens. This script reads in some parameters from here and included meshes from the meshes directory.
The package exposes a few different things:
- An
XML_PATHvariable that points to the xml files to load a mujoco simulation. - A
baloo_mj_apiutility module that has a few helper functions for interacting with the mujoco simulation.
Example usage:
import mujoco
import baloo_mujoco_sim as baloo_mj
from baloo_mujoco_sim.utils.baloo_mj_api import set_joint_pressure_commands
# Load the simulation
model = mujoco.MjModel.from_xml_path(baloo_mj.XML_PATH)
data = mujoco.MjData(model)
# later in simulation loop...
set_joint_pressure_commands(model, data, 'left', 0, [0,0,0,0])See utils/baloo_mj_api.py for more details on the functions that are available. In general, the functions are for setting joint commands, getting joint angles, and getting tactile sensor readings, etc.
- The inertia of the links (since this is tough to measure accurately) is assumed to be a solid cylinder
- The mass of the joints is divided evenly (i.e. lumped evenly) between the disks that compose the joint. Each disk is assumed to be a solid cylinder as well. This also assumes that the distribution of mass is roughly uniform along the length of the joint.
- The joint_angle_estimator plugin assumes constant curvature of the joint. This is not true in the real world and is also not assumed in the simulation. The plugin is a simply estimates a constant curvature angle based on the first and last disks of the joint.
- Mostly for RL training, I used custom contact filtering using the contype and conaffinity parameters in Mujoco. The parameters are set so that the only thing that can trigger a tactile sensor response is the manipuland, not the robot itself. This is not realistic, but it is useful for training RL agents to avoid learning to punch itself.
Right now, the joint limits are implemented by setting the maximum bend angle in the .yaml file. This is then divided evenly between the universal joints.
A secondary effect is that there are contacts allowed between disks1, which also limits the range of motion depending on how thick the disks are. Right now, the length of the joints is divided evenly between the numbers of disks + gaps.
We could instead specify the maximum length for each of the tendons, which might work better. Either way, it's unclear how the actual joint limit changes with respect to the number of disks used.
The installation script has only been tested on Ubuntu 20.04. It would be good to test on newer version of Ubuntu to ensure compatibility.
It would also be good to add support for other operating systems, such as MacOS and Windows, though that might take more work.
Footnotes
-
Technically, its between every other disk, since by default, MuJoCo disables contacts between geom pairs that have a parent-child body relationship. So in essence, we have contacts between parent-grandchild disks right now, which happens to land each joint at about the right limit. This could be disabled, but then the thickness of the disks needs to be adjusted to provide the correct joint limit. Disabling the parent-child filter isn't a great idea though, as it will break a bunch of other things. Alternatively, the contact between disks could be disabled completely using the
contypeandconaffinityparameters to rely solely on the joint limits specified in another way. ↩
