Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

mc-rtc-nix : the mc_rtc ecosystem in Nix

Warning

While being used daily by core maintainers of the framework, this is still considered a work-in-progress and usage / design choice may chage without notice.

This project contains:

  • Package definitions for most of the mc_rtc ecosystem:
    • core framework mc_rtc and its dependencies
    • tools (mc-rtc-magnum for vizualisation, etc)
    • most robots supported by the framework, in particular those used at LIRMM and JRL
    • a limited set of downstream controllers and plugins
    • and more
  • They are:
    • exposed in an overlay…
    • …with a reusable flake module built on top of flakoboros for easy integration in your projects with:
      • options to control how to build the framework in mc-rtc-nix.<option> (e.g with-ros=false, overlays.private=true, etc)
      • a superbuild module similar to mc-rtc-superbuild to configure the runtime dependencies of your project in mc-rtc-superbuild.<options>

Here is a quick primer on how to use its features:

Setup Nix

If you are here and don’t have nix yet, here is probably the easiest and fastest way to get started on ubuntu >= 24.04 “noble” / debian >= 13 “trixie” (because we need nix >= 2.18):

# 1. install the right apt package
sudo apt install -y nix-setup-systemd

# 2. activate the new CLI and flake features
echo 'experimental-features = nix-command flakes' | sudo tee -a /etc/nix/nix.conf

# 3. (optional) if you trust us, add our binary caches to avoid recompiling everything
echo 'extra-substituters = https://gepetto.cachix.org https://attic.iid.ciirc.cvut.cz/ros https://mc-rtc-nix.cachix.org' | sudo tee -a /etc/nix/nix.conf
echo 'extra-trusted-public-keys = gepetto.cachix.org-1:toswMl31VewC0jGkN6+gOelO2Yom0SOHzPwJMY2XiDY= ros:JR95vUYsShSqfA1VTYoFt1Nz6uXasm5QrcOsGry9f6Q= mc-rtc-nix.cachix.org-1:5M3sLvHXJCep4wc1tQl7QuFWL2eH2I0jkuvWtqJDYQs=' | sudo tee -a /etc/nix/nix.conf

# 4. activate your new nix.conf
sudo systemctl restart nix-daemon

# 5. allow yourself to use nix
sudo usermod -aG nix-users $(whoami)
newgrp nix-users

# 6. test everything is fine
nix run nixpkgs#ponysay it works

Other setup methods

If you don’t want this nix-setup-systemd apt package, other options include:

Use mc-rtc-nix directly

This [mc-rtc/nixpkgs] repository exposes packages, some of which may be used directly. To try out mc_rtc, you can use:

nix develop github:mc-rtc/nixpkgs#mc-rtc-superbuild-default

This will put you in a shell with mc_rtc and its default robots/controllers installed. To get started, use

(mc-rtc-magnum &) # run visualizer in the background
mc_rtc_ticker # run an open-loop controller

You should see the JVRC1 robot appear in the visualizer. If that is not the case and you are not on NixOS, you may need to configure Nix to use your graphics drivers. This can be achieved with

sudo nix run github:gepetto/nix#system-manager -- switch --flake github:gepetto/nix

Warning

This will install configurations system-wide (hence the sudo). If you are ensure about it, please read about system-manager

Module overview

Our module is based on flakoboros circular packaging concept, and uses flakoboros extensively. Please familiarize yourself with flakoboros first by reading their documentation.

The concept is to define a flake.nix file in your own projects that include the module provided by this repository. This will:

  • Make all packages of the mc_rtc ecosystem through overlays
  • Allow you to modify/extend their packages through flakoboros’s overrides (see flakoboros overrides documentation)
  • Provide an mc-rtc-superbuild shell configurable though options to configure mc_rtc’s runtime dependencies (plugins, controllers, robots, etc) for your project

Creating a new controller

To get started, use:

# create a new project folder initialized with a controller
nix shell github:mc-rtc/nixpkgs#mc-rtc -c mc_rtc_new_fsm_controller TestController TestController
cd TestController
# adds our nix flake
nix flake init -t github:mc-rtc/nixpkgs#controller

