31 from python_qt_binding
import loadUi
32 from python_qt_binding.QtCore
import Qt, Signal, Slot
33 from python_qt_binding.QtWidgets
import QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QLabel
36 from rospy.exceptions
import ROSException
40 import matplotlib.pyplot
as plt
44 import subsystem_common
48 import subsystem_components
49 import subsystem_state_history
51 import latex_equations
54 from diagnostic_msgs.msg
import DiagnosticArray
58 main class inherits from the ui window class. 64 return (layout.itemAt(i)
for i
in range(layout.count()))
87 ranges = [0.0001, 0.0002, 0.0003, 0.0004, 0.0006, 0.0008, 0.001, 0.0012,
88 0.0014, 0.0016, 0.002, 0.0024, 0.0028, 0.0032, 0.0038, 0.0050,
89 0.0060, 0.0080, 0.01, 0.02, 0.03, 0.05,]
92 ranges_str.append( str(val*1000) )
97 for idx
in range(len(y)):
103 val_rel = val - prev_val
107 y_log.append( val_rel )
109 plt.xticks(x[0:-1]+0.5, ranges_str)
123 @type selected_topics: list of tuples. 124 @param selected_topics: [($NAME_TOPIC$, $TYPE_TOPIC$), ...] 125 @type select_topic_type: int 126 @param select_topic_type: Can specify either the name of topics or by 127 the type of topic, to filter the topics to 128 show. If 'select_topic_type' argument is 129 None, this arg shouldn't be meaningful. 131 super(SubsystemWidget, self).
__init__()
135 rp = rospkg.RosPack()
136 ui_file = os.path.join(rp.get_path(
'rqt_agent'),
'resource',
'SubsystemWidget.ui')
137 loadUi(ui_file, self)
140 print "created Subsystem widget" 143 self.SubsystemName.setText(name)
145 self.SubsystemName.setText(
"<could not get subsystem name>")
183 def __logMsgCallback(self, msg):
187 for status
in msg.status:
188 logger_name = status.name
189 logs[logger_name] = []
190 for value
in status.values:
191 log_str = value.value
192 logs[logger_name].append( log_str )
200 if (
not comp_to)
or (
not comp_from):
201 print 'WARNING: wrong edge(1): ', conn, comp_from, comp_to
204 if conn.find(comp_from.name) != 0:
205 print 'WARNING: wrong edge(2): ', conn, comp_from.name, comp_to.name
208 idx = len(comp_from.name)
210 for p
in comp_from.ports:
211 if conn.find(p.name, idx) == idx:
217 print 'WARNING: wrong edge(3): ', conn, comp_from.name, comp_to.name
220 if conn.find(comp_to.name, idx) != idx:
221 print 'WARNING: wrong edge(4): ', conn, comp_from.name, comp_to.name
223 idx += len(comp_to.name)
226 for p
in comp_to.ports:
227 if conn.find(p.name, idx) == idx:
233 print 'WARNING: wrong edge(5): ', conn, comp_from.name, comp_to.name
236 return (comp_from.name, port_from, comp_to.name, port_to)
242 behavior_graphs_list = [
"<all>"]
244 behavior_graphs_list.append(behavior.name)
246 for graph_name
in behavior_graphs_list:
252 for b
in subsystem_info.behaviors:
253 if b.name == behavior_name:
259 for comp
in subsystem_info.components:
260 if comp.is_converter:
261 conv_comp.add(comp.name)
264 for b
in subsystem_info.behaviors:
265 for r
in b.running_components:
269 for comp
in subsystem_info.components:
270 all_comp.add(comp.name)
272 always_running = all_comp - sw_comp
275 current_running = set()
277 for r
in behavior.running_components:
278 current_running.add(r)
279 other_behaviors_comp = sw_comp - current_running
280 running = always_running.union(current_running)
283 conv_connections = {}
285 for c
in subsystem_info.component_connections:
286 if ((
not c.component_from.strip())
or (
not c.component_to.strip()))
and not c.unconnected:
289 if (
not c.component_from
in current_running)
and (
not c.component_to
in current_running):
291 if c.component_from
in other_behaviors_comp
or c.component_to
in other_behaviors_comp:
296 elif behavior_name ==
"<all>":
299 raise Exception(
'getBehaviorConnectionsSet',
'wrong behavior name: ' + behavior_name)
301 c_from = c.component_from
302 c_to = c.component_to
303 unconnected = c.unconnected
306 if c_from
in conv_comp:
307 if not c_from
in conv_connections:
308 conv_connections[c_from] = (
None, c_to)
311 conv_connections[c_from] = (conv_connections[c_from][0], c_to)
312 c_to = conv_connections[c_from][1]
313 c_from = conv_connections[c_from][0]
315 elif c_to
in conv_comp:
316 if not c_to
in conv_connections:
317 conv_connections[c_to] = (c_from,
None)
320 conv_connections[c_to] = (c_from, conv_connections[c_to][1])
321 c_from = conv_connections[c_to][0]
322 c_to = conv_connections[c_to][1]
326 conn_tuple = (c_from, c_to)
328 if not c_from.strip():
329 conn_tuple = (
None, c_to)
331 conn_tuple = (c_from,
None)
335 elif c.port_from.strip():
337 if not unconnected
and cname.endswith(
"_OUTPORT"):
341 if not unconnected
and cname.endswith(
"_INPORT"):
350 if conn_tuple
in conn_set:
352 conn_set[conn_tuple][0].append(cname)
353 conn_set[conn_tuple][1].append(latex_name)
355 conn_set[conn_tuple] = [[cname], [latex_name]]
357 shown_components = set()
358 for conn_tuple
in conn_set:
359 edge = g.getEdge(conn_tuple[0], conn_tuple[1])
362 edge.id_from = conn_tuple[0]
363 edge.id_to = conn_tuple[1]
364 for i
in range(len(conn_set[conn_tuple][0])):
365 edge.addLabel(conn_set[conn_tuple][0][i], conn_set[conn_tuple][1][i])
366 if conn_tuple[0] !=
None:
367 shown_components.add(conn_tuple[0])
368 if conn_tuple[1] !=
None:
369 shown_components.add(conn_tuple[1])
373 for c
in subsystem_info.components:
374 if not c.name
in shown_components:
378 node.latex_label = c.latex
379 g.nodes[c.name] = node
397 for state
in subsystem_info.state_machine:
403 g.nodes[state.name] = n
404 print " state: " + state.name
406 for b
in state.behavior_names:
409 for next_state
in state.next_states:
412 e.id_from = state.name
413 e.id_to = next_state.name
416 e.addLabel(
's_{' + state.name +
"," + next_state.name +
"}",
'\sigma_{' + latex_equations.toMathText(state.name) +
"," + latex_equations.toMathText(next_state.name) +
'}')
417 print " s_{" + state.name +
"," + next_state.name +
"} = " + next_state.init_cond
420 for behavior
in subsystem_info.behaviors:
421 print " behavior: " + behavior.name
422 print " terminal_condition: " + behavior.terminal_condition
423 print " error_condition: " + behavior.error_condition
433 iterating_identifier =
False 435 for i
in range(len(s)):
436 if not iterating_identifier:
437 if s[i].isalpha()
or s[i] ==
'_':
438 iterating_identifier =
True 441 if not s[i].isalnum()
and s[i] !=
'_':
442 iterating_identifier =
False 443 ident = s[id_begin:i]
444 id_positions.append( (ident, id_begin) )
445 if iterating_identifier:
447 id_positions.append( (ident, id_begin) )
454 for state
in subsystem_info.state_machine:
455 term_err_cond_ids = []
456 for behavior_name
in state.behavior_names:
457 for b
in subsystem_info.behaviors:
458 if b.name == behavior_name:
460 for id_pos
in id_positions:
461 if id_pos[0] !=
'and' and id_pos[0] !=
'or' and not id_pos[0]
in term_err_cond_ids:
462 term_err_cond_ids.append(id_pos[0])
464 for id_pos
in id_positions:
465 if id_pos[0] !=
'and' and id_pos[0] !=
'or' and not id_pos[0]
in term_err_cond_ids:
466 term_err_cond_ids.append(id_pos[0])
469 for next_state
in state.next_states:
472 for id_pos
in id_positions:
473 if id_pos[0] !=
'and' and id_pos[0] !=
'or' and not id_pos[0]
in init_cond_ids:
474 init_cond_ids.append(id_pos[0])
475 transitions[(state.name,next_state.name)] = term_err_cond_ids + init_cond_ids
480 def convertToLatex(condition):
481 cond = copy.copy(condition)
486 last_line_break = -(len(state.name) + len(next_state.name))/2
489 for id_pos
in id_positions:
490 if id_pos[0] ==
'and' or id_pos[0] ==
'or':
491 if id_pos[1]-last_line_break > max_line_len:
492 line_breaks.append(id_pos[1])
493 last_line_break = id_pos[1]
494 last_and_or = id_pos[1]
496 for br
in reversed(line_breaks):
497 cond = cond[0:br] +
"\\\\" + cond[br:]
501 for id_pos
in id_positions:
502 if not id_pos[0]
in ids:
503 ids.append(id_pos[0])
504 ids.sort(key =
lambda s: len(s), reverse=
True)
506 for i
in range(len(ids)):
507 cond = cond.replace(ids[i],
"{" + str(i) +
"}")
509 for i
in range(len(ids)):
514 elif ids[i] ==
"not":
517 ident =
" \\text{" + ids[i] +
"} " 518 cond = cond.replace(
"{" + str(i) +
"}", ident)
525 for state
in subsystem_info.state_machine:
526 print " state: " + state.name
527 for next_state
in state.next_states:
528 init_cond = convertToLatex(next_state.init_cond)
529 init_cond =
"\\sigma_{" + latex_equations.toMathText(state.name) +
"," + latex_equations.toMathText(next_state.name) +
"} = " + init_cond
530 latex_formulas.append(init_cond)
531 file_names.append(self.
subsystem_name +
"_ " + state.name +
"_" + next_state.name +
"_init")
535 for behavior_name
in state.behavior_names:
536 for b
in subsystem_info.behaviors:
537 if b.name == behavior_name:
538 if term_cond ==
None:
539 term_cond =
"(" + b.terminal_condition +
")" 541 term_cond = term_cond +
" or (" + b.terminal_condition +
")" 543 err_cond =
"(" + b.error_condition +
")" 545 err_cond = err_cond +
" or (" + b.error_condition +
")" 548 term_cond = convertToLatex(term_cond)
549 term_cond =
"\\tau_{" + latex_equations.toMathText(state.name) +
"} = " + term_cond
550 latex_formulas.append(term_cond)
551 file_names.append(self.
subsystem_name +
"_ " + state.name +
"_" + next_state.name +
"_term")
553 err_cond = convertToLatex(err_cond)
554 err_cond =
"\\epsilon_{" + latex_equations.toMathText(state.name) +
"} = " + err_cond
555 latex_formulas.append(err_cond)
556 file_names.append(self.
subsystem_name +
"_ " + state.name +
"_" + next_state.name +
"_err")
558 with open(
"formulas.tex",
'w')
as outfile:
559 for i
in range(len(latex_formulas)):
560 outfile.write(
"% " + file_names[i] +
"\n")
562 outfile.write(latex_formulas[i] +
"\n")
575 for value
in msg.status[1].values:
576 if value.key ==
'master_component':
577 self.
state = value.value
578 elif value.key[-2:] ==
'Rx' or value.key[-2:] ==
'Tx':
580 if value.value ==
'<data ok>':
581 self.
all_buffers[value.key[:-2]].setStyleSheet(
"background-color: green")
583 self.
all_buffers[value.key[:-2]].setStyleSheet(
"background-color: red")
584 self.
all_buffers[value.key[:-2]].setToolTip(value.value)
588 draw_unconnected =
False 597 behavior_graphs_list = [
"<all>"]
599 behavior_graphs_list.append(behavior.name)
602 for graph_name
in behavior_graphs_list:
620 components_state = {}
621 for value
in msg.status[0].values:
622 components_state[value.key] = value.value
624 components_diag_msgs = {}
625 for value
in msg.status[1].values:
626 components_diag_msgs[value.key] = value.value
639 except rospy.ServiceException, e:
640 print "Service call failed: %s"%e
653 mcd = subsystem_common.parseMasterComponentDiag(self.
state)
654 if len(mcd.history) > 0:
655 self.SubsystemState.setText(mcd.history[0].state_name)
658 self.PeriodWall.setText(str(mcd.current_period*1000.0) +
'ms')
661 self.SubsystemState.setText(
"unknown")
662 self.PeriodWall.setText(
"unknown")
665 if not self.
isInitialized()
or not subsystem.isInitialized():
667 if (subsystem.subsystem_info ==
None)
or (self.
subsystem_info ==
None):
669 common_buffers =
None 672 for index
in range(len(subsystem.subsystem_info.lower_outputs)):
673 lo_out = subsystem.subsystem_info.lower_outputs[index]
675 if common_buffers ==
None:
677 common_buffers.append(up_in)
681 for index
in range(len(subsystem.subsystem_info.lower_inputs)):
682 lo_in = subsystem.subsystem_info.lower_inputs[index]
684 if common_buffers ==
None:
686 common_buffers.append(up_out)
687 return common_buffers
696 if character ==
None:
698 elif character != s[idx]:
704 if buffer_list ==
None or len(buffer_list) == 0:
705 print "Error in %s.groupBuffers(%s, %s): buffers list is None or empty"%(self.
subsystem_name, buffer_list, subsystem_name)
707 if subsystem_name
in self.buffer_groups:
710 self.buffer_groups[subsystem_name] = buffer_list
717 for buf_name
in buffer_list:
719 lo_in.append(buf_name)
721 up_in.append(buf_name)
723 lo_out.append(buf_name)
725 up_out.append(buf_name)
728 if (len(lo_in) > 0
or len(lo_out) > 0)
and (len(up_in) > 0
or len(up_out) > 0):
729 print "Error in %s.groupBuffers(%s, %s): mixed upper and lower buffers"%(self.
subsystem_name, buffer_list, subsystem_name)
735 for idx
in range(len(buffer_list)):
736 name_list.append( buffer_list[idx][len(common_name):] )
738 print common_name, name_list
742 hbox1 = QHBoxLayout()
745 self.
all_buffers[common_name] = QLabel(common_name)
750 hbox2 = QHBoxLayout()
752 for buf_name
in name_list:
754 if common_name+buf_name
in lo_in
or common_name+buf_name
in up_out:
760 self.
all_buffers[common_name+buf_name] = QPushButton(buf_name + suffix)
761 hbox2.addWidget( self.
all_buffers[common_name+buf_name] )
768 if len(lo_in) > 0
or len(lo_out) > 0:
769 vbox.addLayout(hbox1)
770 vbox.addLayout(hbox2)
771 self.lower_buffers_layout.addLayout(vbox)
772 self.lower_subsystems.append(subsystem_name)
774 vbox.addLayout(hbox2)
775 vbox.addLayout(hbox1)
776 self.upper_buffers_layout.addLayout(vbox)
779 for i
in range(len(self.lower_subsystems)):
780 if self.lower_subsystems[i] == subsystem_name:
785 return self.lower_subsystems
789 This method needs to be called to start updating topic pane. 793 for topic
in self._topics.values():
794 topic[
'info'].stop_monitoring()
795 self._timer_refresh_topics.stop()
800 header_state = self.topics_tree_widget.header().saveState()
801 instance_settings.set_value(
'tree_widget_header_state', header_state)
804 if instance_settings.contains(
'tree_widget_header_state'):
805 header_state = instance_settings.value(
'tree_widget_header_state')
806 if not self.topics_tree_widget.header().restoreState(header_state):
807 rospy.logwarn(
"rqt_topic: Failed to restore header state.")