diff --git a/README.md b/README.md index 36642b2..0545a7f 100644 --- a/README.md +++ b/README.md @@ -50,10 +50,18 @@ By default, it allows to hold a M6 threaded rod aligned with the wrist rotation according to your needs. ### Software modifications -Once the physical modification of the robotic arm has been completed, several files need to be updated to use ROS 2 with the new arm. -The default arm name is `wx250s` and one will create a new arm configuration `wx250s_custom`. To do so: -1. Copy the file [/wx250s_custom/xs_common.py] to `~/interbotix_ws/install/interbotix_xs_modules/lib/python3.10/site-packages/interbotix_xs_modules/xs_common/xs_common.py`. -2. Copy the file [/wx250s_custom/wx250s_custom.urdf.xacro](http://sekisushai.net/git/sekisushai/small/src/branch/master/wx250s_custom/wx250s_custom.urdf.xacro) to `~/interbotix_ws/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_descriptions/urdf/`. -3. Copy the file [/wx250s_custom/wx250s_custom.yaml]() to `~/interbotix_ws/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_control/config/wx250s_custom.yaml` -4. Copy the folder [/wx250s_custom/wx259s_custom_meshes]() to `~/interbotix_ws/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_descriptions/meshes/` -10. Run command `colcon build` in folder `~/interbotix_ws/` +Once the Hardware modification has been completed, several files need to be updated in interbotix packages to use the new arm, named `ẁx250s_custom`. To do so, run the `install.sh` script as follows: +``` +./install.sh +``` +The script ask several infos to update the interbotix packages files. Also, the kinematics matrices `M` and `Slist` are computed. These matrices are needed by the Python API which will drive the robotic arm. + + +``` +ros2 launch interbotix_xsarm_descriptions xsarm_description.launch.py robot_model:=wx250s_custom use_joint_pub_gui:=true +``` +You should see this: + +![Alt text](wx250s_custom/rviz.png) + +### diff --git a/wx250s_custom/install.sh b/wx250s_custom/install.sh new file mode 100755 index 0000000..984b38d --- /dev/null +++ b/wx250s_custom/install.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Tweak the default interbotix_ws install to add a customized robot wx250s_custom + +read -p "Enter the interbotix packages installation path [default: ~/interbotix_ws]:" DIR +DIR=${DIR:-~/interbotix_ws} + +cp xs_common.py "$DIR/src/interbotix_ros_toolboxes/interbotix_xs_toolbox/interbotix_xs_modules/interbotix_xs_modules/xs_common/" +cp wx250s_custom.yaml "$DIR/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_control/config/" +cp -r wx250s_custom_meshes "$DIR/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_descriptions/meshes/" + +VAR=`awk 'NR==451{ print; exit }' wx250s_custom.urdf.xacro` +VAR=`awk -F'"' '{print $2}' <<< $VAR` + +read -p "Enter the coordinate between wrist_rotate joint and SMA center in m [default: ${VAR}]:" COORD +COORD=${COORD:-${VAR}} + +cp wx250s_custom.urdf.xacro wx250s_custom.urdf.xacro~ + +sed -i "451s/$VAR/$COORD/" wx250s_custom.urdf.xacro~ + +# convert to urdf file needed for kinematic_from_description package +ros2 run xacro xacro wx250s_custom.urdf.xacro~ > out.urdf + +# move the urdf.xacro file +mv wx250s_custom.urdf.xacro~ "$DIR/src/interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_descriptions/urdf/wx250s_custom.urdf.xacro" + +# +git clone https://github.com/Interbotix/kinematics_from_description.git +cd kinematics_from_description +python setup.py install --user +cd .. +rm -rf kinematics_from_description + +cp mr_descriptions.py mr_descriptions.py~ + +python kinematics.py + +mv mr_descriptions.py "$DIR/src/interbotix_ros_toolboxes/interbotix_xs_toolbox/interbotix_xs_modules/interbotix_xs_modules/xs_robot/" + +mv mr_descriptions.py~ mr_descriptions.py + +rm out.urdf + +cd $DIR + +rm -rf build +rm -rf install + +colcon build diff --git a/wx250s_custom/kinematics.py b/wx250s_custom/kinematics.py new file mode 100644 index 0000000..ff4d60a --- /dev/null +++ b/wx250s_custom/kinematics.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Apr 7 15:38:46 2023 + +@author: Pierre Lecomte +""" +import numpy as np +from kinematics_from_description.kfd import KinematicsFromDescriptionTool as KFD + +tool = KFD( + { + "body_frame": "sma_link", + "space_frame": "base_link", + "namespace": "wx250s_custom", + } + ) + +tool.load_desc_from_file('out.urdf') +tool.run() + +print("Slist:") +print(tool.Slist.T) + +print("M:") +print(tool.M) + +x = f"""class wx250s_custom(ModernRoboticsDescription): + Slist = np.array( + {np.array2string(tool.Slist.T, separator=',')} + ).T + + M = np.array({np.array2string(tool.M, separator=',')}) + """ + +with open("mr_descriptions.py","a") as f: + f.writelines(x) \ No newline at end of file diff --git a/wx250s_custom/matrices.txt b/wx250s_custom/matrices.txt new file mode 100644 index 0000000..8ef65e0 --- /dev/null +++ b/wx250s_custom/matrices.txt @@ -0,0 +1,12 @@ +Slist: +[[ 0. 0. 1. 0. 0. 0. ] + [ 0. 1. 0. -0.11065 0. 0. ] + [ 0. 1. 0. -0.36065 0. 0.04975] + [ 1. 0. 0. 0. 0.36065 0. ] + [ 0. 1. 0. -0.36065 0. 0.29975] + [ 1. 0. 0. 0. 0.36065 0. ]] +M: +[[1. 0. 0. 0.49275] + [0. 1. 0. 0. ] + [0. 0. 1. 0.36065] + [0. 0. 0. 1. ]] diff --git a/wx250s_custom/mr_descriptions.py b/wx250s_custom/mr_descriptions.py new file mode 100644 index 0000000..adb35e0 --- /dev/null +++ b/wx250s_custom/mr_descriptions.py @@ -0,0 +1,233 @@ +# Copyright 2022 Trossen Robotics +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Modern Robotics Descriptions for all Interbotix X-Series Arms. + +This module contains properties required by the Modern Robotics library to perform +kinematic calculations such as the Joint Screw Axes and Home Configuration for each +X-Series robot. + +Note that the end-effector is positioned at '/ee_gripper_link' and that the +Space frame is positioned at '/base_link'. + +To calculate your own MR Description, check out the kinematics_from_description package: + https://github.com/Interbotix/kinematics_from_description +""" + +from abc import ABC + +import numpy as np + + +class ModernRoboticsDescription(ABC): + """ + Abstract base class for other MR Description classes. + + Derived classes should override the Slist and M member variables. + """ + + Slist: np.ndarray = None + """ + Joint screw axes in the space frame when the manipulator is at the home position, in the format + of a matrix with axes as the columns + """ + + M: np.ndarray = None + """The home configuration (position and orientation) of the end-effector""" + + +class px100(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.0931, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.1931, 0.0, 0.035], + [0.0, 1.0, 0.0, -0.1931, 0.0, 0.135]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.248575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.1931], + [0.0, 0.0, 0.0, 1.0]]) + + +class px150(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.10457, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.25457, 0.0, 0.05], + [0.0, 1.0, 0.0, -0.25457, 0.0, 0.2], + [1.0, 0.0, 0.0, 0.0, 0.25457, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.358575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.25457], + [0.0, 0.0, 0.0, 1.0]]) + + +class rx150(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.10457, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.25457, 0.0, 0.05], + [0.0, 1.0, 0.0, -0.25457, 0.0, 0.2], + [1.0, 0.0, 0.0, 0.0, 0.25457, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.358575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.25457], + [0.0, 0.0, 0.0, 1.0]]) + + +class rx200(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.10457, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.30457, 0.0, 0.05], + [0.0, 1.0, 0.0, -0.30457, 0.0, 0.25], + [1.0, 0.0, 0.0, 0.0, 0.30457, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.408575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.30457], + [0.0, 0.0, 0.0, 1.0]]) + + +class vx250(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.12705, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.37705, 0.0, 0.06], + [0.0, 1.0, 0.0, -0.37705, 0.0, 0.31], + [1.0, 0.0, 0.0, 0.0, 0.37705, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.468575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.37705], + [0.0, 0.0, 0.0, 1.0]]) + + +class vx300(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.12705, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.42705, 0.0, 0.05955], + [0.0, 1.0, 0.0, -0.42705, 0.0, 0.35955], + [1.0, 0.0, 0.0, 0.0, 0.42705, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.536494], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.42705], + [0.0, 0.0, 0.0, 1.0]]) + + +class vx300s(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.12705, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.42705, 0.0, 0.05955], + [1.0, 0.0, 0.0, 0.0, 0.42705, 0.0], + [0.0, 1.0, 0.0, -0.42705, 0.0, 0.35955], + [1.0, 0.0, 0.0, 0.0, 0.42705, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.536494], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.42705], + [0.0, 0.0, 0.0, 1.0]]) + + +class wx200(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.11065, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.31065, 0.0, 0.05], + [0.0, 1.0, 0.0, -0.31065, 0.0, 0.25], + [1.0, 0.0, 0.0, 0.0, 0.31065, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.408575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.31065], + [0.0, 0.0, 0.0, 1.0]]) + + +class wx250(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.11065, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.36065, 0.0, 0.04975], + [0.0, 1.0, 0.0, -0.36065, 0.0, 0.29975], + [1.0, 0.0, 0.0, 0.0, 0.36065, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.458325], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.36065], + [0.0, 0.0, 0.0, 1.0]]) + + +class wx250s(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.11065, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.36065, 0.0, 0.04975], + [1.0, 0.0, 0.0, 0.0, 0.36065, 0.0], + [0.0, 1.0, 0.0, -0.36065, 0.0, 0.29975], + [1.0, 0.0, 0.0, 0.0, 0.36065, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.458325], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.36065], + [0.0, 0.0, 0.0, 1.0]]) + + +class mobile_px100(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.08518, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.18518, 0.0, 0.035], + [0.0, 1.0, 0.0, -0.18518, 0.0, 0.135]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.248575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.18518], + [0.0, 0.0, 0.0, 1.0]]) + + +class mobile_wx200(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.104825, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.304825, 0.0, 0.05], + [0.0, 1.0, 0.0, -0.304825, 0.0, 0.25], + [1.0, 0.0, 0.0, 0.0, 0.304825, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.408575], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.304825], + [0.0, 0.0, 0.0, 1.0]]) + + +class mobile_wx250s(ModernRoboticsDescription): + Slist = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.104825, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.354825, 0.0, 0.04975], + [1.0, 0.0, 0.0, 0.0, 0.354825, 0.0], + [0.0, 1.0, 0.0, -0.354825, 0.0, 0.29975], + [1.0, 0.0, 0.0, 0.0, 0.354825, 0.0]]).T + + M = np.array([[1.0, 0.0, 0.0, 0.458325], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.354825], + [0.0, 0.0, 0.0, 1.0]]) + diff --git a/wx250s_custom/rviz.png b/wx250s_custom/rviz.png new file mode 100644 index 0000000..c520b8c Binary files /dev/null and b/wx250s_custom/rviz.png differ diff --git a/wx250s_custom/wx250s_custom.urdf b/wx250s_custom/wx250s_custom.urdf deleted file mode 100644 index aa2f88a..0000000 --- a/wx250s_custom/wx250s_custom.urdf +++ /dev/null @@ -1,700 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wx250s_custom/wx250s_custom.urdf.xacro b/wx250s_custom/wx250s_custom.urdf.xacro index d137f19..7885fc8 100644 --- a/wx250s_custom/wx250s_custom.urdf.xacro +++ b/wx250s_custom/wx250s_custom.urdf.xacro @@ -11,6 +11,7 @@ + @@ -487,9 +488,6 @@ - - -