agent_tk/definitions/agent/
resources.rs

1//! Resources of agent
2
3use futures::lock::{Mutex, MutexGuard};
4
5trait ResourceTrait: From<Resource>
6{
7  fn to_resource(self) -> Resource;
8  fn is_resource(r: &Resource) -> bool;
9}
10
11macro_rules! define_resource {
12  ($type:ident) => {
13    impl ResourceTrait for $type
14    {
15      fn to_resource(self) -> Resource
16      {
17        return Resource::$type(self);
18      }
19      fn is_resource(r: &Resource) -> bool
20      {
21        match r
22        {
23          Resource::$type(_) => true,
24          _ => false,
25        }
26      }
27    }
28    impl From<Resource> for $type
29    {
30      fn from(value: Resource) -> Self
31      {
32        match value
33        {
34          Resource::$type(x) => x,
35          _ => panic!("Invalid resource ask for $type, contains {:?}.", value),
36        }
37      }
38    }
39  };
40}
41
42//  ____
43// / ___|  ___ _ __  ___  ___  _ __
44// \___ \ / _ \ '_ \/ __|/ _ \| '__|
45//  ___) |  __/ | | \__ \ (_) | |
46// |____/ \___|_| |_|___/\___/|_|
47
48/// Trait for tagging sensors
49pub trait Sensor {}
50
51//   ____
52//  / ___|__ _ _ __ ___   ___ _ __ __ _
53// | |   / _` | '_ ` _ \ / _ \ '__/ _` |
54// | |__| (_| | | | | | |  __/ | | (_| |
55//  \____\__,_|_| |_| |_|\___|_|  \__,_|
56
57/// Represent a camera sensor
58#[derive(Clone, Debug)]
59pub struct Camera;
60
61impl Sensor for Camera {}
62
63define_resource!(Camera);
64
65//  _     _     _
66// | |   (_) __| | __ _ _ __
67// | |   | |/ _` |/ _` | '__|
68// | |___| | (_| | (_| | |
69// |_____|_|\__,_|\__,_|_|
70
71/// Represent a Lidar sensor
72#[derive(Clone, Debug)]
73pub struct Lidar;
74
75impl Sensor for Lidar {}
76
77define_resource!(Lidar);
78
79//   ____      _
80//  / ___|_ __(_)_ __  _ __   ___ _ __
81// | |  _| '__| | '_ \| '_ \ / _ \ '__|
82// | |_| | |  | | |_) | |_) |  __/ |
83//  \____|_|  |_| .__/| .__/ \___|_|
84//              |_|   |_|
85
86/// Represent a gripper sensor
87#[derive(Clone, Debug)]
88pub struct Gripper;
89
90define_resource!(Gripper);
91
92//  ____
93// |  _ \ _ __ ___  _ __  _ __   ___ _ __
94// | | | | '__/ _ \| '_ \| '_ \ / _ \ '__|
95// | |_| | | | (_) | |_) | |_) |  __/ |
96// |____/|_|  \___/| .__/| .__/ \___|_|
97//                 |_|   |_|
98
99/// Represent a dropper
100#[derive(Clone, Debug)]
101pub struct Dropper;
102
103define_resource!(Dropper);
104
105//  ____             _        _
106// | __ ) _   _  ___| | _____| |_
107// |  _ \| | | |/ __| |/ / _ \ __|
108// | |_) | |_| | (__|   <  __/ |_
109// |____/ \__,_|\___|_|\_\___|\__|
110
111/// Represent a bucket
112#[derive(Clone, Debug)]
113pub struct Bucket
114{
115  #[allow(dead_code)]
116  capacity: i32,
117}
118
119define_resource!(Bucket);
120
121//  _                                    _   _
122// | |    ___   ___ ___  _ __ ___   ___ | |_(_) ___  _ __
123// | |   / _ \ / __/ _ \| '_ ` _ \ / _ \| __| |/ _ \| '_ \
124// | |__| (_) | (_| (_) | | | | | | (_) | |_| | (_) | | | |
125// |_____\___/ \___\___/|_| |_| |_|\___/ \__|_|\___/|_| |_|
126
127/// Represent the locomotion of an agent
128#[derive(Clone, Debug)]
129pub struct Locomotion;
130
131define_resource!(Locomotion);
132
133//  ____
134// |  _ \ ___  ___  ___  _   _ _ __ ___ ___
135// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \
136// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/
137// |_| \_\___||___/\___/ \__,_|_|  \___\___|
138
139#[derive(Clone, Debug)]
140enum Resource
141{
142  Camera(Camera),
143  Lidar(Lidar),
144  Gripper(Gripper),
145  Dropper(Dropper),
146  Bucket(Bucket),
147  Locomotion(Locomotion),
148}
149
150//  ____                                     ___
151// |  _ \ ___  ___  ___  _   _ _ __ ___ ___ / _ \ _   _  ___ _ __ _   _
152// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \ | | | | | |/ _ \ '__| | | |
153// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/ |_| | |_| |  __/ |  | |_| |
154// |_| \_\___||___/\___/ \__,_|_|  \___\___|\__\_\\__,_|\___|_|   \__, |
155//                                                                |___/
156
157/// Query for resources and borrow them
158pub trait ResourceQuery<'a>
159{
160  /// Type of the answer to a query, should be a tuple
161  type Answer;
162  /// Query if the resources exist
163  fn has_resources(&self, rss: &Resources) -> bool;
164  /// Query and borrow the resources
165  fn borrow_resources(&self, rss: &'a Resources) -> Option<Self::Answer>;
166}
167
168impl<'a, T1: ResourceTrait> ResourceQuery<'a> for T1
169{
170  type Answer = ResourceGuard<'a, T1>;
171  fn has_resources(&self, rss: &Resources) -> bool
172  {
173    for a in rss.resources.iter()
174    {
175      if T1::is_resource(&a.res)
176      {
177        return true;
178      }
179    }
180    false
181  }
182  fn borrow_resources(&self, rss: &'a Resources) -> Option<Self::Answer>
183  {
184    for a in rss.resources.iter()
185    {
186      if T1::is_resource(&a.res)
187      {
188        let lock = a.lock.try_lock();
189        if let Some(guard) = lock
190        {
191          return Some(ResourceGuard::<'a, T1> {
192            res: a.res.clone().into(),
193            guard,
194          });
195        }
196      }
197    }
198    None
199  }
200}
201
202//  ___                       ____
203// |_ _|_ __  _ __   ___ _ __|  _ \ ___  ___  ___  _   _ _ __ ___ ___
204//  | || '_ \| '_ \ / _ \ '__| |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \
205//  | || | | | | | |  __/ |  |  _ <  __/\__ \ (_) | |_| | | | (_|  __/
206// |___|_| |_|_| |_|\___|_|  |_| \_\___||___/\___/ \__,_|_|  \___\___|
207//
208
209struct InnerResource
210{
211  res: Resource,
212  lock: Mutex<()>,
213}
214
215impl InnerResource
216{
217  #[allow(dead_code)]
218  fn is_available(&self) -> bool
219  {
220    true
221  }
222}
223
224//  ____                                     ____                     _
225// |  _ \ ___  ___  ___  _   _ _ __ ___ ___ / ___|_   _  __ _ _ __ __| |
226// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \ |  _| | | |/ _` | '__/ _` |
227// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/ |_| | |_| | (_| | | | (_| |
228// |_| \_\___||___/\___/ \__,_|_|  \___\___|\____|\__,_|\__,_|_|  \__,_|
229
230/// Guard a resource, for as long as the object live, the holder has exclusive access to the resource
231#[allow(private_bounds)]
232pub struct ResourceGuard<'a, T: ResourceTrait>
233{
234  #[allow(dead_code)]
235  res: T,
236  #[allow(dead_code)]
237  guard: MutexGuard<'a, ()>,
238}
239
240//  ____
241// |  _ \ ___  ___  ___  _   _ _ __ ___ ___  ___
242// | |_) / _ \/ __|/ _ \| | | | '__/ __/ _ \/ __|
243// |  _ <  __/\__ \ (_) | |_| | | | (_|  __/\__ \
244// |_| \_\___||___/\___/ \__,_|_|  \___\___||___/
245
246/// Resources of an agent
247#[derive(Default)]
248pub struct Resources
249{
250  resources: Vec<InnerResource>,
251}
252
253#[allow(private_bounds)]
254impl Resources
255{
256  /// Add a resource
257  pub fn add_resource(&mut self, r: impl ResourceTrait) -> crate::Result<&mut Resources>
258  {
259    self.resources.push(InnerResource {
260      res: r.to_resource(),
261      lock: Default::default(),
262    });
263    Ok(self)
264  }
265  /// Borrow a resource
266  pub fn borrow_resources<RQ>(&mut self, q: RQ) -> <RQ as ResourceQuery<'_>>::Answer
267  where
268    RQ: for<'a> ResourceQuery<'a>,
269  {
270    loop
271    {
272      if let Some(b) = q.borrow_resources(self)
273      {
274        return b;
275      }
276    }
277  }
278}