We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Robot Model-Specific Parameters Should be in External Files
Robot Model-Specific Parameters (e.g., MDH, joint limits, etc) Should be in External Files (e.g., csv, json, etc). This way, new models and modifications to models are not tied to the codebase. `robot_model.py` should be deprecated and example models should be saved in a separate `example` folder in the repo.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pybotics/__init__.py`
Content:
```
1 # make the follow accessible from pybotics namespace
2 from . import geometry
3 from . import kinematics
4 from .robot import *
5 from . import robot_model
6
```

Path: `pybotics/robot_model.py`
Content:
```
1 import numpy as np
2 
3 '''
4 Modified DH parameter matrices of various robots (rx, tx, rz, tz) aka (alpha, a, theta, d)
5 '''
6 
7 
8 def ur10():
9     model = np.array([
10         [0, 0, 0, 118.0],
11         [np.pi / 2.0, 0, np.pi, 0],
12         [0, 612.7, 0, 0],
13         [0, 571.6, 0, 163.9],
14         [-np.pi / 2.0, 0, 0, 115.7],
15         [np.pi / 2.0, 0, np.pi, 92.2]
16     ])
17     return model
18 
19 
20 def puma_560():
21     model = np.array([
22         [0, 0, 0, 0],
23         [-np.pi / 2.0, 0, 0, 0],
24         [0, 612.7, 0, 0],
25         [0, 571.6, 0, 163.9],
26         [-np.pi / 2.0, 0, 0, 115.7],
27         [np.pi / 2.0, 0, np.pi, 92.2]
28     ])
29     return model
30 
31 
32 def kuka_lbr_iiwa_7():
33     model = np.array([
34         [0, 0, 0, 340],
35         [-np.pi / 2.0, 0, 0, 0],
36         [np.pi / 2.0, 0, 0, 400],
37         [np.pi / 2.0, 0, 0, 0],
38         [-np.pi / 2.0, 0, 0, 400],
39         [-np.pi / 2.0, 0, 0, 0],
40         [np.pi / 2.0, 0, 0, 126]
41     ])
42     return model
43
```

Path: `examples/example_robot.py`
Content:
```
1 import copy
2 
3 import pybotics as py
4 import numpy as np
5 
6 # set numpy print options
7 np.set_printoptions(precision=3)
8 np.set_printoptions(suppress=True)
9 
10 # create robot
11 ideal_robot = py.Robot()
12 ideal_robot.robot_model = py.robot_model.ur10()
13 
14 # create pseudo-realistic robot with kinematic errors
15 real_robot = copy.deepcopy(ideal_robot)
16 real_robot.impair_robot_model()
17 
18 print('Ideal Robot Model:\n', ideal_robot.robot_model, '\n')
19 print('Pseudo-Real Robot Model:\n', real_robot.robot_model, '\n')
20 
21 # demonstrate forward kinematics
22 joints = [0, 0, 0, 0, 0, 0]
23 
24 print('Ideal Pose:\n', ideal_robot.fk(joints), '\n')
25 print('Pseudo-Real Pose:\n', real_robot.fk(joints), '\n')
26
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/examples/example_robot.py b/examples/example_robot.py
--- a/examples/example_robot.py
+++ b/examples/example_robot.py
@@ -8,18 +8,17 @@
 np.set_printoptions(suppress=True)
 
 # create robot
-ideal_robot = py.Robot()
-ideal_robot.robot_model = py.robot_model.ur10()
+model = np.loadtxt('ur10-mdh.csv', delimiter=',')
+robot = py.Robot(model)
 
-# create pseudo-realistic robot with kinematic errors
-real_robot = copy.deepcopy(ideal_robot)
-real_robot.impair_robot_model()
-
-print('Ideal Robot Model:\n', ideal_robot.robot_model, '\n')
-print('Pseudo-Real Robot Model:\n', real_robot.robot_model, '\n')
+print('Robot Model:\n{}\n'.format(robot.robot_model))
 
 # demonstrate forward kinematics
-joints = [0, 0, 0, 0, 0, 0]
+joints = [0] * robot.num_dof()
+pose = robot.fk(joints)
+
+print('Pose:\n{}\n'.format(pose))
 
-print('Ideal Pose:\n', ideal_robot.fk(joints), '\n')
-print('Pseudo-Real Pose:\n', real_robot.fk(joints), '\n')
+# demonstrate inverse kinematics
+new_joints = robot.ik(pose)
+print('Solved Joints:\n{}\n'.format(new_joints))
diff --git a/pybotics/__init__.py b/pybotics/__init__.py
--- a/pybotics/__init__.py
+++ b/pybotics/__init__.py
@@ -1,5 +1,4 @@
 # make the follow accessible from pybotics namespace
 from . import geometry
 from . import kinematics
