marker.py
Go to the documentation of this file.
1 # Marker object definition and creation
2 
3 from __future__ import print_function
4 
5 from collections import namedtuple
6 from string import Template
7 from os import makedirs, path
8 
9 import cv2
10 import numpy as np
11 import math
12 
13 Marker = namedtuple('Marker',
14  ['id_', 'size', 'x', 'y', 'z', 'roll', 'pitch', 'yaw'])
15 
16 
17 MARKER_MODEL_CFG_TEMPLATE = Template('''
18 <?xml version="1.0"?>
19 <model>
20  <name>${model_name}</name>
21  <version>1.0</version>
22  <sdf version="1.6">${sdf_name}</sdf>
23  <author>
24  <name>Marker Generator script</name>
25  <email>marker@generator.sh</email>
26  </author>
27  <description>
28  ${model_name}
29  </description>
30 </model>
31 ''')
32 
33 
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>
38  <geometry>
39  <box>
40  <size>${marker_full_size} ${marker_full_size} 1e-3</size>
41  </box>
42  </geometry>
43  <material>
44  <script>
45  <uri>model://${model_directory}/materials/scripts</uri>
46  <uri>model://${model_directory}/materials/textures</uri>
47  <name>aruco/marker_${marker_id}</name>
48  </script>
49  </material>
50 </visual>
51 ''')
52 
53 
54 MARKER_MODEL_SDF_TEMPLATE = Template('''
55 <?xml version="1.0"?>
56 <sdf version="1.5">
57  <model name="${model_name}">
58  <static>true</static>
59  <link name="${model_name}_link">
60  ${model_visuals}
61  </link>
62  </model>
63 </sdf>
64 ''')
65 
66 
67 MARKER_MATERIAL_TEMPLATE = Template('''
68 material aruco/marker_${marker_id}
69 {
70  technique
71  {
72  pass
73  {
74  texture_unit
75  {
76  texture aruco_marker_${marker_id}.png
77  filtering none
78  scale 1.0 1.0
79  }
80  }
81  }
82 }
83 ''')
84 
85 
86 def model_name(model_directory):
87  '''
88  Extract model name from model directory.
89 
90  model_directory: Full path to the model.
91 
92  Returns Gazebo-compatible model name (available through model:// URI schema)
93  '''
94  return path.split(model_directory)[1]
95 
96 
97 def generate_markers(markers, model_directory, dictionary_id=2, map_source=''):
98  '''
99  Generate markers from a list. Result is a single Gazebo
100  model with all markers inside it.
101 
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.
106  '''
107  script_directory = path.join(model_directory, 'materials', 'scripts')
108  texture_directory = path.join(model_directory, 'materials', 'textures')
109 
110  try:
111  if not path.exists(script_directory):
112  makedirs(script_directory)
113  if not path.exists(texture_directory):
114  makedirs(texture_directory)
115  except:
116  print('Could not create material/texture directories!')
117 
118  aruco_dict = cv2.aruco.getPredefinedDictionary(dictionary_id)
119  marker_bits = aruco_dict.markerSize
120  marker_outer_bits = marker_bits + 2 # "black border" bits
121  marker_border_bits = marker_bits + 4 # "white border" bits
122  materials = []
123  visuals = []
124 
125  for marker in markers:
126  texture_name = 'aruco_marker_{}_{}.png'.format(dictionary_id, marker.id_)
127 
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_)
135  ))
136  visuals.append(MARKER_VISUAL_TEMPLATE.substitute(
137  marker_id='{}_{}'.format(dictionary_id, marker.id_),
138  x=marker.x,
139  y=marker.y,
140  z=marker.z,
141  roll=marker.roll,
142  pitch=marker.pitch,
143  yaw=marker.yaw + (math.pi / 2),
144  model_directory=model_name(model_directory),
145  marker_full_size=marker.size * marker_border_bits / marker_outer_bits
146  ))
147 
148  with open(path.join(script_directory, 'aruco_materials.material'), 'w') as f:
149  f.write(''.join(materials))
150 
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)
155  ))
156 
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,
161  dictionary_id),
162  sdf_name='aruco_model.sdf'
163  ))
def generate_markers(markers, model_directory, dictionary_id=2, map_source='')
Definition: marker.py:97
def model_name(model_directory)
Definition: marker.py:86


clover_simulation
Author(s): Alexey Rogachevskiy, Andrey Ryabov, Arthur Golubtsov, Oleg Kalachev, Svyatoslav Zhuravlev
autogenerated on Mon Feb 28 2022 22:08:36