Ubuntu 22.04安装ROS 1教程汇总

# Software License Agreement (BSD License) # # [License text保持不变] from python_qt_binding.QtCore import qDebug, QPointF, QRectF, Qt, qWarning, Signal from python_qt_binding.QtGui import QBrush, QCursor, QColor, QFont, \ QFontMetrics, QPen, QPolygonF from python_qt_binding.QtWidgets import QGraphicsItem import rospy import bisect import threading from .index_cache_thread import IndexCacheThread from .plugins.raw_view import RawView class _SelectionMode(object): """ SelectionMode states consolidated for readability NONE = no region marked or started LEFT_MARKED = one end of the region has been marked MARKED = both ends of the region have been marked SHIFTING = region is marked; currently dragging the region MOVE_LEFT = region is marked; currently changing the left boundary of the selected region MOVE_RIGHT = region is marked; currently changing the right boundary of the selected region """ NONE = 'none' LEFT_MARKED = 'left marked' MARKED = 'marked' SHIFTING = 'shifting' MOVE_LEFT = 'move left' MOVE_RIGHT = 'move right' class TimelineFrame(QGraphicsItem): """ TimelineFrame Draws the framing elements for the bag messages (time delimiters, labels, topic names and backgrounds). Also handles mouse callbacks since they interact closely with the drawn elements """ def __init__(self, bag_timeline): super(TimelineFrame, self).__init__() self._bag_timeline = bag_timeline self._clicked_pos = None self._dragged_pos = None # Timeline boundaries self._start_stamp = None # earliest of all stamps self._end_stamp = None # latest of all stamps self._stamp_left = None # earliest currently visible timestamp on the timeline self._stamp_right = None # latest currently visible timestamp on the timeline self._history_top = 30 self._history_left = 0 self._history_width = 0 self._history_bottom = 0 self._history_bounds = {} self._margin_left = 4 self._margin_right = 20 self._margin_bottom = 20 self._history_top = 30 # Background Rendering # color of background of timeline before first message and after last self._bag_end_color = QColor(0, 0, 0, 25) self._history_background_color_alternate = QColor(179, 179, 179, 25) self._history_background_color = QColor(204, 204, 204, 102) # Timeline Division Rendering # Possible time intervals used between divisions # 1ms, 5ms, 10ms, 50ms, 100ms, 500ms # 1s, 5s, 15s, 30s # 1m, 2m, 5m, 10m, 15m, 30m # 1h, 2h, 3h, 6h, 12h # 1d, 7d self._sec_divisions = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 15, 30, 1 * 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 1 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 6 * 60 * 60, 12 * 60 * 60, 1 * 60 * 60 * 24, 7 * 60 * 60 * 24] self._minor_spacing = 15 self._major_spacing = 50 self._major_divisions_label_indent = 3 # padding in px between line and label self._major_division_pen = QPen(QBrush(Qt.black), 0, Qt.DashLine) self._minor_division_pen = QPen(QBrush(QColor(153, 153, 153, 128)), 0, Qt.DashLine) self._minor_division_tick_pen = QPen(QBrush(QColor(128, 128, 128, 128)), 0) # Topic Rendering self.topics = [] self._topics_by_datatype = {} self._topic_font_height = None self._topic_name_sizes = None # minimum pixels between end of topic name and start of history self._topic_name_spacing = 3 self._topic_font_size = 10.0 self._topic_font = QFont("cairo") self._topic_font.setPointSize(int(self._topic_font_size)) self._topic_font.setBold(False) self._topic_vertical_padding = 4 # percentage of the horiz space that can be used for topic display self._topic_name_max_percent = 25.0 # Time Rendering self._time_tick_height = 5 self._time_font_height = None self._time_font_size = 10.0 self._time_font = QFont("cairo") self._time_font.setPointSize(int(self._time_font_size)) self._time_font.setBold(False) # Defaults self._default_brush = QBrush(Qt.black, Qt.SolidPattern) self._default_pen = QPen(Qt.black) self._default_datatype_color = QColor(0, 0, 102, 204) self._datatype_colors = { 'sensor_msgs/CameraInfo': QColor(0, 0, 77, 204), 'sensor_msgs/Image': QColor(0, 77, 77, 204), 'sensor_msgs/LaserScan': QColor(153, 0, 0, 204), 'pr2_msgs/LaserScannerSignal': QColor(153, 0, 0, 204), 'pr2_mechanism_msgs/MechanismState': QColor(0, 153, 0, 204), 'tf/tfMessage': QColor(0, 153, 0, 204), } # minimum number of pixels allowed between two bag messages before they are combined self._default_msg_combine_px = 1.0 self._active_message_line_width = 3 # Selected Region Rendering self._selected_region_color = QColor(0, 179, 0, 21) self._selected_region_outline_top_color = QColor(0, 77, 0, 51) self._selected_region_outline_ends_color = QColor(0, 77, 0, 102) self._selecting_mode = _SelectionMode.NONE self._selected_left = None self._selected_right = None self._selection_handle_width = 3.0 # Playhead Rendering self._playhead = None # timestamp of the playhead self._paused = False self._playhead_pointer_size = (6, 6) self._playhead_line_width = 1 self._playhead_color = QColor(255, 0, 0, 191) # Zoom self._zoom_sensitivity = 0.005 self._min_zoom_speed = 0.5 self._max_zoom_speed = 2.0 self._min_zoom = 0.0001 # max zoom out (in px/s) self._max_zoom = 50000.0 # max zoom in (in px/s) # Plugin management self._viewer_types = {} self._timeline_renderers = {} self._rendered_topics = set() self.load_plugins() # Bag indexer for rendering the default message views on the timeline self.index_cache_cv = threading.Condition() self.index_cache = {} self.invalidated_caches = set() self._index_cache_thread = IndexCacheThread(self) # TODO the API interface should exist entirely at the bag_timeline level. # Add a "get_draw_parameters()" at the bag_timeline level to access these # Properties, work in progress API for plugins: # property: playhead def _get_playhead(self): return self._playhead def _set_playhead(self, playhead): """ Sets the playhead to the new position, notifies the threads and updates the scene so it will redraw :signal: emits status_bar_changed_signal if the playhead is successfully set :param playhead: Time to set the playhead to, ''rospy.Time()'' """ with self.scene()._playhead_lock: if playhead == self._playhead: return self._playhead = playhead if self._playhead != self._end_stamp: self.scene().stick_to_end = False playhead_secs = playhead.to_sec() if playhead_secs > self._stamp_right: dstamp = playhead_secs - self._stamp_right + \ (self._stamp_right - self._stamp_left) * 0.75 if dstamp > self._end_stamp.to_sec() - self._stamp_right: dstamp = self._end_stamp.to_sec() - self._stamp_right self.translate_timeline(dstamp) elif playhead_secs < self._stamp_left: dstamp = self._stamp_left - playhead_secs + \ (self._stamp_right - self._stamp_left) * 0.75 if dstamp > self._stamp_left - self._start_stamp.to_sec(): dstamp = self._stamp_left - self._start_stamp.to_sec() self.translate_timeline(-dstamp) # Update the playhead positions for topic in self.topics: bag, entry = self.scene().get_entry(self._playhead, topic) if entry: if topic in self.scene()._playhead_positions and \ self.scene()._playhead_positions[topic] == (bag, entry.position): continue new_playhead_position = (bag, entry.position) else: new_playhead_position = (None, None) with self.scene()._playhead_positions_cvs[topic]: self.scene()._playhead_positions[topic] = new_playhead_position # notify all message loaders that a new message needs to be loaded self.scene()._playhead_positions_cvs[topic].notify_all() self.scene().update() self.scene().status_bar_changed_signal.emit() playhead = property(_get_playhead, _set_playhead) # TODO add more api variables here to allow plugin access @property def _history_right(self): return self._history_left + self._history_width @property def has_selected_region(self): return self._selected_left is not None and self._selected_right is not None @property def play_region(self): if self.has_selected_region: return ( rospy.Time.from_sec(self._selected_left), rospy.Time.from_sec(self._selected_right)) else: return (self._start_stamp, self._end_stamp) def emit_play_region(self): play_region = self.play_region if(play_region[0] is not None and play_region[1] is not None): self.scene().selected_region_changed.emit(*play_region) @property def start_stamp(self): return self._start_stamp @property def end_stamp(self): return self._end_stamp # QGraphicsItem implementation def boundingRect(self): return QRectF( 0, 0, self._history_left + self._history_width + self._margin_right, self._history_bottom + self._margin_bottom) def paint(self, painter, option, widget): if self._start_stamp is None: return self._layout() self._draw_topic_dividers(painter) self._draw_selected_region(painter) self._draw_time_divisions(painter) self._draw_topic_histories(painter) self._draw_bag_ends(painter) self._draw_topic_names(painter) self._draw_history_border(painter) self._draw_playhead(painter) # END QGraphicsItem implementation # Drawing Functions def _qfont_width(self, name): return QFontMetrics(self._topic_font).width(name) def _trimmed_topic_name(self, topic_name): """ This function trims the topic name down to a reasonable percentage of the viewable scene area """ allowed_width = self._scene_width * (self._topic_name_max_percent / 100.0) allowed_width = allowed_width - self._topic_name_spacing - self._margin_left trimmed_return = topic_name if allowed_width < self._qfont_width(topic_name): # We need to trim the topic trimmed = '' split_name = topic_name.split('/') split_name = list(filter(lambda a: a != '', split_name)) # Save important last element of topic name provided it is small popped_last = False if self._qfont_width(split_name[-1]) < .5 * allowed_width: popped_last = True last_item = split_name[-1] split_name = split_name[:-1] allowed_width = allowed_width - self._qfont_width(last_item) # Shorten and add remaining items keeping lengths roughly equal for item in split_name: if self._qfont_width(item) > allowed_width / float(len(split_name)): trimmed_item = item[:-3] + '..' while self._qfont_width(trimmed_item) > allowed_width / float(len(split_name)): if len(trimmed_item) >= 3: trimmed_item = trimmed_item[:-3] + '..' else: break trimmed = trimmed + '/' + trimmed_item else: trimmed = trimmed + '/' + item if popped_last: trimmed = trimmed + '/' + last_item trimmed = trimmed[1:] trimmed_return = trimmed return trimmed_return def _layout(self): """ Recalculates the layout of the timeline to take into account any changes that have occurred """ # Calculate history left and history width self._scene_width = self.scene().views()[0].size().width() max_topic_name_width = -1 for topic in self.topics: topic_width = self._qfont_width(self._trimmed_topic_name(topic)) if max_topic_name_width <= topic_width: max_topic_name_width = topic_width # Calculate font height for each topic self._topic_font_height = -1 for topic in self.topics: topic_height = QFontMetrics(self._topic_font).height() if self._topic_font_height <= topic_height: self._topic_font_height = topic_height # Update the timeline boundaries new_history_left = self._margin_left + max_topic_name_width + self._topic_name_spacing new_history_width = self._scene_width - new_history_left - self._margin_right self._history_left = new_history_left self._history_width = new_history_width # Calculate the bounds for each topic self._history_bounds = {} y = self._history_top for topic in self.topics: datatype = self.scene().get_datatype(topic) topic_height = None if topic in self._rendered_topics: renderer = self._timeline_renderers.get(datatype) if renderer: topic_height = renderer.get_segment_height(topic) if not topic_height: topic_height = self._topic_font_height + self._topic_vertical_padding self._history_bounds[topic] = (self._history_left, y, self._history_width, topic_height) y += topic_height # new_history_bottom = max([y + h for (x, y, w, h) in self._history_bounds.values()]) - 1 new_history_bottom = max([y + h for (_, y, _, h) in self._history_bounds.values()]) - 1 if new_history_bottom != self._history_bottom: self._history_bottom = new_history_bottom def _draw_topic_histories(self, painter): """ Draw all topic messages :param painter: allows access to paint functions,''QPainter'' """ f
上一篇:一篇文章解释AI中的“算力”与“数据”两个概念!


下一篇:Sql面试题二:请查询出用户连续三天登录的所有数据记录