Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying relative poses #317

Merged
merged 9 commits into from
Jan 6, 2025
Merged

Allow specifying relative poses #317

merged 9 commits into from
Jan 6, 2025

Conversation

sea-bass
Copy link
Owner

@sea-bass sea-bass commented Jan 4, 2025

This PR implements a mechanism to express poses relative to other entities.

Closes #298

@sea-bass
Copy link
Owner Author

sea-bass commented Jan 4, 2025

@kumar-sanjeeev Since I've been giving you a hard time with reviews, I'd like to give you a chance to do the same for this one, if you'd like.

There are still lots more cases to handle, but initially I'm curious what you think of this way to express relative poses, both in the programmatic and YAML interfaces.

The other open question is what the "reference pose" is defined as.

  • For Locations, Objects, and Robots, I think it's okay.
  • For Rooms and Object Spawns, it's currently just the centroid of the polygon... which probably needs to change.
  • For Hallways ...? Maybe we don't support that now.

Perhaps the "offset" of the polygon footprint will need to be used more faithfully than it currently is, but TBD.

Copy link

github-actions bot commented Jan 4, 2025

Coverage

Coverage Report
FileStmtsMissCoverMissing
__init__.py00100% 
core
   __init__.py90100% 
   dynamics.py49197%142
   gazebo.py137894%55, 128, 234, 248–252
   hallway.py97891%206, 248–251, 295–297
   locations.py1371787%76, 78, 111, 124–125, 127–128, 145, 204, 237, 262, 272, 329–330, 332–333, 362
   objects.py73494%113, 144, 191, 219
   robot.py4978682%271, 274, 286, 289, 293–294, 299–300, 340–342, 358, 375–376, 415–417, 421–425, 450, 453, 457–459, 486, 488, 530–531, 533–534, 540–541, 550–553, 558, 560, 569–571, 578–580, 642–644, 669–671, 677–678, 686–690, 735–737, 748–749, 809–811, 816, 863–865, 870, 888, 894, 897, 899, 901, 904–906, 956–957, 990, 1008, 1011
   room.py65296%74, 140
   world.py83319276%163, 166, 200–201, 205, 277–278, 280, 283, 313–314, 376, 390–391, 393, 396, 411–413, 433–437, 439–441, 443–444, 447, 449–452, 456–460, 463–464, 467, 470–481, 497–498, 516–518, 532, 534, 537–538, 543–545, 564–565, 567–568, 584, 586, 589–590, 595–597, 607–609, 626–627, 629–630, 644, 646, 649–650, 655–657, 680, 682, 685–686, 691–693, 729, 735, 771–772, 775, 798, 818, 821, 832, 835, 843, 859–863, 865, 868–869, 872–875, 877, 880, 883–884, 887–889, 891–893, 895–897, 899, 914, 921, 932–936, 971–972, 976–977, 995–996, 1002–1003, 1005–1006, 1008, 1010–1011, 1013, 1015–1016, 1026–1027, 1030, 1032, 1046, 1048, 1055, 1115, 1146–1147, 1170–1171, 1175–1176, 1195–1196, 1200–1201, 1226–1227, 1280–1281, 1305, 1370, 1377, 1487–1488, 1517, 1523, 1569, 1649–1650, 1716, 1726
   yaml_utils.py150696%90, 96, 194, 197, 217, 220
gui
   __init__.py20100% 
   action_runners.py914847%32–33, 35–39, 41, 74–75, 77–81, 83, 109–110, 112–116, 118, 144–145, 147–151, 153, 176–177, 179–183, 185, 208–209, 211–215, 217
   main.py2777473%23–25, 46, 94, 98–101, 248–257, 269–279, 286–289, 291, 294–300, 304, 309–310, 314–315, 326, 369–370, 379–380, 384–385, 397, 400–403, 405–406, 408–409, 412–415, 417–419, 423–426
   world_canvas.py2635280%134–137, 141–142, 147–148, 155, 157, 159, 216–218, 224, 226, 246–248, 293, 350–351, 378–379, 381, 383–384, 386–389, 391–392, 396–402, 405, 408–409, 422, 440–441, 443, 449, 451–454
manipulation
   __init__.py10100% 
   grasping.py2396473%100, 108, 110–112, 114–122, 124, 132, 462, 464–466, 470–472, 566–567, 569–571, 574–578, 586, 589–591, 596–597, 603–607, 610–617, 620–622, 631, 633, 635–641
navigation
   __init__.py16287%37, 54
   a_star.py801186%82–84, 87–89, 91–93, 182, 191
   execution.py96792%81–83, 88–90, 125
   occupancy_grid.py1391489%45–48, 50–54, 57, 193, 227, 235, 239
   prm.py58493%59–60, 139, 148
   rrt.py1630100% 
   visualization.py32681%88–93
   world_graph.py61690%117, 120, 130, 139, 148, 150
planning
   __init__.py00100% 
   actions.py1120100% 
planning/pddlstream
   __init__.py7185%13
   default_mappings.py90100% 
   planner.py40880%119–126
   primitives.py61493%68, 82, 94, 232
   utils.py99891%66, 93, 105, 115–116, 207–208, 211
utils
   __init__.py00100% 
   general.py47295%25, 47
   knowledge.py1522086%91, 122, 163–168, 170–171, 174–178, 209–210, 252, 268, 331
   logging.py16568%24–27, 56
   motion.py70395%93–94, 96
   polygon.py1110100% 
   pose.py1170100% 
   search_graph.py93396%239–241
   trajectory.py67297%130, 167
TOTAL456666885% 

Tests Skipped Failures Errors Time
205 0 💤 0 ❌ 0 🔥 3m 56s ⏱️

