openrr_apps/
robot_teleop_config.rs

1use std::{
2    collections::HashMap,
3    path::{Path, PathBuf},
4};
5
6use arci_gamepad_gilrs::GilGamepadConfig;
7#[cfg(feature = "ros")]
8use arci_ros::RosJoyGamepadConfig;
9use openrr_client::resolve_relative_path;
10use openrr_teleop::ControlModesConfig;
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13
14use crate::{resolve_plugin_path, Error};
15
16#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
17#[serde(rename_all = "kebab-case")]
18pub enum BuiltinGamepad {
19    Gilrs,
20    Keyboard,
21    RosJoyGamepad,
22}
23
24#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
25#[serde(untagged)]
26pub enum GamepadKind {
27    Builtin(BuiltinGamepad),
28    Plugin(String),
29}
30
31impl Default for GamepadKind {
32    fn default() -> Self {
33        Self::Builtin(BuiltinGamepad::Gilrs)
34    }
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
38#[serde(deny_unknown_fields)]
39pub struct TeleopPluginConfig {
40    /// Path to the plugin. If no extension is specified, the default extension
41    /// for `cdylib` on the current OS will be selected.
42    /// (linux: `.so`, macos: `.dylib`, windows: `.dll`)
43    pub path: PathBuf,
44    /// Arguments passed when creating this instance.
45    pub args: Option<String>,
46    /// Pass the contents of the specified file as an argument.
47    pub args_from_path: Option<PathBuf>,
48}
49
50#[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)]
51#[serde(deny_unknown_fields)]
52pub struct RobotTeleopConfig {
53    pub robot_config_path: Option<String>,
54    robot_config_full_path: Option<PathBuf>,
55    #[serde(default)]
56    pub initial_mode: String,
57    #[serde(default)]
58    pub gamepad: GamepadKind,
59    pub control_modes_config: ControlModesConfig,
60    #[serde(default)]
61    pub gil_gamepad_config: GilGamepadConfig,
62    #[cfg(feature = "ros")]
63    #[serde(default)]
64    pub ros_joy_gamepad_config: RosJoyGamepadConfig,
65    #[serde(default)]
66    pub plugins: HashMap<String, TeleopPluginConfig>,
67}
68
69impl RobotTeleopConfig {
70    pub fn new<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
71        Self::from_str(
72            &std::fs::read_to_string(&path)
73                .map_err(|e| Error::NoFile(path.as_ref().to_owned(), e))?,
74            path,
75        )
76    }
77
78    pub fn from_str<P: AsRef<Path>>(s: &str, path: P) -> Result<Self, Error> {
79        let path = path.as_ref();
80        let mut config: RobotTeleopConfig =
81            toml::from_str(s).map_err(|e| Error::TomlParseFailure(path.to_owned(), e))?;
82        config.robot_config_full_path = config
83            .robot_config_path
84            .as_ref()
85            .map(|robot_config_path| resolve_relative_path(path, robot_config_path))
86            .transpose()?;
87        for plugin_config in config.plugins.values_mut() {
88            resolve_plugin_path(&mut plugin_config.path, path)?;
89            if let Some(args_path) = plugin_config.args_from_path.take() {
90                plugin_config.args_from_path =
91                    Some(openrr_client::resolve_relative_path(path, args_path)?);
92            }
93        }
94        Ok(config)
95    }
96
97    pub fn robot_config_full_path(&self) -> &Option<PathBuf> {
98        &self.robot_config_full_path
99    }
100}