diff --git a/.eslintignore b/.eslintignore index a26b71a..e5c5bf1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,3 +11,6 @@ examples .eslintignore .eslintrc.js .gitignore + +.github +CHANGELOG.md diff --git a/.prettierignore b/.prettierignore index 6d1c10b..fc7a99e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,3 +3,6 @@ node_modules **/lib **/package.json jupyterlab_lego_boost + +.github +CHANGELOG.md \ No newline at end of file diff --git a/examples/controller.ipynb b/examples/controller.ipynb new file mode 100644 index 0000000..2f35109 --- /dev/null +++ b/examples/controller.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "21a70f02-65b0-4d1c-8023-c95188dd4d0c", + "metadata": {}, + "source": [ + "## Control the Lego Boost using a Game Controller" + ] + }, + { + "cell_type": "markdown", + "id": "b778cc3a-4bd6-48fd-94c5-456652ec7de6", + "metadata": {}, + "source": [ + "Run the cells below to import the needed libraries, as well as initialize the controller. Buttons are corresponding to a 8BitDo controller." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5c2db71d-d832-4ab3-8026-5ba8529032ae", + "metadata": {}, + "outputs": [], + "source": [ + "# uncomment the line below to download ipywidgets\n", + "# !pip install ipywidgets" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1f5760ec-3540-461a-84ed-359bac5a7db4", + "metadata": {}, + "outputs": [], + "source": [ + "import ipywidgets as wid\n", + "from pylgbst.hub import MoveHub, VisionSensor, TiltSensor\n", + "from pylgbst import get_connection_bleak\n", + "import time\n", + "import random" + ] + }, + { + "cell_type": "markdown", + "id": "e50a51b4-686a-40ea-b9a2-62ad13067a55", + "metadata": {}, + "source": [ + "Make sure to add the Bluetooth address of your MoveHub, which can be found in settings. Before running the cell below, press the button on your MoveHub such that the LED is flashing, this means its looking for a connection. Once the connection is stable, the LED will turn blue." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5f9947e7-b4a9-42fb-aff9-e8fb2060da5f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Have no dedicated class for peripheral type 0x42 (UNKNOWN) on port 0x46\n" + ] + } + ], + "source": [ + "# connecting to the MoveHub using its individual Bluetooth address \n", + "conn = get_connection_bleak(hub_mac='00:16:53:C3:C2:4F', hub_name=MoveHub.DEFAULT_NAME)\n", + "hub = MoveHub(conn)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "58d8a6f4-e17a-4a87-beb3-23d1e683015c", + "metadata": {}, + "outputs": [], + "source": [ + "# initializing the controller\n", + "gamepad = wid.Controller()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8fb85790-a43c-4b8c-b609-fb0caf7b5dea", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "43816f3d07814309874f31798f4b06e1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Controller(axes=(Axis(value=0.0), Axis(value=0.0), Axis(value=0.0), Axis(value=0.0)), buttons=(Button(value=0.…" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def on_sent(data):\n", + " if gamepad.connected:\n", + " # moving forward (right joystick)\n", + " if data['owner'].axes[3].value < 0:\n", + " hub.motor_AB.timed(1, 0.1, 0.1)\n", + " \n", + " # moving backwards (right joystick)\n", + " if data['owner'].axes[3].value > 0:\n", + " hub.motor_AB.timed(1, -0.1, -0.1)\n", + " \n", + " # moving to the right (right joystick)\n", + " if data['owner'].axes[0].value < 0:\n", + " hub.motor_B.timed(1, 0.1)\n", + " \n", + " # moving to the left (right joystick)\n", + " if data['owner'].axes[0].value > 0:\n", + " hub.motor_A.timed(1, 0.1)\n", + " \n", + " # speeding forward (R2 button)\n", + " if data['owner'].buttons[7].value:\n", + " hub.motor_AB.timed(1, 1, 1)\n", + " \n", + " # stoping the motors fully (L2 button)\n", + " if data['owner'].buttons[6].value:\n", + " hub.motor_external.stop()\n", + " \n", + " # changing led color (select button)\n", + " if data['owner'].buttons[8].value:\n", + " # randomly generated color\n", + " color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))\n", + " hub.led.set_color(color)\n", + " \n", + " # move in a square (B button)\n", + " if data['owner'].buttons[0].value:\n", + " for count in range(2):\n", + " hub.motor_AB.timed(1, 0.1, 0.1)\n", + " hub.motor_A.angled(540, 1)\n", + " \n", + " # move in a circle (A button)\n", + " if data['owner'].buttons[1].value:\n", + " for count in range(2):\n", + " hub.motor_AB.timed(1, 0.1, 0.5)\n", + " \n", + " # rotate 360° (Y button)\n", + " if data['owner'].buttons[2].value:\n", + " hub.motor_A.timed(1.5, 1)\n", + " \n", + " # shoot arrow (X button)\n", + " if data['owner'].buttons[3].value:\n", + " hub.port_D.timed(0.3, 0.5)\n", + " hub.port_D.timed(0.3, -0.4)\n", + " \n", + " # distance detection (up arrow) \n", + " if data['owner'].buttons[12].value:\n", + " def callback(distance):\n", + " print(\"Distance: %s\" % (distance))\n", + " \n", + " hub.vision_sensor.subscribe(callback, mode=VisionSensor.DISTANCE_INCHES)\n", + " time.sleep(2)# play with sensor while it waits\n", + " hub.vision_sensor.unsubscribe(callback)\n", + " \n", + " # color detection (left arrow) \n", + " if data['owner'].buttons[14].value:\n", + " def callback(color):\n", + " print(\"Color: %s\" % (color))\n", + " \n", + " hub.vision_sensor.subscribe(callback, mode=VisionSensor.COLOR_INDEX)\n", + " time.sleep(2)# play with sensor while it waits\n", + " hub.vision_sensor.unsubscribe(callback)\n", + " \n", + " # detect color and distance (down arrow)\n", + " if data['owner'].buttons[13].value:\n", + " def callback(color, distance):\n", + " print(\"Color: %s / Distance: %s\" % (color, distance))\n", + " \n", + " hub.vision_sensor.subscribe(callback, mode=VisionSensor.COLOR_DISTANCE_FLOAT)\n", + " time.sleep(2)# play with sensor while it waits\n", + " hub.vision_sensor.unsubscribe(callback)\n", + " \n", + " # detect 3-axis position (right arrow)\n", + " if data['owner'].buttons[15].value:\n", + " def callback(roll, pitch, yaw):\n", + " print(\"Roll: %s / Pitch: %s / Yaw: %s\" % (roll, pitch, yaw))\n", + " \n", + " hub.tilt_sensor.subscribe(callback, mode=TiltSensor.MODE_3AXIS_ACCEL)\n", + " time.sleep(2)# play with sensor while it waits\n", + " hub.tilt_sensor.unsubscribe(callback)\n", + "\n", + " # turn head to left (L1 button)\n", + " if data['owner'].buttons[4].value:\n", + " hub.port_D.timed(0.15, 0.4)\n", + " \n", + " # turn head to the right (R1 button)\n", + " if data['owner'].buttons[5].value:\n", + " hub.port_D.timed(0.15, -0.4)\n", + " \n", + "gamepad.observe(on_sent)\n", + "gamepad" + ] + }, + { + "cell_type": "markdown", + "id": "62a0684a-1a0b-4899-8708-7a9a7ae23132", + "metadata": {}, + "source": [ + "Run the cell below to disconnect from the MoveHub. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "926e52ba-251f-4495-8859-9ad61f2d90b7", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Hub disconnects\n" + ] + } + ], + "source": [ + "hub.disconnect()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e57f611-dd04-474b-93d7-222058c6da26", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.10.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}