コード例 #1
0
class SbpRelayView(HasTraits):
    """
    Class allows user to specify port, IP address, and message set
    to relay over UDP.
    """
    running = Bool(False)
    _network_info = List()
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    network_refresh_button = SVGButton(
        label='Refresh Network Status',
        tooltip='Refresh Network Status',
        filename=resource_filename('console/images/fontawesome/refresh.svg'),
        width=16,
        height=16,
        aligment='center')
    cell_modem_view = Instance(CellModemView)
    view = View(
        VGroup(
            spring,
            HGroup(
                VGroup(
                    Item('msg_enum',
                         label="Messages to broadcast",
                         style='custom',
                         enabled_when='not running'),
                    Item('ip_ad',
                         label='IP Address',
                         enabled_when='not running'),
                    Item('port', label="Port", enabled_when='not running'),
                    HGroup(
                        spring,
                        UItem('start',
                              enabled_when='not running',
                              show_label=False),
                        UItem('stop', enabled_when='running',
                              show_label=False), spring)),
                VGroup(
                    Item('information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                )), spring,
            HGroup(
                Item('cell_modem_view', style='custom', show_label=False),
                VGroup(Item(
                    '_network_info',
                    style='readonly',
                    editor=TabularEditor(adapter=SimpleNetworkAdapter()),
                    show_label=False,
                ),
                       Item('network_refresh_button',
                            show_label=False,
                            width=0.50),
                       show_border=True,
                       label="Network"),
            )))

    def _network_callback(self, m, **metadata):
        txstr = sizeof_fmt(m.tx_bytes),
        rxstr = sizeof_fmt(m.rx_bytes)
        if m.interface_name.startswith(
                b'ppp0'):  # Hack for ppp tx and rx which doesn't work
            txstr = "---"
            rxstr = "---"
        elif m.interface_name.startswith(b'lo') or m.interface_name.startswith(
                b'sit0'):
            return
        table_row = ((m.interface_name.decode('ascii'),
                      ip_bytes_to_string(m.ipv4_address),
                      ((m.flags & (1 << 6)) != 0), txstr, rxstr))
        exists = False
        for i, each in enumerate(self._network_info):
            if each[0][0] == table_row[0][0]:
                self._network_info[i] = table_row
                exists = True
        if not exists:
            self._network_info.append(table_row)

    def __init__(self, link):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.cell_modem_view = CellModemView(link)
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        self.python_console_cmds = {'update': self}
        self.cellmodem_interface_name = "ppp0"
        self.link.add_callback(self._network_callback,
                               SBP_MSG_NETWORK_STATE_RESP)

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def update_network_state(self):
        self._network_refresh_button_fired()

    def _network_refresh_button_fired(self):
        self._network_info = []
        self.link(MsgNetworkStateReq())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:  # noqa
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:  # noqa
            import traceback
            print(traceback.format_exc())
コード例 #2
0
class ScatterPlot(Template):

    #-- Template Traits --------------------------------------------------------

    # The plot index data source:
    index = TDataSource

    # The plot value data source:
    value = TDataSource

    # The title of the plot:
    title = TStr('Scatter Plot')

    # The type of marker to use.  This is a mapped trait using strings as the
    # keys:
    marker = marker_trait(template='copy', event='update')

    # The pixel size of the marker (doesn't include the thickness of the
    # outline):
    marker_size = TRange(1, 5, 1, event='update')

    # The thickness, in pixels, of the outline to draw around the marker.  If
    # this is 0, no outline will be drawn.
    line_width = TRange(0.0, 5.0, 1.0)

    # The fill color of the marker:
    color = TColor('red', event='update')

    # The color of the outline to draw around the marker
    outline_color = TColor('black', event='update')

    #-- Derived Traits ---------------------------------------------------------

    plot = TDerived  # Instance( ScatterPlot )

    #-- Traits UI Views --------------------------------------------------------

    # The scatter plot view:
    template_view = View(VGroup(
        Item('title',
             show_label=False,
             style='readonly',
             editor=ThemedTextEditor(theme=Theme('@GBB', alignment='center'))),
        Item('plot',
             show_label=False,
             resizable=True,
             editor=EnableEditor(),
             item_theme=Theme('@GF5', margins=0))),
                         resizable=True)

    # The scatter plot options view:
    options_view = View(
        VGroup(
            VGroup(Label('Scatter Plot Options',
                         item_theme=Theme('@GBB', alignment='center')),
                   show_labels=False),
            VGroup(Item('title', editor=TextEditor()),
                   Item('marker'),
                   Item('marker_size', editor=ThemedSliderEditor()),
                   Item('line_width',
                        label='Line Width',
                        editor=ThemedSliderEditor()),
                   Item('color', label='Fill Color'),
                   Item('outline_color', label='Outline Color'),
                   group_theme=Theme('@GF5', margins=(-5, -1)),
                   item_theme=Theme('@G0B', margins=0))))

    #-- Default Values ---------------------------------------------------------

    def _index_default(self):
        """ Returns the default value for the 'index' trait.
        """
        return TemplateDataSource(
            items=[ValueDataNameItem(name='index', flatten=True)],
            description='Scatter Plot Index')

    def _value_default(self):
        """ Returns the default value for the 'value' trait.
        """
        return TemplateDataSource(
            items=[ValueDataNameItem(name='value', flatten=True)],
            description='Scatter Plot Value')

    #-- ITemplate Interface Implementation -------------------------------------

    def activate_template(self):
        """ Converts all contained 'TDerived' objects to real objects using the
            template traits of the object. This method must be overridden in
            subclasses.

            Returns
            -------
            None
        """
        # If our data sources are still unbound, then just exit; someone must
        # have marked them as optional:
        if ((self.index.context_data is Undefined)
                or (self.value.context_data is Undefined)):
            return

        # Create a plot data object and give it this data:
        pd = ArrayPlotData()
        pd.set_data('index', self.index.context_data)
        pd.set_data('value', self.value.context_data)

        # Create the plot:
        self.plot = plot = Plot(pd)
        plot.plot(('index', 'value'),
                  type='scatter',
                  index_sort='ascending',
                  marker=self.marker,
                  color=self.color,
                  outline_color=self.outline_color,
                  marker_size=self.marker_size,
                  line_width=self.line_width,
                  bgcolor='white')
        plot.set(padding_left=50,
                 padding_right=0,
                 padding_top=0,
                 padding_bottom=20)

        # Attach some tools to the plot:
        plot.tools.append(PanTool(plot, constrain_key='shift'))
        zoom = SimpleZoom(component=plot, tool_mode='box', always_on=False)
        plot.overlays.append(zoom)

    #-- Trait Event Handlers ---------------------------------------------------

    def _update_changed(self):
        """ Handles a plot option being changed.
        """
        self.plot = Undefined
コード例 #3
0
    def create_editor(self):
        """ Returns the default traits UI editor to use for a trait.
        """
        from traitsui.api import TextEditor

        return TextEditor()
コード例 #4
0
class TVTKClassChooser(HasTraits):

    # The selected object, is None if no valid class_name was made.
    object = Property

    # The TVTK class name to choose.
    class_name = Str('', desc='class name of TVTK class (case sensitive)')

    # The string to search for in the class docs -- the search supports
    # 'and' and 'or' keywords.
    search = Str('', desc='string to search in TVTK class documentation '\
                          'supports the "and" and "or" keywords. '\
                          'press <Enter> to start search. '\
                          'This is case insensitive.')

    clear_search = Button

    # The class documentation.
    doc = Str(_search_help_doc)

    # Completions for the choice of class.
    completions = List(Str)

    # List of available class names as strings.
    available = List(TVTK_CLASSES)

    ########################################
    # Private traits.

    finder = Instance(DocSearch)

    n_completion = Int(25)

    ########################################
    # View related traits.

    view = View(Group(
        Item(name='class_name', editor=EnumEditor(name='available')),
        Item(name='class_name', has_focus=True),
        Item(name='search', editor=TextEditor(enter_set=True, auto_set=False)),
        Item(name='clear_search', show_label=False), Item('_'),
        Item(name='completions',
             editor=ListEditor(columns=3),
             style='readonly'),
        Item(name='doc', resizable=True, label='Documentation',
             style='custom')),
                id='tvtk_doc',
                resizable=True,
                width=800,
                height=600,
                title='TVTK class chooser',
                buttons=["OK", "Cancel"])

    ######################################################################
    # `object` interface.
    ######################################################################
    def __init__(self, **traits):
        super(TVTKClassChooser, self).__init__(**traits)
        self._orig_available = list(self.available)

    ######################################################################
    # Non-public interface.
    ######################################################################
    def _get_object(self):
        o = None
        if len(self.class_name) > 0:
            try:
                o = getattr(tvtk, self.class_name)()
            except (AttributeError, TypeError):
                pass
        return o

    def _class_name_changed(self, value):
        av = self.available
        comp = [x for x in av if x.startswith(value)]
        self.completions = comp[:self.n_completion]
        if len(comp) == 1 and value != comp[0]:
            self.class_name = comp[0]

        o = self.object
        if o is not None:
            self.doc = get_tvtk_class_doc(o)
        else:
            self.doc = _search_help_doc

    def _finder_default(self):
        return DocSearch()

    def _clear_search_fired(self):
        self.search = ''

    def _search_changed(self, value):
        if len(value) < 3:
            self.available = self._orig_available
            return

        f = self.finder
        result = f.search(value)
        if len(result) == 0:
            self.available = self._orig_available
        elif len(result) == 1:
            self.class_name = result[0]
        else:
            self.available = result
            self.completions = result[:self.n_completion]