diff --git a/CMakeLists.txt b/CMakeLists.txt
index a3f9f81..782435d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,10 +18,11 @@ cmake_minimum_required(VERSION 3.5)
# Set proyect name
-project(micro_ros_agent)
+project(uros_agent)
# Find packages depencences
+find_package(rosidl_cmake REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(fastcdr REQUIRED CONFIG)
find_package(fastrtps REQUIRED CONFIG)
@@ -35,26 +36,178 @@ ament_export_dependencies(fastrtps)
ament_export_dependencies(micrortps_agent)
-# Install python files
-ament_python_install_package(${PROJECT_NAME})
+# Set variables
+set(_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/python")
+
+set(_XML_INTERFACE_GEN_BIN "${_OUTPUT_PATH}/bin/Xml_interface_gen.py")
+normalize_path(_XML_INTERFACE_GEN_BIN "${_XML_INTERFACE_GEN_BIN}")
+
+set(_XML_DEFAULT_READ_BIN "${_OUTPUT_PATH}/bin/Xml_read_default_profiles.py")
+normalize_path(_XML_DEFAULT_READ_BIN "${_XML_DEFAULT_READ_BIN}")
+
+set(_PYTHON_PKG_TOOL ${PROJECT_NAME})
+
+set(_RESOURCE_DIR "${_OUTPUT_PATH}/resource")
+normalize_path(_RESOURCE_DIR "${_RESOURCE_DIR}")
-# Register package resource in order to be called when a new msg package is generated
-ament_index_register_resource("rosidl_typesupport_c")
+set(_DEFAULT_FASTRTPS_PROFILES_PATH "${_OUTPUT_PATH}/gen/DEFAULT_FASTRTPS_PROFILES.xml")
+normalize_path(_DEFAULT_FASTRTPS_PROFILES_PATH "${_DEFAULT_FASTRTPS_PROFILES_PATH}")
+
+
+# Get colcon call dir
+get_filename_component(_COLCON_CALL_DIR "${CMAKE_INSTALL_PREFIX}" DIRECTORY)
+get_filename_component(_COLCON_CALL_DIR "${_COLCON_CALL_DIR}" DIRECTORY)
+
+
+# Generate python header
+set(
+_PYTHON_SCRIPT_HEAD
+"
+import os\n
+import sys\n
+sys.path.append('${_OUTPUT_PATH}')\n
+from ${_PYTHON_PKG_TOOL} import *\n
+"
+)
+
+
+# Copy pyton files
+file(COPY "bin" "${_PYTHON_PKG_TOOL}" "resource" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/python")
+
+
+# Extract all packages and manifiest paths
+execute_process(
+ COMMAND
+ "${PYTHON_EXECUTABLE}"
+ "-c"
+ "${_PYTHON_SCRIPT_HEAD}for package in GetInterfacePackages(GetPackageList('${_COLCON_CALL_DIR}')): print ('%s,%s' % (package, GetPackageName(package)))"
+ OUTPUT_VARIABLE _packages
+ RESULT_VARIABLE _result
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if(NOT _result EQUAL 0)
+ message(FATAL_ERROR "Error finding xml packages")
+endif()
+
+
+# Convert output to list
+string(REPLACE "\n" ";" _packages ${_packages})
+
+
+# Extract all msg from each package (stored in ${package}_MSG_FILES)
+set(ALL_MSG_FILES "")
+foreach(package ${_packages})
+
+ # Extract info
+ string(REPLACE "," ";" package ${package})
+ list(GET package 0 package_file)
+ list(GET package 1 package)
+
+
+ # Get all msg files
+ execute_process(
+ COMMAND
+ "${PYTHON_EXECUTABLE}"
+ "-c"
+ "${_PYTHON_SCRIPT_HEAD}for msg in GetInterfacePackageMsgs('${package_file}'): print ('%s' % msg)"
+ OUTPUT_VARIABLE ${package}_MSG_FILES
+ RESULT_VARIABLE _result
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT _result EQUAL 0)
+ message(FATAL_ERROR "Error finding .msg files")
+ endif()
+
+ # Skip if there are no msgs to create
+ if(${package}_MSG_FILES STREQUAL "")
+ continue()
+ endif()
+
+ # Generate list
+ string(REPLACE "\n" ";" ${package}_MSG_FILES ${${package}_MSG_FILES})
+
+endforeach()
+
+
+# Append defaul xml profiles
+execute_process(
+ COMMAND "${PYTHON_EXECUTABLE}" "${_XML_DEFAULT_READ_BIN}" "--default-xml-path" "${_RESOURCE_DIR}"
+ OUTPUT_VARIABLE _XmlDoc
+ RESULT_VARIABLE _result
+ )
+if(NOT _result EQUAL 0)
+ message(FATAL_ERROR "Error in typesuppor generation")
+endif()
+
+
+# Create one xml for each message
+foreach(package ${_packages})
+ string(REPLACE "," ";" package ${package})
+ list(GET package 0 package_file)
+ list(GET package 1 package)
+
+
+ # Skip this generation if there are no msgs to process
+ if(${package}_MSG_FILES STREQUAL "")
+ continue()
+ endif()
+
+
+
+ # generate script argument file
+ set(generator_arguments_file "${_OUTPUT_PATH}/XML_ArgFiles/${package}_Args.json")
+ rosidl_write_generator_arguments(
+ "${generator_arguments_file}"
+ PACKAGE_NAME "${package}"
+ ROS_INTERFACE_FILES "${${package}_MSG_FILES}"
+ ROS_INTERFACE_DEPENDENCIES "NULL"
+ OUTPUT_DIR "NULL"
+ TEMPLATE_DIR "NULL"
+ TARGET_DEPENDENCIES "NULL"
+ ADDITIONAL_FILES ""
+ )
+
+
+ # execute python script
+ execute_process(
+ COMMAND "${PYTHON_EXECUTABLE}" "${_XML_INTERFACE_GEN_BIN}" --generator-arguments-file "${generator_arguments_file}"
+ OUTPUT_VARIABLE _XmlGen
+ RESULT_VARIABLE _result
+ )
+ if(NOT _result EQUAL 0)
+ message(FATAL_ERROR "Error in typesuppor generation")
+ endif()
+
+
+ # Strore xml
+ set(_XmlDoc "${_XmlDoc}${_XmlGen}")
+
+endforeach()
+
+
+# Close profile
+set (_XmlDoc "\n${_XmlDoc}\n")
+
+
+# Save
+file(WRITE "${_DEFAULT_FASTRTPS_PROFILES_PATH}" "${_XmlDoc}")
+
# Install the package.xml file, and generate code for ``find_package`` so that other packages can get information about this package.
-ament_package(
- CONFIG_EXTRAS "micro_ros_agent-extras.cmake.in"
+ament_package()
+
+
+#Install
+install(
+ FILES "${_DEFAULT_FASTRTPS_PROFILES_PATH}"
+ DESTINATION "../micrortps_agent/bin"
)
-install(
- PROGRAMS bin/micro_ros_agent
- DESTINATION lib/micro_ros_agent
-)
-
-install(
- DIRECTORY cmake resource
- DESTINATION share/${PROJECT_NAME}
-)
\ No newline at end of file
+# Install package
+#install(
+# DIRECTORY cmake resource
+# DESTINATION share/${PROJECT_NAME}
+#)
\ No newline at end of file
diff --git a/bin/Xml_interface_gen.py b/bin/Xml_interface_gen.py
new file mode 100644
index 0000000..07fdb7d
--- /dev/null
+++ b/bin/Xml_interface_gen.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)),'..'))
+
+from rosidl_cmake import read_generator_arguments
+from rosidl_parser import UnknownMessageType
+from uros_agent import generate_XML
+
+
+def main(argv=sys.argv[1:]):
+ parser = argparse.ArgumentParser(
+ description='Generate the C interfaces for Micro RTPS.',
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument(
+ '--generator-arguments-file',
+ required=True,
+ help='The location of the file containing the generator arguments')
+ args = parser.parse_args(argv)
+
+ generator_args = read_generator_arguments(args.generator_arguments_file)
+ rc = generate_XML(generator_args)
+ return rc
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/bin/Xml_read_default_profiles.py b/bin/Xml_read_default_profiles.py
new file mode 100644
index 0000000..001d256
--- /dev/null
+++ b/bin/Xml_read_default_profiles.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import argparse
+import xml.etree.ElementTree
+
+sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)),'..'))
+
+from uros_agent import *
+
+def main(argv=sys.argv[1:]):
+ parser = argparse.ArgumentParser(
+ description='Import default xml files',
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument(
+ '--default-xml-path',
+ required=True,
+ help='The location of the default profiles')
+ args = parser.parse_args(argv)
+ ReadDefaultXMLs(args.default_xml_path)
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
\ No newline at end of file
diff --git a/bin/micro_ros_agent b/bin/micro_ros_agent
deleted file mode 100644
index a717221..0000000
--- a/bin/micro_ros_agent
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-import sys
-
-from rosidl_cmake import read_generator_arguments
-from rosidl_parser import UnknownMessageType
-from micro_ros_agent import generate_micro_ros_agent_xml_support
-
-def is_valid_file(parser, file_name):
- if not os.path.exists(file_name):
- parser.error("File does not exist: '{0}'".format(file_name))
- file_name_abs = os.path.abspath(file_name)
- if not os.path.isfile(file_name_abs):
- parser.error("Path exists but is not a file: '{0}'".format(file_name_abs))
- return file_name
-
-
-def main(argv=sys.argv[1:]):
- parser = argparse.ArgumentParser(
- description='Generate xml files for micrortps agent.',
- formatter_class=argparse.ArgumentDefaultsHelpFormatter)
- parser.add_argument(
- '--generator-arguments-file',
- required=True,
- help='The location of the file containing the generator arguments')
- args = parser.parse_args(argv)
-
- generator_args = read_generator_arguments(args.generator_arguments_file)
-
- try:
- rc = generate_micro_ros_agent_xml_support(generator_args)
-
- return 0
- except UnknownMessageType as e:
- print(str(e), file=sys.stderr)
- return 1
- if rc:
- return rc
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/cmake/micrortps_agent_xml_generator.cmake b/cmake/micrortps_agent_xml_generator.cmake
deleted file mode 100644
index 6f269f0..0000000
--- a/cmake/micrortps_agent_xml_generator.cmake
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2016-2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
-#
-# 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.
-
-
-# list msg files
-set(_ros_idl_files "")
-foreach(_idl_file ${rosidl_generate_interfaces_IDL_FILES})
- get_filename_component(_extension "${_idl_file}" EXT)
- # Skip .srv files
- if(_extension STREQUAL ".msg")
- list(APPEND _ros_idl_files "${_idl_file}")
- endif()
-endforeach()
-
-
-# Set output dir
-set(_output_path "${CMAKE_CURRENT_BINARY_DIR}/../micro_ros_agent/xml_gen")
-
-
-# check if all templates exits
-set(target_dependencies
- "${micro_ros_agent_BIN}"
- "${micro_ros_agent_GENERATOR_FILES}"
- ${rosidl_generate_interfaces_IDL_FILES}
- ${_dependency_files})
-foreach(dep ${target_dependencies})
- if(NOT EXISTS "${dep}")
- message(FATAL_ERROR "Target dependency '${dep}' does not exist")
- endif()
-endforeach()
-
-
-# generate script argument file
-set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/micro_ros_agent__arguments.json")
-rosidl_write_generator_arguments(
- "${generator_arguments_file}"
- PACKAGE_NAME "${PROJECT_NAME}"
- ROS_INTERFACE_FILES "${rosidl_generate_interfaces_IDL_FILES}"
- ROS_INTERFACE_DEPENDENCIES "${_dependencies}"
- OUTPUT_DIR "${_output_path}"
- TEMPLATE_DIR "${micro_ros_agent_DEFAULT_PROFILES_DIR}"
- TARGET_DEPENDENCIES ${target_dependencies}
- ADDITIONAL_FILES ${_dds_idl_files}
-)
-
-
-# Execute python script
-execute_process(
- COMMAND ${PYTHON_EXECUTABLE} ${micro_ros_agent_BIN}
- --generator-arguments-file "${generator_arguments_file}"
- )
-
-
-#Install
-install(
- DIRECTORY "${_output_path}/"
- DESTINATION "../micrortps_agent/bin"
-)
\ No newline at end of file
diff --git a/micro_ros_agent-extras.cmake.in b/micro_ros_agent-extras.cmake.in
deleted file mode 100644
index aa4e047..0000000
--- a/micro_ros_agent-extras.cmake.in
+++ /dev/null
@@ -1,14 +0,0 @@
-find_package(ament_cmake_core QUIET REQUIRED)
-ament_register_extension(
- "rosidl_generate_interfaces"
- "micro_ros_agent"
- "micrortps_agent_xml_generator.cmake")
-
-set(micro_ros_agent_BIN "${micro_ros_agent_DIR}/../../../lib/micro_ros_agent/micro_ros_agent")
-normalize_path(micro_ros_agent_BIN "${micro_ros_agent_BIN}")
-
-set(micro_ros_agent_GENERATOR_FILES "${micro_ros_agent_DIR}/../../../@PYTHON_INSTALL_DIR@/micro_ros_agent/__init__.py")
-normalize_path(micro_ros_agent_GENERATOR_FILES "${micro_ros_agent_GENERATOR_FILES}")
-
-set(micro_ros_agent_DEFAULT_PROFILES_DIR "${micro_ros_agent_DIR}/../resource")
-normalize_path(micro_ros_agent_DEFAULT_PROFILES_DIR "${micro_ros_agent_DEFAULT_PROFILES_DIR}")
\ No newline at end of file
diff --git a/package.xml b/package.xml
index 461ed8a..f895d2a 100644
--- a/package.xml
+++ b/package.xml
@@ -1,8 +1,8 @@
- micro_ros_agent
- 0.0.1
+ uros_agent
+ 0.0.2
DDS-XCRE agent implementation
Javier Moreno
Apache License 2.0
@@ -15,11 +15,12 @@
fastcdr
fastrtps
micrortps_agent
+ rosidl_cmake
ament_lint_auto
ament_lint_common
- rosidl_typesupport_c_packages
+ rosidl_interface_packages
ament_cmake
diff --git a/micro_ros_agent/__init__.py b/uros_agent/__init__.py
similarity index 54%
rename from micro_ros_agent/__init__.py
rename to uros_agent/__init__.py
index 34ad0b0..a785b15 100644
--- a/micro_ros_agent/__init__.py
+++ b/uros_agent/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2016-2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+# Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,19 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import struct
import os
import sys
-
-if os.name == 'nt':
- import win32con
- import win32file
- import pywintypes
- __overlapped = pywintypes.OVERLAPPED()
-elif os.name == 'posix':
- import fcntl
-else:
- raise RuntimeError('PortaLocker only defined for nt and posix platforms')
+import xml.etree.ElementTree
from rosidl_cmake import convert_camel_case_to_lower_case_underscore
from rosidl_cmake import expand_template
@@ -33,14 +23,103 @@ from rosidl_cmake import get_newest_modification_time
from rosidl_parser import parse_message_file
from rosidl_parser import parse_service_file
from rosidl_parser import validate_field_types
-from shutil import copyfile
-from pathlib import Path
-def generate_micro_ros_agent_xml_support(args):
+def GetPackage(Dir):
+
+ # ignore?
+ for f in os.listdir(Dir):
+ full_path = os.path.join(Dir, f)
+ if os.path.isfile(full_path):
+ if f == "COLCON_IGNORE":
+ return "COLCON_IGNORE"
+
+ # found package
+ found_package_path = ""
+ for f in os.listdir(Dir):
+ if f == "package.xml":
+ found_package_path = os.path.join(Dir, f)
+ found_package_path = os.path.abspath(found_package_path)
+ break
+
+
+ return found_package_path
+
+
+def GetPackageList(Dir):
+ package_list = []
+ package_path = GetPackage(Dir)
+
+ if package_path == "":
+ for f in os.listdir(Dir):
+ full_path = os.path.join(Dir, f)
+ if os.path.isdir(full_path):
+ for l in GetPackageList(full_path):
+ package_list.append(l)
+ elif package_path != "COLCON_IGNORE":
+ package_list.append(package_path)
+
+ return package_list
+
+
+def GetInterfacePackages(packages_list):
+ package_interface_list = []
+ for package in packages_list:
+ xml_root = xml.etree.ElementTree.parse(package).getroot()
+ for element in xml_root.findall('member_of_group'):
+ if element.text == "rosidl_interface_packages":
+ package_interface_list.append(package)
+ return package_interface_list
+
+
+def GetPackageName(package_path):
+ xml_root = xml.etree.ElementTree.parse(package_path).getroot()
+ xml_name_elements = xml_root.findall('name')
+ if len(xml_name_elements) != 1:
+ return ""
+ else:
+ return xml_name_elements[0].text
+
+
+def GetInterfacePackageMsgs(package_path):
+ msg_list = []
+ package_dir = os.path.dirname(package_path)
+ for root, dirs, files in os.walk(package_dir):
+ for file in files:
+ if file.endswith(".msg"):
+ full_path = os.path.join(root, file)
+ msg_list.append(full_path)
+
+ return msg_list
+
+def GetInterfacePackageSrvs(package_path):
+ msg_list = []
+ package_dir = os.path.dirname(package_path)
+ for root, dirs, files in os.walk(package_dir):
+ for file in files:
+ if file.endswith(".srv"):
+ full_path = os.path.join(root, file)
+ msg_list.append(full_path)
+
+ return msg_list
+
+
+def ReadDefaultXMLs(Path):
+ for f in os.listdir(Path):
+ full_path = os.path.join(Path, f)
+ if os.path.isfile(full_path) and f.endswith(".xml"):
+ #xml_root = xml.etree.ElementTree.parse(full_path).getroot()
+ #if xml_root.iselement():
+ fd = open(full_path)
+ print ("%s" % fd.read())
+ fd.close()
+
+
+
+def generate_XML(args):
pkg_name = args['package_name']
- known_msg_types = extract_message_types(
- pkg_name, args['ros_interface_files'], args.get('ros_interface_dependencies', []))
+ #known_msg_types = extract_message_types(
+ # pkg_name, args['ros_interface_files'], args.get('ros_interface_dependencies', []))
functions = {
'get_header_filename_from_msg_name': convert_camel_case_to_lower_case_underscore,
@@ -48,7 +127,6 @@ def generate_micro_ros_agent_xml_support(args):
# Set file format
- file_format = ".xml"
ros2_prefix = "rt/"
@@ -63,14 +141,6 @@ def generate_micro_ros_agent_xml_support(args):
if not os.path.exists(srcs_dir):
os.makedirs(srcs_dir)
-
- # Copy all included xml files
- for filename in os.listdir(args['template_dir']):
- if filename.endswith(file_format):
- template_src_path = os.path.join(args['template_dir'], filename)
- template_dest_path = os.path.join(srcs_dir, filename)
- if not os.path.isfile(template_dest_path):
- copyfile(template_src_path, template_dest_path)
# Iterate throw all msgs/srvs
@@ -78,7 +148,7 @@ def generate_micro_ros_agent_xml_support(args):
extension = os.path.splitext(idl_file)[1]
if extension == '.msg':
spec = parse_message_file(pkg_name, idl_file)
- validate_field_types(spec, known_msg_types)
+ #validate_field_types(spec, known_msg_types)
subfolder = os.path.basename(os.path.dirname(idl_file))
data = {
@@ -137,95 +207,9 @@ def generate_micro_ros_agent_xml_support(args):
# Write file content
- fd1 = open(src_file, "w")
- if os.name == 'nt':
- # Lock
- hfile1 = win32file._get_osfhandle(fd1.fileno())
- win32file.LockFileEx(hfile1, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped)
-
- # Write
- fd1.write(file_content)
-
- # Unlock
- win32file.UnlockFileEx(hfile1, 0, -0x10000, __overlapped)
- elif os.name == 'posix':
- # Lock
- fcntl.flock(fd1.fileno(), fcntl.LOCK_EX)
-
- # Write
- fd1.write(file_content)
-
- # Unlock
- fcntl.flock(fd1.fileno(), fcntl.LOCK_UN)
- fd1.close()
+ print ("%s" % file_content)
- # Open collect file
- collec_file = os.path.join(args['output_dir'], "DEFAULT_FASTRTPS_PROFILES.xml")
- fd2 = open(collec_file, "w")
- if os.name == 'nt':
- # Lock
- hfile2 = win32file._get_osfhandle(fd2.fileno())
- win32file.LockFileEx(hfile2, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped)
-
- # Generate head
- fd2.write("\n")
-
- # Append all files contents
- for filename in os.listdir(srcs_dir):
- if filename.endswith(".xml"):
- # Open
- fd3 = open(os.path.join(srcs_dir, filename), "r+")
-
- # Lock
- hfile3 = win32file._get_osfhandle(fd3.fileno())
- win32file.LockFileEx(hfile3, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped)
-
- # Write
- fd2.write(fd3.read())
-
- # Unlock
- win32file.UnlockFileEx(hfile3, 0, -0x10000, __overlapped)
- fd3.close()
-
- # Generate tail
- fd2.write("\n")
-
- # UnLock
- win32file.UnlockFileEx(hfile2, 0, -0x10000, __overlapped)
- elif os.name == 'posix':
- # Lock
- fcntl.flock(fd2.fileno(), fcntl.LOCK_EX)
-
- # Generate head
- fd2.write("\n")
-
- # Append all files contents
- for filename in os.listdir(srcs_dir):
- if filename.endswith(".xml"):
- # Open
- fd3 = open(os.path.join(srcs_dir, filename), "r+")
-
- # Lock
- fcntl.flock(fd3, fcntl.LOCK_EX)
-
- # Write
- fd2.write(fd3.read())
-
- # Unlock
- fcntl.flock(fd3.fileno(), fcntl.LOCK_UN)
-
- # Close
- fd3.close()
-
- # Generate tail
- fd2.write("\n")
-
- # UnLock
- fcntl.flock(fd2.fileno(), fcntl.LOCK_UN)
- # Close file
- fd2.close()
-
#elif extension == '.srv':