Skip to content

Commit bd400de

Browse files
committed
Fix add/remove object in backward operation
- addObject() will actually remove the object from scene - removeObject() is not supported (we would need to know which object to add)
1 parent 1daef93 commit bd400de

File tree

3 files changed

+89
-29
lines changed

3 files changed

+89
-29
lines changed

core/include/moveit/task_constructor/stages/modify_planning_scene.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ class ModifyPlanningScene : public PropagatingEitherWay
149149

150150
protected:
151151
// apply stored modifications to scene
152-
InterfaceState apply(const InterfaceState& from, bool invert);
153-
void processCollisionObject(planning_scene::PlanningScene& scene, const moveit_msgs::CollisionObject& object);
152+
std::pair<InterfaceState, SubTrajectory> apply(const InterfaceState& from, bool invert);
153+
void processCollisionObject(planning_scene::PlanningScene& scene, moveit_msgs::CollisionObject& object, bool invert);
154154
void attachObjects(planning_scene::PlanningScene& scene, const std::pair<std::string, std::pair<Names, bool>>& pair,
155155
bool invert);
156156
void allowCollisions(planning_scene::PlanningScene& scene, const CollisionMatrixPairs& pairs, bool invert);

core/python/test/rostest_mps.py

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,87 @@ class TestModifyPlanningScene(unittest.TestCase):
2525
def setUp(self):
2626
super(TestModifyPlanningScene, self).setUp()
2727
self.psi = PlanningSceneInterface(synchronous=True)
28+
self.make_box = self.psi._PlanningSceneInterface__make_box
2829
# insert a box to collide with
2930
self.psi.add_box("box", make_pose(0.8, 0.25, 1.25), [0.2, 0.2, 0.2])
31+
self.task = task = core.Task()
32+
task.add(stages.CurrentState("current"))
3033

34+
def insertMove(self, position=-1):
3135
# colliding motion
3236
move = stages.MoveRelative("move", core.JointInterpolationPlanner())
3337
move.group = self.PLANNING_GROUP
3438
move.setDirection({"joint_1": 0.3})
35-
36-
self.task = task = core.Task()
37-
task.add(stages.CurrentState("current"), move)
39+
self.task.insert(move, position)
3840

3941
def test_collision(self):
42+
self.insertMove()
4043
self.assertFalse(self.task.plan())
4144

4245
def test_allow_collision_list(self):
43-
mps = stages.ModifyPlanningScene("mps")
46+
mps = stages.ModifyPlanningScene("allow specific collisions for box")
4447
mps.allowCollisions("box", ["link_4", "link_5", "link_6"], True)
45-
self.task.insert(mps, 1)
48+
self.task.add(mps)
49+
self.insertMove()
4650
self.assertTrue(self.task.plan())
4751

4852
def test_allow_collision_all(self):
4953
# insert an extra collision object that is unknown to ACM
5054
self.psi.add_box("block", make_pose(0.8, 0.55, 1.25), [0.2, 0.2, 0.2])
5155
# attach box to end effector
5256
self.psi.attach_box("link_6", "box")
53-
mps = stages.ModifyPlanningScene("mps")
57+
self.insertMove()
5458
self.assertFalse(self.task.plan())
5559

5660
# allow all collisions for attached "box" object
61+
mps = stages.ModifyPlanningScene("allow all collisions for box")
5762
mps.allowCollisions("box", True)
5863
self.task.insert(mps, 1)
5964
self.assertTrue(self.task.plan())
6065
# restore original state
6166
self.psi.remove_attached_object("link_6", "box")
6267
self.psi.remove_world_object("block")
6368

