201            "ikfast_plugin_pkg_path",
 
  202            get_package_share_directory(args.ikfast_plugin_pkg),
 
  204    except PackageNotFoundError:
 
  205        args.ikfast_plugin_pkg_path = os.path.abspath(args.ikfast_plugin_pkg)
 
  207            "Failed to find package: %s. Will create it in %s." 
  208            % (args.ikfast_plugin_pkg, args.ikfast_plugin_pkg_path)
 
  211        args.ikfast_plugin_pkg = os.path.basename(args.ikfast_plugin_pkg_path)
 
  213    src_path = args.ikfast_plugin_pkg_path + 
"/src/" 
  214    if not os.path.exists(src_path):
 
  215        os.makedirs(src_path)
 
  217    include_path = args.ikfast_plugin_pkg_path + 
"/include/" 
  218    if not os.path.exists(include_path):
 
  219        os.makedirs(include_path)
 
  222    pkg_xml_path = args.ikfast_plugin_pkg_path + 
"/package.xml" 
  223    if not os.path.exists(pkg_xml_path):
 
  225        root.append(
xmlElement(
"name", text=args.ikfast_plugin_pkg))
 
  226        root.append(
xmlElement(
"version", text=
"0.0.0"))
 
  228            xmlElement(
"description", text=
"IKFast plugin for " + args.robot_name)
 
  230        root.append(
xmlElement(
"license", text=
"BSD"))
 
  231        user_name = getuser()
 
  233            xmlElement(
"maintainer", email=
"%s@todo.todo" % user_name, text=user_name)
 
  235        root.append(
xmlElement(
"buildtool_depend", text=
"ament_cmake"))
 
  237        export.append(
xmlElement(
"build_type", text=
"ament_cmake"))
 
  239        etree.ElementTree(root).write(
 
  240            pkg_xml_path, xml_declaration=
True, pretty_print=
True, encoding=
"UTF-8" 
  242        print(
"Created package.xml at: '%s'" % pkg_xml_path)
 
  245    parameters_yaml_path = src_path + 
"ikfast_kinematics_parameters.yaml" 
  246    if not os.path.exists(parameters_yaml_path):
 
  247        print(
"Create parameters.yaml at: '%s'" % parameters_yaml_path)
 
  248        with open(parameters_yaml_path, 
"w") 
as file:
 
 
  267    src_path = args.ikfast_plugin_pkg_path + 
"/src/" 
  272        + args.planning_group_name
 
  273        + 
"_ikfast_solver.cpp" 
  275    if not os.path.exists(solver_file_path) 
or not os.path.samefile(
 
  276        args.ikfast_output_path, solver_file_path
 
  278        shutil.copy2(args.ikfast_output_path, solver_file_path)
 
  280    if not os.path.exists(solver_file_path):
 
  282            "Failed to copy IKFast source code from '%s' to '%s'\n" 
  283            "Manually copy the source file generated by IKFast to this location and re-run" 
  284            % (args.ikfast_output_path, solver_file_path)
 
  287    args.ikfast_output_path = solver_file_path
 
  293    setattr(args, 
"namespace", args.robot_name + 
"_" + args.planning_group_name)
 
  295        _ROBOT_NAME_=args.robot_name,
 
  296        _GROUP_NAME_=args.planning_group_name,
 
  297        _SEARCH_MODE_=args.search_mode,
 
  298        _EEF_LINK_=args.eef_link_name,
 
  299        _BASE_LINK_=args.base_link_name,
 
  300        _PACKAGE_NAME_=args.ikfast_plugin_pkg,
 
  301        _NAMESPACE_=args.namespace,
 
  306        template_dir + 
"/ikfast.h",
 
  307        args.ikfast_plugin_pkg_path + 
"/include/ikfast.h",
 
  308        "ikfast header file",
 
  314        + str(args.template_version)
 
  315        + 
"_moveit_plugin_template.cpp",
 
  316        args.ikfast_plugin_pkg_path
 
  320        + args.planning_group_name
 
  321        + 
"_ikfast_moveit_plugin.cpp",
 
  322        "ikfast plugin file",
 
  327    ik_library_name = args.namespace + 
"_moveit_ikfast_plugin" 
  328    plugin_def = etree.Element(
"library", path=ik_library_name)
 
  329    setattr(args, 
"plugin_name", args.namespace + 
"/IKFastKinematicsPlugin")
 
  330    cl = etree.SubElement(
 
  333        name=args.plugin_name,
 
  334        type=args.namespace + 
"::IKFastKinematicsPlugin",
 
  335        base_class_type=
"kinematics::KinematicsBase",
 
  337    desc = etree.SubElement(cl, 
"description")
 
  339        "IKFast{template} plugin for closed-form kinematics of {robot} {group}".format(
 
  340            template=args.template_version,
 
  341            robot=args.robot_name,
 
  342            group=args.planning_group_name,
 
  347    plugin_file_name = ik_library_name + 
"_description.xml" 
  348    plugin_file_path = args.ikfast_plugin_pkg_path + 
"/" + plugin_file_name
 
  349    etree.ElementTree(plugin_def).write(
 
  350        plugin_file_path, xml_declaration=
True, pretty_print=
True, encoding=
"UTF-8" 
  352    print(
"Created plugin definition at  '%s'" % plugin_file_path)
 
  355    replacements.update(dict(_LIBRARY_NAME_=ik_library_name))
 
  357        template_dir + 
"/CMakeLists.txt",
 
  358        args.ikfast_plugin_pkg_path + 
"/CMakeLists.txt",
 
  364    parser = etree.XMLParser(remove_blank_text=
True)
 
  365    package_file_name = args.ikfast_plugin_pkg_path + 
"/package.xml" 
  366    package_xml = etree.parse(package_file_name, parser).getroot()
 
  377    run_deps = [
"liblapack-dev", 
"moveit_core", 
"pluginlib", 
"rclcpp"]
 
  379    update_deps(build_deps, 
"build_depend", package_xml)
 
  383    new_export = etree.Element(
"moveit_core", plugin=
"${prefix}/" + plugin_file_name)
 
  385    export_element = package_xml.find(
"export")
 
  386    if export_element 
is None:
 
  387        export_element = etree.SubElement(package_xml, 
"export")
 
  390    for el 
in export_element.findall(
"moveit_core"):
 
  391        found = etree.tostring(new_export) == etree.tostring(el)
 
  396        export_element.append(new_export)
 
  400    etree.ElementTree(package_xml).write(
 
  401        package_file_name, xml_declaration=
True, pretty_print=
True, encoding=
"UTF-8" 
  403    print(
"Wrote package.xml at  '%s'" % package_file_name)
 
  406    easy_script_file_path = args.ikfast_plugin_pkg_path + 
"/update_ikfast_plugin.sh" 
  407    with open(easy_script_file_path, 
"w") 
as f:
 
  415            + 
"robot_name_in_srdf=" 
  416            + args.robot_name_in_srdf
 
  418            + 
"moveit_config_pkg=" 
  419            + args.moveit_config_pkg
 
  424            + 
"planning_group_name=" 
  425            + args.planning_group_name
 
  427            + 
"ikfast_plugin_pkg=" 
  428            + args.ikfast_plugin_pkg
 
  431            + args.base_link_name
 
  436            + 
"ikfast_output_path=" 
  437            + args.ikfast_output_path
 
  439            + 
"rosrun moveit_kinematics create_ikfast_moveit_plugin.py\\\n" 
  440            + 
"  --search_mode=$search_mode\\\n" 
  441            + 
"  --srdf_filename=$srdf_filename\\\n" 
  442            + 
"  --robot_name_in_srdf=$robot_name_in_srdf\\\n" 
  443            + 
"  --moveit_config_pkg=$moveit_config_pkg\\\n" 
  445            + 
"  $planning_group_name\\\n" 
  446            + 
"  $ikfast_plugin_pkg\\\n" 
  447            + 
"  $base_link_name\\\n" 
  448            + 
"  $eef_link_name\\\n" 
  449            + 
"  $ikfast_output_path\n" 
  452    print(
"Created update plugin script at '%s'" % easy_script_file_path)
 
 
  457        moveit_config_pkg_path = get_package_share_directory(args.moveit_config_pkg)
 
  458    except PackageNotFoundError:
 
  459        raise Exception(
"Failed to find package: " + args.moveit_config_pkg)
 
  462        srdf_file_name = moveit_config_pkg_path + 
"/config/" + args.srdf_filename
 
  463        srdf = etree.parse(srdf_file_name).getroot()
 
  465        raise Exception(
"Failed to find SRDF file: " + srdf_file_name)
 
  466    except etree.XMLSyntaxError 
as err:
 
  468            "Failed to parse xml in file: %s\n%s" % (srdf_file_name, err.msg)
 
  471    if args.robot_name_in_srdf != srdf.get(
"name"):
 
  473            "Robot name in srdf ('%s') doesn't match expected name ('%s')" 
  474            % (srdf.get(
"name"), args.robot_name_in_srdf)
 
  477    groups = srdf.findall(
"group")
 
  479        raise Exception(
"No planning groups are defined in the SRDF")
 
  481    planning_group = 
None 
  483        if group.get(
"name").lower() == args.planning_group_name.lower():
 
  484            planning_group = group
 
  486    if planning_group 
is None:
 
  488            "Planning group '%s' not defined in the SRDF. Available groups: \n%s" 
  490                args.planning_group_name,
 
  491                ", ".join([group_name.get(
"name") 
for group_name 
in groups]),
 
  496    kin_yaml_file_name = moveit_config_pkg_path + 
"/config/kinematics.yaml" 
  497    with open(kin_yaml_file_name, 
"r") 
as f:
 
  498        kin_yaml_data = yaml.safe_load(f)
 
  500    kin_yaml_data[args.planning_group_name][
"kinematics_solver"] = args.plugin_name
 
  501    with open(kin_yaml_file_name, 
"w") 
as f:
 
  502        yaml.dump(kin_yaml_data, f, default_flow_style=
False)
 
  504    print(
"Modified kinematics.yaml at '%s'" % kin_yaml_file_name)
 
 
  507def copy_file(src_path, dest_path, description, replacements=None):
 
  508    if not os.path.exists(src_path):
 
  509        raise Exception(
"Can't find %s at '%s'" % (description, src_path))
 
  511    if replacements 
is None:
 
  512        replacements = dict()
 
  514    with open(src_path, 
"r") 
as f:
 
  518    for key, value 
in replacements.items():
 
  519        content = re.sub(key, value, content)
 
  521    with open(dest_path, 
"w") 
as f:
 
  523    print(
"Created %s at '%s'" % (description, dest_path))