diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 78b6c92..e8ab8f5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -30,7 +30,7 @@ jobs: - name: Build the JupyterLite site shell: bash -l {0} run: | - jupyter lite build --output-dir dist --contents examples/introduction.ipynb + jupyter lite build --output-dir dist --contents examples/test-widget-with-ipykernel.ipynb - name: Upload artifact uses: actions/upload-pages-artifact@v3 diff --git a/examples/introduction.ipynb b/examples/introduction.ipynb deleted file mode 100644 index f0dace3..0000000 --- a/examples/introduction.ipynb +++ /dev/null @@ -1,416 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "879f4b73-57fd-4828-8511-0337efd1f45f", - "metadata": {}, - "outputs": [], - "source": [ - "%gui asyncio\n", - "\n", - "#This file comes from https://github.com/jupyter-robotics/ipylgbst/examples and has been adapted for the current extension\n", - "#Copyright (c) Dr Thorsten Beier\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "762d552a-dafd-4b4b-9b0c-8b6612d2415b", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "import asyncio \n", - "from bluetooth_manager import MoveHubWidget,LedColor,Port, Sensor\n", - "from ipywidgets import Output\n", - "from IPython.display import display\n", - "\n", - "# the robot's LED supports the following colors\n", - "colors = [\n", - " \n", - " LedColor.pink,\n", - " LedColor.purple,\n", - " LedColor.blue,\n", - " LedColor.lightblue,\n", - " LedColor.cyan,\n", - " LedColor.green,\n", - " LedColor.yellow,\n", - " LedColor.orange,\n", - " LedColor.red,\n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "f225a4fb-0b23-4107-9bbe-c130000730af", - "metadata": {}, - "source": [ - "# Connect the device \n", - "Note that connecting the device should take 5-10 sec" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "aae633ad-bbb2-45c2-a1ff-5fab18146172", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b4963924a83143199f0756442e81826b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MoveHubWidget(n_lanes=4)" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# number of concurrent \"lanes\"\n", - "n_lanes = 4 \n", - "widget = MoveHubWidget(n_lanes=n_lanes)\n", - "output = Output()\n", - "display(widget)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9b5f6086-3605-47ee-a170-57d3b97600e2", - "metadata": {}, - "outputs": [], - "source": [ - "# Case 1 : Execute this cell if there is no MoveHub connected\n", - "widget.connect(output=output)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "514c7c39-8b62-4caa-a506-4abb79891592", - "metadata": {}, - "outputs": [], - "source": [ - "# Case 2 : Execute this cell if there is/are one/some MoveHub(s) connected\n", - "# Choose one of them and paste its identifier\n", - "widget.identifier = \"dcRIlxx9l8bQ3T6UVofW8Q==\"\n", - "widget.connect(output=output, identifier=widget.identifier)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e2b06dac-4056-435f-800a-60134c48c27e", - "metadata": {}, - "outputs": [], - "source": [ - "display(widget)" - ] - }, - { - "cell_type": "markdown", - "id": "618790a2-da4d-4b46-92d7-cd925f5407b5", - "metadata": {}, - "source": [ - "# Change Color of LED" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "62924267-c398-4274-8780-91739cdacafe", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "output = Output()\n", - "async def main(lane, log):\n", - "\n", - " for color in colors:\n", - " print(color)\n", - " log(f\"set color to {color.value}\")\n", - " await lane.set_led_async(color)\n", - " await asyncio.sleep(2)\n", - "\n", - "movehub.run_async_program(main,output=output);" - ] - }, - { - "cell_type": "markdown", - "id": "d8d8c5d9-35b4-419a-be13-083b40888475", - "metadata": {}, - "source": [ - "# Drive a polygon like path" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39cfdc45-1d1a-4965-b83c-9048320d6a4d", - "metadata": {}, - "outputs": [], - "source": [ - "speed = 50\n", - "d_forward = 200\n", - "d_rotate = 300\n", - "output = Output()\n", - "async def main(lane,log): \n", - " for i in range(4):\n", - " await lane.set_led_async(\"red\")\n", - " await lane.motor_angle_multi_async(angle=d_forward, power_a=speed,power_b=speed)\n", - " await lane.set_led_async(\"green\")\n", - " await lane.motor_angle_multi_async(angle=d_rotate, power_a=speed,power_b=-1.0*speed)\n", - " \n", - "movehub.run_async_program(main, output=output);\n", - "output" - ] - }, - { - "cell_type": "markdown", - "id": "1eb52d1d-3aa6-49d7-97d5-a643a9167196", - "metadata": {}, - "source": [ - "# Buttons (sync but non blocking API)\n", - "\n", - "the non-blocking sync API is the best for a \"remote-controlled-rc-car\" experience" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9e9e863c-9b4e-4455-968c-98219c92ea26", - "metadata": {}, - "outputs": [], - "source": [ - "import ipywidgets as widgets\n", - "\n", - "button_up = widgets.Button(description='Up')\n", - "button_down = widgets.Button(description='Down')\n", - "button_left = widgets.Button(description='Left')\n", - "button_right = widgets.Button(description='Right')\n", - "button_stop = widgets.Button(description='Stop')\n", - "\n", - "box_ud = widgets.VBox([button_up,button_stop,button_down])\n", - "box = widgets.HBox([button_left,box_ud,button_right])\n", - "output = Output()\n", - "\n", - "def on_up(lane, log):\n", - " # run sync but NON blocking\n", - " lane.motor_time_multi(10, 50, 50)\n", - " \n", - "def on_down(lane, log):\n", - " # run sync but NON blocking\n", - " lane.motor_time_multi(10, -50, -50)\n", - " \n", - "def on_left(lane, log):\n", - " # run sync but NON blocking\n", - " lane.motor_time_multi(10, -50, 50)\n", - " \n", - "def on_right(lane, log):\n", - " # run sync but NON blocking\n", - " lane.motor_time_multi(10, 50, -50)\n", - " \n", - "def on_stop(lane, log):\n", - " # run sync but NON blocking\n", - " lane.motor_time_multi(0, 0, 0)\n", - " \n", - "button_up.on_click(lambda _: movehub.run_program(on_up, output=output))\n", - "button_down.on_click(lambda _: movehub.run_program(on_down, output=output))\n", - "button_left.on_click(lambda _: movehub.run_program(on_left, output=output))\n", - "button_right.on_click(lambda _: movehub.run_program(on_right, output=output))\n", - "button_stop.on_click(lambda _: movehub.run_program(on_stop, output=output))\n", - "\n", - "display(box, output)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbfa931-e3ad-4c58-9922-281bba85532a", - "metadata": {}, - "source": [ - "# Buttons (async api)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "09e74256-33e1-4b30-9502-9f4088d27b69", - "metadata": {}, - "outputs": [], - "source": [ - "import ipywidgets\n", - "\n", - "button_disco = ipywidgets.Button(description='Disco')\n", - "button_motors_ab = ipywidgets.Button(description='Motors AB')\n", - "button_motor_c = ipywidgets.Button(description='Motor C')\n", - "\n", - "\n", - "box = ipywidgets.HBox([button_disco, button_motors_ab, button_motor_c])\n", - "output = Output()\n", - "\n", - "async def disco(lane, log):main\n", - " button_disco.disabled = True\n", - " for i in range(10):\n", - " await lane.set_led_async(LedColor.pink)\n", - " await lane.set_led_async(LedColor.blue)\n", - " button_disco.disabled = False\n", - "\n", - "\n", - "async def motor_ab(lane, log):\n", - " button_motors_ab.disabled = True\n", - " await lane.motor_time_multi_async(seconds=2, power_a=10, power_b=10)\n", - " await lane.motor_time_multi_async(seconds=2, power_a=-10, power_b=10)\n", - " await lane.motor_time_multi_async(seconds=2, power_a=10, power_b=-10)\n", - " await lane.motor_time_multi_async(seconds=2, power_a=-10, power_b=-10)\n", - " button_motors_ab.disabled =main False\n", - "\n", - "async def motor_c(lane, log):\n", - " button_motor_c.disabled = True\n", - " await lane.motor_time_async(port=Port.D, seconds=2, power=10)\n", - " await lane.motor_time_async(port=Port.D, seconds=2, power=-10)\n", - " button_motor_c.disabled = False\n", - "\n", - "# each program runs on its own lane st. they can run concurrent\n", - "button_disco.on_click(lambda _: movehub.run_async_program(disco, lane=0, output=output))\n", - "button_motors_ab.on_click(lambda _: movehub.run_async_program(motor_ab, lane=1, output=output))\n", - "button_motor_c.on_click(lambda _: movehub.run_async_program(motor_c, lane=2, output=output))\n", - "display(box,output)" - ] - }, - { - "cell_type": "markdown", - "id": "2d2eea32-e03d-4b86-818f-b20ba2ae42d3", - "metadata": {}, - "source": [ - "# Sensors" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7915b860-56c2-4034-9951-09a12ce37b2c", - "metadata": {}, - "outputs": [], - "source": [ - "has_bqplot = True\n", - "try:\n", - " import bqplot\n", - "except ImportError:\n", - " has_bqplot = False\n", - "\n", - "if has_bqplot:\n", - " from bqplot import pyplot as plt\n", - " from bqplot import topo_load\n", - " import numpy\n", - " \n", - " output = Output()\n", - " \n", - " duration = 10.0\n", - " dt = 0.10\n", - " clip_value = 200\n", - "\n", - " sensor_values = []\n", - " time_points = []\n", - "\n", - " plt.figure()\n", - " plt.plot([], [])\n", - " plt.xlim(0,duration)\n", - " plt.ylim(0, clip_value)\n", - " plt.xlabel(\"time\")\n", - " plt.ylabel(\"distance sensor\")\n", - " plt.show()\n", - "\n", - " async def poll_distance_sensor(lane, log):\n", - " global sensor_values\n", - " global time_points\n", - " t = 0.0\n", - " while t < duration:\n", - " time_points.append(t)\n", - " d = numpy.nan_to_num(await lane.get_distance_async(), clip_value)\n", - " d = numpy.clip(d,0, clip_value)\n", - " sensor_values.append(d)\n", - " await asyncio.sleep(dt)\n", - " t += dt\n", - " plt.plot(time_points, sensor_values)\n", - "\n", - " movehub.run_async_program(poll_distance_sensor, output=output);\n", - " display(output)" - ] - }, - { - "cell_type": "markdown", - "id": "3117c875-176e-4caa-a918-eadfd6f13f5f", - "metadata": {}, - "source": [ - "# Concurrent Programs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8c8410d3-e1da-4a36-b40e-15a8076611ae", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "async def set_leds(lane, log):\n", - "\n", - " for color in colors:\n", - " log(f\"set color to {color.value}\")\n", - " await lane.set_led_async(color)\n", - " await asyncio.sleep(0.5)\n", - " \n", - "\n", - "speed = 26\n", - "d_forward = 200\n", - "d_rotate = 300\n", - "async def drive(lane, output): \n", - " for i in range(4):\n", - " await lane.motor_angle_multi_async(angle=d_forward, power_a=speed,power_b=speed)\n", - " await lane.motor_angle_multi_async(angle=d_rotate, power_a=speed,power_b=-1.0*speed)\n", - "\n", - "output = Output()\n", - "movehub.run_async_programs_concurrently([set_leds,drive], output=output);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57544bf7-6d12-4fc0-b58b-d97e80d3743d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/test-widget-with-ipykernel.ipynb b/examples/test-widget-with-ipykernel.ipynb new file mode 100644 index 0000000..09de47c --- /dev/null +++ b/examples/test-widget-with-ipykernel.ipynb @@ -0,0 +1,223 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "879f4b73-57fd-4828-8511-0337efd1f45f", + "metadata": {}, + "outputs": [], + "source": [ + "%gui asyncio\n", + "\n", + "#This file comes initially from https://github.com/jupyter-robotics/ipylgbst/examples and has been adapted for the current extension\n", + "#Copyright (c) Dr Thorsten Beier\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "762d552a-dafd-4b4b-9b0c-8b6612d2415b", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import asyncio \n", + "from bluetooth_manager import MoveHubWidget,LedColor,Port, Sensor\n", + "from ipywidgets import Output\n", + "from IPython.display import display\n", + "\n", + "# the robot's LED supports the following colors\n", + "colors = [\n", + " \n", + " LedColor.pink,\n", + " LedColor.purple,\n", + " LedColor.blue,\n", + " LedColor.lightblue,\n", + " LedColor.cyan,\n", + " LedColor.green,\n", + " LedColor.yellow,\n", + " LedColor.orange,\n", + " LedColor.red,\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "f225a4fb-0b23-4107-9bbe-c130000730af", + "metadata": {}, + "source": [ + "# Connect the device \n", + "Note that connecting the device should take 5-10 sec" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "aae633ad-bbb2-45c2-a1ff-5fab18146172", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a58eafee0b6946458034ba2966c7d767", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MoveHubWidget(n_lanes=4)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# number of concurrent \"lanes\"\n", + "n_lanes = 4 \n", + "widget = MoveHubWidget(n_lanes=n_lanes)\n", + "output = Output()\n", + "display(widget)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "9b5f6086-3605-47ee-a170-57d3b97600e2", + "metadata": {}, + "outputs": [], + "source": [ + "# Case 1 : Execute this cell if there is no MoveHub connected\n", + "widget.connect(output=output)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "514c7c39-8b62-4caa-a506-4abb79891592", + "metadata": {}, + "outputs": [], + "source": [ + "# Case 2 : Execute this cell if there is/are one/some MoveHub(s) connected\n", + "# Choose one of them and paste its identifier\n", + "widget.identifier = \"dcRIlxx9l8bQ3T6UVofW8Q==\"\n", + "widget.connect(output=output, identifier=widget.identifier)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e2b06dac-4056-435f-800a-60134c48c27e", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a58eafee0b6946458034ba2966c7d767", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MoveHubWidget(identifier='dcRIlxx9l8bQ3T6UVofW8Q==', n_lanes=4)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(widget)" + ] + }, + { + "cell_type": "markdown", + "id": "618790a2-da4d-4b46-92d7-cd925f5407b5", + "metadata": {}, + "source": [ + "# Change Color of LED" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "62924267-c398-4274-8780-91739cdacafe", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "output = Output()\n", + "async def main(lane, log, identifier):\n", + "\n", + " for color in colors:\n", + " print(color)\n", + " log(f\"set color to {color.value}\")\n", + " await lane.set_led_async(color)\n", + " await asyncio.sleep(2)\n", + "\n", + "widget.run_async_program(main,output=output);" + ] + }, + { + "cell_type": "markdown", + "id": "d8d8c5d9-35b4-419a-be13-083b40888475", + "metadata": {}, + "source": [ + "# Drive a polygon like path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39cfdc45-1d1a-4965-b83c-9048320d6a4d", + "metadata": {}, + "outputs": [], + "source": [ + "speed = 50\n", + "d_forward = 200\n", + "d_rotate = 300\n", + "output = Output()\n", + "async def main(lane,log, identifier): \n", + " for i in range(4):\n", + " await lane.set_led_async(\"red\")\n", + " await lane.motor_angle_multi_async(angle=d_forward, power_a=speed,power_b=speed)\n", + " await lane.set_led_async(\"green\")\n", + " await lane.motor_angle_multi_async(angle=d_rotate, power_a=speed,power_b=-1.0*speed)\n", + " \n", + "widget.run_async_program(main, output=output);\n", + "output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86ec19bd-f82c-4181-819b-f862932610f2", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}