69+
def test_fw_add_object(self):
70+
mps = stages.ModifyPlanningScene("addObject(block)")
71+
mps.addObject(self.make_box("block", make_pose(0.8, 0.55, 1.25), [0.2, 0.2, 0.2]))
72+
self.task.add(mps)
73+
self.insertMove()
74+
self.assertFalse(self.task.plan())
75+
76+
def test_fw_remove_object(self):
77+
mps = stages.ModifyPlanningScene("removeObject(box)")
78+
mps.removeObject("box")
79+
self.task.insert(mps, 1)
80+
self.assertTrue(self.task.plan())
81+
s = self.task.solutions[0].toMsg()
82+
self.assertEqual(s.sub_trajectory[1].scene_diff.world.collision_objects[0].id, "box")
83+
84+
def test_bw_add_object(self):
85+
# add object to move_group's planning scene
86+
self.psi.add_box("block", make_pose(0.8, 0.55, 1.25), [0.2, 0.2, 0.2])
87+
88+
# backward operation will actually remove the object
89+
mps = stages.ModifyPlanningScene("addObject(block) backwards")
90+
mps.addObject(self.make_box("block", make_pose(0.8, 0.55, 1.25), [0.2, 0.2, 0.2]))
91+
self.task.insert(mps, 0)
92+
self.insertMove(0)
93+
self.assertTrue(self.task.plan())
94+
95+
self.psi.remove_world_object("block") # restore original state
96+
97+
s = self.task.solutions[0].toMsg()
98+
for ps in [s.start_scene] + [s.sub_trajectory[i].scene_diff for i in [0, 1]]:
99+
objects = [o.id for o in ps.world.collision_objects]
100+
self.assertTrue(objects == ["block", "box"])
101+
102+
def test_bw_remove_object(self):
103+
mps = stages.ModifyPlanningScene("removeObject(box) backwards")
104+
mps.removeObject("box")
105+
self.task.insert(mps, 0)
106+
self.insertMove(0)
107+
self.assertFalse(self.task.plan())
108+
64109

65110
if __name__ == "__main__":
66111
roscpp_initialize("test_mtc")

core/src/stages/modify_planning_scene.cpp

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ void ModifyPlanningScene::allowCollisions(const std::string& first, const moveit
8484
}
8585

8686
void ModifyPlanningScene::computeForward(const InterfaceState& from) {
87-
sendForward(from, apply(from, false), SubTrajectory());
87+
auto result = apply(from, false);
88+
sendForward(from, std::move(result.first), std::move(result.second));
8889
}
8990

9091
void ModifyPlanningScene::computeBackward(const InterfaceState& to) {
91-
sendBackward(apply(to, true), to, SubTrajectory());
92+
auto result = apply(to, true);
93+
sendBackward(std::move(result.first), to, std::move(result.second));
9294
}
9395

9496
void ModifyPlanningScene::attachObjects(planning_scene::PlanningScene& scene,
@@ -121,30 +123,43 @@ void ModifyPlanningScene::allowCollisions(planning_scene::PlanningScene& scene,
121123

122124
// invert indicates, whether to detach instead of attach (and vice versa)
123125
// as well as to forbid instead of allow collision (and vice versa)
124-
InterfaceState ModifyPlanningScene::apply(const InterfaceState& from, bool invert) {
126+
std::pair<InterfaceState, SubTrajectory> ModifyPlanningScene::apply(const InterfaceState& from, bool invert) {
125127
planning_scene::PlanningScenePtr scene = from.scene()->diff();
126-
InterfaceState result(scene);
127-
// add/remove objects
128-
for (const auto& collision_object : collision_objects_)
129-
processCollisionObject(*scene, collision_object);
130-
131-
// attach/detach objects
132-
for (const auto& pair : attach_objects_)
133-
attachObjects(*scene, pair, invert);
134-
135-
// allow/forbid collisions
136-
for (const auto& pairs : collision_matrix_edits_)
137-
allowCollisions(*scene, pairs, invert);
138-
139-
if (callback_)
140-
callback_(scene, properties());
141-
142-
return result;
128+
InterfaceState state(scene);
129+
SubTrajectory traj;
130+
try {
131+
// add/remove objects
132+
for (auto& collision_object : collision_objects_)
133+
processCollisionObject(*scene, collision_object, invert);
134+
135+
// attach/detach objects
136+
for (const auto& pair : attach_objects_)
137+
attachObjects(*scene, pair, invert);
138+
139+
// allow/forbid collisions
140+
for (const auto& pairs : collision_matrix_edits_)
141+
allowCollisions(*scene, pairs, invert);
142+
143+
if (callback_)
144+
callback_(scene, properties());
145+
} catch (const std::exception& e) {
146+
traj.markAsFailure(e.what());
147+
}
148+
return std::make_pair(state, traj);
143149
}
144150

145151
void ModifyPlanningScene::processCollisionObject(planning_scene::PlanningScene& scene,
146-
const moveit_msgs::CollisionObject& object) {
152+
moveit_msgs::CollisionObject& object, bool invert) {
153+
auto op = object.operation;
154+
if (invert) {
155+
if (op == moveit_msgs::CollisionObject::ADD)
156+
op = moveit_msgs::CollisionObject::REMOVE;
157+
else if (op == moveit_msgs::CollisionObject::REMOVE)
158+
throw std::runtime_error("cannot apply removeObject() backwards");
159+
}
160+
147161
scene.processCollisionObjectMsg(object);
162+
object.operation = op;
148163
}
149164
} // namespace stages
150165
} // namespace task_constructor

0 commit comments

Comments
 (0)