1
- from jinja2 import Template
2
- import os
3
1
import enum
4
2
import functools
5
- import yaml
3
+ import os
6
4
from typing import Dict
7
5
6
+ from jinja2 import Template
7
+ import yaml
8
+
8
9
9
10
def load_yaml (file_path : str ) -> Dict :
10
11
with open (file_path , "r" ) as stream :
@@ -14,6 +15,7 @@ def load_yaml(file_path: str) -> Dict:
14
15
print (exc )
15
16
return None
16
17
18
+
17
19
class Transformation :
18
20
def __init__ (self , transformation : Dict , base_frame : str , child_frame : str ):
19
21
try :
@@ -51,9 +53,7 @@ def serialize(self) -> str:
51
53
class Calibration :
52
54
def __init__ (self , calibration : Dict ):
53
55
self .base_dict : Dict = calibration
54
- assert (
55
- len (calibration .keys ()) == 1
56
- ), "Calibration file should have only one base frame"
56
+ assert len (calibration .keys ()) == 1 , "Calibration file should have only one base frame"
57
57
assert isinstance (
58
58
list (calibration .keys ())[0 ], str
59
59
), "Calibration file should have only one base frame with key as a string"
@@ -78,8 +78,9 @@ def __init__(self, calibration: Dict):
78
78
79
79
class LinkType (enum .Enum ):
80
80
"""
81
- Enum class for the type of the link
81
+ Enum class for the type of the link
82
82
"""
83
+
83
84
CAMERA = "monocular_camera"
84
85
IMU = "imu"
85
86
LIVOX = "livox_horizon"
@@ -93,44 +94,46 @@ class LinkType(enum.Enum):
93
94
RADAR = "radar"
94
95
JOINT_UNITS = "units"
95
96
96
- def determine_link_type (link_name :str )-> LinkType :
97
- if 'cam' in link_name :
97
+
98
+ def determine_link_type (link_name : str ) -> LinkType :
99
+ if "cam" in link_name :
98
100
return LinkType .CAMERA
99
-
100
- if ' imu' in link_name or ' gnss' in link_name :
101
+
102
+ if " imu" in link_name or " gnss" in link_name :
101
103
return LinkType .IMU
102
-
103
- if ' livox' in link_name :
104
+
105
+ if " livox" in link_name :
104
106
return LinkType .LIVOX
105
-
106
- if ' velodyne' in link_name :
107
- if ' top' in link_name :
107
+
108
+ if " velodyne" in link_name :
109
+ if " top" in link_name :
108
110
return LinkType .VLS128
109
111
else :
110
112
return LinkType .VELODYNE16
111
-
112
- if ' radar' in link_name or ' ars' in link_name :
113
+
114
+ if " radar" in link_name or " ars" in link_name :
113
115
return LinkType .RADAR
114
-
115
- if ' pandar_40p' in link_name :
116
+
117
+ if " pandar_40p" in link_name :
116
118
return LinkType .PANDAR_40P
117
-
118
- if ' pandar_qt' in link_name :
119
+
120
+ if " pandar_qt" in link_name :
119
121
return LinkType .PANDAR_QT
120
-
121
- if ' hesai_top' in link_name :
122
+
123
+ if " hesai_top" in link_name :
122
124
return LinkType .PANDAR_OT128
123
-
124
- if ' hesai_front' in link_name :
125
+
126
+ if " hesai_front" in link_name :
125
127
return LinkType .PANDAR_XT32
126
128
127
- if ' hesai' in link_name :
129
+ if " hesai" in link_name :
128
130
return LinkType .PANDAR_XT32
129
-
131
+
130
132
else :
131
133
print (f"Link type not found for { link_name } , suspected to be a joint unit" )
132
134
return LinkType .JOINT_UNITS
133
135
136
+
134
137
BASE_STRING = """<xacro:{type}
135
138
name=\" {child_frame}\"
136
139
parent=\" {base_frame}\"
@@ -154,7 +157,8 @@ def determine_link_type(link_name:str)->LinkType:
154
157
/>
155
158
</xacro:{type}>"""
156
159
157
- def base_string_func (type :str , transform :Transformation )-> str :
160
+
161
+ def base_string_func (type : str , transform : Transformation ) -> str :
158
162
if type == "monocular_camera_macro" :
159
163
extra = """fps=\" 30\"
160
164
width=\" 800\"
@@ -167,80 +171,104 @@ def base_string_func(type:str, transform:Transformation)->str:
167
171
else :
168
172
extra = ""
169
173
return BASE_STRING .format (
170
- type = type , base_frame = transform .base_frame , child_frame = transform .child_frame ,
171
- x = transform .serialize_single ('x' ), y = transform .serialize_single ('y' ), z = transform .serialize_single ('z' ),
172
- roll = transform .serialize_single ('roll' ), pitch = transform .serialize_single ('pitch' ), yaw = transform .serialize_single ('yaw' ),
173
- extra = extra )
174
+ type = type ,
175
+ base_frame = transform .base_frame ,
176
+ child_frame = transform .child_frame ,
177
+ x = transform .serialize_single ("x" ),
178
+ y = transform .serialize_single ("y" ),
179
+ z = transform .serialize_single ("z" ),
180
+ roll = transform .serialize_single ("roll" ),
181
+ pitch = transform .serialize_single ("pitch" ),
182
+ yaw = transform .serialize_single ("yaw" ),
183
+ extra = extra ,
184
+ )
174
185
175
- def VLP16_func (transform :Transformation )-> str :
186
+
187
+ def VLP16_func (transform : Transformation ) -> str :
176
188
return VLD_STRING .format (
177
- type = "VLP-16" , base_frame = transform .base_frame , child_frame = transform .child_frame ,
178
- x = transform .serialize_single ('x' ), y = transform .serialize_single ('y' ), z = transform .serialize_single ('z' ),
179
- roll = transform .serialize_single ('roll' ), pitch = transform .serialize_single ('pitch' ), yaw = transform .serialize_single ('yaw' )
189
+ type = "VLP-16" ,
190
+ base_frame = transform .base_frame ,
191
+ child_frame = transform .child_frame ,
192
+ x = transform .serialize_single ("x" ),
193
+ y = transform .serialize_single ("y" ),
194
+ z = transform .serialize_single ("z" ),
195
+ roll = transform .serialize_single ("roll" ),
196
+ pitch = transform .serialize_single ("pitch" ),
197
+ yaw = transform .serialize_single ("yaw" ),
180
198
)
181
199
182
- def VLS128_func (transform :Transformation )-> str :
200
+
201
+ def VLS128_func (transform : Transformation ) -> str :
183
202
return VLD_STRING .format (
184
- type = "VLS-128" , base_frame = transform .base_frame , child_frame = transform .child_frame ,
185
- x = transform .serialize_single ('x' ), y = transform .serialize_single ('y' ), z = transform .serialize_single ('z' ),
186
- roll = transform .serialize_single ('roll' ), pitch = transform .serialize_single ('pitch' ), yaw = transform .serialize_single ('yaw' )
203
+ type = "VLS-128" ,
204
+ base_frame = transform .base_frame ,
205
+ child_frame = transform .child_frame ,
206
+ x = transform .serialize_single ("x" ),
207
+ y = transform .serialize_single ("y" ),
208
+ z = transform .serialize_single ("z" ),
209
+ roll = transform .serialize_single ("roll" ),
210
+ pitch = transform .serialize_single ("pitch" ),
211
+ yaw = transform .serialize_single ("yaw" ),
187
212
)
188
213
214
+
189
215
link_dicts = {
190
- LinkType .CAMERA :{
216
+ LinkType .CAMERA : {
191
217
"including_file" : "$(find camera_description)/urdf/monocular_camera.xacro" ,
192
- "string_api" : functools .partial (base_string_func , "monocular_camera_macro" )
218
+ "string_api" : functools .partial (base_string_func , "monocular_camera_macro" ),
193
219
},
194
- LinkType .IMU :{
220
+ LinkType .IMU : {
195
221
"including_file" : "$(find imu_description)/urdf/imu.xacro" ,
196
- "string_api" : functools .partial (base_string_func , "imu_macro" )
222
+ "string_api" : functools .partial (base_string_func , "imu_macro" ),
197
223
},
198
- LinkType .VELODYNE16 :{
224
+ LinkType .VELODYNE16 : {
199
225
"including_file" : "$(find velodyne_description)/urdf/VLP-16.urdf.xacro" ,
200
- "string_api" : VLP16_func
226
+ "string_api" : VLP16_func ,
201
227
},
202
- LinkType .VLS128 :{
228
+ LinkType .VLS128 : {
203
229
"including_file" : "$(find vls_description)/urdf/VLS-128.urdf.xacro" ,
204
- "string_api" : VLS128_func
230
+ "string_api" : VLS128_func ,
205
231
},
206
- LinkType .PANDAR_40P :{
232
+ LinkType .PANDAR_40P : {
207
233
"including_file" : "$(find pandar_description)/urdf/pandar_40p.xacro" ,
208
- "string_api" : functools .partial (base_string_func , "Pandar40P" )
234
+ "string_api" : functools .partial (base_string_func , "Pandar40P" ),
209
235
},
210
- LinkType .PANDAR_OT128 :{
236
+ LinkType .PANDAR_OT128 : {
211
237
"including_file" : "$(find pandar_description)/urdf/pandar_ot128.xacro" ,
212
- "string_api" : functools .partial (base_string_func , "PandarOT-128" )
238
+ "string_api" : functools .partial (base_string_func , "PandarOT-128" ),
213
239
},
214
- LinkType .PANDAR_XT32 :{
240
+ LinkType .PANDAR_XT32 : {
215
241
"including_file" : "$(find pandar_description)/urdf/pandar_xt32.xacro" ,
216
- "string_api" : functools .partial (base_string_func , "PandarXT-32" )
242
+ "string_api" : functools .partial (base_string_func , "PandarXT-32" ),
217
243
},
218
- LinkType .PANDAR_QT :{
244
+ LinkType .PANDAR_QT : {
219
245
"including_file" : "$(find pandar_description)/urdf/pandar_qt.xacro" ,
220
- "string_api" : functools .partial (base_string_func , "PandarQT" )
246
+ "string_api" : functools .partial (base_string_func , "PandarQT" ),
221
247
},
222
- LinkType .PANDAR_QT128 :{
248
+ LinkType .PANDAR_QT128 : {
223
249
"including_file" : "$(find pandar_description)/urdf/pandar_qt128.xacro" ,
224
- "string_api" : functools .partial (base_string_func , "PandarQT-128" )
250
+ "string_api" : functools .partial (base_string_func , "PandarQT-128" ),
225
251
},
226
- LinkType .LIVOX :{
252
+ LinkType .LIVOX : {
227
253
"including_file" : "$(find livox_description)/urdf/livox_horizon.xacro" ,
228
- "string_api" : functools .partial (base_string_func , "livox_horizon_macro" )
254
+ "string_api" : functools .partial (base_string_func , "livox_horizon_macro" ),
229
255
},
230
- LinkType .RADAR :{
256
+ LinkType .RADAR : {
231
257
"including_file" : "$(find radar_description)/urdf/radar.xacro" ,
232
- "string_api" : functools .partial (base_string_func , "radar_macro" )
258
+ "string_api" : functools .partial (base_string_func , "radar_macro" ),
233
259
},
234
- LinkType .JOINT_UNITS :{
260
+ LinkType .JOINT_UNITS : {
235
261
"including_file" : "{filename}.xacro" ,
236
- }
262
+ },
237
263
}
238
264
239
265
240
- def main (template_directory :str , calibration_directory :str , output_directory :str , project_name :str ):
266
+ def main (
267
+ template_directory : str , calibration_directory : str , output_directory : str , project_name : str
268
+ ):
241
269
os .makedirs (output_directory , exist_ok = True )
242
270
# Load the template
243
- with open (os .path .join (template_directory , ' sensors.xacro.template' ), 'r' ) as file :
271
+ with open (os .path .join (template_directory , " sensors.xacro.template" ), "r" ) as file :
244
272
base_template = Template (file .read ())
245
273
246
274
# Render the template
@@ -249,31 +277,34 @@ def main(template_directory:str, calibration_directory:str, output_directory:str
249
277
calib = Calibration (calib_yaml )
250
278
251
279
render_meta_data = dict ()
252
- render_meta_data ['default_config_path' ] = f"$(find { project_name } )/config"
253
- render_meta_data ["sensor_calibration_yaml_path" ] = f"$(find { project_name } )/config/sensors_calibration.yaml"
280
+ render_meta_data ["default_config_path" ] = f"$(find { project_name } )/config"
281
+ render_meta_data [
282
+ "sensor_calibration_yaml_path"
283
+ ] = f"$(find { project_name } )/config/sensors_calibration.yaml"
254
284
render_meta_data ["sensor_units_includes" ] = []
255
285
render_meta_data ["sensor_units" ] = []
256
286
render_meta_data ["isolated_sensors_includes" ] = []
257
287
render_meta_data ["isolated_sensors" ] = []
258
288
259
-
260
289
include_text = set ()
261
290
sensor_items = []
262
291
for _ , transform in calib .transforms .items ():
263
- link_type :LinkType = determine_link_type (transform .child_frame )
292
+ link_type : LinkType = determine_link_type (transform .child_frame )
264
293
if link_type == LinkType .JOINT_UNITS :
265
- render_meta_data ["sensor_units_includes" ].append (link_dicts [link_type ]['including_file' ].format (filename = transform .name ))
294
+ render_meta_data ["sensor_units_includes" ].append (
295
+ link_dicts [link_type ]["including_file" ].format (filename = transform .name )
296
+ )
266
297
render_meta_data ["sensor_units" ].append (
267
298
dict (
268
299
base_frame = transform .base_frame ,
269
300
child_frame = transform .child_frame ,
270
301
macro_name = f"{ transform .name } _macro" ,
271
- name = transform .name
302
+ name = transform .name ,
272
303
)
273
304
)
274
305
else :
275
- include_text .add (link_dicts [link_type ][' including_file' ])
276
- sensor_items .append (link_dicts [link_type ][' string_api' ](transform ))
306
+ include_text .add (link_dicts [link_type ][" including_file" ])
307
+ sensor_items .append (link_dicts [link_type ][" string_api" ](transform ))
277
308
278
309
render_meta_data ["isolated_sensors_includes" ] = list (include_text )
279
310
render_meta_data ["isolated_sensors" ] = sensor_items
@@ -283,39 +314,43 @@ def main(template_directory:str, calibration_directory:str, output_directory:str
283
314
284
315
print ("=====================================" )
285
316
# Save the rendered template
286
- with open (os .path .join (output_directory , ' sensors.xacro' ), 'w' ) as file :
317
+ with open (os .path .join (output_directory , " sensors.xacro" ), "w" ) as file :
287
318
file .write (rendered )
288
319
289
-
290
320
## Write Sensor Units into separate files
291
- with open (os .path .join (template_directory , ' sensor_unit.xacro.template' ), 'r' ) as file :
321
+ with open (os .path .join (template_directory , " sensor_unit.xacro.template" ), "r" ) as file :
292
322
sensor_units_template = Template (file .read ())
293
323
294
324
for i , sensor_unit in enumerate (render_meta_data ["sensor_units" ]):
295
- sensor_unit_calib_path = os .path .join (calibration_directory , f"{ sensor_unit ['name' ]} _calibration.yaml" )
325
+ sensor_unit_calib_path = os .path .join (
326
+ calibration_directory , f"{ sensor_unit ['name' ]} _calibration.yaml"
327
+ )
296
328
sensor_unit_calib_yaml = load_yaml (sensor_unit_calib_path )
297
329
sensor_unit_calib = Calibration (sensor_unit_calib_yaml )
298
330
sensor_unit_render_meta_data = dict ()
299
- sensor_unit_render_meta_data ['unit_macro_name' ] = sensor_unit ['macro_name' ]
300
- sensor_unit_render_meta_data ['default_config_path' ] = render_meta_data ['default_config_path' ]
331
+ sensor_unit_render_meta_data ["unit_macro_name" ] = sensor_unit ["macro_name" ]
332
+ sensor_unit_render_meta_data ["default_config_path" ] = render_meta_data [
333
+ "default_config_path"
334
+ ]
301
335
302
- sensor_unit_render_meta_data [' current_base_link' ] = sensor_unit_calib .base_frame
336
+ sensor_unit_render_meta_data [" current_base_link" ] = sensor_unit_calib .base_frame
303
337
sensor_unit_isolated_sensors = []
304
338
for _ , transform in sensor_unit_calib .transforms .items ():
305
- link_type :LinkType = determine_link_type (transform .child_frame )
306
- include_text .add (link_dicts [link_type ][' including_file' ])
307
- sensor_unit_isolated_sensors .append (link_dicts [link_type ][' string_api' ](transform ))
339
+ link_type : LinkType = determine_link_type (transform .child_frame )
340
+ include_text .add (link_dicts [link_type ][" including_file" ])
341
+ sensor_unit_isolated_sensors .append (link_dicts [link_type ][" string_api" ](transform ))
308
342
sensor_unit_render_meta_data ["isolated_sensors_includes" ] = list (include_text )
309
343
sensor_unit_render_meta_data ["isolated_sensors" ] = sensor_unit_isolated_sensors
310
344
311
345
rendered = sensor_units_template .render (sensor_unit_render_meta_data )
312
346
print (rendered )
313
- with open (os .path .join (output_directory , f'{ sensor_unit ["name" ]} .xacro' ), 'w' ) as file :
347
+ with open (os .path .join (output_directory , f'{ sensor_unit ["name" ]} .xacro' ), "w" ) as file :
314
348
file .write (rendered )
315
349
print ("=====================================" )
316
-
350
+
317
351
return 0
318
352
353
+
319
354
if __name__ == "__main__" :
320
355
# import argparse
321
356
# parser = argparse.ArgumentParser(description="Compile xacro files from calibration files")
@@ -325,5 +360,6 @@ def main(template_directory:str, calibration_directory:str, output_directory:str
325
360
# parser.add_argument("--project_name", type=str, help="Name of the project", required=True)
326
361
# args = parser.parse_args()
327
362
from fire import Fire
363
+
328
364
Fire (main )
329
- # main(args.template_directory, args.calibration_directory, args.output_directory, args.project_name)
365
+ # main(args.template_directory, args.calibration_directory, args.output_directory, args.project_name)
0 commit comments