-from .robot import *
-from . import robot_model
+from .robot import Robot
diff --git a/pybotics/robot_model.py b/pybotics/robot_model.py
deleted file mode 100644
--- a/pybotics/robot_model.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import numpy as np
-
-'''
-Modified DH parameter matrices of various robots (rx, tx, rz, tz) aka (alpha, a, theta, d)
-'''
-
-
-def ur10():
-    model = np.array([
-        [0, 0, 0, 118.0],
-        [np.pi / 2.0, 0, np.pi, 0],
-        [0, 612.7, 0, 0],
-        [0, 571.6, 0, 163.9],
-        [-np.pi / 2.0, 0, 0, 115.7],
-        [np.pi / 2.0, 0, np.pi, 92.2]
-    ])
-    return model
-
-
-def puma_560():
-    model = np.array([
-        [0, 0, 0, 0],
-        [-np.pi / 2.0, 0, 0, 0],
-        [0, 612.7, 0, 0],
-        [0, 571.6, 0, 163.9],
-        [-np.pi / 2.0, 0, 0, 115.7],
-        [np.pi / 2.0, 0, np.pi, 92.2]
-    ])
-    return model
-
-
-def kuka_lbr_iiwa_7():
-    model = np.array([
-        [0, 0, 0, 340],
-        [-np.pi / 2.0, 0, 0, 0],
-        [np.pi / 2.0, 0, 0, 400],
-        [np.pi / 2.0, 0, 0, 0],
-        [-np.pi / 2.0, 0, 0, 400],
-        [-np.pi / 2.0, 0, 0, 0],
-        [np.pi / 2.0, 0, 0, 126]
-    ])
-    return model

