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 pub path: PathBuf,
44 pub args: Option<String>,
46 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}