mirror of
https://github.com/lopsided98/nix-ros-overlay.git
synced 2025-06-14 19:48:39 +03:00
Add basic NixOS modules for starting ROS nodes.
This commit is contained in:
parent
f860994164
commit
9a75bf34af
3 changed files with 229 additions and 0 deletions
48
modules/core.nix
Normal file
48
modules/core.nix
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
rosCfg = config.services.ros;
|
||||||
|
cfg = rosCfg.core;
|
||||||
|
in {
|
||||||
|
# Interface
|
||||||
|
|
||||||
|
options.services.ros.core = {
|
||||||
|
enable = mkEnableOption "roscore";
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.ints.unsigned;
|
||||||
|
default = 11311;
|
||||||
|
description = ''
|
||||||
|
Port the ROS master will bind to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.roscore = {
|
||||||
|
description = "ROS core";
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "exec";
|
||||||
|
ExecStart = let
|
||||||
|
env = with rosCfg.pkgs; buildEnv {
|
||||||
|
name = "roscore-env";
|
||||||
|
paths = [ roslaunch ];
|
||||||
|
};
|
||||||
|
in "${env}/bin/roscore -p ${toString cfg.port}";
|
||||||
|
User = "ros";
|
||||||
|
Group = "ros";
|
||||||
|
StateDirectory = "ros";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
environment = {
|
||||||
|
ROS_HOSTNAME = rosCfg.hostname;
|
||||||
|
ROS_MASTER_URI = rosCfg.masterUri;
|
||||||
|
ROS_HOME = "/var/lib/ros";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
6
modules/default.nix
Normal file
6
modules/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{ ... }: {
|
||||||
|
imports = [
|
||||||
|
./ros.nix
|
||||||
|
./core.nix
|
||||||
|
];
|
||||||
|
}
|
175
modules/ros.nix
Normal file
175
modules/ros.nix
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.ros;
|
||||||
|
|
||||||
|
pkgsType = mkOptionType {
|
||||||
|
name = "ros-packages";
|
||||||
|
description = "ROS package set";
|
||||||
|
check = p: isAttrs p && hasAttr "roslaunch" p;
|
||||||
|
};
|
||||||
|
overlayType = mkOptionType {
|
||||||
|
name = "ros-overlay";
|
||||||
|
description = "ROS package set overlay";
|
||||||
|
check = isFunction;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
# Interface
|
||||||
|
|
||||||
|
options.services.ros = {
|
||||||
|
enable = mkEnableOption "Robot Operating System";
|
||||||
|
|
||||||
|
distro = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "noetic";
|
||||||
|
description = ''
|
||||||
|
ROS distro to use. Must be defined in distros/default.nix.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
pkgs = mkOption {
|
||||||
|
type = pkgsType;
|
||||||
|
description = ''
|
||||||
|
ROS package set for the selected distro.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
overlays = mkOption {
|
||||||
|
type = types.listOf overlayType;
|
||||||
|
default = [];
|
||||||
|
apply = foldr composeExtensions (_: _: {});
|
||||||
|
description = ''
|
||||||
|
Set of package overlays to apply to ROS package set for the configured
|
||||||
|
distro.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hostname = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "localhost";
|
||||||
|
description = ''
|
||||||
|
Value of the ROS_HOSTNAME environment variable. Defaults to
|
||||||
|
<option>networking.hostName</option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
masterUri = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "https://localhost:11311/";
|
||||||
|
description = ''
|
||||||
|
Value of the ROS_MASTER_URI environment variable.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
package = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
ROS package name containing this node. This is the ROS name for
|
||||||
|
the package, rather than the attribute name, meaning it uses
|
||||||
|
underscores rather than dashes.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
node = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Name of the node to launch.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
args = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Arguments to pass to the node.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
paths = mkOption {
|
||||||
|
type = types.listOf types.package;
|
||||||
|
description = ''
|
||||||
|
Additional paths to add to the environment of this node. The
|
||||||
|
<option>package</option> option will be turned into an attribute
|
||||||
|
name and automatically added to this option if valid.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
env = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
description = ''
|
||||||
|
Environment created with the ROS specific buildEnv function for
|
||||||
|
this node.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# Try to convert package name to attribute and add it to the
|
||||||
|
# environment
|
||||||
|
paths = [ cfg.pkgs.rosbash ] ++ (let
|
||||||
|
packageAttr = replaceStrings ["_"] ["-"] config.package;
|
||||||
|
in optional (hasAttr packageAttr cfg.pkgs) cfg.pkgs."${packageAttr}");
|
||||||
|
|
||||||
|
env = mkDefault (cfg.pkgs.buildEnv {
|
||||||
|
name = "ros-node-${name}-env";
|
||||||
|
inherit (config) paths;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
ROS nodes to launch at boot as systemd services.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# FIXME: mkAfter is used to make sure the Python overlay is applied. That
|
||||||
|
# means all other user configured Python overlays are ignored. This needs a
|
||||||
|
# fix in nixpkgs: https://github.com/NixOS/nixpkgs/issues/44426
|
||||||
|
nixpkgs.overlays = mkAfter (singleton (import ../overlay.nix));
|
||||||
|
|
||||||
|
services.ros = {
|
||||||
|
pkgs = mkDefault (pkgs.rosPackages."${cfg.distro}".extend cfg.overlays);
|
||||||
|
|
||||||
|
hostname = mkDefault config.networking.hostName;
|
||||||
|
masterUri = mkDefault "http://${cfg.hostname}:11311/";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.variables = {
|
||||||
|
ROS_HOSTNAME = cfg.hostname;
|
||||||
|
ROS_MASTER_URI = cfg.masterUri;
|
||||||
|
};
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users.ros = {
|
||||||
|
group = "ros";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
groups.ros = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services = mapAttrs' (name: config: nameValuePair name {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "exec";
|
||||||
|
StateDirectory = "ros";
|
||||||
|
User = "ros";
|
||||||
|
Group = "ros";
|
||||||
|
ExecStart = escapeShellArgs ([ "${config.env}/bin/rosrun" config.package config.node ] ++ config.args);
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
environment = {
|
||||||
|
ROS_HOSTNAME = cfg.hostname;
|
||||||
|
ROS_MASTER_URI = cfg.masterUri;
|
||||||
|
ROS_HOME = "/var/lib/ros";
|
||||||
|
};
|
||||||
|
}) cfg.nodes;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue