1#![allow(
2 clippy::missing_errors_doc,
3 clippy::use_self,
4 clippy::module_name_repetitions,
5 clippy::must_use_candidate,
6 clippy::return_self_not_must_use,
7 clippy::module_inception
8)]
9#![warn(
10 clippy::unwrap_used,
11 clippy::panic,
12 clippy::todo,
13 clippy::unimplemented,
14 missing_docs,
15 clippy::missing_panics_doc
16)]
17
18pub mod domain;
22pub mod error;
24pub mod lexer;
26pub mod plan;
28pub mod problem;
30pub mod tokens;
32
33#[cfg(test)]
34mod tests {
35 use crate::domain::domain::Domain;
36 use crate::domain::durative_action::DurativeAction;
37 use crate::domain::expression::{BinaryOp, DurationInstant, Expression};
38 use crate::domain::requirement::Requirement;
39 use crate::domain::typed_parameter::TypedParameter;
40 use crate::domain::typed_predicate::TypedPredicate;
41 use crate::domain::typedef::TypeDef;
42 use crate::domain::{self};
43 use crate::plan;
44 use crate::plan::action::Action;
45 use crate::plan::plan::Plan;
46 use crate::plan::simple_action::SimpleAction;
47 use crate::problem::{Object, Problem};
48
49 #[test]
50 fn test_domain_to_pddl() {
51 std::env::set_var("RUST_LOG", "debug");
52 let _ = pretty_env_logger::try_init();
53 let domain_example = include_str!("../tests/domain.pddl");
54 let domain = Domain::parse(domain_example.into()).expect("Failed to parse domain");
55 eprintln!("{}", domain.to_pddl());
56 let redomain = Domain::parse(domain.to_pddl().as_str().into()).expect("Failed to parse domain again");
57 assert_eq!(domain, redomain);
58 }
59
60 #[test]
61 fn test_problem_to_pddl() {
62 std::env::set_var("RUST_LOG", "debug");
63 let _ = pretty_env_logger::try_init();
64 let problem_example = include_str!("../tests/problem.pddl");
65 let problem = Problem::parse(problem_example.into()).expect("Failed to parse problem");
66 eprintln!("{}", problem.to_pddl());
67 let reproblem = Problem::parse(problem.to_pddl().as_str().into()).expect("Failed to parse problem again");
68 assert_eq!(problem, reproblem);
69 }
70
71 #[test]
72 fn test_plan() {
73 std::env::set_var("RUST_LOG", "debug");
74 let _ = pretty_env_logger::try_init();
75 let plan_example = include_str!("../tests/plan.txt");
76 assert_eq!(
77 Plan::parse(plan_example.into()).expect("Failed to parse plan"),
78 Plan(vec![
79 Action::Simple(SimpleAction {
80 name: "pick-up".into(),
81 parameters: vec!["arm".into(), "cupcake".into(), "table".into()]
82 }),
83 Action::Simple(SimpleAction {
84 name: "move".into(),
85 parameters: vec!["arm".into(), "table".into(), "plate".into()]
86 }),
87 Action::Simple(SimpleAction {
88 name: "drop".into(),
89 parameters: vec!["arm".into(), "cupcake".into(), "plate".into()]
90 }),
91 ])
92 );
93 }
94
95 #[test]
96 fn test_problem() {
97 std::env::set_var("RUST_LOG", "debug");
98 let _ = pretty_env_logger::try_init();
99 let problem_example = include_str!("../tests/problem.pddl");
100 assert_eq!(
101 Problem::parse(problem_example.into()).expect("Failed to parse problem"),
102 Problem {
103 name: "letseat-simple".into(),
104 domain: "letseat".into(),
105 objects: vec![
106 Object {
107 name: "arm".into(),
108 type_: "robot".into(),
109 },
110 Object {
111 name: "cupcake".into(),
112 type_: "cupcake".into(),
113 },
114 Object {
115 name: "table".into(),
116 type_: "location".into(),
117 },
118 Object {
119 name: "plate".into(),
120 type_: "location".into(),
121 },
122 ],
123 init: vec![
124 Expression::Atom {
125 name: "on".into(),
126 parameters: vec!["arm".into(), "table".into(),]
127 },
128 Expression::Atom {
129 name: "on".into(),
130 parameters: vec!["cupcake".into(), "table".into(),]
131 },
132 Expression::Atom {
133 name: "arm-empty".into(),
134 parameters: vec![]
135 },
136 Expression::Atom {
137 name: "path".into(),
138 parameters: vec!["table".into(), "plate".into(),]
139 },
140 ],
141 goal: Expression::Atom {
142 name: "on".into(),
143 parameters: vec!["cupcake".into(), "plate".into()]
144 }
145 }
146 );
147 }
148
149 #[test]
150 #[allow(clippy::too_many_lines)]
151 fn test_domain() {
152 std::env::set_var("RUST_LOG", "debug");
153 let _ = pretty_env_logger::try_init();
154 let domain_example = include_str!("../tests/domain.pddl");
155 assert_eq!(
156 Domain::parse(domain_example.into()).expect("Failed to parse domain"),
157 Domain {
158 name: "letseat".into(),
159 requirements: vec![Requirement::Typing],
160 types: vec![
161 TypeDef {
162 name: "location".into(),
163 parent: Some("object".into()),
164 },
165 TypeDef {
166 name: "locatable".into(),
167 parent: Some("object".into()),
168 },
169 TypeDef {
170 name: "bot".into(),
171 parent: Some("locatable".into()),
172 },
173 TypeDef {
174 name: "cupcake".into(),
175 parent: Some("locatable".into()),
176 },
177 TypeDef {
178 name: "robot".into(),
179 parent: Some("bot".into()),
180 },
181 ],
182 constants: vec![],
183 predicates: vec![
184 TypedPredicate {
185 name: "on".into(),
186 parameters: vec![
187 TypedParameter {
188 name: "?obj".into(),
189 type_: "locatable".into(),
190 },
191 TypedParameter {
192 name: "?loc".into(),
193 type_: "location".into(),
194 },
195 ],
196 },
197 TypedPredicate {
198 name: "holding".into(),
199 parameters: vec![
200 TypedParameter {
201 name: "?arm".into(),
202 type_: "locatable".into(),
203 },
204 TypedParameter {
205 name: "?cupcake".into(),
206 type_: "locatable".into(),
207 },
208 ],
209 },
210 TypedPredicate {
211 name: "arm-empty".into(),
212 parameters: vec![],
213 },
214 TypedPredicate {
215 name: "path".into(),
216 parameters: vec![
217 TypedParameter {
218 name: "?location1".into(),
219 type_: "location".into(),
220 },
221 TypedParameter {
222 name: "?location2".into(),
223 type_: "location".into(),
224 },
225 ],
226 },
227 ],
228 functions: vec![],
229 actions: vec![
230 domain::action::Action::Simple(domain::simple_action::SimpleAction {
231 name: "pick-up".into(),
232 parameters: vec![
233 TypedParameter {
234 name: "?arm".into(),
235 type_: "bot".into(),
236 },
237 TypedParameter {
238 name: "?cupcake".into(),
239 type_: "locatable".into(),
240 },
241 TypedParameter {
242 name: "?loc".into(),
243 type_: "location".into(),
244 },
245 ],
246 precondition: Some(Expression::And(vec![
247 Expression::Atom {
248 name: "on".into(),
249 parameters: vec!["?arm".into(), "?loc".into()],
250 },
251 Expression::Atom {
252 name: "on".into(),
253 parameters: vec!["?cupcake".into(), "?loc".into(),],
254 },
255 Expression::Atom {
256 name: "arm-empty".into(),
257 parameters: vec![],
258 },
259 ])),
260 effect: Expression::And(vec![
261 Expression::Not(Box::new(Expression::Atom {
262 name: "on".into(),
263 parameters: vec!["?cupcake".into(), "?loc".into()],
264 })),
265 Expression::Atom {
266 name: "holding".into(),
267 parameters: vec!["?arm".into(), "?cupcake".into()],
268 },
269 Expression::Not(Box::new(Expression::Atom {
270 name: "arm-empty".into(),
271 parameters: vec![],
272 })),
273 ])
274 }),
275 domain::action::Action::Simple(domain::simple_action::SimpleAction {
276 name: "drop".into(),
277 parameters: vec![
278 TypedParameter {
279 name: "?arm".into(),
280 type_: "bot".into(),
281 },
282 TypedParameter {
283 name: "?cupcake".into(),
284 type_: "locatable".into(),
285 },
286 TypedParameter {
287 name: "?loc".into(),
288 type_: "location".into(),
289 },
290 ],
291 precondition: Some(Expression::And(vec![
292 Expression::Atom {
293 name: "on".into(),
294 parameters: vec!["?arm".into(), "?loc".into(),],
295 },
296 Expression::Atom {
297 name: "holding".into(),
298 parameters: vec!["?arm".into(), "?cupcake".into(),],
299 },
300 ])),
301 effect: Expression::And(vec![
302 Expression::Atom {
303 name: "on".into(),
304 parameters: vec!["?cupcake".into(), "?loc".into(),],
305 },
306 Expression::Atom {
307 name: "arm-empty".into(),
308 parameters: vec![],
309 },
310 Expression::Not(Box::new(Expression::Atom {
311 name: "holding".into(),
312 parameters: vec!["?arm".into(), "?cupcake".into(),],
313 })),
314 ])
315 }),
316 domain::action::Action::Simple(domain::simple_action::SimpleAction {
317 name: "move".into(),
318 parameters: vec![
319 TypedParameter {
320 name: "?arm".into(),
321 type_: "bot".into(),
322 },
323 TypedParameter {
324 name: "?from".into(),
325 type_: "location".into(),
326 },
327 TypedParameter {
328 name: "?to".into(),
329 type_: "location".into(),
330 },
331 ],
332 precondition: Some(Expression::And(vec![
333 Expression::Atom {
334 name: "on".into(),
335 parameters: vec!["?arm".into(), "?from".into(),],
336 },
337 Expression::Atom {
338 name: "path".into(),
339 parameters: vec!["?from".into(), "?to".into(),],
340 },
341 ])),
342 effect: Expression::And(vec![
343 Expression::Not(Box::new(Expression::Atom {
344 name: "on".into(),
345 parameters: vec!["?arm".into(), "?from".into(),],
346 })),
347 Expression::Atom {
348 name: "on".into(),
349 parameters: vec!["?arm".into(), "?to".into(),],
350 },
351 ])
352 })
353 ],
354 }
355 );
356 }
357
358 #[test]
359 #[allow(clippy::too_many_lines)]
360 fn test_durative_domain() {
361 std::env::set_var("RUST_LOG", "debug");
362 let _ = pretty_env_logger::try_init();
363 let durative_actions_domain = include_str!("../tests/durative-actions-domain.pddl");
364 assert_eq!(
365 Domain::parse(durative_actions_domain.into()).expect("Failed to parse domain"),
366 Domain {
367 name: "collaborative-cloth-piling".into(),
368 requirements: vec![
369 Requirement::Strips,
370 Requirement::Typing,
371 Requirement::DurativeActions,
372 Requirement::NumericFluents,
373 ],
374 types: vec![
375 TypeDef {
376 name: "robot".into(),
377 parent: Some("agent".into()),
378 },
379 TypeDef {
380 name: "human".into(),
381 parent: Some("agent".into()),
382 },
383 TypeDef {
384 name: "garment".into(),
385 parent: Some("physical-object".into()),
386 },
387 TypeDef {
388 name: "pile".into(),
389 parent: Some("physical-object".into()),
390 },
391 TypeDef {
392 name: "agent".into(),
393 parent: Some("physical-object".into()),
394 },
395 TypeDef {
396 name: "garment-type".into(),
397 parent: Some("concept".into()),
398 },
399 TypeDef {
400 name: "concept".into(),
401 parent: Some("social-object".into()),
402 },
403 TypeDef {
404 name: "social-object".into(),
405 parent: Some("object".into()),
406 },
407 TypeDef {
408 name: "physical-object".into(),
409 parent: Some("object".into()),
410 },
411 TypeDef {
412 name: "object".into(),
413 parent: Some("entity".into()),
414 },
415 TypeDef {
416 name: "entity".into(),
417 parent: None,
418 },
419 ],
420 predicates: vec![
421 TypedPredicate {
422 name: "grasped-by".into(),
423 parameters: vec![
424 TypedParameter {
425 name: "?o".into(),
426 type_: "object".into(),
427 },
428 TypedParameter {
429 name: "?a".into(),
430 type_: "agent".into(),
431 },
432 ],
433 },
434 TypedPredicate {
435 name: "graspable".into(),
436 parameters: vec![TypedParameter {
437 name: "?o".into(),
438 type_: "object".into(),
439 },],
440 },
441 TypedPredicate {
442 name: "free-to-manipulate".into(),
443 parameters: vec![TypedParameter {
444 name: "?a".into(),
445 type_: "agent".into(),
446 },],
447 },
448 TypedPredicate {
449 name: "on-pile".into(),
450 parameters: vec![
451 TypedParameter {
452 name: "?g".into(),
453 type_: "garment".into(),
454 },
455 TypedParameter {
456 name: "?p".into(),
457 type_: "pile".into(),
458 },
459 ],
460 },
461 TypedPredicate {
462 name: "piled".into(),
463 parameters: vec![TypedParameter {
464 name: "?g".into(),
465 type_: "garment".into(),
466 },],
467 },
468 TypedPredicate {
469 name: "supported".into(),
470 parameters: vec![TypedParameter {
471 name: "?g".into(),
472 type_: "garment".into(),
473 },],
474 },
475 TypedPredicate {
476 name: "lifted".into(),
477 parameters: vec![TypedParameter {
478 name: "?g".into(),
479 type_: "garment".into(),
480 },],
481 },
482 TypedPredicate {
483 name: "folded".into(),
484 parameters: vec![TypedParameter {
485 name: "?g".into(),
486 type_: "garment".into(),
487 },],
488 },
489 TypedPredicate {
490 name: "unfolded".into(),
491 parameters: vec![TypedParameter {
492 name: "?g".into(),
493 type_: "garment".into(),
494 },],
495 },
496 ],
497 constants: vec![],
498 functions: vec![
499 TypedPredicate {
500 name: "grasp-time".into(),
501 parameters: vec![TypedParameter {
502 name: "?a".into(),
503 type_: "agent".into(),
504 },],
505 },
506 TypedPredicate {
507 name: "current-number-of-garments-on-pile".into(),
508 parameters: vec![TypedParameter {
509 name: "?p".into(),
510 type_: "pile".into(),
511 },],
512 },
513 TypedPredicate {
514 name: "target-number-of-garments-on-pile".into(),
515 parameters: vec![TypedParameter {
516 name: "?p".into(),
517 type_: "pile".into(),
518 },],
519 },
520 ],
521 actions: vec![
522 domain::action::Action::Durative(DurativeAction {
523 name: "grasp-folded-garment".into(),
524 parameters: vec![
525 TypedParameter {
526 name: "?g".into(),
527 type_: "garment".into(),
528 },
529 TypedParameter {
530 name: "?a".into(),
531 type_: "agent".into(),
532 },
533 ],
534 duration: Expression::BinaryOp(
535 BinaryOp::Equal,
536 Box::new(Expression::Atom {
537 name: "?duration".into(),
538 parameters: vec![]
539 }),
540 Box::new(Expression::Atom {
541 name: "grasp-time".into(),
542 parameters: vec!["?a".into()],
543 })
544 ),
545 condition: Some(Expression::And(vec![
546 Expression::Duration(
547 DurationInstant::Start,
548 Box::new(Expression::Atom {
549 name: "free-to-manipulate".into(),
550 parameters: vec!["?a".into()],
551 })
552 ),
553 Expression::Duration(
554 DurationInstant::Start,
555 Box::new(Expression::Atom {
556 name: "folded".into(),
557 parameters: vec!["?g".into()],
558 })
559 ),
560 Expression::Duration(
561 DurationInstant::Start,
562 Box::new(Expression::Atom {
563 name: "graspable".into(),
564 parameters: vec!["?g".into()],
565 })
566 ),
567 ])),
568 effect: Expression::And(vec![
569 Expression::Duration(
570 DurationInstant::Start,
571 Box::new(Expression::Not(Box::new(Expression::Atom {
572 name: "free-to-manipulate".into(),
573 parameters: vec!["?a".into()],
574 })))
575 ),
576 Expression::Duration(
577 DurationInstant::Start,
578 Box::new(Expression::Not(Box::new(Expression::Atom {
579 name: "graspable".into(),
580 parameters: vec!["?g".into()],
581 })))
582 ),
583 Expression::Duration(
584 DurationInstant::End,
585 Box::new(Expression::Atom {
586 name: "grasped-by".into(),
587 parameters: vec!["?g".into(), "?a".into()],
588 })
589 ),
590 ])
591 }),
592 domain::action::Action::Durative(DurativeAction {
593 name: "grasp-unfolded-garment".into(),
594 parameters: vec![
595 TypedParameter {
596 name: "?g".into(),
597 type_: "garment".into(),
598 },
599 TypedParameter {
600 name: "?h".into(),
601 type_: "human".into(),
602 },
603 ],
604 duration: Expression::BinaryOp(
605 BinaryOp::Equal,
606 Box::new(Expression::Atom {
607 name: "?duration".into(),
608 parameters: vec![]
609 }),
610 Box::new(Expression::Number(100))
611 ),
612 condition: Some(Expression::And(vec![
613 Expression::Duration(
614 DurationInstant::Start,
615 Box::new(Expression::Atom {
616 name: "free-to-manipulate".into(),
617 parameters: vec!["?h".into()],
618 })
619 ),
620 Expression::Duration(
621 DurationInstant::Start,
622 Box::new(Expression::Atom {
623 name: "unfolded".into(),
624 parameters: vec!["?g".into()],
625 })
626 ),
627 Expression::Duration(
628 DurationInstant::Start,
629 Box::new(Expression::Atom {
630 name: "graspable".into(),
631 parameters: vec!["?g".into()],
632 })
633 ),
634 ])),
635 effect: Expression::And(vec![
636 Expression::Duration(
637 DurationInstant::Start,
638 Box::new(Expression::Not(Box::new(Expression::Atom {
639 name: "free-to-manipulate".into(),
640 parameters: vec!["?h".into()],
641 })))
642 ),
643 Expression::Duration(
644 DurationInstant::Start,
645 Box::new(Expression::Not(Box::new(Expression::Atom {
646 name: "graspable".into(),
647 parameters: vec!["?g".into()],
648 })))
649 ),
650 Expression::Duration(
651 DurationInstant::End,
652 Box::new(Expression::Atom {
653 name: "grasped-by".into(),
654 parameters: vec!["?g".into(), "?h".into()],
655 })
656 ),
657 ])
658 }),
659 domain::action::Action::Durative(DurativeAction {
660 name: "lift".into(),
661 parameters: vec![
662 TypedParameter {
663 name: "?g".into(),
664 type_: "garment".into(),
665 },
666 TypedParameter {
667 name: "?a".into(),
668 type_: "agent".into(),
669 },
670 ],
671 duration: Expression::BinaryOp(
672 BinaryOp::Equal,
673 Box::new(Expression::Atom {
674 name: "?duration".into(),
675 parameters: vec![]
676 }),
677 Box::new(Expression::Number(100))
678 ),
679 condition: Some(Expression::And(vec![
680 Expression::Duration(
681 DurationInstant::Start,
682 Box::new(Expression::Atom {
683 name: "grasped-by".into(),
684 parameters: vec!["?g".into(), "?a".into()],
685 })
686 ),
687 Expression::Duration(
688 DurationInstant::Start,
689 Box::new(Expression::Atom {
690 name: "supported".into(),
691 parameters: vec!["?g".into()],
692 })
693 ),
694 ])),
695 effect: Expression::And(vec![
696 Expression::Duration(
697 DurationInstant::End,
698 Box::new(Expression::Not(Box::new(Expression::Atom {
699 name: "supported".into(),
700 parameters: vec!["?g".into()],
701 })))
702 ),
703 Expression::Duration(
704 DurationInstant::End,
705 Box::new(Expression::Atom {
706 name: "lifted".into(),
707 parameters: vec!["?g".into()],
708 })
709 ),
710 ])
711 }),
712 domain::action::Action::Durative(DurativeAction {
713 name: "pile-garment".into(),
714 parameters: vec![
715 TypedParameter {
716 name: "?g".into(),
717 type_: "garment".into(),
718 },
719 TypedParameter {
720 name: "?p".into(),
721 type_: "pile".into(),
722 },
723 TypedParameter {
724 name: "?t".into(),
725 type_: "garment-type".into(),
726 },
727 TypedParameter {
728 name: "?a".into(),
729 type_: "agent".into(),
730 },
731 ],
732 duration: Expression::BinaryOp(
733 BinaryOp::Equal,
734 Box::new(Expression::Atom {
735 name: "?duration".into(),
736 parameters: vec![]
737 }),
738 Box::new(Expression::Atom {
739 name: "grasp-time".into(),
740 parameters: vec!["?a".into()],
741 })
742 ),
743 condition: Some(Expression::And(vec![
744 Expression::Duration(
745 DurationInstant::Start,
746 Box::new(Expression::Atom {
747 name: "grasped-by".into(),
748 parameters: vec!["?g".into(), "?a".into()],
749 })
750 ),
751 Expression::Duration(
752 DurationInstant::Start,
753 Box::new(Expression::Atom {
754 name: "lifted".into(),
755 parameters: vec!["?g".into()],
756 })
757 ),
758 Expression::Duration(
759 DurationInstant::Start,
760 Box::new(Expression::Atom {
761 name: "folded".into(),
762 parameters: vec!["?g".into()],
763 })
764 ),
765 ])),
766 effect: Expression::And(vec![
767 Expression::Duration(
768 DurationInstant::Start,
769 Box::new(Expression::Not(Box::new(Expression::Atom {
770 name: "grasped-by".into(),
771 parameters: vec!["?g".into(), "?a".into()],
772 })))
773 ),
774 Expression::Duration(
775 DurationInstant::End,
776 Box::new(Expression::Atom {
777 name: "graspable".into(),
778 parameters: vec!["?g".into()],
779 })
780 ),
781 Expression::Duration(
782 DurationInstant::End,
783 Box::new(Expression::Atom {
784 name: "free-to-manipulate".into(),
785 parameters: vec!["?a".into()],
786 })
787 ),
788 Expression::Duration(
789 DurationInstant::End,
790 Box::new(Expression::Atom {
791 name: "piled".into(),
792 parameters: vec!["?g".into()],
793 })
794 ),
795 Expression::Duration(
796 DurationInstant::End,
797 Box::new(Expression::Atom {
798 name: "on-pile".into(),
799 parameters: vec!["?g".into(), "?p".into()],
800 })
801 ),
802 Expression::Duration(
803 DurationInstant::End,
804 Box::new(Expression::Increase(
805 Box::new(Expression::Atom {
806 name: "current-number-of-garments-on-pile".into(),
807 parameters: vec!["?p".into()],
808 }),
809 Box::new(Expression::Number(1))
810 ))
811 ),
812 ])
813 }),
814 domain::action::Action::Durative(DurativeAction {
815 name: "fold-garment".into(),
816 parameters: vec![
817 TypedParameter {
818 name: "?g".into(),
819 type_: "garment".into(),
820 },
821 TypedParameter {
822 name: "?h".into(),
823 type_: "human".into(),
824 },
825 ],
826 duration: Expression::BinaryOp(
827 BinaryOp::Equal,
828 Box::new(Expression::Atom {
829 name: "?duration".into(),
830 parameters: vec![]
831 }),
832 Box::new(Expression::Number(100))
833 ),
834 condition: Some(Expression::And(vec![
835 Expression::Duration(
836 DurationInstant::Start,
837 Box::new(Expression::Atom {
838 name: "unfolded".into(),
839 parameters: vec!["?g".into()],
840 })
841 ),
842 Expression::Duration(
843 DurationInstant::Start,
844 Box::new(Expression::Atom {
845 name: "lifted".into(),
846 parameters: vec!["?g".into()],
847 })
848 ),
849 Expression::Duration(
850 DurationInstant::Start,
851 Box::new(Expression::Atom {
852 name: "grasped-by".into(),
853 parameters: vec!["?g".into(), "?h".into()],
854 })
855 ),
856 ])),
857 effect: Expression::And(vec![
858 Expression::Duration(
859 DurationInstant::End,
860 Box::new(Expression::Atom {
861 name: "free-to-manipulate".into(),
862 parameters: vec!["?h".into()],
863 })
864 ),
865 Expression::Duration(
866 DurationInstant::End,
867 Box::new(Expression::Not(Box::new(Expression::Atom {
868 name: "unfolded".into(),
869 parameters: vec!["?g".into()],
870 })))
871 ),
872 Expression::Duration(
873 DurationInstant::End,
874 Box::new(Expression::Not(Box::new(Expression::Atom {
875 name: "lifted".into(),
876 parameters: vec!["?g".into()],
877 })))
878 ),
879 Expression::Duration(
880 DurationInstant::End,
881 Box::new(Expression::Not(Box::new(Expression::Atom {
882 name: "grasped-by".into(),
883 parameters: vec!["?g".into(), "?h".into()],
884 })))
885 ),
886 Expression::Duration(
887 DurationInstant::End,
888 Box::new(Expression::Atom {
889 name: "graspable".into(),
890 parameters: vec!["?g".into()],
891 })
892 ),
893 Expression::Duration(
894 DurationInstant::End,
895 Box::new(Expression::Atom {
896 name: "folded".into(),
897 parameters: vec!["?g".into()],
898 })
899 ),
900 Expression::Duration(
901 DurationInstant::End,
902 Box::new(Expression::Atom {
903 name: "supported".into(),
904 parameters: vec!["?g".into()],
905 })
906 ),
907 ])
908 }),
909 domain::action::Action::Durative(DurativeAction {
910 name: "grasp-pile-of-garments".into(),
911 parameters: vec![
912 TypedParameter {
913 name: "?p".into(),
914 type_: "pile".into(),
915 },
916 TypedParameter {
917 name: "?h".into(),
918 type_: "human".into(),
919 },
920 ],
921 duration: Expression::BinaryOp(
922 BinaryOp::Equal,
923 Box::new(Expression::Atom {
924 name: "?duration".into(),
925 parameters: vec![]
926 }),
927 Box::new(Expression::Number(100))
928 ),
929 condition: Some(Expression::And(vec![
930 Expression::Duration(
931 DurationInstant::Start,
932 Box::new(Expression::Atom {
933 name: "free-to-manipulate".into(),
934 parameters: vec!["?h".into()],
935 })
936 ),
937 Expression::Duration(
938 DurationInstant::Start,
939 Box::new(Expression::BinaryOp(
940 BinaryOp::Equal,
941 Box::new(Expression::Atom {
942 name: "current-number-of-garments-on-pile".into(),
943 parameters: vec!["?p".into()],
944 }),
945 Box::new(Expression::Atom {
946 name: "target-number-of-garments-on-pile".into(),
947 parameters: vec!["?p".into()],
948 })
949 ))
950 ),
951 Expression::Duration(
952 DurationInstant::Start,
953 Box::new(Expression::Atom {
954 name: "graspable".into(),
955 parameters: vec!["?p".into()],
956 })
957 ),
958 ])),
959 effect: Expression::And(vec![
960 Expression::Duration(
961 DurationInstant::Start,
962 Box::new(Expression::Not(Box::new(Expression::Atom {
963 name: "free-to-manipulate".into(),
964 parameters: vec!["?h".into()],
965 })))
966 ),
967 Expression::Duration(
968 DurationInstant::Start,
969 Box::new(Expression::Not(Box::new(Expression::Atom {
970 name: "graspable".into(),
971 parameters: vec!["?p".into()],
972 })))
973 ),
974 Expression::Duration(
975 DurationInstant::End,
976 Box::new(Expression::Atom {
977 name: "grasped-by".into(),
978 parameters: vec!["?p".into(), "?h".into()],
979 })
980 ),
981 ])
982 }),
983 ]
984 }
985 );
986 }
987
988 #[test]
989 #[allow(clippy::too_many_lines)]
990 fn test_durative_plan() {
991 std::env::set_var("RUST_LOG", "debug");
992 let _ = pretty_env_logger::try_init();
993 let durative_plan = include_str!("../tests/durative-plan.txt");
994 assert_eq!(
995 Plan::parse(durative_plan.into()).expect("Failed to parse plan"),
996 Plan(vec![
997 Action::Durative(plan::durative_action::DurativeAction {
998 name: "grasp-folded-garment".into(),
999 parameters: vec!["towel-01".into(), "robot-01".into()],
1000 duration: 100.0,
1001 timestamp: 0.0,
1002 }),
1003 Action::Durative(plan::durative_action::DurativeAction {
1004 name: "grasp-unfolded-garment".into(),
1005 parameters: vec!["dish-towel-01".into(), "human-01".into()],
1006 duration: 100.0,
1007 timestamp: 0.0,
1008 }),
1009 Action::Durative(plan::durative_action::DurativeAction {
1010 name: "lift".into(),
1011 parameters: vec!["dish-towel-01".into(), "human-01".into()],
1012 duration: 100.0,
1013 timestamp: 100.001,
1014 }),
1015 Action::Durative(plan::durative_action::DurativeAction {
1016 name: "lift".into(),
1017 parameters: vec!["towel-01".into(), "robot-01".into()],
1018 duration: 100.0,
1019 timestamp: 100.001,
1020 }),
1021 Action::Durative(plan::durative_action::DurativeAction {
1022 name: "pile-garment".into(),
1023 parameters: vec![
1024 "towel-01".into(),
1025 "pile-01".into(),
1026 "dish-towel".into(),
1027 "robot-01".into()
1028 ],
1029 duration: 100.0,
1030 timestamp: 200.002,
1031 }),
1032 Action::Durative(plan::durative_action::DurativeAction {
1033 name: "fold-garment".into(),
1034 parameters: vec!["dish-towel-01".into(), "human-01".into()],
1035 duration: 100.0,
1036 timestamp: 200.002,
1037 }),
1038 Action::Durative(plan::durative_action::DurativeAction {
1039 name: "grasp-folded-garment".into(),
1040 parameters: vec!["dish-towel-01".into(), "robot-01".into()],
1041 duration: 100.0,
1042 timestamp: 300.003,
1043 }),
1044 Action::Durative(plan::durative_action::DurativeAction {
1045 name: "grasp-unfolded-garment".into(),
1046 parameters: vec!["towel-02".into(), "human-01".into()],
1047 duration: 100.0,
1048 timestamp: 300.003,
1049 }),
1050 Action::Durative(plan::durative_action::DurativeAction {
1051 name: "lift".into(),
1052 parameters: vec!["towel-02".into(), "human-01".into()],
1053 duration: 100.0,
1054 timestamp: 400.004,
1055 }),
1056 Action::Durative(plan::durative_action::DurativeAction {
1057 name: "lift".into(),
1058 parameters: vec!["dish-towel-01".into(), "robot-01".into()],
1059 duration: 100.0,
1060 timestamp: 400.004,
1061 }),
1062 Action::Durative(plan::durative_action::DurativeAction {
1063 name: "pile-garment".into(),
1064 parameters: vec![
1065 "dish-towel-01".into(),
1066 "pile-01".into(),
1067 "dish-towel".into(),
1068 "robot-01".into()
1069 ],
1070 duration: 100.0,
1071 timestamp: 500.005,
1072 }),
1073 Action::Durative(plan::durative_action::DurativeAction {
1074 name: "fold-garment".into(),
1075 parameters: vec!["towel-02".into(), "human-01".into()],
1076 duration: 100.0,
1077 timestamp: 500.005,
1078 }),
1079 Action::Durative(plan::durative_action::DurativeAction {
1080 name: "grasp-folded-garment".into(),
1081 parameters: vec!["towel-02".into(), "robot-01".into()],
1082 duration: 100.0,
1083 timestamp: 600.006,
1084 }),
1085 Action::Durative(plan::durative_action::DurativeAction {
1086 name: "lift".into(),
1087 parameters: vec!["towel-02".into(), "robot-01".into()],
1088 duration: 100.0,
1089 timestamp: 700.007,
1090 }),
1091 Action::Durative(plan::durative_action::DurativeAction {
1092 name: "pile-garment".into(),
1093 parameters: vec![
1094 "towel-02".into(),
1095 "pile-01".into(),
1096 "dish-towel".into(),
1097 "robot-01".into()
1098 ],
1099 duration: 100.0,
1100 timestamp: 800.008,
1101 }),
1102 ])
1103 );
1104 }
1105}