From c36780d57d4afa9e915eb9fd3a019de6a5467475 Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 13:28:06 +0100 Subject: [PATCH 1/7] [actions] added workflow and changed pr2 urdf in launch --- .github/workflows/pycram-ci.yml | 90 ++++++++++++++++++++++++++++++++ launch/ik_and_description.launch | 3 +- 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pycram-ci.yml diff --git a/.github/workflows/pycram-ci.yml b/.github/workflows/pycram-ci.yml new file mode 100644 index 000000000..1ad533e36 --- /dev/null +++ b/.github/workflows/pycram-ci.yml @@ -0,0 +1,90 @@ +name: CI standalone +defaults: + run: + shell: bash -ieo pipefail {0} +on: + push: + branches: + - ci + - dev + - master + pull_request: + branches: + - master + - dev + - ci +jobs: + Build_and_run_Tests: + runs-on: ubuntu-20.04 + steps: + - name: Checkout pycram + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/pycram' + repository: ${{github.repository}} + ref: ${{github.ref}} + submodules: recursive + + - name: Checkout iai_maps + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/iai_maps' + repository: code-iai/iai_maps + ref: master + - name: Checkout iai_robots + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/iai_robots' + repository: code-iai/iai_robots + ref: master + - name: Checkout pr2_common + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/pr2_common' + repository: PR2/pr2_common + ref: master + - name: Checkout kdl_ik_service + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/kdl_ik_service' + repository: cram2/kdl_ik_service + ref: master + - name: Checkout pr2_kinematics + uses: actions/checkout@v3 + with: + path: 'ros_ws/src/pr2_kinematics' + repository: PR2/pr2_kinematics + ref: kinetic-devel + - name: install ros and deps + uses: betwo/github-setup-catkin@master + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: true + with: + # Version range or exact version of ROS version to use, using SemVer's version range syntax. + ros-version: noetic + build-tool: 'catkin_tools' + # Root directory of the catkin workspace + workspace: $GITHUB_WORKSPACE/ros_ws + - name: build and source workspace + run: | + cd ros_ws + catkin_make + echo 'export ROS_HOSTNAME=localhost' >> ~/.bashrc + echo 'source $GITHUB_WORKSPACE/ros_ws/devel/setup.bash' >> ~/.bashrc + - name: Install requirements + run: | + cd $GITHUB_WORKSPACE/ros_ws/src/pycram + sudo pip3 install -r requirements.txt + - name: upgrade numpy + run: | + sudo pip3 install --upgrade numpy + - name: install additional requirements + run: | + sudo pip3 install pytest pyjpt mlflow + - name: start roscore + run: | + roslaunch pycram ik_and_description.launch & + - name: Run Tests + run: | + roscd pycram + pytest -v test diff --git a/launch/ik_and_description.launch b/launch/ik_and_description.launch index 61f2315da..c10e9e68f 100644 --- a/launch/ik_and_description.launch +++ b/launch/ik_and_description.launch @@ -9,8 +9,7 @@ + textfile="$(find pycram)/resources/pr2.urdf"/> From b54e1985768271f8eb262454a61b42edbd788c13 Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 13:53:01 +0100 Subject: [PATCH 2/7] [tests] split bullet world tetsts into testCase and unittests --- src/pycram/bullet_world.py | 2 +- test/bullet_world_testcase.py | 54 +++++++++++++++++++++++++++++ test/local_transformer_tests.py | 4 +-- test/test_action_designator.py | 4 +-- test/test_bullet_world.py | 49 +++----------------------- test/test_bullet_world_reasoning.py | 4 +-- test/test_costmaps.py | 4 +-- test/test_location_designator.py | 4 +-- test/test_object_designator.py | 4 +-- test/test_orm.py | 6 ++-- test/test_task_tree.py | 4 +-- 11 files changed, 76 insertions(+), 63 deletions(-) create mode 100644 test/bullet_world_testcase.py diff --git a/src/pycram/bullet_world.py b/src/pycram/bullet_world.py index 23c40d591..af4f307fa 100644 --- a/src/pycram/bullet_world.py +++ b/src/pycram/bullet_world.py @@ -408,7 +408,7 @@ def __enter__(self): def __exit__(self, *args): if not self.prev_world == None: BulletWorld.current_bullet_world = self.prev_world - BulletWorld.current_bullet_world.world_sync.pause_sync = False + BulletWorld.current_bullet_world.world_sync.pause_sync = False class WorldSync(threading.Thread): diff --git a/test/bullet_world_testcase.py b/test/bullet_world_testcase.py new file mode 100644 index 000000000..6770a5f17 --- /dev/null +++ b/test/bullet_world_testcase.py @@ -0,0 +1,54 @@ +import unittest + +import numpy as np +import rospkg + +from pycram.bullet_world import BulletWorld, Object, fix_missing_inertial +from pycram.pose import Pose +from pycram.robot_descriptions import robot_description +from pycram.process_module import ProcessModule +from pycram.enums import ObjectType +import os +import xml.etree.ElementTree as ET +import tf + + +class BulletWorldTestCase(unittest.TestCase): + + world: BulletWorld + + @classmethod + def setUpClass(cls): + cls.world = BulletWorld("DIRECT") + cls.robot = Object(robot_description.name, ObjectType.ROBOT, robot_description.name + ".urdf") + cls.kitchen = Object("kitchen", ObjectType.ENVIRONMENT, "kitchen.urdf") + cls.milk = Object("milk", ObjectType.MILK, "milk.stl", pose=Pose([1.3, 1, 0.9])) + cls.cereal = Object("cereal", ObjectType.BREAKFAST_CEREAL, "breakfast_cereal.stl", pose=Pose([1.3, 0.7, 0.95])) + ProcessModule.execution_delay = False + + def setUp(self): + self.world.reset_bullet_world() + + + + def tearDown(self): + self.world.reset_bullet_world() + + @classmethod + def tearDownClass(cls): + cls.world.exit() + + +class XMLTester(unittest.TestCase): + + def setUp(self) -> None: + rospack = rospkg.RosPack() + filename = rospack.get_path('pycram') + '/resources/' + 'pr2.urdf' + with open(filename, "r") as f: + self.urdf_string = f.read() + + def test_inertial(self): + result = fix_missing_inertial(self.urdf_string) + resulting_tree = ET.ElementTree(ET.fromstring(result)) + for element in resulting_tree.iter("link"): + self.assertTrue(len([*element.iter("inertial")]) > 0) diff --git a/test/local_transformer_tests.py b/test/local_transformer_tests.py index ee7375fcb..7629b2248 100644 --- a/test/local_transformer_tests.py +++ b/test/local_transformer_tests.py @@ -7,10 +7,10 @@ from src.pycram.local_transformer import LocalTransformer from pycram.robot_descriptions import robot_description from pycram.pose import Pose, Transform -import test_bullet_world +import bullet_world_testcase -class TestLocalTransformer(test_bullet_world.BulletWorldTest): +class TestLocalTransformer(test_bullet_world.BulletWorldTestCase): def test_singelton(self): l1 = LocalTransformer() diff --git a/test/test_action_designator.py b/test/test_action_designator.py index 49c58c436..0a452e9bf 100644 --- a/test/test_action_designator.py +++ b/test/test_action_designator.py @@ -6,11 +6,11 @@ from pycram.pose import Pose from pycram.enums import ObjectType import pycram.enums -import test_bullet_world +from bullet_world_testcase import BulletWorldTestCase import numpy as np -class TestActionDesignatorGrounding(test_bullet_world.BulletWorldTest): +class TestActionDesignatorGrounding(BulletWorldTestCase): """Testcase for the grounding methods of action designators.""" def test_move_torso(self): diff --git a/test/test_bullet_world.py b/test/test_bullet_world.py index 6417e739c..ac5e0db5b 100644 --- a/test/test_bullet_world.py +++ b/test/test_bullet_world.py @@ -1,31 +1,9 @@ -import unittest - -import numpy as np -from pycram.bullet_world import BulletWorld, Object, fix_missing_inertial +from bullet_world_testcase import BulletWorldTestCase from pycram.pose import Pose -from pycram.robot_descriptions import robot_description -from pycram.process_module import ProcessModule -from pycram.enums import ObjectType -import os -import xml.etree.ElementTree as ET -import tf - - -class BulletWorldTest(unittest.TestCase): - - world: BulletWorld +import numpy as np - @classmethod - def setUpClass(cls): - cls.world = BulletWorld("DIRECT") - cls.robot = Object(robot_description.name, ObjectType.ROBOT, robot_description.name + ".urdf") - cls.kitchen = Object("kitchen", ObjectType.ENVIRONMENT, "kitchen.urdf") - cls.milk = Object("milk", ObjectType.MILK, "milk.stl", pose=Pose([1.3, 1, 0.9])) - cls.cereal = Object("cereal", ObjectType.BREAKFAST_CEREAL, "breakfast_cereal.stl", pose=Pose([1.3, 0.7, 0.95])) - ProcessModule.execution_delay = False - def setUp(self): - self.world.reset_bullet_world() +class BulletWorldTest(BulletWorldTestCase): def test_object_movement(self): self.milk.set_position(Pose([0, 1, 1])) @@ -36,23 +14,4 @@ def test_robot_orientation(self): head_position = self.robot.get_link_position('head_pan_link').z #self.robot.set_orientation(list(2*tf.transformations.quaternion_from_euler(0, 0, np.pi, axes="sxyz"))) self.robot.set_orientation(Pose(orientation=[0, 0, 1, 1])) - self.assertEqual(self.robot.get_link_position('head_pan_link').z, head_position) - - def tearDown(self): - self.world.reset_bullet_world() - - @classmethod - def tearDownClass(cls): - cls.world.exit() - - -class XMLTester(unittest.TestCase): - - def setUp(self) -> None: - self.urdf_string = open(os.path.join("..", "resources", "pr2.urdf"), "r").read() - - def test_inertial(self): - result = fix_missing_inertial(self.urdf_string) - resulting_tree = ET.ElementTree(ET.fromstring(result)) - for element in resulting_tree.iter("link"): - self.assertTrue(len([*element.iter("inertial")]) > 0) + self.assertEqual(self.robot.get_link_position('head_pan_link').z, head_position) \ No newline at end of file diff --git a/test/test_bullet_world_reasoning.py b/test/test_bullet_world_reasoning.py index da537fff3..735bc7773 100644 --- a/test/test_bullet_world_reasoning.py +++ b/test/test_bullet_world_reasoning.py @@ -1,12 +1,12 @@ import time -from test_bullet_world import BulletWorldTest +from bullet_world_testcase import BulletWorldTestCase import pycram.bullet_world_reasoning as btr from pycram.pose import Pose from pycram.robot_descriptions import robot_description -class TestBulletWorldReasoning(BulletWorldTest): +class TestCaseBulletWorldReasoning(BulletWorldTestCase): def test_contact(self): self.milk.set_pose(Pose([1, 1, 1])) diff --git a/test/test_costmaps.py b/test/test_costmaps.py index 5afc1c7c6..457bbd577 100644 --- a/test/test_costmaps.py +++ b/test/test_costmaps.py @@ -1,10 +1,10 @@ -from test_bullet_world import BulletWorldTest +from bullet_world_testcase import BulletWorldTestCase from pycram.costmaps import OccupancyCostmap from pycram.pose import Pose import numpy as np -class TestCostmaps(BulletWorldTest): +class TestCostmapsCase(BulletWorldTestCase): def test_raytest_bug(self): for i in range(30): diff --git a/test/test_location_designator.py b/test/test_location_designator.py index ab94ec6bb..ff4f4ea5f 100644 --- a/test/test_location_designator.py +++ b/test/test_location_designator.py @@ -5,10 +5,10 @@ from pycram.process_module import simulated_robot from pycram.pose import Pose import pycram.enums -import test_bullet_world +from bullet_world_testcase import BulletWorldTestCase -class TestActionDesignatorGrounding(test_bullet_world.BulletWorldTest): +class TestActionDesignatorGrounding(BulletWorldTestCase): def test_reachability(self): self.robot.set_joint_state(robot_description.torso_joint, 0.3) diff --git a/test/test_object_designator.py b/test/test_object_designator.py index fa2079e5b..625e107a2 100644 --- a/test/test_object_designator.py +++ b/test/test_object_designator.py @@ -1,10 +1,10 @@ import unittest -import test_bullet_world +from bullet_world_testcase import BulletWorldTestCase from pycram.designators.object_designator import * from pycram.enums import ObjectType -class TestObjectDesignator(test_bullet_world.BulletWorldTest): +class TestObjectDesignator(BulletWorldTestCase): def test_object_grounding(self): description = ObjectDesignatorDescription(["milk"], [ObjectType.MILK]) diff --git a/test/test_orm.py b/test/test_orm.py index 0f4e6cf63..ceec18c5d 100644 --- a/test/test_orm.py +++ b/test/test_orm.py @@ -11,7 +11,7 @@ import pycram.orm.task import pycram.task import pycram.task -import test_bullet_world +from bullet_world_testcase import BulletWorldTestCase import test_task_tree from pycram.designators import action_designator, object_designator from pycram.pose import Pose @@ -148,7 +148,7 @@ def test_meta_data_alternation(self): self.assertEqual(metadata_result.description, "Test") -class ORMObjectDesignatorTestCase(test_bullet_world.BulletWorldTest): +class ORMObjectDesignatorTestCase(BulletWorldTestCase): """Test ORM functionality with a plan including object designators. """ engine: sqlalchemy.engine.Engine @@ -251,7 +251,7 @@ def test_task_tree_node_parents(self): self.assertTrue([r[i].parent == r[r[i].parent_id - 1] for i in range(len(r)) if r[i].parent_id is not None]) -class MotionDesigTest(test_bullet_world.BulletWorldTest): +class MotionDesigTest(BulletWorldTestCase): engine: sqlalchemy.engine.Engine session: sqlalchemy.orm.Session diff --git a/test/test_task_tree.py b/test/test_task_tree.py index abe3f3ab8..1a89f6650 100644 --- a/test/test_task_tree.py +++ b/test/test_task_tree.py @@ -4,12 +4,12 @@ from pycram.task import with_tree import unittest import anytree -import test_bullet_world +from bullet_world_testcase import BulletWorldTestCase import pycram.plan_failures from pycram.designators import object_designator, action_designator -class TaskTreeTestCase(test_bullet_world.BulletWorldTest): +class TaskTreeTestCase(BulletWorldTestCase): @with_tree def plan(self): From fcf2f367677be787c7a7600080e4107d4a694e57 Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 13:58:45 +0100 Subject: [PATCH 3/7] [orm] fix user for ci --- src/pycram/orm/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pycram/orm/base.py b/src/pycram/orm/base.py index dad386fe7..fcb9cbc62 100644 --- a/src/pycram/orm/base.py +++ b/src/pycram/orm/base.py @@ -1,5 +1,6 @@ """Implementation of base classes for orm modelling.""" import datetime +import getpass import os from typing import Optional @@ -136,7 +137,7 @@ class ProcessMetaData(MappedAsDataclass, _Base): init=False) """The timestamp where this row got created. This is an aid for versioning.""" - created_by: Mapped[str] = mapped_column(default=os.getlogin(), init=False) + created_by: Mapped[str] = mapped_column(default=getpass.getuser(), init=False) """The user that created the experiment.""" description: Mapped[str] = mapped_column(init=False) From 1e1890e876a6725268ca58b4218022e5247d3542 Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 14:05:21 +0100 Subject: [PATCH 4/7] [general] updated requirements --- requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6aadbfe08..fa776baf6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,4 +12,6 @@ urdf-parser-py~=0.0.3 graphviz anytree>=2.8.0 SQLAlchemy>=2.0.9 - +tqdm==4.66.1 +psutil==5.9.7 +lxml==4.5.1 From 51bd58c2e51df093a6a04af331030fba6584a75e Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 14:18:53 +0100 Subject: [PATCH 5/7] [general] update of numpy dependency and coment in bullet_world_testcase --- requirements.txt | 2 +- test/bullet_world_testcase.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index fa776baf6..f0702c7ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ rospkg~=1.4.0 roslibpy~=1.2.1 # rospy~=1.14.11 pathlib~=1.0.1 -numpy~=1.19.5 +numpy~=1.22.2 pytransform3d~=1.9.1 # tf~=1.12.1 # actionlib~=1.12.1 diff --git a/test/bullet_world_testcase.py b/test/bullet_world_testcase.py index 6770a5f17..8b8ff9352 100644 --- a/test/bullet_world_testcase.py +++ b/test/bullet_world_testcase.py @@ -29,7 +29,9 @@ def setUpClass(cls): def setUp(self): self.world.reset_bullet_world() - + # DO NOT WRITE TESTS HERE!!! + # Test related to the BulletWorld should be written in test_bullet_world.py + # Tests in here would not be properly executed in the CI def tearDown(self): self.world.reset_bullet_world() From d998714d1cae4d2265b085192862822e6d3d1ec2 Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 14:21:19 +0100 Subject: [PATCH 6/7] [workflow] removed ci branch as trigger --- .github/workflows/pycram-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pycram-ci.yml b/.github/workflows/pycram-ci.yml index 1ad533e36..c7bf4db3c 100644 --- a/.github/workflows/pycram-ci.yml +++ b/.github/workflows/pycram-ci.yml @@ -5,14 +5,12 @@ defaults: on: push: branches: - - ci - dev - master pull_request: branches: - master - dev - - ci jobs: Build_and_run_Tests: runs-on: ubuntu-20.04 From dbe783b9660a76ebf8ad70fedac335a94db73a4c Mon Sep 17 00:00:00 2001 From: Jonas Dech Date: Wed, 3 Jan 2024 14:31:27 +0100 Subject: [PATCH 7/7] [tests] moved XML test to test_bullet_world --- test/bullet_world_testcase.py | 13 ------------- test/test_bullet_world.py | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/test/bullet_world_testcase.py b/test/bullet_world_testcase.py index 8b8ff9352..b34b434c4 100644 --- a/test/bullet_world_testcase.py +++ b/test/bullet_world_testcase.py @@ -9,7 +9,6 @@ from pycram.process_module import ProcessModule from pycram.enums import ObjectType import os -import xml.etree.ElementTree as ET import tf @@ -41,16 +40,4 @@ def tearDownClass(cls): cls.world.exit() -class XMLTester(unittest.TestCase): - def setUp(self) -> None: - rospack = rospkg.RosPack() - filename = rospack.get_path('pycram') + '/resources/' + 'pr2.urdf' - with open(filename, "r") as f: - self.urdf_string = f.read() - - def test_inertial(self): - result = fix_missing_inertial(self.urdf_string) - resulting_tree = ET.ElementTree(ET.fromstring(result)) - for element in resulting_tree.iter("link"): - self.assertTrue(len([*element.iter("inertial")]) > 0) diff --git a/test/test_bullet_world.py b/test/test_bullet_world.py index ac5e0db5b..c4144ff09 100644 --- a/test/test_bullet_world.py +++ b/test/test_bullet_world.py @@ -1,6 +1,12 @@ +import unittest + +import rospkg + from bullet_world_testcase import BulletWorldTestCase from pycram.pose import Pose import numpy as np +from pycram.bullet_world import fix_missing_inertial +import xml.etree.ElementTree as ET class BulletWorldTest(BulletWorldTestCase): @@ -14,4 +20,20 @@ def test_robot_orientation(self): head_position = self.robot.get_link_position('head_pan_link').z #self.robot.set_orientation(list(2*tf.transformations.quaternion_from_euler(0, 0, np.pi, axes="sxyz"))) self.robot.set_orientation(Pose(orientation=[0, 0, 1, 1])) - self.assertEqual(self.robot.get_link_position('head_pan_link').z, head_position) \ No newline at end of file + self.assertEqual(self.robot.get_link_position('head_pan_link').z, head_position) + + +class XMLTester(unittest.TestCase): + + def setUp(self) -> None: + rospack = rospkg.RosPack() + filename = rospack.get_path('pycram') + '/resources/' + 'pr2.urdf' + with open(filename, "r") as f: + self.urdf_string = f.read() + + def test_inertial(self): + result = fix_missing_inertial(self.urdf_string) + resulting_tree = ET.ElementTree(ET.fromstring(result)) + for element in resulting_tree.iter("link"): + self.assertTrue(len([*element.iter("inertial")]) > 0) +