mirror of
https://github.com/lopsided98/nix-ros-overlay.git
synced 2025-06-12 02:34:50 +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