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