|
4 | 4 | # This source code is licensed under the MIT license found in the
|
5 | 5 | # LICENSE file in the root directory of this source tree.
|
6 | 6 |
|
| 7 | +import math |
7 | 8 | from os import path as osp
|
8 | 9 |
|
9 | 10 | import numpy as np
|
@@ -353,7 +354,8 @@ def test_fetch_robot_wrapper(fixed_base):
|
353 | 354 |
|
354 | 355 | # set base ground position using object transformation approach
|
355 | 356 | target_base_pos = sim.pathfinder.snap_point(fetch.sim_obj.translation)
|
356 |
| - target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi] |
| 357 | + # Note, don't test equivalency of pi, because that is the wrap point and is often negated. |
| 358 | + target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi * 0.99] |
357 | 359 | for target_base_rot in target_base_rots:
|
358 | 360 | set_agent_base_via_obj_trans(
|
359 | 361 | target_base_pos, target_base_rot, fetch
|
@@ -614,7 +616,8 @@ def test_spot_robot_wrapper(fixed_base):
|
614 | 616 |
|
615 | 617 | # set base ground position using object transformation approach
|
616 | 618 | target_base_pos = sim.pathfinder.snap_point(spot.sim_obj.translation)
|
617 |
| - target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi] |
| 619 | + # Note, don't test equivalency of pi, because that is the wrap point and is often negated. |
| 620 | + target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi * 0.99] |
618 | 621 | for target_base_rot in target_base_rots:
|
619 | 622 | set_agent_base_via_obj_trans(
|
620 | 623 | target_base_pos, target_base_rot, spot
|
@@ -705,6 +708,77 @@ def test_spot_robot_wrapper(fixed_base):
|
705 | 708 | )
|
706 | 709 |
|
707 | 710 |
|
| 711 | +@pytest.mark.skipif( |
| 712 | + not osp.exists("data/robots/hab_spot_arm"), |
| 713 | + reason="Test requires Spot w/ arm robot URDF and assets.", |
| 714 | +) |
| 715 | +@pytest.mark.skipif( |
| 716 | + not habitat_sim.built_with_bullet, |
| 717 | + reason="Robot wrapper API requires Bullet physics.", |
| 718 | +) |
| 719 | +def test_base_rot(): |
| 720 | + # set this to output test results as video for easy investigation |
| 721 | + produce_debug_video = False |
| 722 | + observations = [] |
| 723 | + cfg_settings = default_sim_settings.copy() |
| 724 | + cfg_settings["scene"] = "NONE" |
| 725 | + cfg_settings["enable_physics"] = True |
| 726 | + |
| 727 | + # loading the physical scene |
| 728 | + hab_cfg = make_cfg(cfg_settings) |
| 729 | + |
| 730 | + with habitat_sim.Simulator(hab_cfg) as sim: |
| 731 | + # setup the camera for debug video (looking at 0,0,0) |
| 732 | + sim.agents[0].scene_node.translation = [0.0, -1.0, 2.0] |
| 733 | + |
| 734 | + # add the robot to the world via the wrapper |
| 735 | + robot_path = "data/robots/hab_spot_arm/urdf/hab_spot_arm.urdf" |
| 736 | + agent_config = DictConfig({"articulated_agent_urdf": robot_path}) |
| 737 | + spot = spot_robot.SpotRobot(agent_config, sim) |
| 738 | + spot.reconfigure() |
| 739 | + spot.update() |
| 740 | + |
| 741 | + # check that for range (-pi, pi) getter and setter are consistent |
| 742 | + num_samples = 100 |
| 743 | + for i in range(1, num_samples): |
| 744 | + angle = -math.pi + (math.pi * 2 * i) / num_samples |
| 745 | + spot.base_rot = angle |
| 746 | + assert np.allclose(angle, spot.base_rot, atol=1e-5) |
| 747 | + if produce_debug_video: |
| 748 | + observations.append(sim.get_sensor_observations()) |
| 749 | + |
| 750 | + # check that for range [-2pi, 2pi] increment is accurate |
| 751 | + spot.base_rot = -math.pi * 2 |
| 752 | + inc = (math.pi * 4) / num_samples |
| 753 | + rot_check = -math.pi * 2 |
| 754 | + for _ in range(0, num_samples): |
| 755 | + spot.base_rot = spot.base_rot + inc |
| 756 | + rot_check += inc |
| 757 | + # NOTE: here we check that the angle is accurate (allow an offset of one full rotation to cover redundant options) |
| 758 | + accurate_angle = False |
| 759 | + for offset in [0, math.pi * 2, math.pi * -2]: |
| 760 | + if np.allclose(rot_check, spot.base_rot + offset, atol=1e-5): |
| 761 | + accurate_angle = True |
| 762 | + break |
| 763 | + assert ( |
| 764 | + accurate_angle |
| 765 | + ), f"should be {rot_check}, but was {spot.base_rot}." |
| 766 | + if produce_debug_video: |
| 767 | + observations.append(sim.get_sensor_observations()) |
| 768 | + |
| 769 | + # produce some test debug video |
| 770 | + if produce_debug_video: |
| 771 | + from habitat_sim.utils import viz_utils as vut |
| 772 | + |
| 773 | + vut.make_video( |
| 774 | + observations, |
| 775 | + "color_sensor", |
| 776 | + "color", |
| 777 | + "test_base_rot", |
| 778 | + open_vid=True, |
| 779 | + ) |
| 780 | + |
| 781 | + |
708 | 782 | @pytest.mark.skipif(
|
709 | 783 | not osp.exists("data/robots/hab_stretch"),
|
710 | 784 | reason="Test requires Stretch w/ robot URDF and assets.",
|
@@ -763,7 +837,8 @@ def test_stretch_robot_wrapper(fixed_base):
|
763 | 837 | target_base_pos = sim.pathfinder.snap_point(
|
764 | 838 | stretch.sim_obj.translation
|
765 | 839 | )
|
766 |
| - target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi] |
| 840 | + # Note, don't test equivalency of pi, because that is the wrap point and is often negated. |
| 841 | + target_base_rots = [0.0, np.pi * 0.25, np.pi * 0.50, np.pi * 0.99] |
767 | 842 | for target_base_rot in target_base_rots:
|
768 | 843 | set_agent_base_via_obj_trans(
|
769 | 844 | target_base_pos, target_base_rot, stretch
|
|
0 commit comments