You should get (simplified here):

{
  description = "mc-rtc-superbuild release and development shells";

  inputs = {
    mc-rtc-nix.url = "github:mc-rtc/nixpkgs";
    flake-parts.follows = "mc-rtc-nix/flake-parts";
    systems.follows = "mc-rtc-nix/systems";
  };

  outputs =
    inputs:
    inputs.flake-parts.lib.mkFlake { inherit inputs; } (
      { ... }:
      {
        systems = import inputs.systems;
        imports = [
          inputs.mc-rtc-nix.flakeModule
          {
            mc-rtc-nix = {}; # options for mc-rtc-nix
            mc-rtc-superbuild = {}; # options for building superbuild shells
            flakoboros = {}; # flakoboros configuration
          }
        ];
      }
    );
}

This:

  • Declares the flake inputs
  • Initializes a flake using flake-parts
  • Declares the supported systems (x86_64-linux, darwin, etc).
  • Imports our flake module.

You can configure the flake overlay with:

mc-rtc-nix
{
  with-ros = true; # whether to build with ROS
  with-python = true; # whether to build with python bindings
  overlays.private = false; # whether to include private repositories in the overlay (robots HRP, etc). You will need an SSH key and appropriate permissions to use them.
  # ...
}

To define a superbuild configuration for our example controller, we need two things:

  1. Declare how to build the package itself (since this is not upstreamed here)
  2. Tell mc_rtc how to use it.

We furthermore want the ability to:

  1. Let nix deploy the project
  2. Build and install it from source

This can be achieved as follows:

mc-rtc-superbuild =
{ pkgs, ... }:
{
  enable = true; # enables the mc-rtc-superbuild module
  project.pname = "test-controller-superbuild"; # prefix shell names
  configurations = { # adds configurations for your controller
    your-controller-minimal = {
      extends = [ "minimal" ]; # adds a configuration based on the "minimal" preset
      runtime = { # define runtime dependencies installed by nix
        robots = [];

        apps = [
          pkgs.mc-rtc-magnum
        ];
        config = "lib/mc_controller/etc/your-controller/mc_rtc.yaml";
      };
      # define devel dependencies:
      # - In devel shells, these are not built by Nix, you must build them from source.
      # - In release shells, they are merged wiith the runtime configuration
      # mc_rtc.yaml is configured to use them
      devel = {
        config = "lib64/mc_controller/etc/your-controller/mc_rtc.yaml";
        controllers = [ pkgs.test-controller];
      };
    };
  };
};

Now you can get a developpement shell, with the current source tree built by Nix with

nix develop .#test-controller-superbuild-minimal

Or built from source, with mc_rtc’s runtime paths pre-configured to use-it with

nix develop .#test-controller-superbuild-minimal-devel
cmake -B build $cmakeFlags -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -G Ninja
cmake --build build --target install

And execute in both cases with

(mc-rtc-magnum &) # visualization from apps category
mc_rtc_ticker # default open-loop control of mc_rtc

Plain lib

lib._convertListToDrvs

Converts a list of strings or derivations into a list of derivations from pkgs.

Arguments:

  • pkgs: The package set to resolve string names to derivations.
  • vals: A list of strings (attribute names) or derivations. Null elements are ignored.
  • ignoreMissing (optional, default: false): If true, missing derivations are skipped with a warning.

Returns:

  • A list of derivations, resolving strings via pkgs.

@example

lib._convertListToDrvs {
  pkgs = pkgs;
  vals = [ pkgs.human-mj-description "human-mj-description" ];
}

Type: { pkgs: AttrSet, vals: [String | Derivation], ignoreMissing?: Bool } -> [Derivation]

lib.convertListToDrvsStrict

Converts a list of strings or derivations into a list of derivations from pkgs, throwing an error if any string is not found.

Arguments:

  • pkgs: The package set to resolve string names to derivations.
  • vals: A list of strings (attribute names) or derivations.