{"golden_diff": "diff --git a/examples/example_robot.py b/examples/example_robot.py\n--- a/examples/example_robot.py\n+++ b/examples/example_robot.py\n@@ -8,18 +8,17 @@\n np.set_printoptions(suppress=True)\n \n # create robot\n-ideal_robot = py.Robot()\n-ideal_robot.robot_model = py.robot_model.ur10()\n+model = np.loadtxt('ur10-mdh.csv', delimiter=',')\n+robot = py.Robot(model)\n \n-# create pseudo-realistic robot with kinematic errors\n-real_robot = copy.deepcopy(ideal_robot)\n-real_robot.impair_robot_model()\n-\n-print('Ideal Robot Model:\\n', ideal_robot.robot_model, '\\n')\n-print('Pseudo-Real Robot Model:\\n', real_robot.robot_model, '\\n')\n+print('Robot Model:\\n{}\\n'.format(robot.robot_model))\n \n # demonstrate forward kinematics\n-joints = [0, 0, 0, 0, 0, 0]\n+joints = [0] * robot.num_dof()\n+pose = robot.fk(joints)\n+\n+print('Pose:\\n{}\\n'.format(pose))\n \n-print('Ideal Pose:\\n', ideal_robot.fk(joints), '\\n')\n-print('Pseudo-Real Pose:\\n', real_robot.fk(joints), '\\n')\n+# demonstrate inverse kinematics\n+new_joints = robot.ik(pose)\n+print('Solved Joints:\\n{}\\n'.format(new_joints))\ndiff --git a/pybotics/__init__.py b/pybotics/__init__.py\n--- a/pybotics/__init__.py\n+++ b/pybotics/__init__.py\n@@ -1,5 +1,4 @@\n # make the follow accessible from pybotics namespace\n from . import geometry\n from . import kinematics\n-from .robot import *\n-from . import robot_model\n+from .robot import Robot\ndiff --git a/pybotics/robot_model.py b/pybotics/robot_model.py\ndeleted file mode 100644\n--- a/pybotics/robot_model.py\n+++ /dev/null\n@@ -1,42 +0,0 @@\n-import numpy as np\n-\n-'''\n-Modified DH parameter matrices of various robots (rx, tx, rz, tz) aka (alpha, a, theta, d)\n-'''\n-\n-\n-def ur10():\n-    model = np.array([\n-        [0, 0, 0, 118.0],\n-        [np.pi / 2.0, 0, np.pi, 0],\n-        [0, 612.7, 0, 0],\n-        [0, 571.6, 0, 163.9],\n-        [-np.pi / 2.0, 0, 0, 115.7],\n-        [np.pi / 2.0, 0, np.pi, 92.2]\n-    ])\n-    return model\n-\n-\n-def puma_560():\n-    model = np.array([\n-        [0, 0, 0, 0],\n-        [-np.pi / 2.0, 0, 0, 0],\n-        [0, 612.7, 0, 0],\n-        [0, 571.6, 0, 163.9],\n-        [-np.pi / 2.0, 0, 0, 115.7],\n-        [np.pi / 2.0, 0, np.pi, 92.2]\n-    ])\n-    return model\n-\n-\n-def kuka_lbr_iiwa_7():\n-    model = np.array([\n-        [0, 0, 0, 340],\n-        [-np.pi / 2.0, 0, 0, 0],\n-        [np.pi / 2.0, 0, 0, 400],\n-        [np.pi / 2.0, 0, 0, 0],\n-        [-np.pi / 2.0, 0, 0, 400],\n-        [-np.pi / 2.0, 0, 0, 0],\n-        [np.pi / 2.0, 0, 0, 126]\n-    ])\n-    return model\n", "issue": "Robot Model-Specific Parameters Should be in External Files\nRobot Model-Specific Parameters (e.g., MDH, joint limits, etc) Should be in External Files (e.g., csv, json, etc). This way, new models and modifications to models are not tied to the codebase. `robot_model.py` should be deprecated and example models should be saved in a separate `example` folder in the repo.\n", "before_files": [{"content": "# make the follow accessible from pybotics namespace\nfrom . import geometry\nfrom . import kinematics\nfrom .robot import *\nfrom . import robot_model\n", "path": "pybotics/__init__.py"}, {"content": "import numpy as np\n\n'''\nModified DH parameter matrices of various robots (rx, tx, rz, tz) aka (alpha, a, theta, d)\n'''\n\n\ndef ur10():\n    model = np.array([\n        [0, 0, 0, 118.0],\n        [np.pi / 2.0, 0, np.pi, 0],\n        [0, 612.7, 0, 0],\n        [0, 571.6, 0, 163.9],\n        [-np.pi / 2.0, 0, 0, 115.7],\n        [np.pi / 2.0, 0, np.pi, 92.2]\n    ])\n    return model\n\n\ndef puma_560():\n    model = np.array([\n        [0, 0, 0, 0],\n        [-np.pi / 2.0, 0, 0, 0],\n        [0, 612.7, 0, 0],\n        [0, 571.6, 0, 163.9],\n        [-np.pi / 2.0, 0, 0, 115.7],\n        [np.pi / 2.0, 0, np.pi, 92.2]\n    ])\n    return model\n\n\ndef kuka_lbr_iiwa_7():\n    model = np.array([\n        [0, 0, 0, 340],\n        [-np.pi / 2.0, 0, 0, 0],\n        [np.pi / 2.0, 0, 0, 400],\n        [np.pi / 2.0, 0, 0, 0],\n        [-np.pi / 2.0, 0, 0, 400],\n        [-np.pi / 2.0, 0, 0, 0],\n        [np.pi / 2.0, 0, 0, 126]\n    ])\n    return model\n", "path": "pybotics/robot_model.py"}, {"content": "import copy\n\nimport pybotics as py\nimport numpy as np\n\n# set numpy print options\nnp.set_printoptions(precision=3)\nnp.set_printoptions(suppress=True)\n\n# create robot\nideal_robot = py.Robot()\nideal_robot.robot_model = py.robot_model.ur10()\n\n# create pseudo-realistic robot with kinematic errors\nreal_robot = copy.deepcopy(ideal_robot)\nreal_robot.impair_robot_model()\n\nprint('Ideal Robot Model:\\n', ideal_robot.robot_model, '\\n')\nprint('Pseudo-Real Robot Model:\\n', real_robot.robot_model, '\\n')\n\n# demonstrate forward kinematics\njoints = [0, 0, 0, 0, 0, 0]\n\nprint('Ideal Pose:\\n', ideal_robot.fk(joints), '\\n')\nprint('Pseudo-Real Pose:\\n', real_robot.fk(joints), '\\n')\n", "path": "examples/example_robot.py"}], "after_files": [{"content": "# make the follow accessible from pybotics namespace\nfrom . import geometry\nfrom . import kinematics\nfrom .robot import Robot\n", "path": "pybotics/__init__.py"}, {"content": null, "path": "pybotics/robot_model.py"}, {"content": "import copy\n\nimport pybotics as py\nimport numpy as np\n\n# set numpy print options\nnp.set_printoptions(precision=3)\nnp.set_printoptions(suppress=True)\n\n# create robot\nmodel = np.loadtxt('ur10-mdh.csv', delimiter=',')\nrobot = py.Robot(model)\n\nprint('Robot Model:\\n{}\\n'.format(robot.robot_model))\n\n# demonstrate forward kinematics\njoints = [0] * robot.num_dof()\npose = robot.fk(joints)\n\nprint('Pose:\\n{}\\n'.format(pose))\n\n# demonstrate inverse kinematics\nnew_joints = robot.ik(pose)\nprint('Solved Joints:\\n{}\\n'.format(new_joints))\n", "path": "examples/example_robot.py"}]}