@kumar-sanjeeev
Copy link
Contributor

@kumar-sanjeeev Since I've been giving you a hard time with reviews, I'd like to give you a chance to do the same for this one, if you'd like.

There are still lots more cases to handle, but initially I'm curious what you think of this way to express relative poses, both in the programmatic and YAML interfaces.

The other open question is what the "reference pose" is defined as.

  • For Locations, Objects, and Robots, I think it's okay.
  • For Rooms and Object Spawns, it's currently just the centroid of the polygon... which probably needs to change.
  • For Hallways ...? Maybe we don't support that now.

Perhaps the "offset" of the polygon footprint will need to be used more faithfully than it currently is, but TBD.

@sea-bass thank you for giving me this chance :). I will get back to you.

@kumar-sanjeeev
Copy link
Contributor

@kumar-sanjeeev Since I've been giving you a hard time with reviews, I'd like to give you a chance to do the same for this one, if you'd like.

There are still lots more cases to handle, but initially I'm curious what you think of this way to express relative poses, both in the programmatic and YAML interfaces.

The other open question is what the "reference pose" is defined as.

  • For Locations, Objects, and Robots, I think it's okay.
  • For Rooms and Object Spawns, it's currently just the centroid of the polygon... which probably needs to change.
  • For Hallways ...? Maybe we don't support that now.

Perhaps the "offset" of the polygon footprint will need to be used more faithfully than it currently is, but TBD.

I like the thought process behind relative poses. I have one question that comes to mind, after obtaining the absolute pose of an entity using world.get_pose_relative_to(), should we also need to verify if that pose is valid, as a safety check? Valid I mean to say collision checking with other entities.

@sea-bass
Copy link
Owner Author

sea-bass commented Jan 5, 2025

I like the thought process behind relative poses. I have one question that comes to mind, after obtaining the absolute pose of an entity using world.get_pose_relative_to(), should we also need to verify if that pose is valid, as a safety check? Valid I mean to say collision checking with other entities.

Yes it should, but this already happens when you try to add the entity with the transformed pose -- not when you do the transformation.

@kumar-sanjeeev
Copy link
Contributor

I like the thought process behind relative poses. I have one question that comes to mind, after obtaining the absolute pose of an entity using world.get_pose_relative_to(), should we also need to verify if that pose is valid, as a safety check? Valid I mean to say collision checking with other entities.

Yes it should, but this already happens when you try to add the entity with the transformed pose -- not when you do the transformation.

Okay, understood. At the moment, I don't see any significant challenges in implementing the suggested logic for relative pose.

@sea-bass sea-bass marked this pull request as ready for review January 5, 2025 22:03
@sea-bass
Copy link
Owner Author

sea-bass commented Jan 5, 2025

@kumar-sanjeeev this is ready for review!

Copy link
Contributor

@kumar-sanjeeev kumar-sanjeeev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noice!

LGTM. Just a few basic comments for improving readability:

I was wondering if it would make sense to mention at the top of the World schema:
"Refer to the Specifying Poses section below to better understand how poses can be specified in PyRoboSim."

This addition could help users quickly locate the relevant section on poses when they are reading the YAML file.

pyrobosim/pyrobosim/core/world.py Outdated Show resolved Hide resolved
pyrobosim/pyrobosim/core/yaml_utils.py Outdated Show resolved Hide resolved
docs/source/yaml/world_schema.rst Outdated Show resolved Hide resolved
docs/source/yaml/world_schema.rst Outdated Show resolved Hide resolved
pyrobosim/examples/demo.py Show resolved Hide resolved
pyrobosim/pyrobosim/core/world.py Outdated Show resolved Hide resolved
Comment on lines +16 to +34
def construct_pose_from_args(pose_args, world):
"""
Constructs a PyRoboSim pose from a dictionary of YAML arguments.

This handles poses of different formats, as well as relative pose specification.

:param pose_args: A dictionary containing the pose arguments.
:type pose_args: dict
:param world: The world to use for looking up entities.
:type world: :class:`pyrobosim.core.world.World`
:return: Pose object
:rype: :class:`pyrobosim.utils.pose.Pose`
"""
pose = Pose.construct(pose_args)
if "relative_to" in pose_args:
pose = world.get_pose_relative_to(pose, pose_args["relative_to"])
return pose


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to put this function in pose.py ?

Copy link
Owner Author

@sea-bass sea-bass Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to do this, but it felt strange to have to pass in a world in a function in pose.py. If we were using Python type hints, then this would actually cause a circular import of World.

Perhaps a better candidate might be pyrobosim/utils/knowledge.py? All the other functions in this file already accept worlds, so this file you definitely need to have World imported first.


It's the same reason World.get_pose_relative_to() wasn't just a free function in pose.py that accepted a World object as input. This one is even worse because it has many other imports in the body of this function (including Room, Location, etc.) and would cause several circular imports even without type hints.

I think at some point the world.py file (currently 1740 lines of code) will need to be split up into more utilities, and this would be one of them when that time comes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand. Let’s keep it as is for now. I remember when I was working on the type hints issue, I encountered a lot of circular import errors.

pyrobosim/test/core/test_yaml_utils.py Outdated Show resolved Hide resolved
Copy link
Contributor

@kumar-sanjeeev kumar-sanjeeev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect !

I also tested the changes locally. The examples seem to be working fine, and the docs and test cases are running fine as well.

@sea-bass sea-bass merged commit b5a3c18 into main Jan 6, 2025
6 checks passed
@sea-bass sea-bass deleted the relative-poses branch January 6, 2025 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow specifying poses relative to other locations
2 participants