jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.13k stars 949 forks source link

How to control robot using gamepad controller #2581

Open cagz opened 4 years ago

cagz commented 4 years ago

Perhaps a query more than an issue, hope nobody minds.

I am trying to control a robot with left/right motors using a gamepad controller. If I dlink one axis to left motor, another to the right motor all works fine.

However instead of commanding motors individually, I'd like to have one axis for forward / backward, the other for left / right. So I need to calculate each motors speed based on both axis values.

1 - I tried to get axis values in a while loop and calculate left/right motor values. However, axes values does not update within the while loop. I suppose these are only passed to the code at the beginning of execution and updates stay behind in the web context ? 2 - I looked into transform parameter of dlink however it doesn't seem like I can pass two axes values for transform function to calculate given motor's value.

What would be a good solution for this problem ?

pbugnion commented 4 years ago

Thanks for raising this, and apologies for the late response.

If I understand correctly, you want to update a single value based on the current value of two sliders?

You can do this with something like the following:

import ipywidgets as widgets

class App:

    def __init__(self):
        self.sliders = [widgets.IntSlider(), widgets.IntSlider()]
        self._attach_slider_callbacks()
        self.result = widgets.Label()
        self._on_slider_change()
        self.container = widgets.VBox([widgets.HBox(self.sliders), self.result])

    def _attach_slider_callbacks(self):
        for slider in self.sliders:
            slider.observe(self._on_slider_change, ["value"])

    def _on_slider_change(self, _=None):
        all_values = [slider.value for slider in self.sliders]
        self.result.value = f"result: {sum(all_values)}"  # replace this with whatever function depends on all the inputs

    def display(self):
        return self.container

App().display()

In the above, we observe a change on the slider value for each slider and, on change, recompute the value of a label.

Does this address what you're trying to do?