12. Integrating New Simulators
November 2, 2023 ยท View on GitHub
In this chapter we want to describe the required steps to add a new physics engine to the ALR Simulation Framework. You must implement 4 required interfaces:
Also, it might be helpful to users to define a new interface <SIM>Loadable, similar to MujocoLoadable or PybulletLoadable and use this to extend the PrimitiveObjects classes.
12.0 Attention: Quaternions
Within the SimFramework, we use the wxyz order of defining quaternions. Some simulators, such as pybullet, use xyzw instead. Always use the wxyz convention, especially for user facing methods. You can use helper functions in geometric_transformation.py to convert the order when interfacing with your simulator.
12.1. Scene
The Scene interface acts like a repository for the simulation. It holds all the loaded objects and surroundings and encapsulates the internal simulation state.
Important things to consider:
- Your simulation should only begin once
scene.start()is called. - Does your simulator support instantiation of objects after it has been started?
- Use the
SimObjectRepositoryclass to keep track of simulated objects by reference, name or sim_id. This required steps to load objects and set their ids should occur when adding the objects, or when executing the internal setup functionscene._setup_scene(). - Keep in mind, that your simulation scene should supported multiple robots at once, also known as the multi-bot feature.
12.2. RobotBase
As the name implies, the RobotBase interface defines the robot. The two most important functions to implement are:
receiveState, in which the robot should ask its simulator what its current state is, especially with respect to its joints.prepareStep, in which the robot should receive atarget_joint_accfrom its active controller and compute the required command for the sim, e.g. motor torques. TheMujocoRobotimplementation is a good reference implementation.
12.3. Camera
The camera must be able to capture images of the current simulated environment.
12.4. SimFactory
Implement a SimFactory which acts as a kind of Facade for the various newly implemented interfaces. For more details on its functionality, please refer to Chapter 5.
Remember to register your SimFactory at the SimRepository, e.g.
"""classic_framework/new_sim/NewSimFactory.py"""
class NewSimFactory:
...
# Class Ends
# On Module Level, after defining the class
SimRepository.register(NewSimFactory(), 'newsim')
#--------------
"""classic_framework/new_sim/__init__.py"""
import NewSimFactory
Having the import statement in the packages __init__.py file imports the module, when the package is loaded, thus executing the register() statement.
Refer to the Mujoco SimFactory and Mujoco init.py for a reference implementation.
12.5. Loadable Interface
We do not define a global "Loadable" interface class, but it might be helpful for your Simulator to define one on its own. This interface should be used by your Scene implementation to load objects into the simulation.
With this mechanism, simulation objects such as the PrimitiveObjects can implement the various Loadable interfaces and can be used in the different simulators without the user needing to adjust their code.