Hello, everyone!

I’m Vadim Manaenko, DevOps at Airalab. If you decided to connect your robot to the Robonomics network, you will inevitably work with the Robonomics stack and the AIRA client. In general, you need to write a ROS package that will subscribe to the relevant topics and will give commands directly to the robot. In this article, we will consider issues related to the features of creating such a package in a NixOS environment.

What is NixOS and how is this system more attractive than Ubuntu for the developer and DevOps?

NixOS is a distribution based on the Linux core, the main distinguishing feature of which is its own purely functional package manager Nix. At the time of this writing, this distribution is in the 59th place by the version of Distrowatch.

Features of distribution:

Declarative style

NixOS is configured in a completely declarative style: you describe with the Nix language what specification you would like to receive, and the package manager does all the dirty work.

Reliability

NixOS has atomic updates and rollbacks to previous versions. Unlike other distributions, here each package is stored in its directory. If something went wrong after the update, you can always go back to the previous state.

Suitable for DevOps

Its declarative approach and security when upgrading make NixOS an ideal candidate for DevOps engineers. There is also NixOps, a system for uploading and deploying NixOS, which allows you to manage a network of machines running on NixOS.

More information, from NixOS installation and application programs to configuration, can be found on the official NixOS website. There is very detailed documentation. To understand the package manager and Nix language, click on the following link.

How can I deploy ROS packages on python?

Before you continue, let’s say a couple of words about delivering packets to NixOS. The Nix Package Manager works with .nix files that contain package descriptions. Each such file tells Nix how to build a specific package, including, if necessary, dependencies. For convenience, .nix files are collected in one place, which is called a channel. For example, there is a release-18.09 channel, where all the checked packages are located to the current release. Or nixos-unstable, where you can install packages that have not yet passed all the checks and can work unstably.

To develop economic agents for the Robonomics network, you need to install additional packages from the airapkgs channel. First, add a channel:

Now you can install packages, but they will be built from the source files on your machine. To install immediately collected packages, you need to make changes to /etc/nixos/configuration.nix:

Now from root user we execute:

# nixos-rebuild switch

Next, we install the package and activate the necessary environment variables:

$ nix-env -i robonomics_dev

$ nix-env -i gnumake

$ source .nix-profile/setup.bash

How to install Python dependencies?

A tangible contribution to the support of ROS under NixOS is made by akru. We should bear in mind that the packages are assembled and work only with Python 3.

You may not have enough Python packages that come in a standard complectation. Below we will analyze how to set the dependencies correctly.

If we want to install a module that will be available throughout the system, we do the following:

Create a file, for example, build.nix.

Create file contents.

with import <nixpkgs> {}; python36.withPackages (ps: with ps; [ numpy toolz ])

Here we specify for Python 3.6 to install the Numpy and Toolz modules.

Execute it.

$ nix-env -if build.nix

The same effect can be achieved if you register everything in /etc/nixos/configuration.nix:

{ # ... environment.systemPackages = with pkgs; [

(python36.withPackages(ps: with ps; [ numpy toolz ]))

];

}

There are situations when we work with different versions of one package. More frequent situation, when for different packages we need different dependencies. It is most convenient to describe the dependencies in a file with the .nix extension and pass it on to the nix-shell. You can find the name in nixpkgs on this page.

In the simplest case, you can pass dependencies as an argument to the nix-shell:

$ nix-shell -p ‘python36.withPackages(ps: with ps; [ numpy toolz ])’

or

$ nix-shell -p python36.pkgs.numpy python36.pkgs.toolz

Now we can run our package. Numpy and Toolz will be available for it.

If there are many dependencies, it’s more convenient to describe them in the default.nix file:

with import <nixpkgs> {};

python36.withPackages (ps: [ps.numpy ps.toolz])

We put this file in the project directory and call nix-shell. If the file is named differently, it must be explicitly specified.

The syntax here is very simple. We import the <nixpkgs> function. The keyword `with` adds everything to the local scope. Next, we add Python 3.6 to the environment variable with the numpy and toolz dependencies.

The nix-shell command is extremely useful. I recommend that you get familiar with other options for using it from the official documentation.

How to build a package and distribute your packages?

Let’s say we have a GitHub repository of the form https://github.com/<owner>/<repo>/

We can collect your package manually. The script will be as follows:

$ mkdir -p ws/src && cd ws/gsrc

$ git clone https://github.com/<owner>/<repo>/

$ cd .. && catkin_init_workspace

$ catkin_make

Now in the devel folder we have the setup.bash (.zsh) file, in which there are environment variables ROS with our package.

Obviously, this method requires a lot of action from the user. Therefore, consider how to create a package that will include assembly instructions and the necessary dependencies.

NixOS way

Usually the file is called default.nix, but you can choose a different name. Contents:

{ stdenv

, fetchFromGitHub

, python3Packages

, mkRosPackage

}: mkRosPackage rec { name = "<package-name>"; src = fetchFromGitHub {

owner = "<owner>";

repo = "<repo>";

rev = "<commit>";

sha256 = "<sha256>";

};

description = "Package description";

homepage =

license = licenses.bsd3;

maintainers = [ maintainers.<owner> ];

}; meta = with stdenv.lib; {description = "Package description";homepage = http://github.com/ / ;license = licenses.bsd3;maintainers = [ maintainers. ];}; }

Variables that need to be filled out separately are identified by angled brackets. The necessary data for the fetchFromGitHub section is obtained as follows:

$ nix-shell -p nix-prefetch-git

$ nix-prefetch-git https://github.com/<owner>/<repo> --rev <commit>

To test, you need to make a https://github.com/airalab/airapkgs clone of the repository and make some changes. First, select the category in the pkgs folder and create a subfolder with the package name, put the newly created default.nix there. It should look like this: pkgs / applications / science / robotics / <repo> /default.nix

We make changes to the pkgs / top-level / all-packages.nix file, similar to the existing records.

Now, while being in the airapkgs directory, we assemble:

$ nix-build -A <repo>

If you think that this package should be included in the repository airapkgs, send pull request. Or you can create a fork and add your own packages.

You can find additional information using this link: https://nixos.org/nixpkgs/manual/

How to launch your package in the environment of Robonomics?

If you have an AIRA client running, you can install your package there and start from the client.

If you deploy everything yourself, check that the following services are launched and running: Parity, IPFS, Lighthouse, Liability. After that, you can start your package with roslaunch.

If you are working on the Airalab lighthouse (airalab.lighthouse.1.robonomics.eth), you do not need to specify anything else. Otherwise, specify an argument for the Lighthouse and Liability services

lighthouse_contract:=<name>

Here we would consider this tour of the development for the Robonomics, over. Specific examples of the implementation of economic agents will appear in the documentation for the AIRA client .