Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rosapi tries to parse IDL files as msg files and errors #913

Open
russkel opened this issue Mar 13, 2024 · 4 comments
Open

rosapi tries to parse IDL files as msg files and errors #913

russkel opened this issue Mar 13, 2024 · 4 comments
Labels

Comments

@russkel
Copy link

russkel commented Mar 13, 2024

Description

If there is no msg files get_interface_path will return an idl path. This is then fed into the parse_message_string function for msg files. This ends up with a lot of errors spamming in the log.

https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/rosapi/src/rosapi/stringify_field_types.py#L20

https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/rosapi/src/rosapi/stringify_field_types.py#L24

  • Library Version: main
  • ROS Version: Iron release
  • Platform / OS: Linux

Steps To Reproduce

Expected Behavior

Either parses IDL using the rosidl parser or errors once it detects the IDL extension and doesn't try to load it again.

Actual Behavior

[rosapi_node-19] Error processing '// generated from nmea0183_adapter/resource/msg_definition.idl.em' of 'nmea0183_msgs/UtcDateTime': '//'
@russkel russkel added the bug label Mar 13, 2024
@charlielito
Copy link

charlielito commented Jun 21, 2024

I think this happens for custom-built messages. I managed to implement a workaround to be able to parse them:

def extract_msg_path_from_idl(idl_path):
    with open(idl_path, 'r', encoding='utf-8') as idl_file:
        idl_content = idl_file.read()
    
    # Try to extract the original .msg file path from content. Usually in the first lines
    # there is a part that says "// with input from <path>" and path is related to the original .msg file
    msg_file_info = [line for line in idl_content.split('\n') if '// with input from' in line]
    if msg_file_info:
        msg_path = msg_file_info[0].split('// with input from')[-1].strip()
        # Remove "msg/" from the path, since the actual path doesn't have it
        msg_path = msg_path.replace('msg/', '')
        # Find parent directory of the idl just before the share folder
        share_dir = idl_path.split('share')[0]
        # Construct the full path to the .msg file
        return os.path.join(share_dir, 'share', msg_path)
    
    return idl_path

def stringify_field_types(root_type):
    definition = ""
    seen_types = set()
    deps = [root_type]
    is_root = True
    while deps:
        ty = deps.pop()
        parts = ty.split("/")
        if not is_root:
            definition += "\n================================================================================\n"
            definition += f"MSG: {ty}\n"
        is_root = False

        msg_name = parts[2] if len(parts) == 3 else parts[1]
        interface_name = ty if len(parts) == 3 else f"{parts[0]}/msg/{parts[1]}"

        # Try to get the .msg file first
        msg_path = get_interface_path(interface_name)

        # If custom we get instead the .idl implementation
        if msg_path.endswith('.idl'):
            msg_path = extract_msg_path_from_idl(msg_path)

        with open(msg_path, encoding="utf-8") as msg_file:
            msg_definition = msg_file.read()
        definition += msg_definition

        spec = parse_message_string(parts[0], msg_name, msg_definition)
        for field in spec.fields:
            is_builtin = field.type.pkg_name is None
            if not is_builtin:
                field_ty = f"{field.type.pkg_name}/{field.type.type}"
                if field_ty not in seen_types:
                    deps.append(field_ty)
                    seen_types.add(field_ty)

    return definition

Hope it helps

@russkel
Copy link
Author

russkel commented Jun 22, 2024

I have a PR on rosidl_parser which adds a parser for IDL files, but as per tradition it just sits there unreviewed.

Thanks for your patch, but we stopped using rosbridge and changed to foxbridge due to performance increases.

@charlielito
Copy link

@russkel can you point me to the PR url? Thanks!

@russkel
Copy link
Author

russkel commented Jun 24, 2024

ros2/rosidl#697

@russkel can you point me to the PR url? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants