diff --git a/.vscode/settings.json b/massrobotics_amr_sender_py/.vscode/settings.json similarity index 71% rename from .vscode/settings.json rename to massrobotics_amr_sender_py/.vscode/settings.json index aedfc3c..c9086f5 100644 --- a/.vscode/settings.json +++ b/massrobotics_amr_sender_py/.vscode/settings.json @@ -5,5 +5,6 @@ ], "python.testing.unittestEnabled": false, "python.testing.nosetestsEnabled": false, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "restructuredtext.confPath": "" } \ No newline at end of file diff --git a/massrobotics_amr_sender_py/CHANGELOG.rst b/massrobotics_amr_sender_py/CHANGELOG.rst new file mode 100644 index 0000000..4df82c2 --- /dev/null +++ b/massrobotics_amr_sender_py/CHANGELOG.rst @@ -0,0 +1,24 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package massrobotics_amr_sender +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +0.0.2 (2021-06-24) +------------------- +* Changed package name to ``massrobotics_amr_sender`` +* Changed repository folder organization + +0.0.1 (2021-06-23) +------------------- +* Added support for Identity and Status reports +* Added support for several ROS2 messages + + * ``geometry_msgs/TwistStamped`` + * ``sensor_msgs/BatteryState`` + * ``geometry_msgs/PoseStamped`` + * ``nav_msgs/Path`` + * ``std_msgs/String`` + * ``std_msgs/Float32`` + * ``std_msgs/Float64`` + +* Added unit tests for all message callbacks +* Added ``3-Clause BSD License`` \ No newline at end of file diff --git a/CONTRIBUTING.md b/massrobotics_amr_sender_py/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to massrobotics_amr_sender_py/CONTRIBUTING.md diff --git a/README.md b/massrobotics_amr_sender_py/README.md similarity index 60% rename from README.md rename to massrobotics_amr_sender_py/README.md index 2f93c0a..ce3968f 100644 --- a/README.md +++ b/massrobotics_amr_sender_py/README.md @@ -1,15 +1,16 @@ -# ros2-to-mass-amr-interop +# massrobotics_amr_sender -Configuration-based ROS2 package for sending MassRobotics [AMR Standard messages](https://github.com/MassRobotics-AMR/AMR_Interop_Standard) to complaint receivers. +Configuration-based ROS2 package for sending MassRobotics [AMR Interop Standard messages](https://github.com/MassRobotics-AMR/AMR_Interop_Standard) to complaint receivers. -## Installing +## Running from source Make sure `ros2` is installed properly. Clone this repository inside your `src` folder on your local workspace and build the package: ```bash mkdir -p ~/ros2_ws/src && cd ros2_ws/ -git clone https://github.com/inorbit-ai/ros2-to-mass-amr-interop.git ./src -colcon build --packages-select ros2-to-mass-amr-interop +git clone https://github.com/inorbit-ai/ros_amr_interop.git ./src + +colcon build --packages-select massrobotics_amr_sender ``` ## Running the node @@ -20,7 +21,7 @@ The node takes the Mass AMR config file path as parameter. If not provided, it i # Source the local overlay by running `. install/setup.sh` if # using bash or `. install/setup.zsh` if using zsh. # Also, install dependencies by running `rosdep install --ignore-src --from-paths src/` -ros2 run ros2_to_mass_amr_interop ros2_to_mass_node \ +ros2 run massrobotics_amr_sender massrobotics_amr_node \ --ros-args -p config_file:=/path/to/config.yaml --log-level debug ``` @@ -29,6 +30,6 @@ ros2 run ros2_to_mass_amr_interop ros2_to_mass_node \ On you local workspace: ```bash -colcon test --packages-select ros2-to-mass-amr-interop +colcon test --packages-select massrobotics_amr_sender colcon test-result --verbose ``` diff --git a/ros2_to_mass_amr_interop/__init__.py b/massrobotics_amr_sender_py/massrobotics_amr_sender/__init__.py similarity index 98% rename from ros2_to_mass_amr_interop/__init__.py rename to massrobotics_amr_sender_py/massrobotics_amr_sender/__init__.py index 50f4443..91ceb66 100644 --- a/ros2_to_mass_amr_interop/__init__.py +++ b/massrobotics_amr_sender_py/massrobotics_amr_sender/__init__.py @@ -47,7 +47,7 @@ from .config import CFG_PARAMETER_ENVVAR from .config import CFG_PARAMETER_ROS_TOPIC from .config import CFG_PARAMETER_ROS_PARAMETER # noqa: F401 -from .config import MassAMRInteropConfig +from .config import MassRoboticsAMRInteropConfig from .config import STATUS_REPORT_INTERVAL @@ -60,9 +60,9 @@ def timestamp_to_isoformat(timestamp): return datetime.fromtimestamp(timestamp).replace(microsecond=0).astimezone().isoformat() -class MassAMRInteropNode(Node): +class MassRoboticsAMRInteropNode(Node): """ - ROS node implementing WebSocket communication to Mass. + ROS node implementing WebSocket communication to MassRobotics AMR Receiver. The node configuration is obtained from a configuration file that can be provided externally. On initialization, the node subscribes to various @@ -192,7 +192,7 @@ def _read_config_file(self, config_file_path): raise ValueError(f"Configuration file '{config_file_path}' doesn't exist!") self.logger.info(f"Using configuration file '{config_file_path}'") - return MassAMRInteropConfig(str(config_file_path)) + return MassRoboticsAMRInteropConfig(str(config_file_path)) def _get_frame_id_from_header(self, msg): msg_frame_id = msg.header.frame_id diff --git a/ros2_to_mass_amr_interop/config.py b/massrobotics_amr_sender_py/massrobotics_amr_sender/config.py similarity index 99% rename from ros2_to_mass_amr_interop/config.py rename to massrobotics_amr_sender_py/massrobotics_amr_sender/config.py index 4d78537..8a07f64 100644 --- a/ros2_to_mass_amr_interop/config.py +++ b/massrobotics_amr_sender_py/massrobotics_amr_sender/config.py @@ -49,7 +49,7 @@ STATUS_REPORT_INTERVAL = 1 -class MassAMRInteropConfig: +class MassRoboticsAMRInteropConfig: """ Configuration file parsing and value gathering. diff --git a/ros2_to_mass_amr_interop/ros2_to_mass_node.py b/massrobotics_amr_sender_py/massrobotics_amr_sender/massrobotics_amr_node.py similarity index 95% rename from ros2_to_mass_amr_interop/ros2_to_mass_node.py rename to massrobotics_amr_sender_py/massrobotics_amr_sender/massrobotics_amr_node.py index af13eec..09351ba 100644 --- a/ros2_to_mass_amr_interop/ros2_to_mass_node.py +++ b/massrobotics_amr_sender_py/massrobotics_amr_sender/massrobotics_amr_node.py @@ -30,14 +30,14 @@ import rclpy -from . import MassAMRInteropNode +from . import MassRoboticsAMRInteropNode # Interesting example https://github.com/clalancette/mtexec_example def main(args=None): rclpy.init(args=args) - node = MassAMRInteropNode() + node = MassRoboticsAMRInteropNode() rclpy.spin(node) rclpy.shutdown() diff --git a/ros2_to_mass_amr_interop/messages/__init__.py b/massrobotics_amr_sender_py/massrobotics_amr_sender/messages/__init__.py similarity index 100% rename from ros2_to_mass_amr_interop/messages/__init__.py rename to massrobotics_amr_sender_py/massrobotics_amr_sender/messages/__init__.py diff --git a/ros2_to_mass_amr_interop/messages/schema.json b/massrobotics_amr_sender_py/massrobotics_amr_sender/messages/schema.json similarity index 100% rename from ros2_to_mass_amr_interop/messages/schema.json rename to massrobotics_amr_sender_py/massrobotics_amr_sender/messages/schema.json diff --git a/package.xml b/massrobotics_amr_sender_py/package.xml similarity index 88% rename from package.xml rename to massrobotics_amr_sender_py/package.xml index 8240939..1f622d2 100644 --- a/package.xml +++ b/massrobotics_amr_sender_py/package.xml @@ -1,9 +1,9 @@ - ros2-to-mass-amr-interop - 0.0.1 - MassRobotics AMR Interop Standard implementation + massrobotics_amr_sender + 0.0.2 + MassRobotics AMR Interop Sender leandro 3-Clause BSD License diff --git a/resource/ros2_to_mass_amr_interop b/massrobotics_amr_sender_py/resource/massrobotics_amr_sender similarity index 100% rename from resource/ros2_to_mass_amr_interop rename to massrobotics_amr_sender_py/resource/massrobotics_amr_sender diff --git a/sample_config.yaml b/massrobotics_amr_sender_py/sample_config.yaml similarity index 96% rename from sample_config.yaml rename to massrobotics_amr_sender_py/sample_config.yaml index beff0bb..17cdd19 100644 --- a/sample_config.yaml +++ b/massrobotics_amr_sender_py/sample_config.yaml @@ -1,8 +1,8 @@ -# ================================================================== -# ROS2 to Mass AMR Interoperability Standard node configuration file -# ================================================================== +# ==================================================================== +# MassRobotics AMR Interoperability Standard sender configuration file +# ==================================================================== # -# Parameters that are used to configure ROS2 node for connecting to Mass compatible servers. +# Parameters that are used to configure ROS2 node for connecting to MassRobotics compatible servers. # The `server` section expects a string with a WebSocket server URI, while the `mappings` section # contains a list of paramaters for configuring the ROS2 node. As per AMR Interop Standard, # mandatory parameters are `uuid`, `manufacturerName`, `robotModel`, `robotSerialNumber` and diff --git a/massrobotics_amr_sender_py/setup.cfg b/massrobotics_amr_sender_py/setup.cfg new file mode 100644 index 0000000..bbbb2f8 --- /dev/null +++ b/massrobotics_amr_sender_py/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script-dir=$base/lib/massrobotics_amr_sender +[install] +install-scripts=$base/lib/massrobotics_amr_sender \ No newline at end of file diff --git a/setup.py b/massrobotics_amr_sender_py/setup.py similarity index 67% rename from setup.py rename to massrobotics_amr_sender_py/setup.py index d779c86..9d94d6c 100644 --- a/setup.py +++ b/massrobotics_amr_sender_py/setup.py @@ -1,13 +1,13 @@ from setuptools import setup, find_packages -package_name = 'ros2_to_mass_amr_interop' +package_name = 'massrobotics_amr_sender' setup( name=package_name, packages=find_packages(), package_data={'': ['schema.json']}, include_package_data=True, - version='0.1.0', + version='0.0.2', data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), @@ -17,12 +17,12 @@ zip_safe=True, maintainer='InOrbit', maintainer_email='support@inorbit.ai', - description='ROS2 node implementing MassRobotics AMR Interoperability Standard', - license='TODO: License declaration', + description='ROS2 node implementing a MassRobotics AMR Interoperability Sender', + license='3-Clause BSD License', tests_require=['pytest'], entry_points={ 'console_scripts': [ - 'ros2_to_mass_node = ros2_to_mass_amr_interop.ros2_to_mass_node:main' + 'massrobotics_amr_node = massrobotics_amr_sender.massrobotics_amr_node:main' ], }, ) diff --git a/test/README.md b/massrobotics_amr_sender_py/test/README.md similarity index 100% rename from test/README.md rename to massrobotics_amr_sender_py/test/README.md diff --git a/test/scripts/demo_emulation.sh b/massrobotics_amr_sender_py/test/scripts/demo_emulation.sh similarity index 100% rename from test/scripts/demo_emulation.sh rename to massrobotics_amr_sender_py/test/scripts/demo_emulation.sh diff --git a/test/test_copyright.py b/massrobotics_amr_sender_py/test/test_copyright.py similarity index 100% rename from test/test_copyright.py rename to massrobotics_amr_sender_py/test/test_copyright.py diff --git a/test/test_flake8.py b/massrobotics_amr_sender_py/test/test_flake8.py similarity index 100% rename from test/test_flake8.py rename to massrobotics_amr_sender_py/test/test_flake8.py diff --git a/test/test_mass_interop.py b/massrobotics_amr_sender_py/test/test_mass_interop.py similarity index 97% rename from test/test_mass_interop.py rename to massrobotics_amr_sender_py/test/test_mass_interop.py index 4ec9161..6e4d767 100644 --- a/test/test_mass_interop.py +++ b/massrobotics_amr_sender_py/test/test_mass_interop.py @@ -34,7 +34,7 @@ from rclpy import Parameter from pathlib import Path from unittest.mock import AsyncMock -from ros2_to_mass_amr_interop import MassAMRInteropNode +from massrobotics_amr_sender import MassRoboticsAMRInteropNode from std_msgs import msg as ros_std_msgs from geometry_msgs import msg as ros_geometry_msgs @@ -91,7 +91,7 @@ def mock_ws_conn(mocker): def _fake_status_publisher_thread(): pass - mocker.patch('ros2_to_mass_amr_interop.MassAMRInteropNode._status_publisher_thread', + mocker.patch('massrobotics_amr_sender.MassRoboticsAMRInteropNode._status_publisher_thread', side_effect=_fake_status_publisher_thread) @@ -113,13 +113,13 @@ def test_mass_config_load_fails_on_missing_config_file(monkeypatch): monkeypatch.delenv("MY_UUID") rclpy.init() with pytest.raises(ValueError): - MassAMRInteropNode() + MassRoboticsAMRInteropNode() rclpy.shutdown() -def test_ros2_to_mass_node_init(): +def test_massrobotics_amr_node_init(): rclpy.init() - node = MassAMRInteropNode(parameter_overrides=[ + node = MassRoboticsAMRInteropNode(parameter_overrides=[ Parameter("config_file", value=str(config_file_test)) ]) rclpy.spin_once(node, timeout_sec=.1) @@ -343,10 +343,10 @@ def test_ros2_to_mass_node_init(): ] -def test_ros2_to_mass_node_status_report_callbacks(event_loop): +def test_massrobotics_amr_node_status_report_callbacks(event_loop): rclpy.init() # create the node we want to test - node = MassAMRInteropNode(parameter_overrides=[ + node = MassRoboticsAMRInteropNode(parameter_overrides=[ Parameter("config_file", value=str(config_file_test)) ]) # also create an additional node to publish messages diff --git a/test/test_mass_interop_config.py b/massrobotics_amr_sender_py/test/test_mass_interop_config.py similarity index 85% rename from test/test_mass_interop_config.py rename to massrobotics_amr_sender_py/test/test_mass_interop_config.py index b2a0cfb..db4423a 100644 --- a/test/test_mass_interop_config.py +++ b/massrobotics_amr_sender_py/test/test_mass_interop_config.py @@ -29,17 +29,17 @@ import pytest from pathlib import Path -from ros2_to_mass_amr_interop.config import MassAMRInteropConfig -from ros2_to_mass_amr_interop.config import CFG_PARAMETER_LOCAL -from ros2_to_mass_amr_interop.config import CFG_PARAMETER_ROS_TOPIC -from ros2_to_mass_amr_interop.config import CFG_PARAMETER_ENVVAR +from massrobotics_amr_sender.config import MassRoboticsAMRInteropConfig +from massrobotics_amr_sender.config import CFG_PARAMETER_LOCAL +from massrobotics_amr_sender.config import CFG_PARAMETER_ROS_TOPIC +from massrobotics_amr_sender.config import CFG_PARAMETER_ENVVAR cwd = Path(__file__).resolve().parent def test_mass_config_load(): cfg_file_path = Path(cwd).parent / "sample_config.yaml" - assert MassAMRInteropConfig(str(cfg_file_path)).mappings != {} + assert MassRoboticsAMRInteropConfig(str(cfg_file_path)).mappings != {} @pytest.mark.parametrize("param_name, param_type", [ @@ -51,7 +51,7 @@ def test_mass_config_load(): ]) def test_mass_config_get_parameter_type(param_name, param_type): cfg_file_path = Path(cwd).parent / "sample_config.yaml" - mass_config = MassAMRInteropConfig(str(cfg_file_path)) + mass_config = MassRoboticsAMRInteropConfig(str(cfg_file_path)) assert mass_config.get_parameter_source(param_name) == param_type @@ -64,7 +64,7 @@ def test_mass_config_get_parameter_type(param_name, param_type): def test_mass_config_get_parameter_value(monkeypatch, param_name, value): monkeypatch.setenv("MY_UUID", "foo") # Environment variable used on config file cfg_file_path = Path(cwd).parent / "sample_config.yaml" - mass_config = MassAMRInteropConfig(str(cfg_file_path)) + mass_config = MassRoboticsAMRInteropConfig(str(cfg_file_path)) assert mass_config.get_parameter_value(param_name) == value @@ -78,5 +78,5 @@ def test_mass_config_get_parameter_value(monkeypatch, param_name, value): def test_mass_config_get_parameters_by_source(monkeypatch, param_name, source): monkeypatch.setenv("MY_UUID", "foo") # Environment variable used on config file cfg_file_path = Path(cwd).parent / "sample_config.yaml" - mass_config = MassAMRInteropConfig(str(cfg_file_path)) + mass_config = MassRoboticsAMRInteropConfig(str(cfg_file_path)) assert param_name in mass_config.parameters_by_source[source] diff --git a/test/test_pep257.py b/massrobotics_amr_sender_py/test/test_pep257.py similarity index 100% rename from test/test_pep257.py rename to massrobotics_amr_sender_py/test/test_pep257.py diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f5fd2fc..0000000 --- a/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[develop] -script-dir=$base/lib/ros2_to_mass_amr_interop -[install] -install-scripts=$base/lib/ros2_to_mass_amr_interop \ No newline at end of file