agent_tk/definitions/agent/
capabilities.rs

1//! capabilities
2//! ============
3//!
4//! Support for defining capabilities of an agent.
5
6use std::any::TypeId;
7use std::ops::{Deref, DerefMut};
8
9use crate::{Error, Result};
10
11// Structures
12
13/// Trait for capability
14pub trait CapabilityTrait
15{
16  /// Indicate if the capability is unique
17  const IS_UNIQUE: bool;
18  /// Convert to the capability enum
19  fn to_capability(self) -> Capability;
20}
21
22/// Capability enum
23#[derive(Clone)]
24#[allow(missing_docs)]
25pub enum Capability
26{
27  Move(Move),
28  Acquire(Acquire),
29  Grasp(Grasp),
30}
31
32macro_rules! define_capability {
33  ($type:ident, unique) => {
34    impl CapabilityTrait for $type
35    {
36      const IS_UNIQUE: bool = true;
37      fn to_capability(self) -> Capability
38      {
39        return Capability::$type(self);
40      }
41    }
42  };
43  ($type:ident) => {
44    impl CapabilityTrait for $type
45    {
46      const IS_UNIQUE: bool = false;
47      fn to_capability(self) -> Capability
48      {
49        return Capability::$type(self);
50      }
51    }
52  };
53}
54
55/// Move Capability
56#[derive(Copy, Clone)]
57pub struct Move
58{
59  max_velocity: f32,
60}
61
62impl Move
63{
64  /// New move capability with the given max velocity
65  pub fn new(max_velocity: f32) -> Move
66  {
67    Move { max_velocity }
68  }
69  /// Get the max velocity
70  pub fn get_max_velocity(&self) -> f32
71  {
72    self.max_velocity
73  }
74}
75
76define_capability!(Move, unique);
77
78/// Acquire capability, needs a sensor
79
80#[derive(Clone)]
81pub struct Acquire {}
82
83impl Default for Acquire
84{
85  fn default() -> Self
86  {
87    Self::new()
88  }
89}
90
91impl Acquire
92{
93  /// New acquire capability
94  pub fn new() -> Acquire
95  {
96    Acquire {}
97  }
98}
99
100define_capability!(Acquire);
101
102/// Grasp
103#[derive(Clone)]
104pub struct Grasp {}
105
106define_capability!(Grasp);
107
108/// Capabilities of an agent
109#[derive(Default, Clone)]
110pub struct Capabilities(Vec<Capability>);
111
112impl Deref for Capabilities
113{
114  type Target = Vec<Capability>;
115  fn deref(&self) -> &Self::Target
116  {
117    &self.0
118  }
119}
120
121impl DerefMut for Capabilities
122{
123  fn deref_mut(&mut self) -> &mut Self::Target
124  {
125    &mut self.0
126  }
127}
128
129macro_rules! build_capability_getter {
130  ($name:tt, $type:tt) => {
131    /// Get the capability for $name
132    pub fn $name(&self) -> Result<$type>
133    {
134      let res = self.0.iter().find_map(|x| match x
135      {
136        Capability::$type(p) => Some(p),
137        _ => None,
138      });
139      if res.is_none()
140      {
141        Err(Error::UnknownCapability(std::any::type_name::<$type>()))
142      }
143      else
144      {
145        Ok(*res.unwrap())
146      }
147    }
148  };
149}
150
151macro_rules! build_capabilities_getter {
152  ($name:tt, $type:tt) => {
153    /// Get the capability for $name
154    pub fn $name(&self) -> Result<Vec<$type>>
155    {
156      let res = self
157        .0
158        .iter()
159        .filter_map(|x| match x
160        {
161          Capability::$type(p) => Some(p),
162          _ => None,
163        })
164        .map(|x| x.clone())
165        .collect::<Vec<$type>>();
166      if res.is_empty()
167      {
168        Err(Error::UnknownCapability(std::any::type_name::<$type>()))
169      }
170      else
171      {
172        Ok(res)
173      }
174    }
175  };
176}
177
178impl Capabilities
179{
180  build_capability_getter!(get_move, Move);
181  build_capabilities_getter!(get_acquire, Acquire);
182  /// Add a capability to an agent
183  pub fn add_capability<T: CapabilityTrait + 'static>(
184    &mut self,
185    t: T,
186  ) -> crate::Result<&mut Capabilities>
187  {
188    // If the capability is unique, check it wasn't already added
189    if T::IS_UNIQUE
190    {
191      let it = self.0.iter().find(|x| match x
192      {
193        Capability::Move(_) => TypeId::of::<Move>() == TypeId::of::<T>(),
194        Capability::Acquire(_) => TypeId::of::<Acquire>() == TypeId::of::<T>(),
195        Capability::Grasp(_) => TypeId::of::<Grasp>() == TypeId::of::<T>(),
196      });
197      if it.is_none()
198      {
199        self.push(t.to_capability());
200        Ok(self)
201      }
202      else
203      {
204        Err(Error::DuplicateCapability(std::any::type_name::<T>()))
205      }
206    }
207    else
208    {
209      self.push(t.to_capability());
210      Ok(self)
211    }
212  }
213}