Returns:

  • A list of derivations, resolving strings via pkgs. Throws an error if a string is missing.

@example

lib.convertListToDrvsStrict pkgs [ pkgs.human-mj-description "human-mj-description" ]
lib.convertListToDrvsStrict pkgs [ "mc-hrp4" ]

Type: pkgs: AttrSet -> vals: [String | Derivation] -> [Derivation]

lib.convertListToDrvs

Converts a list of strings or derivations into a list of derivations from pkgs, skipping missing strings with a warning.

Arguments:

  • pkgs: The package set to resolve string names to derivations.
  • vals: A list of strings (attribute names) or derivations.

Returns:

  • A list of derivations, resolving strings via pkgs. Missing strings are skipped with a warning.

@example

lib.convertListToDrvs pkgs [ pkgs.human-mj-description "human-mj-description" ]
lib.convertListToDrvs pkgs [ "mc-hrp4" ]

Type: pkgs: AttrSet -> vals: [String | Derivation] -> [Derivation]

lib.drvsFromPassthruField

Returns a list of derivations from a passthru attribute (which may be a derivation, a string, or a list of both) in a list of derivations.

Arguments:

  • pkgs: The package set to resolve string names to derivations.
  • getField: A function that extracts the attribute from a derivation (e.g., drv: drv.passthru.robot.module).
  • drvs: A list of derivations containing the field.

Returns:

  • A flat list of derivations extracted from the passthru field of each input derivation.

@example

lib.drvsFromPassthruField pkgs (drv: drv.passthru.robot.module) [
  pkgs.human-mj-description
  pkgs.g1-mj-description
]

Type: pkgs: AttrSet -> getField: (Derivation -> a) -> drvs: [Derivation] -> [Derivation]

lib.mujocoRobotsFromRobotModules

Gathers MuJoCo robot derivations from a list of robot modules.

Each robot module should provide passthru.mujocoRobots = [ "robot-mj-description" ].

@param pkgs Set. The package set to look up derivations. @param robots List of derivations. The robot modules. @return List of derivations. The MuJoCo robot derivations from the modules.

lib.replaceMcMujocoInApps

Replaces the mc-mujoco derivation in the apps list with a version overridden with the given MuJoCo robots.

If an app in the list is pkgs.mc-mujoco, it is replaced with an overridden version using the provided mujocoRobots. Other apps are left unchanged.

@param apps List of derivations. The applications list. @param pkgs Set. The package set containing mc-mujoco and mc-mujoco-robots. @param mujocoRobots List of derivations. The MuJoCo robots to use in the override. @return List of derivations. The updated applications list.

lib.mkControllerSuperbuild

mkControllerSuperbuild

Constructs a superbuild attribute set for a given controller derivation.

Arguments:

  • pkgs: The Nixpkgs package set.
  • controller-drv: The controller derivation (attribute set) to wrap.
  • extends (default: []): List of superbuilds to extend from.
  • with-suggested (default: true): Whether to include suggested apps/robots.

Returns:

  • extends: The list of extended superbuilds.
  • runtime: Runtime environment (controllers, plugins, observers).
  • apps: (optional) Suggested apps, if with-suggested is true.
  • robots: (optional) Suggested robots, if with-suggested is true.
  • devel: Development environment (controllers).
  • enabled: The enabled controller name, if set.

Example

  let
    myControllerDrv = pkgs.stdenv.mkDerivation {
      name = "my-controller";
      # ... build instructions ...
      passthru = {
        plugins = [ footsteps-planner-plugin mc-joystick-plugin ];
        observers = [ some-observer ];
        controller = {
          Enabled = "ismpc_walking";
          MainRobot = "JVRC1";
        };
        suggests = {
          robots = [ "mc-hrp4" "mc-hrp2" ];
          apps = [ "mc-mujoco" ];
        };
      };
    };
  in
    mkControllerSuperbuild pkgs myControllerDrv { with-suggested = true; }

Full module options search