3 from __future__
import print_function
5 from collections
import namedtuple
6 from string
import Template
7 from os
import makedirs, path
13 Marker = namedtuple(
'Marker',
14 [
'id_',
'size',
'x',
'y',
'z',
'roll',
'pitch',
'yaw'])
17 MARKER_MODEL_CFG_TEMPLATE = Template(
''' 20 <name>${model_name}</name> 21 <version>1.0</version> 22 <sdf version="1.6">${sdf_name}</sdf> 24 <name>Marker Generator script</name> 25 <email>marker@generator.sh</email> 34 MARKER_VISUAL_TEMPLATE = Template(
''' 35 <visual name="visual_marker_${marker_id}"> 36 <pose>${x} ${y} ${z} ${roll} ${pitch} ${yaw}</pose> 37 <cast_shadows>false</cast_shadows> 40 <size>${marker_full_size} ${marker_full_size} 1e-3</size> 45 <uri>model://${model_directory}/materials/scripts</uri> 46 <uri>model://${model_directory}/materials/textures</uri> 47 <name>aruco/marker_${marker_id}</name> 54 MARKER_MODEL_SDF_TEMPLATE = Template(
''' 57 <model name="${model_name}"> 59 <link name="${model_name}_link"> 67 MARKER_MATERIAL_TEMPLATE = Template(
''' 68 material aruco/marker_${marker_id} 76 texture aruco_marker_${marker_id}.png 88 Extract model name from model directory. 90 model_directory: Full path to the model. 92 Returns Gazebo-compatible model name (available through model:// URI schema) 94 return path.split(model_directory)[1]
99 Generate markers from a list. Result is a single Gazebo 100 model with all markers inside it. 102 markers: A List-like object containing Marker objects. 103 model_directory: Target directory for the model. 104 dictionary_id: Predefined ArUco dictionary ID, as defined by OpenCV. 105 map_source: An optional string with the name of the ArUco map file. 107 script_directory = path.join(model_directory,
'materials',
'scripts')
108 texture_directory = path.join(model_directory,
'materials',
'textures')
111 if not path.exists(script_directory):
112 makedirs(script_directory)
113 if not path.exists(texture_directory):
114 makedirs(texture_directory)
116 print(
'Could not create material/texture directories!')
118 aruco_dict = cv2.aruco.getPredefinedDictionary(dictionary_id)
119 marker_bits = aruco_dict.markerSize
120 marker_outer_bits = marker_bits + 2
121 marker_border_bits = marker_bits + 4
125 for marker
in markers:
126 texture_name =
'aruco_marker_{}_{}.png'.format(dictionary_id, marker.id_)
128 marker_image = np.zeros((marker_border_bits, marker_border_bits), dtype=np.uint8)
129 marker_image[:,:] = 255
130 marker_image[1:marker_border_bits - 1, 1:marker_border_bits - 1] = cv2.aruco.drawMarker(
131 aruco_dict, marker.id_, marker_outer_bits)
132 cv2.imwrite(path.join(texture_directory, texture_name), marker_image)
133 materials.append(MARKER_MATERIAL_TEMPLATE.substitute(
134 marker_id=
'{}_{}'.format(dictionary_id, marker.id_)
136 visuals.append(MARKER_VISUAL_TEMPLATE.substitute(
137 marker_id=
'{}_{}'.format(dictionary_id, marker.id_),
143 yaw=marker.yaw + (math.pi / 2),
145 marker_full_size=marker.size * marker_border_bits / marker_outer_bits
148 with open(path.join(script_directory,
'aruco_materials.material'),
'w')
as f:
149 f.write(
''.join(materials))
151 with open(path.join(model_directory,
'aruco_model.sdf'),
'w')
as f:
152 f.write(MARKER_MODEL_SDF_TEMPLATE.substitute(
153 model_name=
'aruco_{}_{}'.format(dictionary_id, len(markers)),
154 model_visuals=
''.join(visuals)
157 with open(path.join(model_directory,
'model.config'),
'w')
as f:
158 f.write(MARKER_MODEL_CFG_TEMPLATE.substitute(
159 model_name=
'ArUco {} (dictionary {})'.format(
160 markers[0].id_
if len(markers) == 1
else 'field from ' + map_source,
162 sdf_name=
'aruco_model.sdf' def generate_markers(markers, model_directory, dictionary_id=2, map_source='')
def model_name(model_directory)