urdfeus 0.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
urdfeus/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ # flake8: noqa
2
+
3
+ import pkg_resources
4
+
5
+
6
+ __version__ = pkg_resources.get_distribution("urdfeus").version
File without changes
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env python
2
+
3
+ import argparse
4
+
5
+ from urdfeus.mesh2eus import mesh2eus
6
+
7
+
8
+ def main():
9
+ parser = argparse.ArgumentParser(description='Convert mesh to Euslisp')
10
+ parser.add_argument('input_mesh_path', type=str,
11
+ help='Input mesh file path')
12
+ parser.add_argument('output_euslisp_path', type=str,
13
+ help='Output Euslisp path')
14
+ parser.add_argument(
15
+ '--simplify-vertex-clustering-voxel-size', '--voxel-size',
16
+ default=None,
17
+ type=float,
18
+ help='Specifies the voxel size for the simplify_vertex_clustering'
19
+ ' function in open3d. When this value is provided, '
20
+ 'it is used as the voxel size in the function to perform '
21
+ 'mesh simplification. This process reduces the complexity'
22
+ ' of the mesh by clustering vertices within the specified voxel size.')
23
+ args = parser.parse_args()
24
+ with open(args.output_euslisp_path, 'w') as f:
25
+ mesh2eus(args.input_mesh_path,
26
+ args.simplify_vertex_clustering_voxel_size,
27
+ fp=f)
28
+
29
+
30
+ if __name__ == '__main__':
31
+ main()
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python
2
+
3
+ import argparse
4
+
5
+ from urdfeus.urdf2eus import urdf2eus
6
+
7
+
8
+ def main():
9
+ parser = argparse.ArgumentParser(description='Convert URDF to Euslisp')
10
+ parser.add_argument('input_urdf_path', type=str, help='Input URDF path')
11
+ parser.add_argument('output_euslisp_path', type=str,
12
+ help='Output Euslisp path')
13
+ parser.add_argument('--yaml-path', type=str,
14
+ default=None,
15
+ help='Config yaml path')
16
+ parser.add_argument(
17
+ '--simplify-vertex-clustering-voxel-size', '--voxel-size',
18
+ default=None,
19
+ type=float,
20
+ help='Specifies the voxel size for the simplify_vertex_clustering'
21
+ ' function in open3d. When this value is provided, '
22
+ 'it is used as the voxel size in the function to perform '
23
+ 'mesh simplification. This process reduces the complexity'
24
+ ' of the mesh by clustering vertices within the specified voxel size.')
25
+ args = parser.parse_args()
26
+ with open(args.output_euslisp_path, 'w') as f:
27
+ urdf2eus(args.input_urdf_path,
28
+ args.yaml_path,
29
+ args.simplify_vertex_clustering_voxel_size,
30
+ fp=f)
31
+
32
+
33
+ if __name__ == '__main__':
34
+ main()
urdfeus/common.py ADDED
@@ -0,0 +1,23 @@
1
+ from skrobot.model import FixedJoint
2
+ from skrobot.model import Joint
3
+
4
+
5
+ meter2millimeter = 1000.0
6
+
7
+
8
+ def is_linear_joint(joint: Joint) -> bool:
9
+ return joint.__class__.__name__ == 'LinearJoint'
10
+
11
+
12
+ def is_fixed_joint(joint: Joint) -> bool:
13
+ return joint.__class__.__name__ == 'FixedJoint'
14
+
15
+
16
+ def collect_all_joints_of_robot(robot):
17
+ """Collects and returns all joints of the robot, including fixed joints.
18
+
19
+ """
20
+ all_fixed_joints = [value for _, value in robot.__dict__.items()
21
+ if isinstance(value, FixedJoint)]
22
+ all_joints = robot.joint_list + all_fixed_joints
23
+ return all_joints
urdfeus/mesh2eus.py ADDED
@@ -0,0 +1,29 @@
1
+ import os.path as osp
2
+ import sys
3
+ import tempfile
4
+
5
+ from urdfeus.templates.urdf_template import urdf_template
6
+ from urdfeus.urdf2eus import urdf2eus
7
+
8
+
9
+ def mesh2eus(mesh_path, simplify_vertex_clustering_voxel_size=None,
10
+ fp=sys.stdout, mesh_name=None):
11
+ if mesh_name is None:
12
+ mesh_name, _ = osp.splitext(osp.basename(mesh_path))
13
+ collision_mesh_filepath = osp.abspath(mesh_path)
14
+ visual_mesh_filepath = osp.abspath(mesh_path)
15
+
16
+ formatted_urdf = urdf_template.format(
17
+ mesh_name=mesh_name,
18
+ collision_mesh_filepath=collision_mesh_filepath,
19
+ visual_mesh_filepath=visual_mesh_filepath
20
+ )
21
+
22
+ with tempfile.NamedTemporaryFile(delete=True) as temp:
23
+ temp_urdf_path = temp.name
24
+ temp.write(formatted_urdf.encode('utf-8'))
25
+ temp.seek(0)
26
+ voxel_size = simplify_vertex_clustering_voxel_size
27
+ urdf2eus(temp_urdf_path,
28
+ simplify_vertex_clustering_voxel_size=voxel_size,
29
+ fp=fp)
urdfeus/read_yaml.py ADDED
@@ -0,0 +1,165 @@
1
+ import sys
2
+
3
+ import yaml
4
+
5
+ from urdfeus.common import meter2millimeter
6
+
7
+
8
+ def read_config_from_yaml(
9
+ robot, config_file,
10
+ fp=sys.stdout, add_link_suffix=True, add_joint_suffix=True):
11
+ print('\n', end='', file=fp)
12
+ with open(config_file, 'r') as file:
13
+ doc = yaml.load(file, Loader=yaml.FullLoader)
14
+
15
+ for limb in [k for k in doc.keys() if k.endswith('-end-coords')]:
16
+ suffix_to_remove = '-end-coords'
17
+ limb_name = limb[:-len(suffix_to_remove)]
18
+ end_coords_parent_name = doc[f"{limb_name}-end-coords"]["parent"]
19
+
20
+ if add_link_suffix:
21
+ print(f" (setq {limb_name}-end-coords (make-cascoords :coords (send {end_coords_parent_name}_lk :copy-worldcoords) :name :{limb_name}-end-coords))", file=fp) # NOQA
22
+ else:
23
+ print(f" (setq {limb_name}-end-coords (make-cascoords :coords (send {end_coords_parent_name} :copy-worldcoords) :name {limb_name}-end-coords))", file=fp) # NOQA
24
+
25
+ try:
26
+ n = doc[f"{limb_name}-end-coords"]["translate"]
27
+ values = [meter2millimeter * val for val in n[:3]]
28
+ print(f" (send {limb_name}-end-coords :translate (float-vector {' '.join(map(str, values))}))", file=fp) # NOQA
29
+ except Exception as _: # NOQA
30
+ pass
31
+
32
+ try:
33
+ n = doc[f"{limb_name}-end-coords"]["rotate"]
34
+ if n:
35
+ values = [val for val in n[:3]]
36
+ rotation_value = (3.141592653589793/180) * n[3]
37
+ print(f" (send {limb_name}-end-coords :rotate {rotation_value} (float-vector {' '.join(map(str, values))}))", file=fp) # NOQA
38
+ except Exception as _: # NOQA
39
+ pass
40
+
41
+ if add_link_suffix:
42
+ print(f" (send {end_coords_parent_name}_lk :assoc {limb_name}-end-coords)", file=fp) # NOQA
43
+ else:
44
+ print(f" (send {end_coords_parent_name} :assoc {limb_name}-end-coords)", file=fp) # NOQA
45
+
46
+ print("", file=fp)
47
+ print(" ;; limbs", file=fp)
48
+
49
+ limb_candidates = [k for k in doc.keys()
50
+ if not k.endswith('-coords')
51
+ and not k.endswith('-vector')]
52
+ limb_order = [(limb, idx) for idx, limb in enumerate(limb_candidates)]
53
+ limb_order.sort(key=lambda x: x[1])
54
+
55
+ limbs = []
56
+ for limb, _ in limb_order:
57
+ limb_name = limb
58
+ tmp_link_names = []
59
+ tmp_joint_names = []
60
+ try:
61
+ limb_doc = doc[limb_name]
62
+ except Exception as _: # NOQA
63
+ continue
64
+
65
+ for item in limb_doc:
66
+ for key, value in item.items():
67
+ if key in robot.__dict__:
68
+ joint = robot.__dict__[key]
69
+ tmp_joint_names.append(key)
70
+ tmp_link_names.append(joint.child_link.name)
71
+ if tmp_link_names:
72
+ print(f" (setq {limb_name} (list", end="", file=fp)
73
+ if add_link_suffix:
74
+ for link in tmp_link_names:
75
+ print(f" {link}_lk", end="", file=fp)
76
+ else:
77
+ for link in tmp_link_names:
78
+ print(f" {link}", end="", file=fp)
79
+ print("))", file=fp)
80
+ print("", file=fp)
81
+
82
+ print(f" (setq {limb_name}-root-link", file=fp)
83
+ print(f" (labels ((find-parent (l) (if (find (send l :parent) {limb_name}) (find-parent (send l :parent)) l)))", file=fp) # NOQA
84
+ print(f" (find-parent (car {limb_name}))))", file=fp)
85
+ limbs.append((limb, (tmp_link_names, tmp_joint_names)))
86
+ print("", file=fp)
87
+ print(" ;; links", file=fp)
88
+ if add_link_suffix:
89
+ print(f" (setq links (list {robot.__dict__['root_link'].name}_lk", end="", file=fp) # NOQA
90
+ else:
91
+ print(f" (setq links (list {robot.__dict__['root_link'].name}", end="", file=fp) # NOQA
92
+
93
+ for limb, (link_names, joint_names) in limbs:
94
+ if add_link_suffix:
95
+ for link in link_names:
96
+ print(f" {link}_lk", end="", file=fp)
97
+ else:
98
+ for link in link_names:
99
+ print(f" {link}", end="", file=fp)
100
+
101
+ print("))", file=fp)
102
+ print("", file=fp)
103
+ print(" ;; joint-list", file=fp)
104
+ print(" (setq joint-list (list", end="", file=fp)
105
+ for limb, (link_names, joint_names) in limbs:
106
+ if add_joint_suffix:
107
+ for joint in joint_names:
108
+ print(f" {joint}_jt", end="", file=fp)
109
+ else:
110
+ for joint in joint_names:
111
+ print(f" {joint}", end="", file=fp)
112
+ print("))", file=fp)
113
+ print("", file=fp)
114
+
115
+ print(" ;; init-ending\n", file=fp)
116
+ print(" (send self :init-ending) ;; :urdf\n", file=fp)
117
+ print(" ;; overwrite bodies to return draw-things links not (send link :bodies)\n", file=fp) # NOQA
118
+ print(" (setq bodies (flatten (mapcar #'(lambda (b) (if (find-method b :bodies) (send b :bodies))) (list", end="", file=fp) # NOQA
119
+ for link in robot.link_list:
120
+ if add_link_suffix:
121
+ print(f" {link.name}_lk", end="", file=fp)
122
+ else:
123
+ print(f" {link.name}", end="", file=fp)
124
+ print("))))\n", file=fp)
125
+
126
+ print(" (when (member :reset-pose (send self :methods))", file=fp)
127
+ print(" (send self :reset-pose)) ;; :set reset-pose\n", file=fp)
128
+ print(" self)) ;; end of :init", file=fp)
129
+
130
+ if 'angle-vector' in doc:
131
+ n = doc['angle-vector']
132
+ if len(n) > 0:
133
+ print(" ;; pre-defined pose methods\n", file=fp)
134
+
135
+ for name, v in n.items():
136
+ limbs_symbols = " ".join([f":{limb[0]}" for limb in limbs])
137
+ print(f"\n (:{name} (&optional (limbs '({limbs_symbols})))\n",
138
+ file=fp)
139
+ print(f" \"Predefined pose named {name}.\"\n", file=fp)
140
+ print(" (unless (listp limbs) (setq limbs (list limbs)))\n",
141
+ file=fp)
142
+ print(" (dolist (limb limbs)\n", file=fp)
143
+ print(" (case limb", file=fp)
144
+
145
+ i_joint = 0
146
+ for limb in limbs:
147
+ limb_name = limb[0]
148
+ print(f"\n (:{limb_name} (send self limb :angle-vector (float-vector", file=fp) # NOQA
149
+ joint_names = limb[1][1]
150
+
151
+ for j in range(len(joint_names)):
152
+ try:
153
+ angle_value = v[i_joint]
154
+ print(f" {angle_value}", file=fp)
155
+ i_joint += 1
156
+ except IndexError as e: # NOQA
157
+ sys.stderr.write("****** Angle-vector may be shorter than joint-list, please fix .yaml ******\n") # NOQA
158
+ while j < len(joint_names):
159
+ print(" 0.0", file=fp) # padding dummy
160
+ j += 1
161
+
162
+ print(")))", file=fp)
163
+
164
+ print("\n (t (format t \"Unknown limb is passed: ~a~%\" limb))", file=fp) # NOQA
165
+ print("))\n (send self :angle-vector))", file=fp)
@@ -0,0 +1,9 @@
1
+ import os.path as osp
2
+
3
+
4
+ data_dir = osp.abspath(osp.dirname(__file__))
5
+
6
+
7
+ def get_euscollada_string():
8
+ with open(osp.join(data_dir, 'euscollada-robot.l')) as f:
9
+ return f.read()
@@ -0,0 +1,241 @@
1
+ ;;
2
+ ;; copy euscollada-robot class definition from euscollada/src/euscollada-robot.l
3
+ ;;
4
+ (defclass euscollada-robot
5
+ ;; This euscollada-robot class is for robots converted from collada files.
6
+ ;; This class provides :init-ending override.
7
+ :super robot-model
8
+ :slots ())
9
+
10
+ (defmethod euscollada-robot
11
+ (:init-ending
12
+ (&optional (type :urdf))
13
+ (when (eq type :collada)
14
+ ;; fix all links' mass properties ;; root link relative (collada) -> link local (euslisp)
15
+ (dolist (l (append links
16
+ (mapcan #'(lambda (x) (if (and (derivedp (cdr x) bodyset-link)
17
+ (not (memq (cdr x) links)))
18
+ (list (cdr x)))) (send self :slots))))
19
+ (unless (= (send l :weight) 0.0)
20
+ (setq (l . acentroid) (send l :inverse-transform-vector
21
+ (send (send (car links) :worldcoords) :transform-vector
22
+ (l . acentroid))))
23
+ (setq (l . inertia-tensor) (m* (transpose (send l :worldrot))
24
+ (m* (send (car links) :worldrot)
25
+ (l . inertia-tensor)))))))
26
+ (send-super :init-ending)
27
+ (send self :make-collision-model-for-links)
28
+ ;;
29
+ (dolist (j (mapcan #'(lambda (x) (if (and (derivedp (cdr x) joint)
30
+ (not (memq (cdr x) (send self :joint-list))))
31
+ (list (cdr x)))) (send self :slots)))
32
+ (send (send j :child-link) :add-joint j)
33
+ (send (send j :child-link) :add-parent-link (send j :parent-link))
34
+ (send (send j :parent-link) :add-child-links (send j :child-link))))
35
+ (:change-visual
36
+ (&optional (visual :convex))
37
+ (dolist (lk (send self :links))
38
+ (dolist (bd (send lk :bodies))
39
+ (when (derivedp bd collada-body)
40
+ (send bd :change-visual visual)))))
41
+ ;; fullbody-inverse-kinematics overwrite
42
+ ;; reduce root-link's weight based on leg's joint limit
43
+ ;; increase stop and cog-gain
44
+ (:fullbody-inverse-kinematics
45
+ (target-coords &rest args &key (stop 250) (cog-gain 2.0) (additional-weight-list) (use-6dof-joint-leg-gain nil) &allow-other-keys)
46
+ (let* ((leg-ul (send self :calc-union-link-list (send self :legs :links))))
47
+ (send self :reset-joint-angle-limit-weight-old leg-ul)
48
+ (send-message* self robot-model :fullbody-inverse-kinematics
49
+ target-coords
50
+ :stop stop :cog-gain cog-gain
51
+ :additional-weight-list
52
+ (append
53
+ additional-weight-list
54
+ (if use-6dof-joint-leg-gain
55
+ (list
56
+ (list (car (send self :links))
57
+ #'(lambda ()
58
+ ;; set root-link 6dof-joint's weight based on legs' joint limit
59
+ (let* ((min-weight
60
+ (reduce #'(lambda (x y) (min x y))
61
+ (coerce (send self :calc-inverse-kinematics-weight-from-link-list
62
+ leg-ul :union-link-list leg-ul) cons))))
63
+ (fill (instantiate float-vector 6) min-weight)))))))
64
+ args)))
65
+ ;; make collision model from faces or gl-vertices
66
+ (:make-collision-model-for-links
67
+ (&key (fat 0) (collision-func 'pqp-collision-check) ((:links ls) (send self :links)))
68
+ (dolist (ll ls)
69
+ (let (fs glv usefs)
70
+ (dolist (bd (send ll :bodies))
71
+ (if (derivedp bd collada-body)
72
+ (push (send bd :glvertices) glv)
73
+ (push (send bd :faces) fs)))
74
+ (setq fs (flatten fs))
75
+ (cond
76
+ ((and (not fs) glv) ;; if there is no faces, use glvertices for creating pqpmodel
77
+ (setq usefs (instance gl::glvertices :init nil))
78
+ (send usefs :transform (send ll :worldcoords))
79
+ (send usefs :append-glvertices glv)
80
+ (let ((m (send usefs (read-from-string
81
+ (format nil ":make-~Amodel"
82
+ (string-right-trim "-COLLISION-CHECK" (string collision-func))))
83
+ :fat fat)))
84
+ (setf (get ll :pqpmodel) m)))
85
+ (fs
86
+ (setq usefs
87
+ (append fs
88
+ (mapcar #'(lambda (gv) (send gv :convert-to-faces :wrt :world)) glv)))
89
+ (send ll
90
+ (read-from-string
91
+ (format nil ":make-~Amodel"
92
+ (string-right-trim "-COLLISION-CHECK" (string collision-func))))
93
+ :fat fat
94
+ :faces usefs)))))))
95
+
96
+ ;; copy euscollada-body class definition from euscollada/src/euscollada-robot.l
97
+ ;; This euscollada-body class is for bodies in robot model converted from collada files.
98
+ (defclass collada-body
99
+ :super gl::glbody
100
+ :slots (glvertices) ;; glvertices slot for backward compatibility
101
+ )
102
+ (defmethod collada-body
103
+ (:init (&key (name) (replace-obj))
104
+ (if replace-obj
105
+ (replace-object self replace-obj)
106
+ (replace-object self (make-cube 10 10 10)))
107
+ (if name (send self :name name))
108
+ (setq glvertices gl::aglvertices)
109
+ self)
110
+ (:change-visual
111
+ (&optional (visual :convex))
112
+ (case visual
113
+ ((list :convex :hull :convex-hull)
114
+ (unless (send self :get :original-mesh)
115
+ (send self :put :original-mesh gl::aglvertices)) ;; store original mesh
116
+ (let* ((org-mesh (send self :get :original-mesh))
117
+ (org-cds (send org-mesh :copy-worldcoords))
118
+ (glv (gl::make-glvertices-from-faces (send self :faces))))
119
+ (send glv :set-offset (send org-cds :inverse-transformation))
120
+ (send glv :transform org-cds)
121
+ (send org-mesh :assoc glv)
122
+ (setq gl::aglvertices glv)
123
+ glv))
124
+ ((list :original :mesh :glvertices :original-mesh)
125
+ (let ((org-mesh (send self :get :original-mesh)))
126
+ (when org-mesh
127
+ (dolist (d (send org-mesh :descendants)) ;; dissoc all discendants
128
+ (send org-mesh :dissoc d))
129
+ (setq gl::aglvertices org-mesh)
130
+ org-mesh))))))
131
+
132
+ ;; copy mimic-joint class definition from euscollada/src/euscollada-robot.l
133
+ ;; This mimic-joint class is for mimic-joints in URDF file
134
+ (defclass mimic-joint-param
135
+ :super propertied-object
136
+ :slots (joint multiplier offset))
137
+ (defmethod mimic-joint-param
138
+ (:init (j &key ((:multiplier m) 1) ((:offset o) 0))
139
+ (setq joint j multiplier m offset o)
140
+ self)
141
+ (:joint (&rest args) (forward-message-to joint args))
142
+ (:multiplier (&rest args) (forward-message-to multiplier args))
143
+ (:offset (&rest args) (forward-message-to offset args)))
144
+
145
+ (defun calc-jacobian-mimic
146
+ (mimic-joints
147
+ fik row column joint paxis child-link world-default-coords child-reverse
148
+ move-target transform-coords rotation-axis translation-axis
149
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
150
+ (let* ((fik-tmp (copy-object fik))
151
+ (dim (* 6 (if (atom rotation-axis) 1 (length rotation-axis)))))
152
+ (dolist (axis (append (if (atom translation-axis)
153
+ (list translation-axis) translation-axis)
154
+ (if (atom rotation-axis)
155
+ (list rotation-axis) rotation-axis)))
156
+ (case axis
157
+ ((:x :y :z :xx :yy :zz) (decf dim 1))
158
+ ((:xy :yx :yz :zy :zx :xz) (decf dim 2))
159
+ (nil (decf dim 3))))
160
+ ;;
161
+ (dolist (mj mimic-joints)
162
+ (let* ((j (send mj :joint))
163
+ (paxis (case (j . axis)
164
+ (:x #f(1 0 0)) (:y #f(0 1 0)) (:z #f(0 0 1))
165
+ (:xx #f(1 0 0)) (:yy #f(0 1 0)) (:zz #f(0 0 1))
166
+ (:-x #f(-1 0 0)) (:-y #f(0 -1 0)) (:-z #f(0 0 -1))
167
+ (t (j . axis))))
168
+ (child-link (send j :child-link))
169
+ (parent-link (send j :parent-link))
170
+ (default-coords (j . default-coords))
171
+ (world-default-coords (send (send parent-link :copy-worldcoords)
172
+ :transform default-coords)))
173
+ (fill (array-entity fik-tmp) 0)
174
+ (send j :calc-jacobian
175
+ fik-tmp row column j paxis child-link world-default-coords child-reverse
176
+ move-target transform-coords rotation-axis translation-axis
177
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
178
+ ;;
179
+ (dotimes (i dim)
180
+ (setf (aref fik (+ i row) column)
181
+ (+ (aref fik (+ i row) column)
182
+ (* (send mj :multiplier) (aref fik-tmp (+ i row) column)))))))
183
+ fik))
184
+
185
+ (defclass rotational-mimic-joint
186
+ :super rotational-joint
187
+ :slots (mimic-joints))
188
+ (defmethod rotational-mimic-joint
189
+ (:init (&rest args &key ((:mimic-joints mjs)) &allow-other-keys)
190
+ (send-super* :init args)
191
+ (setq mimic-joints mjs)
192
+ (dolist (j mimic-joints)
193
+ (send (send j :joint :child-link) :rotate (send j :offset) ((send j :joint) . axis))
194
+ (setq ((send j :joint) . default-coords) (send j :joint :child-link :copy-coords)))
195
+ self)
196
+ (:joint-angle (&rest args)
197
+ (prog1
198
+ (send-super* :joint-angle args)
199
+ (dolist (j mimic-joints)
200
+ (send j :joint :joint-angle (* joint-angle (send j :multiplier))))))
201
+ (:calc-jacobian (fik row column joint paxis child-link world-default-coords child-reverse
202
+ move-target transform-coords rotation-axis translation-axis
203
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
204
+ (calc-jacobian-rotational fik row column joint paxis child-link world-default-coords child-reverse
205
+ move-target transform-coords rotation-axis translation-axis
206
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
207
+ (calc-jacobian-mimic mimic-joints
208
+ fik row column joint paxis child-link world-default-coords child-reverse
209
+ move-target transform-coords rotation-axis translation-axis
210
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)))
211
+
212
+ (defclass linear-mimic-joint
213
+ :super linear-joint
214
+ :slots (mimic-joints))
215
+ (defmethod linear-mimic-joint
216
+ (:init (&rest args &key ((:mimic-joints mjs)) &allow-other-keys)
217
+ (send-super* :init args)
218
+ (setq mimic-joints mjs)
219
+ (dolist (j mimic-joints)
220
+ (send (send j :joint :child-link) :translate (scale (* 1000 (send j :offset)) ((send j :joint) . axis)))
221
+ (setq ((send j :joint) . default-coords) (send j :joint :child-link :copy-coords)))
222
+ self)
223
+ (:joint-angle (&rest args)
224
+ (prog1
225
+ (send-super* :joint-angle args)
226
+ (dolist (j mimic-joints)
227
+ (send j :joint :joint-angle (* joint-angle (send j :multiplier))))))
228
+ (:calc-jacobian (fik row column joint paxis child-link world-default-coords child-reverse
229
+ move-target transform-coords rotation-axis translation-axis
230
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
231
+ (calc-jacobian-linear fik row column joint paxis child-link world-default-coords child-reverse
232
+ move-target transform-coords rotation-axis translation-axis
233
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)
234
+ (calc-jacobian-mimic mimic-joints
235
+ fik row column joint paxis child-link world-default-coords child-reverse
236
+ move-target transform-coords rotation-axis translation-axis
237
+ tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33)))
238
+
239
+ ;;
240
+ ;; end of copy from jsk_model_tools/euscollada/src/euscollada-robot.l
241
+ ;;
@@ -0,0 +1,23 @@
1
+ urdf_template = """<?xml version="1.0" ?>
2
+ <robot name="{mesh_name}">
3
+ <link name="link0">
4
+ <inertial>
5
+ <origin rpy="0 0 0" xyz="0 0 0" />
6
+ <mass value="1.0" />
7
+ <inertia ixx="1.00E+00" ixy="0.00E+00" ixz="0.00E+00" iyy="1.00E+00" iyz="0.00E+00" izz="1.00E+00" />
8
+ </inertial>
9
+ <collision>
10
+ <origin rpy="0 0 0" xyz="0 0 0" />
11
+ <geometry>
12
+ <mesh filename="{collision_mesh_filepath}" scale="1 1 1" />
13
+ </geometry>
14
+ </collision>
15
+ <visual>
16
+ <origin rpy="0 0 0" xyz="0 0 0" />
17
+ <geometry>
18
+ <mesh filename="{visual_mesh_filepath}" scale="1 1 1" />
19
+ </geometry>
20
+ </visual>
21
+ </link>
22
+ </robot>
23
+ """ # NOQA
urdfeus/urdf2eus.py ADDED
@@ -0,0 +1,349 @@
1
+ import datetime
2
+ import platform
3
+ import socket
4
+ import sys
5
+
6
+ import numpy as np
7
+ from skrobot.model import Link
8
+ from skrobot.model import RobotModel
9
+ from skrobot.utils.mesh import simplify_vertex_clustering
10
+ from skrobot.utils.mesh import split_mesh_by_face_color
11
+ import trimesh
12
+
13
+ from urdfeus.common import collect_all_joints_of_robot
14
+ from urdfeus.common import is_fixed_joint
15
+ from urdfeus.common import is_linear_joint
16
+ from urdfeus.common import meter2millimeter
17
+ from urdfeus.read_yaml import read_config_from_yaml
18
+ from urdfeus.templates import get_euscollada_string
19
+
20
+
21
+ def print_link(link: Link, simplify_vertex_clustering_voxel_size=None,
22
+ add_link_suffix: bool = True, fp=sys.stdout):
23
+ if add_link_suffix:
24
+ link_name = link.name + "_lk"
25
+ else:
26
+ link_name = link.name
27
+ print(f" ;; link: {link_name}", file=fp)
28
+ print(" (let ((geom-lst (list ", end='', file=fp)
29
+
30
+ geom_counter = 0
31
+ if link.visual_mesh is not None and len(link.visual_mesh) > 0:
32
+ print(f"(send self :_make_instance_{link.name}_geom{geom_counter})", end='', file=fp) # NOQA
33
+ geom_counter += 1
34
+
35
+ print(")))", file=fp)
36
+ print(" (dolist (g (cdr geom-lst)) (send (car geom-lst) :assoc g))", file=fp) # NOQA
37
+ print(f" (setq {link_name}", file=fp)
38
+ print(" (instance bodyset-link", file=fp)
39
+ print(" :init (make-cascoords)", file=fp)
40
+ print(f" :bodies geom-lst", file=fp) # NOQA
41
+ print(f" :name \"{link.name}\"))", file=fp)
42
+ print(f" (progn (send {link_name} :weight 0.0) (setq ({link_name} . acentroid) (float-vector 0 0 0)) (send {link_name} :inertia-tensor #2f((0 0 0)(0 0 0)(0 0 0))))", file=fp) # NOQA
43
+
44
+ print(f" ;; global coordinates for {link_name}", file=fp)
45
+ print(" (let ((world-cds (make-coords :pos ", end="", file=fp)
46
+ x, y, z = meter2millimeter * link.worldpos()
47
+ print(f"(float-vector {x:.6f} {y:.6f} {z:.6f})", end="", file=fp)
48
+
49
+ qw, qx, qy, qz = link.copy_worldcoords().quaternion
50
+ print(f"\n :rot (quaternion2matrix (float-vector {qw:.6f} {qx:.6f} {qy:.6f} {qz:.6f}))", end="", file=fp) # NOQA
51
+ print(")))\n", end='', file=fp)
52
+ print(f" (send {link_name} :transform world-cds)))", file=fp) # NOQA
53
+ print("\n", end='', file=fp)
54
+
55
+
56
+ def print_joint(joint, add_joint_suffix=True, add_link_suffix=True,
57
+ fp=sys.stdout):
58
+ linear = is_linear_joint(joint)
59
+
60
+ joint_name = joint.name
61
+ if add_joint_suffix:
62
+ if is_fixed_joint(joint):
63
+ joint_name += "_fixed_jt"
64
+ else:
65
+ joint_name += "_jt"
66
+
67
+ print("\n", end='', file=fp)
68
+ print(f" ;; joint: {joint_name}", file=fp)
69
+ print(f" (setq {joint_name}", file=fp)
70
+ print(f" (instance {'linear-joint' if linear else 'rotational-joint'} :init", file=fp) # NOQA
71
+ print(f" :name \"{joint.name}\"", file=fp)
72
+ if add_link_suffix:
73
+ print(f" :parent-link {joint.parent_link.name}_lk :child-link {joint.child_link.name}_lk", file=fp) # NOQA
74
+ else:
75
+ print(f" :parent-link {joint.parent_link.name} :child-link {joint.child_link.name}", file=fp) # NOQA
76
+
77
+ x, y, z = joint.axis
78
+ if x == 0.0 and y == 0.0 and z == 0.0:
79
+ print(" :axis (float-vector 1 1 1) ;; fixed joint??", file=fp) # NOQA
80
+ else:
81
+ print(f" :axis (float-vector {x:.16f} {y:.16f} {z:.16f})", file=fp) # NOQA
82
+
83
+ min_val = joint.min_angle
84
+ max_val = joint.max_angle
85
+ print(" ", end="", file=fp)
86
+ if np.isinf(min_val) or np.isinf(max_val):
87
+ print(":min *-inf* :max *inf*", file=fp)
88
+ else:
89
+ if linear:
90
+ min_angle = meter2millimeter * min_val
91
+ max_angle = meter2millimeter * max_val
92
+ else:
93
+ min_angle = np.rad2deg(min_val)
94
+ max_angle = np.rad2deg(max_val)
95
+ min_str = "*-inf*" if min_val == -float('inf') else str(min_angle)
96
+ max_str = "*inf*" if max_val == float('inf') else str(max_angle)
97
+ print(f":min {min_str} :max {max_str}", file=fp)
98
+ print(f" :max-joint-velocity {joint.max_joint_velocity}", file=fp) # NOQA
99
+ print(f" :max-joint-torque {joint.joint_torque}", end='', file=fp) # NOQA
100
+ print("))", file=fp)
101
+
102
+
103
+ def print_mimic_joints(robot, fp=sys.stdout):
104
+ print("\n ;; mimic joint re-definition\n", file=fp)
105
+ mimic_joint_list = {}
106
+
107
+ for j in robot.urdf_robot_model.joints:
108
+ if j.mimic is None:
109
+ continue
110
+ joint_a = robot.__dict__[j.mimic.joint]
111
+ joint_b = robot.__dict__[j.name]
112
+ multiplier = j.mimic.multiplier
113
+ offset = j.mimic.offset
114
+
115
+ if joint_a not in mimic_joint_list:
116
+ mimic_joint_list[joint_a] = []
117
+ mimic_joint_list[joint_a].append((joint_b, multiplier, offset))
118
+
119
+ for mimic_joint, joints in mimic_joint_list.items():
120
+ linear = is_linear_joint(mimic_joint)
121
+ print(f" ;; re-define {mimic_joint.name} as mimic-joint", file=fp)
122
+ print(" (let (tmp-mimic-joint)", file=fp)
123
+ joint_type = "linear-mimic-joint" if linear else "rotational-mimic-joint" # NOQA
124
+ print(f" (setq tmp-mimic-joint (replace-object (instance {joint_type} :init :parent-link (make-cascoords) :child-link (make-cascoords) :max-joint-velocity 0 :max-joint-torque 0) {mimic_joint.name}_jt))", file=fp) # NOQA
125
+ print(f" (setq {mimic_joint.name}_jt tmp-mimic-joint))", file=fp)
126
+ print(f" (setq ({mimic_joint.name}_jt . mimic-joints)", file=fp)
127
+ print(" (list", file=fp)
128
+ for joint, multiplier, offset in joints:
129
+ print(f" (instance mimic-joint-param :init {joint.name}_jt :multiplier {multiplier} :offset {offset})", end='', file=fp) # NOQA
130
+ print("))", file=fp)
131
+ print(f" ;; set offset as default-coords", file=fp) # NOQA
132
+ print(f" (dolist (j ({mimic_joint.name}_jt . mimic-joints))", file=fp) # NOQA
133
+ print(" (cond ((derivedp (send j :joint) rotational-joint)", file=fp) # NOQA
134
+ print(" (send (send j :joint :child-link) :rotate (send j :offset) ((send j :joint) . axis)))", file=fp) # NOQA
135
+ print(" ((derivedp (send j :joint) linear-joint)", file=fp) # NOQA
136
+ print(" (send (send j :joint :child-link) :translate (scale (* 1000 (send j :offset)) ((send j :joint) . axis))))", file=fp) # NOQA
137
+ print(" (t (error \"unsupported mimic joint ~A\" (send j :joint))))", file=fp) # NOQA
138
+ print(" (setq ((send j :joint) . default-coords) (send j :joint :child-link :copy-coords)))", file=fp) # NOQA
139
+
140
+
141
+ def print_geometry(link, simplify_vertex_clustering_voxel_size=None,
142
+ fp=sys.stdout):
143
+ x, y, z = link.translation
144
+ name = link.name + '_geom' + str(0)
145
+ print(f' (:_make_instance_{name} ()', file=fp)
146
+ print(' (let (geom glv qhull', file=fp)
147
+ print(' (local-cds (make-coords :pos ', end='', file=fp)
148
+ print(f'(float-vector {x * meter2millimeter:.6f} {y * meter2millimeter:.6f} {z * meter2millimeter:.6f})', end='', file=fp) # NOQA
149
+
150
+ qw, qx, qy, qz = link.quaternion
151
+
152
+ print('\n', end='', file=fp)
153
+ print(f' :rot (quaternion2matrix ', end='', file=fp) # NOQA
154
+ print(f'(float-vector {qw:.6f} {qx:.6f} {qy:.6f} {qz:.6f}))', end='', file=fp) # NOQA
155
+ print(')))', file=fp)
156
+ print(" (setq glv", file=fp)
157
+ print(" (instance gl::glvertices :init", end='', file=fp)
158
+ if link.visual_mesh is not None and len(link.visual_mesh) > 0:
159
+ # TODO(someone): use g.scale
160
+ print_mesh(link, simplify_vertex_clustering_voxel_size, fp=fp)
161
+ else:
162
+ print('))', file=fp)
163
+ print(" (send glv :transform local-cds)", file=fp)
164
+ print(" (send glv :calc-normals)", file=fp)
165
+
166
+ # TODO(someone) qhull
167
+ gname = link.name
168
+ print(f" (setq geom (instance collada-body :init :replace-obj nil :name \"{gname}\"))", file=fp) # NOQA
169
+ print(" (when glv", file=fp)
170
+ print(" (setq (geom . gl::aglvertices) glv)", file=fp)
171
+ print(" (send geom :assoc glv))", file=fp)
172
+ print(" geom))", file=fp)
173
+
174
+
175
+ def print_mesh(link, simplify_vertex_clustering_voxel_size=None,
176
+ fp=sys.stdout):
177
+ print("\n (list ;; mesh list", file=fp)
178
+ mesh = trimesh.util.concatenate(link.visual_mesh)
179
+ if simplify_vertex_clustering_voxel_size:
180
+ mesh = simplify_vertex_clustering(
181
+ mesh, simplify_vertex_clustering_voxel_size)[0]
182
+ for input_mesh in split_mesh_by_face_color(mesh):
183
+ print(" (list ;; mesh description", file=fp)
184
+ print(" (list :type :triangles)", file=fp)
185
+ print(" (list :material (list", file=fp)
186
+ print(f" (list :ambient (float-vector {input_mesh.visual.main_color[0] / 255.0} {input_mesh.visual.main_color[1]/ 255.0} {input_mesh.visual.main_color[2]/ 255.0} {input_mesh.visual.main_color[3]/ 255.0}))", file=fp) # NOQA
187
+ print(f" (list :diffuse (float-vector {input_mesh.visual.main_color[0]/ 255.0} {input_mesh.visual.main_color[1]/ 255.0} {input_mesh.visual.main_color[2]/ 255.0} {input_mesh.visual.main_color[3]/ 255.0}))", end="", file=fp) # NOQA
188
+ print("))", file=fp)
189
+ print(" (list :indices #i(", end="", file=fp)
190
+ print(' '.join(map(str, input_mesh.faces.reshape(-1))), end="", file=fp) # NOQA
191
+ print("))", file=fp)
192
+ print(f" (list :vertices (let ((mat (make-matrix {len(input_mesh.vertices)} 3))) (fvector-replace (array-entity mat) #f(", end="", file=fp) # NOQA
193
+ vertices = np.array(input_mesh.vertices)
194
+ vertices = link.inverse_transformation().transform_vector(vertices)
195
+ vertices = meter2millimeter * vertices
196
+ # Modified the vertex printing format to reduce mesh file size, considering the unit is in millimeters (mm). # NOQA
197
+ # Since the coordinates are in mm, having them formatted to just one decimal place is sufficiently precise for most applications. # NOQA
198
+ # This change not only preserves the necessary precision for mm-scale measurements but also effectively compresses the data, # NOQA
199
+ # resulting in a smaller file size due to reduced numerical precision in the vertex coordinates. # NOQA
200
+ print(' '.join(map(lambda x: '{0:.1f}'.format(x),
201
+ vertices.reshape(-1))),
202
+ end='', file=fp)
203
+ print(")) mat))", end="", file=fp)
204
+ # TODO(someone) normal
205
+ print(")", end='', file=fp)
206
+ print(")))", file=fp)
207
+
208
+
209
+ def print_end_coords(robot, config_yaml_path=None,
210
+ add_link_suffix=True, add_joint_suffix=True,
211
+ fp=sys.stdout):
212
+ if config_yaml_path is not None:
213
+ read_config_from_yaml(robot, config_yaml_path, fp=fp)
214
+ else:
215
+ print(" ;; init-ending\n", file=fp)
216
+ print(" (send self :init-ending) ;; :urdf\n", file=fp)
217
+ print(" ;; overwrite bodies to return draw-things links not (send link :bodies)\n", file=fp) # NOQA
218
+ print(" (setq bodies (flatten (mapcar #'(lambda (b) (if (find-method b :bodies) (send b :bodies))) (list", end="", file=fp) # NOQA
219
+ for link in robot.link_list:
220
+ if add_link_suffix:
221
+ print(f" {link.name}_lk", end="", file=fp)
222
+ else:
223
+ print(f" {link.name}", end="", file=fp)
224
+ print("))))\n", file=fp)
225
+
226
+ print(" (when (member :reset-pose (send self :methods))", file=fp)
227
+ print(" (send self :reset-pose)) ;; :set reset-pose\n", file=fp) # NOQA
228
+ print(" self)) ;; end of :init", file=fp)
229
+
230
+ print("\n", end='', file=fp)
231
+ print(" ;; all joints", file=fp)
232
+ # Assuming URDFDOM_1_0_0_API is a boolean variable
233
+ for joint in collect_all_joints_of_robot(robot):
234
+ joint_name = joint.name
235
+ if add_joint_suffix:
236
+ if is_fixed_joint(joint):
237
+ print(f" (:{joint_name} (&rest args) (forward-message-to {joint_name}_fixed_jt args))", file=fp) # NOQA
238
+ else:
239
+ print(f" (:{joint_name} (&rest args) (forward-message-to {joint_name}_jt args))", file=fp) # NOQA
240
+ else:
241
+ print(f" (:{joint_name} (&rest args) (forward-message-to {joint_name} args))", file=fp) # NOQA
242
+
243
+ if add_link_suffix:
244
+ print("\n ;; all links forwarding", file=fp)
245
+ print(" (:links (&rest args)", file=fp)
246
+ print(" (if (null args) (return-from :links (send-super :links)))", file=fp) # NOQA
247
+ print(" (let ((key (car args))\n (nargs (cdr args)))", file=fp) # NOQA
248
+ print(" (unless (keywordp key)\n (return-from :links (send-super* :links args)))\n (case key", file=fp) # NOQA
249
+
250
+ for link in robot.link_list:
251
+ link_name = link.name
252
+ print(f" (:{link_name} (forward-message-to {link_name}_lk nargs))", file=fp) # NOQA
253
+ print(" (t (send-super* :links args)))))", file=fp)
254
+
255
+ print("\n ;; all links", file=fp)
256
+ for link in robot.link_list:
257
+ link_name = link.name
258
+ if add_link_suffix:
259
+ print(f" (:{link_name}_lk (&rest args) (forward-message-to {link_name}_lk args))", file=fp) # NOQA
260
+ else:
261
+ print(f" (:{link_name} (&rest args) (forward-message-to {link_name} args))", file=fp) # NOQA
262
+
263
+
264
+ def urdf2eus(urdf_path, config_yaml_path=None,
265
+ simplify_vertex_clustering_voxel_size=None,
266
+ fp=sys.stdout):
267
+ r = RobotModel()
268
+ with open(urdf_path, 'r') as f:
269
+ r.load_urdf_file(f)
270
+ robot_name = r.urdf_robot_model.name
271
+
272
+ current_time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
273
+ print(f""";; DO NOT EDIT THIS FILE
274
+ ;;
275
+ ;; this file is automatically generated from {urdf_path} on ({sys.platform} {socket.gethostname()} {platform.platform()}) at {current_time_str}
276
+ ;;
277
+ """, file=fp) # NOQA
278
+
279
+ print(get_euscollada_string(), file=fp)
280
+
281
+ joint_names = []
282
+ for joint in collect_all_joints_of_robot(r):
283
+ joint_name = joint.name
284
+ if is_fixed_joint(joint):
285
+ joint_name += "_fixed_jt"
286
+ else:
287
+ joint_name += "_jt"
288
+ joint_names.append(joint_name)
289
+
290
+ add_link_suffix = True
291
+ link_list = []
292
+ for link in r.link_list:
293
+ if add_link_suffix:
294
+ link_name = link.name + "_lk"
295
+ else:
296
+ link_name = link.name
297
+ link_list.append(link_name)
298
+
299
+ print('\n\n', end='', file=fp)
300
+ print(f"(defun {robot_name} () (setq *{robot_name}* (instance {robot_name}-robot :init)))", file=fp) # NOQA
301
+ print('\n\n', end='', file=fp)
302
+ print(f"(defclass {robot_name}-robot", file=fp)
303
+ print(" :super euscollada-robot", file=fp)
304
+ print(" :slots (;; link names", file=fp)
305
+ print(" " + " ".join(link_list), file=fp)
306
+ print(" ;; joint names", file=fp)
307
+ print(" " + ' '.join(joint_names), file=fp)
308
+ print(" ;; sensor names", file=fp)
309
+ print(" ;; non-default limb names", file=fp)
310
+ print(" ))", file=fp)
311
+ print('\n\n', end='', file=fp)
312
+ print(f"(defmethod {r.urdf_robot_model.name}-robot", file=fp)
313
+ print(" (:init", file=fp)
314
+ print(" (&rest args)", file=fp)
315
+ print(" (let ()", file=fp)
316
+ print(f" (send-super* :init :name \"{r.urdf_robot_model.name}\" args)", file=fp) # NOQA
317
+ print("\n\n", file=fp)
318
+
319
+ for link in r.link_list:
320
+ print_link(link, fp=fp)
321
+
322
+ add_link_suffix = True
323
+ checked_pairs = {}
324
+ for link in r.link_list:
325
+ for child_link in link.child_links:
326
+ if checked_pairs.get((link.name, child_link.name)) \
327
+ or checked_pairs.get((child_link.name, link.name)):
328
+ continue
329
+ if add_link_suffix:
330
+ print(f" (send {link.name}_lk :assoc {child_link.name}_lk)", file=fp) # NOQA
331
+ else:
332
+ print(f" (send {link.name} :assoc {child_link.name})", file=fp) # NOQA
333
+ checked_pairs[(link.name, child_link.name)] = True
334
+ if add_link_suffix:
335
+ print(f" (send self :assoc {r.root_link.name}_lk)", file=fp)
336
+ else:
337
+ print(f" (send self :assoc {r.root_link.name})", file=fp)
338
+
339
+ for j in collect_all_joints_of_robot(r):
340
+ print_joint(j, fp=fp)
341
+ print_mimic_joints(r, fp=fp)
342
+ print_end_coords(r, config_yaml_path, fp=fp)
343
+
344
+ for link in r.link_list:
345
+ print_geometry(link,
346
+ simplify_vertex_clustering_voxel_size, fp=fp)
347
+ print(' )', file=fp)
348
+ print(file=fp)
349
+ print(f'(provide :{robot_name} "({socket.gethostname()} {platform.platform()}) at {current_time_str}")', file=fp) # NOQA
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2023 Iori Yanokura.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.1
2
+ Name: urdfeus
3
+ Version: 0.0.6
4
+ Summary: URDF converter for Euslisp
5
+ Home-page: https://github.com/iory/urdfeus
6
+ Author: iory
7
+ Author-email: ab.ioryz@gmail.com
8
+ License: MIT
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Natural Language :: English
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3.5
15
+ Classifier: Programming Language :: Python :: 3.6
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: Implementation :: CPython
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: open3d
21
+ Requires-Dist: pyglet <=1.5.17
22
+ Requires-Dist: pyyaml
23
+ Requires-Dist: scikit-robot >=0.0.35
24
+
25
+ # urdfeus
@@ -0,0 +1,17 @@
1
+ urdfeus/__init__.py,sha256=Ug8GqHUzOXJzq1G1zVEuFRJz4j1t9Ppt-0_vj_masf8,103
2
+ urdfeus/common.py,sha256=bjPU2LrHzwikPZiHIqLwETZI0PjWA-YaLvqEj5R4S3M,621
3
+ urdfeus/mesh2eus.py,sha256=-_90i5jxYlhp2NAiief-L7NzVqYxEY6E4D2omWmQDIo,987
4
+ urdfeus/read_yaml.py,sha256=PUwT-GaSSz0iRnc6pWu-67vaahEcdVEF4ntnPZpNgkU,7032
5
+ urdfeus/urdf2eus.py,sha256=NCRJ7I77NxrWCSys64D7rkn2LLwvzTSBomB3javt9TU,17040
6
+ urdfeus/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ urdfeus/apps/mesh2eus.py,sha256=JKg0flKRsg6RhBvLIlSouVAkuD893PeejH-rhUQmUN4,1112
8
+ urdfeus/apps/urdf2eus.py,sha256=F-S9iuk2S15FLM7F-2RwaoKrWRYVmvL8jmnJLOJ5OP4,1252
9
+ urdfeus/templates/__init__.py,sha256=f118QjZue3fxxsB6YpNbGko1EVAaK_yyAZQhH3mlgUQ,187
10
+ urdfeus/templates/euscollada-robot.l,sha256=dNrCguOD4gqPDsW4Gr4HubS8hDk3bj3twaWrxa9f8MY,12226
11
+ urdfeus/templates/urdf_template.py,sha256=h52qOWOGkkCBERFJ4Aw6grbx-DxFtt9BjCmm5NAm8Yk,674
12
+ urdfeus-0.0.6.dist-info/LICENSE,sha256=32sGF5yxCI5h7Ii-UqFOUAMeChgbTttAvpoW6w3WMQw,1058
13
+ urdfeus-0.0.6.dist-info/METADATA,sha256=tkn3HVVC_n8n9KkdI9Bysd_vJCrmT5Wz1wqxED1--Xc,830
14
+ urdfeus-0.0.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
15
+ urdfeus-0.0.6.dist-info/entry_points.txt,sha256=b1PIL8Ps8ryD5iTPfFnbnx3a20BYyO2Y1CpSg7_dfuU,94
16
+ urdfeus-0.0.6.dist-info/top_level.txt,sha256=NaalN7YfuV0m4TT6vNs2efjsgTqY0iyErAU9JQQwuFo,8
17
+ urdfeus-0.0.6.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.42.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ mesh2eus = urdfeus.apps.mesh2eus:main
3
+ urdf2eus = urdfeus.apps.urdf2eus:main
@@ -0,0 +1 @@
1
+ urdfeus