diff --git a/README.md b/README.md
index ab1418b..36642b2 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,8 @@ 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. Open the file `~/interbotix_ws/install/interbotix_xs_modules/lib/python3.10/site-packages/interbotix_xs_modules/xs_common/xs_common.py` and add `wx250_custom` to the `_XSARM_MODELS` tuple (near line 32).
-2. Copy the [/wx250s_custom](http://sekisushai.net/git/sekisushai/small/src/branch/master/wx250s_custom/wx250s_custom.urdf.xacro) to folder `~/interbotix_ws/install/interbotix_xsarm_descriptions/share/interbotix_xsarm_descriptions/urdf/`.
-3. Open the file `wx250s_custom.urdf.xacro`
-
+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/`
diff --git a/wx250s_custom/WidowX-250s.pdf b/wx250s_custom/WidowX-250s.pdf
new file mode 100644
index 0000000..fa92caa
Binary files /dev/null and b/wx250s_custom/WidowX-250s.pdf differ
diff --git a/wx250s_custom/wx250s_custom.urdf b/wx250s_custom/wx250s_custom.urdf
new file mode 100644
index 0000000..aa2f88a
--- /dev/null
+++ b/wx250s_custom/wx250s_custom.urdf
@@ -0,0 +1,700 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wx250s_custom/wx250s_custom.urdf.xacro b/wx250s_custom/wx250s_custom.urdf.xacro
new file mode 100644
index 0000000..d137f19
--- /dev/null
+++ b/wx250s_custom/wx250s_custom.urdf.xacro
@@ -0,0 +1,501 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wx250s_custom/wx250s_custom.yaml b/wx250s_custom/wx250s_custom.yaml
new file mode 100644
index 0000000..46545ec
--- /dev/null
+++ b/wx250s_custom/wx250s_custom.yaml
@@ -0,0 +1,104 @@
+port: /dev/ttyDXL
+
+joint_order: [waist, shoulder, elbow, forearm_roll, wrist_angle, wrist_rotate]
+sleep_positions: [0, -1.80, 1.55, 0, 0.8, 0]
+
+joint_state_publisher:
+ update_rate: 100
+ publish_states: true
+ topic_name: joint_states
+
+groups:
+ arm: [waist, shoulder, elbow, forearm_roll, wrist_angle, wrist_rotate]
+
+shadows:
+ shoulder:
+ shadow_list: [shoulder_shadow]
+ calibrate: true
+ elbow:
+ shadow_list: [elbow_shadow]
+ calibrate: true
+
+sisters:
+
+motors:
+ waist:
+ ID: 1
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 0
+ Velocity_Limit: 131
+ Min_Position_Limit: 0
+ Max_Position_Limit: 4095
+ Secondary_ID: 255
+
+ shoulder:
+ ID: 2
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 0
+ Velocity_Limit: 131
+ Min_Position_Limit: 819
+ Max_Position_Limit: 3345
+ Secondary_ID: 255
+
+ shoulder_shadow:
+ ID: 3
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 1
+ Velocity_Limit: 131
+ Min_Position_Limit: 819
+ Max_Position_Limit: 3345
+ Secondary_ID: 2
+
+ elbow:
+ ID: 4
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 0
+ Velocity_Limit: 131
+ Min_Position_Limit: 648
+ Max_Position_Limit: 3094
+ Secondary_ID: 255
+
+ elbow_shadow:
+ ID: 5
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 1
+ Velocity_Limit: 131
+ Min_Position_Limit: 648
+ Max_Position_Limit: 3094
+ Secondary_ID: 4
+
+ forearm_roll:
+ ID: 6
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 0
+ Velocity_Limit: 131
+ Min_Position_Limit: 0
+ Max_Position_Limit: 4095
+ Secondary_ID: 255
+
+ wrist_angle:
+ ID: 7
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 1
+ Velocity_Limit: 131
+ Min_Position_Limit: 910
+ Max_Position_Limit: 3447
+ Secondary_ID: 255
+
+ wrist_rotate:
+ ID: 8
+ Baud_Rate: 3
+ Return_Delay_Time: 0
+ Drive_Mode: 0
+ Velocity_Limit: 131
+ Min_Position_Limit: 0
+ Max_Position_Limit: 4095
+ Secondary_ID: 255
+
diff --git a/wx250s_custom/wx250s_custom_attach.scad b/wx250s_custom/wx250s_custom_attach.scad
index 521470f..7bd4084 100644
--- a/wx250s_custom/wx250s_custom_attach.scad
+++ b/wx250s_custom/wx250s_custom_attach.scad
@@ -2,6 +2,8 @@ include <../cad/threads.scad>;
$fn=128;
+rotate([90,0,0])
+translate([-28.5/2,-46.5/2+11,0])
difference(){
union(){
linear_extrude(4)
diff --git a/wx250s_custom/wx250s_custom_attach.stl b/wx250s_custom/wx250s_custom_attach.stl
index 37217c1..a8d71b4 100644
Binary files a/wx250s_custom/wx250s_custom_attach.stl and b/wx250s_custom/wx250s_custom_attach.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/attach.stl b/wx250s_custom/wx250s_custom_meshes/attach.stl
new file mode 100644
index 0000000..c452fc9
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/attach.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/base.stl b/wx250s_custom/wx250s_custom_meshes/base.stl
new file mode 100644
index 0000000..ff1b0bc
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/base.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/lower_forearm.stl b/wx250s_custom/wx250s_custom_meshes/lower_forearm.stl
new file mode 100644
index 0000000..552f425
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/lower_forearm.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/shoulder.stl b/wx250s_custom/wx250s_custom_meshes/shoulder.stl
new file mode 100644
index 0000000..83df495
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/shoulder.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/sma.stl b/wx250s_custom/wx250s_custom_meshes/sma.stl
new file mode 100644
index 0000000..506559f
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/sma.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/upper_arm.stl b/wx250s_custom/wx250s_custom_meshes/upper_arm.stl
new file mode 100644
index 0000000..4d7c8fc
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/upper_arm.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/upper_forearm.stl b/wx250s_custom/wx250s_custom_meshes/upper_forearm.stl
new file mode 100644
index 0000000..eaf1d04
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/upper_forearm.stl differ
diff --git a/wx250s_custom/wx250s_custom_meshes/wrist.stl b/wx250s_custom/wx250s_custom_meshes/wrist.stl
new file mode 100644
index 0000000..32fdf2b
Binary files /dev/null and b/wx250s_custom/wx250s_custom_meshes/wrist.stl differ
diff --git a/wx250s_custom/xs_common.py b/wx250s_custom/xs_common.py
new file mode 100644
index 0000000..b137d50
--- /dev/null
+++ b/wx250s_custom/xs_common.py
@@ -0,0 +1,88 @@
+# 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.
+
+from typing import List, Tuple
+
+# Tuple of valid Interbotix X-Series arm models
+_XSARM_MODELS = (
+ 'px100',
+ 'px150',
+ 'rx150',
+ 'rx200',
+ 'wx200',
+ 'wx250',
+ 'wx250s',
+ 'wx250s_custom',
+ 'vx250',
+ 'vx300',
+ 'vx300s',
+ 'mobile_px100',
+ 'mobile_wx200',
+ 'mobile_wx250s',
+)
+
+# Tuple of valid Interbotix LoCoBot models
+_XSLOCOBOT_MODELS = (
+ 'locobot_base',
+ 'locobot_px100',
+ 'locobot_wx200',
+ 'locobot_wx250s',
+)
+
+
+def get_interbotix_xsarm_models() -> Tuple[str]:
+ """Get the tuple of valid Interbotix X-Series arm models."""
+ return _XSARM_MODELS
+
+
+def get_interbotix_xslocobot_models() -> Tuple[str]:
+ """Get the tuple of valid Interbotix LoCoBot models."""
+ return _XSLOCOBOT_MODELS
+
+
+def get_interbotix_xsarm_joints(robot_model: str) -> List[str]:
+ """
+ Return a list of joints in the robot_model.
+
+ :param robot_model: The robot model to get the joints of
+ :return: A list of joint names of the given robot model
+ :raises: KeyError if the robot model is not valid
+ """
+ if robot_model in ('mobile_px100', 'px100'):
+ return ['waist', 'shoulder', 'elbow', 'wrist_angle', 'left_finger']
+ elif robot_model in ('px150', 'rx150', 'rx200', 'wx200', 'wx250', 'vx250', 'vx300'):
+ return ['waist', 'shoulder', 'elbow', 'wrist_angle', 'wrist_rotate', 'left_finger']
+ elif robot_model in ('wx250s_custom'):
+ return ['waist', 'shoulder', 'elbow', 'forearm_roll', 'wrist_angle', 'wrist_rotate']
+ elif robot_model in ('mobile_wx250s', 'wx250s', 'vx300s'):
+ return [
+ 'waist', 'shoulder', 'elbow', 'forearm_roll',
+ 'wrist_angle', 'wrist_rotate', 'left_finger'
+ ]
+ else:
+ raise KeyError(f'{robot_model} is not a valid robot model.')