1
+ import rospy
2
+ from visualization_msgs .msg import MarkerArray , Marker
3
+ from geometry_msgs .msg import Pose , Point
4
+ from copy import deepcopy
5
+
6
+ COLORS = [[153 , 51 , 102 ], [0 , 255 , 0 ], [254 , 254 , 0 ], [254 , 0 , 254 ], [0 , 255 , 255 ], [255 , 153 , 0 ]]
7
+
8
+ class ROSMarkerPublisher :
9
+
10
+ """
11
+ Collects ROS Markers
12
+ """
13
+
14
+ def __init__ (self , topic , max_size ):
15
+ self .pub_ = rospy .Publisher (topic , MarkerArray , queue_size = 1 )
16
+ self .marker_list_ = MarkerArray ()
17
+
18
+ self .clear_all ()
19
+
20
+ self .ros_markers_ = []
21
+
22
+ self .topic_ = topic
23
+ self .max_size_ = max_size
24
+ self .id_ = 0
25
+ self .prev_id_ = 0
26
+
27
+ def clear_all (self ):
28
+ remove_marker = Marker ()
29
+ remove_marker .action = remove_marker .DELETEALL
30
+ self .marker_list_ .markers = []
31
+ self .marker_list_ .markers .append (remove_marker )
32
+ self .pub_ .publish (self .marker_list_ )
33
+
34
+ def __del__ (self ):
35
+ self .clear_all ()
36
+
37
+ def publish (self ):
38
+ # print('DEBUG: Publishing markers')
39
+
40
+ remove_marker = Marker ()
41
+ remove_marker .action = remove_marker .DELETE
42
+
43
+ if self .prev_id_ > self .id_ :
44
+ for i in range (self .id_ , self .prev_id_ ):
45
+ remove_marker .id = i
46
+ self .marker_list_ .markers .append (deepcopy (remove_marker ))
47
+
48
+ # Define stamp properties
49
+ for marker in self .marker_list_ .markers :
50
+ marker .header .stamp = rospy .Time .now ()
51
+
52
+ # Publish
53
+ # print(self.marker_list_.markers)
54
+ #print('Publishing {} markers'.format(len(self.marker_list_.markers)))
55
+ self .pub_ .publish (self .marker_list_ )
56
+
57
+ # Reset
58
+ self .marker_list_ .markers = []
59
+
60
+ self .prev_id_ = deepcopy (self .id_ )
61
+ self .id_ = 0
62
+
63
+ def get_cube (self , frame_id = "map" ):
64
+ new_marker = ROSMarker (1 , frame_id , self )
65
+ return self .get_point_marker (new_marker )
66
+
67
+ def get_sphere (self , frame_id = "map" ):
68
+ new_marker = ROSMarker (2 , frame_id , self )
69
+ return self .get_point_marker (new_marker )
70
+
71
+ def get_cylinder (self , frame_id = "map" ):
72
+ new_marker = ROSMarker (3 , frame_id , self )
73
+ return self .get_point_marker (new_marker )
74
+
75
+ def get_circle (self , frame_id = "map" ):
76
+ new_marker = ROSMarker (3 , frame_id , self )
77
+ new_marker .set_scale (1. , 1. , 0.01 )
78
+ return self .get_point_marker (new_marker )
79
+
80
+ def get_line (self , frame_id = "map" ):
81
+ new_marker = ROSLineMarker (frame_id , self )
82
+ return self .get_point_marker (new_marker )
83
+
84
+ def get_point_marker (self , new_marker ):
85
+ self .ros_markers_ .append (new_marker )
86
+ return new_marker # Gives the option to modify it
87
+
88
+ def add_marker_ (self , new_marker ):
89
+ self .marker_list_ .markers .append (new_marker )
90
+
91
+ def get_id_ (self ):
92
+ cur_id = deepcopy (self .id_ )
93
+ self .id_ += 1
94
+ return cur_id
95
+
96
+ class ROSMarker :
97
+
98
+ def __init__ (self , type , frame_id , ros_marker_publisher ):
99
+ self .marker_ = Marker ()
100
+ self .marker_ .header .frame_id = frame_id
101
+ self .type_ = type
102
+ self .marker_ .type = self .type_
103
+ self .ros_marker_publisher_ = ros_marker_publisher
104
+
105
+ self .set_color (0 )
106
+ self .set_scale (1 , 1 , 1 )
107
+
108
+ def set_scale (self , x , y , z ):
109
+ self .marker_ .scale .x = x
110
+ self .marker_ .scale .y = y
111
+ self .marker_ .scale .z = z
112
+
113
+ def set_scale_all (self , all = 1.0 ):
114
+ self .marker_ .scale .x = all
115
+ self .marker_ .scale .y = all
116
+ self .marker_ .scale .z = all
117
+
118
+ def set_color (self , int_val , alpha = 1.0 ):
119
+ red , green , blue = get_viridis_color (int_val )
120
+ self .marker_ .color .r = red
121
+ self .marker_ .color .g = green
122
+ self .marker_ .color .b = blue
123
+ self .marker_ .color .a = alpha
124
+
125
+ def set_lifetime (self , lifetime ):
126
+ self .marker_ .lifetime = rospy .Time (lifetime )
127
+
128
+ def add_marker (self , pose ):
129
+ self .marker_ .id = self .ros_marker_publisher_ .get_id_ ()
130
+ self .marker_ .pose = pose
131
+ self .marker_ .pose .orientation .x = 0
132
+ self .marker_ .pose .orientation .y = 0
133
+ self .marker_ .pose .orientation .z = 0
134
+ self .marker_ .pose .orientation .w = 1
135
+ self .ros_marker_publisher_ .add_marker_ (deepcopy (self .marker_ )) # Note the deepcopy
136
+
137
+ class ROSLineMarker :
138
+
139
+ def __init__ (self , frame_id , ros_marker_publisher ):
140
+ self .marker_ = Marker ()
141
+ self .marker_ .header .frame_id = frame_id
142
+ self .marker_ .type = 5
143
+ self .ros_marker_publisher_ = ros_marker_publisher
144
+
145
+ self .marker_ .scale .x = 0.25
146
+ self .marker_ .pose .orientation .x = 0
147
+ self .marker_ .pose .orientation .y = 0
148
+ self .marker_ .pose .orientation .z = 0
149
+ self .marker_ .pose .orientation .w = 1
150
+ self .set_color (1 )
151
+
152
+ # Ax <= b (visualized)
153
+ def add_constraint_line (self , A , b , length = 10.0 ):
154
+ a1 = A [0 ]
155
+ a2 = A [1 ]
156
+ b = float (b )
157
+ p1 = Point ()
158
+ p2 = Point ()
159
+ if abs (a1 ) < 0.01 and abs (a2 ) >= 0.01 :
160
+ p1 .x = - length
161
+ p1 .y = (b + a1 * length ) / float (a2 )
162
+ p1 .z = 0.
163
+
164
+ p2 .x = length
165
+ p2 .y = (b - a1 * length ) / float (a2 )
166
+ p2 .z = 0.
167
+ elif (abs (a1 ) >= 0.01 ):
168
+ p1 .y = - length
169
+ p1 .x = (b + a2 * length ) / float (a1 )
170
+ p1 .z = 0.
171
+
172
+ p2 .y = length
173
+ p2 .x = (b - a2 * length ) / float (a1 )
174
+ p2 .z = 0.
175
+ else :
176
+ raise Exception ("visualized constrained is zero" )
177
+
178
+ p1 .x = min (max (p1 .x , - 1e5 ), 1e5 )
179
+ p2 .x = min (max (p2 .x , - 1e5 ), 1e5 )
180
+ p1 .y = min (max (p1 .y , - 1e5 ), 1e5 )
181
+ p2 .y = min (max (p2 .y , - 1e5 ), 1e5 )
182
+
183
+ self .add_line (p1 , p2 )
184
+
185
+ def add_line_from_poses (self , pose_one , pose_two ):
186
+ p1 = Point ()
187
+ p1 .x = pose_one .position .x
188
+ p1 .y = pose_one .position .y
189
+ p1 .z = pose_one .position .z
190
+
191
+ p2 = Point ()
192
+ p2 .x = pose_two .position .x
193
+ p2 .y = pose_two .position .y
194
+ p2 .z = pose_two .position .z
195
+
196
+ self .add_line (p1 , p2 )
197
+
198
+ def add_line (self , point_one , point_two ):
199
+ self .marker_ .id = self .ros_marker_publisher_ .get_id_ ()
200
+
201
+ self .marker_ .points .append (point_one )
202
+ self .marker_ .points .append (point_two )
203
+
204
+ self .ros_marker_publisher_ .add_marker_ (deepcopy (self .marker_ ))
205
+
206
+ self .marker_ .points = []
207
+
208
+ def set_color (self , int_val , alpha = 1.0 ):
209
+ red , green , blue = get_viridis_color (int_val )
210
+ self .marker_ .color .r = red
211
+ self .marker_ .color .g = green
212
+ self .marker_ .color .b = blue
213
+ self .marker_ .color .a = alpha
214
+
215
+ def set_scale (self , thickness ):
216
+ self .marker_ .scale .x = thickness
217
+
218
+
219
+ def get_viridis_color (select ):
220
+ # Obtained from https://waldyrious.net/viridis-palette-generator/
221
+ viridis_vals = [253 , 231 , 37 , 234 , 229 , 26 , 210 , 226 , 27 , 186 , 222 , 40 , 162 , 218 , 55 , 139 , 214 , 70 , 119 , 209 , 83 , 99 ,
222
+ 203 , 95 , 80 , 196 , 106 , 63 , 188 , 115 , 49 , 181 , 123 , 38 , 173 , 129 , 33 , 165 , 133 , 30 , 157 , 137 , 31 , 148 , 140 , 34 , 140 ,
223
+ 141 , 37 , 131 , 142 , 41 , 123 , 142 , 44 , 115 , 142 , 47 , 107 , 142 , 51 , 98 , 141 , 56 , 89 , 140 ]
224
+
225
+ VIRIDIS_COLORS = 20
226
+ select %= VIRIDIS_COLORS # only 20 values specified
227
+
228
+ # Invert the color range
229
+ select = VIRIDIS_COLORS - 1 - select
230
+ red = viridis_vals [select * 3 + 0 ]
231
+ green = viridis_vals [select * 3 + 1 ]
232
+ blue = viridis_vals [select * 3 + 2 ]
233
+
234
+ red /= 256.0
235
+ green /= 256.0
236
+ blue /= 256.0
237
+
238
+ return red , green , blue
0 commit comments