diff --git a/projects/hmi_simulation_project_manager/config/auto_launch.bash b/projects/hmi_simulation_project_manager/config/auto_launch.bash new file mode 100644 index 0000000..3eb7a48 --- /dev/null +++ b/projects/hmi_simulation_project_manager/config/auto_launch.bash @@ -0,0 +1,3 @@ +#!/bin/bash + +ros2 launch hmi_simulation_project_manager project_manager.launch.py \ No newline at end of file diff --git a/projects/hmi_simulation_project_manager/hmi_simulation_project_manager/__init__.py b/projects/hmi_simulation_project_manager/hmi_simulation_project_manager/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/projects/hmi_simulation_project_manager/hmi_simulation_project_manager/manager.py b/projects/hmi_simulation_project_manager/hmi_simulation_project_manager/manager.py new file mode 100644 index 0000000..4b10fd6 --- /dev/null +++ b/projects/hmi_simulation_project_manager/hmi_simulation_project_manager/manager.py @@ -0,0 +1,76 @@ +from asyncio import FastChildWatcher +import string +from tkinter.messagebox import NO +import rclpy +from rclpy.node import Node +from turtlebot4_msgs.srv import MyProgram +import subprocess +from ament_index_python.packages import get_package_share_directory, get_package_prefix + + + +class ProjectsManager(Node): + """ + The class ProjectsManager, attributes as a ROS Node that acts as a primary entrypoint + in the ROS system for communication especially for launching multiple packages from HMI display. + + Attributes: + Node: Is a class from rclpy.node.Node + More Information at: https://docs.ros2.org/latest/api/rclpy/api/node.html + + Topics: + - Services: + - Service name: /my_program + - Service desciption: + - Create a service "my_program" to trigger a bool srv "my_program_on" + - When my_program_on is set to True from client node. The my_program service + returns Success + + """ + def __init__(self): + """ + ProjectsManager constructor to initialize nodes, subscribers, publishers and parameters + """ + super().__init__('my_program_service') + self.my_program_request = self.create_service(MyProgram, 'my_program', self.project_manager_callback) + self.response_message = '' + self.response_result = False + + def project_manager_callback(self, request, response): + + self.response_message = response.message + self.response_result = response.success + # If the client requests the service with my_program_on = True, we run a bash script of launch + # Then return Success message upon successful request exectution + if(request.my_program_on): + self.get_logger().info('My Program Mode is turned on') + subprocess.call(["bash", '../projects/hmi_simulation_project_manager/config/auto_launch.bash']) + response.message = "My Program Mode received and running projects" + response.success = True + + else: + self.get_logger().info('My Program Mode rejected') + response.message = "My Program Mode rejected and failed to run projects" + response.success = False + + return response + + +def main(args=None): + """ + Main method to instantiate ROS nodes and TurtleUnDock class to undock the bot + + Args: + None + """ + rclpy.init(args=args) + + projects_manager = ProjectsManager() + + rclpy.spin(projects_manager) + + rclpy.shutdown() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/projects/hmi_simulation_project_manager/launch/project_manager.launch.py b/projects/hmi_simulation_project_manager/launch/project_manager.launch.py new file mode 100644 index 0000000..a8e1dd7 --- /dev/null +++ b/projects/hmi_simulation_project_manager/launch/project_manager.launch.py @@ -0,0 +1,45 @@ +import os +from re import X +from launch import LaunchDescription +from launch_ros.actions import Node +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration + +ARGUMENTS = [DeclareLaunchArgument('my_goal_pose', default_value='[8.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0]', + description='Goal position in X and Y coordinates')] + + +def generate_launch_description(): + HOME = os.environ.get('HOME') + directory = HOME + '/workspace/src/' + + my_list = os.listdir(directory) + + my_goal_pose = LaunchConfiguration('my_goal_pose'), + planner = Node( + package='unit02_simulation_motion_planner', + namespace='tb4_rider', + executable='tb4_rider', + name='turtlebot4_ride' + ) + estimator = Node( + package='unit02_simulation_motion_planner', + namespace='ekf', + executable='ekf', + name='extented_kalman_filter' + ) + goal_pub = Node( + package='unit02_simulation_motion_planner', + namespace='publish_goal', + executable='tb4_goal', + parameters=[ + {'my_goal_pose': LaunchConfiguration('my_goal_pose')}], + name='tb4_goal_pose' + ) + # Define LaunchDescription variable + launch_desc = LaunchDescription(ARGUMENTS) + launch_desc.add_action(planner) + launch_desc.add_action(estimator) + launch_desc.add_action(goal_pub) + + return launch_desc \ No newline at end of file diff --git a/projects/hmi_simulation_project_manager/launch/tb4_ignition.launch.py b/projects/hmi_simulation_project_manager/launch/tb4_ignition.launch.py new file mode 100644 index 0000000..6a8c625 --- /dev/null +++ b/projects/hmi_simulation_project_manager/launch/tb4_ignition.launch.py @@ -0,0 +1,41 @@ +import os +from pathlib import Path + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchContext, LaunchDescription, SomeSubstitutionsType, Substitution +from launch.actions import DeclareLaunchArgument +from launch.actions import IncludeLaunchDescription, SetEnvironmentVariable +from launch.conditions import IfCondition, LaunchConfigurationEquals +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution + +from launch_ros.actions import Node + + +ARGUMENTS = [DeclareLaunchArgument('world', default_value='bug2_world', + description='Ignition World')] + + +def generate_launch_description(): + + # Directories + pkg_turtlebot4_ignition_bringup = get_package_share_directory( + 'turtlebot4_ignition_bringup') + + # Paths + turtlebot4_ros_ignition_launch = PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'launch', 'ignition.launch.py']) + + # ROS world config + turtlebot4_ros_ignition = IncludeLaunchDescription( + PythonLaunchDescriptionSource([turtlebot4_ros_ignition_launch]), + launch_arguments=[('world', LaunchConfiguration('world'))] + ) + + + # Define LaunchDescription variable + launch_desc = LaunchDescription(ARGUMENTS) + launch_desc.add_action(turtlebot4_ros_ignition) + + return launch_desc \ No newline at end of file diff --git a/projects/hmi_simulation_project_manager/package.xml b/projects/hmi_simulation_project_manager/package.xml new file mode 100644 index 0000000..6b51ae3 --- /dev/null +++ b/projects/hmi_simulation_project_manager/package.xml @@ -0,0 +1,22 @@ + + + + hmi_simulation_project_manager + 0.0.0 + TODO: Package description + sumedh + TODO: License declaration + + rclpy + std_msgs + sensor_msgs + turtlebot4_msgs + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/projects/hmi_simulation_project_manager/resource/hmi_simulation_project_manager b/projects/hmi_simulation_project_manager/resource/hmi_simulation_project_manager new file mode 100644 index 0000000..e69de29 diff --git a/projects/hmi_simulation_project_manager/setup.cfg b/projects/hmi_simulation_project_manager/setup.cfg new file mode 100644 index 0000000..4fa95bd --- /dev/null +++ b/projects/hmi_simulation_project_manager/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/hmi_simulation_project_manager +[install] +install_scripts=$base/lib/hmi_simulation_project_manager diff --git a/projects/hmi_simulation_project_manager/setup.py b/projects/hmi_simulation_project_manager/setup.py new file mode 100644 index 0000000..838f644 --- /dev/null +++ b/projects/hmi_simulation_project_manager/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup +import os +from glob import glob + +package_name = 'hmi_simulation_project_manager' + +setup( + name=package_name, + version='0.0.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + (os.path.join('share', package_name), glob('launch/*.launch.py')), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='sumedh', + maintainer_email='sumedhrk@umd.edu', + description='TODO: Package description', + license='TODO: License declaration', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + 'manager = hmi_simulation_project_manager.manager:main', + ], + }, +) diff --git a/projects/hmi_simulation_project_manager/test/test_copyright.py b/projects/hmi_simulation_project_manager/test/test_copyright.py new file mode 100644 index 0000000..cc8ff03 --- /dev/null +++ b/projects/hmi_simulation_project_manager/test/test_copyright.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_copyright.main import main +import pytest + + +@pytest.mark.copyright +@pytest.mark.linter +def test_copyright(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found errors' diff --git a/projects/hmi_simulation_project_manager/test/test_flake8.py b/projects/hmi_simulation_project_manager/test/test_flake8.py new file mode 100644 index 0000000..27ee107 --- /dev/null +++ b/projects/hmi_simulation_project_manager/test/test_flake8.py @@ -0,0 +1,25 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main_with_errors +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc, errors = main_with_errors(argv=[]) + assert rc == 0, \ + 'Found %d code style errors / warnings:\n' % len(errors) + \ + '\n'.join(errors) diff --git a/projects/hmi_simulation_project_manager/test/test_pep257.py b/projects/hmi_simulation_project_manager/test/test_pep257.py new file mode 100644 index 0000000..b234a38 --- /dev/null +++ b/projects/hmi_simulation_project_manager/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings'