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}