From 2625450e33aa7ab40450ca22868b7ab17bc64b07 Mon Sep 17 00:00:00 2001 From: ldania Date: Fri, 25 Nov 2022 18:30:23 +0000 Subject: [PATCH 1/7] Funcitoning Keyboard with turtle control --- jupyros/__init__.py | 1 + .../ROS2_Turtlesim_KeyboardControl.ipynb | 233 ++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 notebooks/ROS2_Turtlesim_KeyboardControl.ipynb diff --git a/jupyros/__init__.py b/jupyros/__init__.py index d988d59..6bb258c 100644 --- a/jupyros/__init__.py +++ b/jupyros/__init__.py @@ -25,6 +25,7 @@ from .ros2.ros_widgets import * from .ros2.subscriber import * from .ros2.key_input import * + from .ros2.turtle_sim import * else: # Default to ROS1 diff --git a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb new file mode 100644 index 0000000..f45dd4d --- /dev/null +++ b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb @@ -0,0 +1,233 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7259a8b6", + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'turtle_sim'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn [1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mrclpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mrp\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjupyros\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mros2\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mjr2\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mturtle_sim\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mturtle\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mturtlesim\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msrv\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Spawn\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mturtlesim\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmsg\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Pose\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'turtle_sim'" + ] + } + ], + "source": [ + "import rclpy as rp\n", + "import jupyros.ros2 as jr2\n", + "import turtle_sim as turtle\n", + "from turtlesim.srv import Spawn\n", + "from turtlesim.msg import Pose\n", + "from time import time\n", + "import os\n", + "from std_msgs.msg import String\n", + "from geometry_msgs.msg import Twist\n", + "from sidecar import Sidecar\n", + "from time import time, sleep\n", + "import math\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize ROS communications for a given context\n", + "if(rp.ok() == False):\n", + " rp.init()\n", + "else:\n", + " print(\"rclpy already initiated\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", + "metadata": {}, + "outputs": [], + "source": [ + "superturtle = rp.create_node(\"superturtle\")\n", + "keyInput = rp.create_node(\"keyInput\")\n", + "com = rp.create_node(\"com\")\n", + "simple = rp.create_node(\"simple\")\n", + "translate = rp.create_node(\"translate\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3bdbfe05-c4d3-4fd3-abfa-f38b039d4541", + "metadata": {}, + "outputs": [], + "source": [ + "key_send = jr2.KeyInput(keyInput, String, '/keyboard_stream')\n", + "key_send.display_inputs()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2dbf024d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n", + "display(turtlesim.canvas)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "347b508d-4568-4cc2-b8da-c05f26b6f606", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ece1ece3-54f6-4df8-be79-42d7f37f6e08", + "metadata": {}, + "source": [ + "**TIP:** When using JupyterLab, you can right-click on the canvas and select *Create New View from Output*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", + "metadata": {}, + "outputs": [], + "source": [ + "poses = {}\n", + "\n", + "for name in turtlesim.turtles.keys():\n", + " poses[name] = turtlesim.turtles[name].pose\n", + " \n", + "print(poses[\"turtle1\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac63dbbb-b388-4b18-890c-e3bcada044a9", + "metadata": {}, + "outputs": [], + "source": [ + "turtlesim.turtles[name].pose" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd2e66dc", + "metadata": {}, + "outputs": [], + "source": [ + "topic_name = '/keyboard_stream'\n", + "def move_turtles(msg):\n", + " scale = 0.1\n", + " name = \"turtle1\"\n", + "\n", + " poses[name] = {\"x\": turtlesim.turtles[name].pose[\"x\"] + msg.linear.x*math.cos(turtlesim.turtles[name].pose[\"theta\"])/scale,\n", + " \"y\": turtlesim.turtles[name].pose[\"y\"] - msg.linear.x*math.sin(turtlesim.turtles[name].pose[\"theta\"] )/scale,\n", + " \"theta\": turtlesim.turtles[name].pose[\"theta\"] + msg.angular.z/ 180 * math.pi}\n", + " \n", + " \n", + " turtlesim.move_turtles(new_poses=poses)\n", + "\n", + "\n", + "\n", + "\n", + "def cb(msg):\n", + " # Receive string msg and translate\n", + " \n", + " key = msg.data\n", + " \n", + " #### General Keybindings \"key: (x, y, z, a (alpha), b (beta), g (gamma)\"\n", + " \n", + " moveBindings = {\n", + " 'ArrowLeft': (0,0,0,0, 0, 1),\n", + " 'ArrowRight':(0,0,0,0, 0, -1),\n", + " 'ArrowUp': (1,0,0,0, 0, 0, 0),\n", + " 'ArrowDown': (-1,0,0,0, 0, 0)\n", + " }\n", + "\n", + " \"\"\"\n", + " 'i': (1, 0, 0, 0, 0, 0),\n", + " 'o': (1, 0, 0, -1, 0, 0)),\n", + " \"\"\"\n", + " \n", + " ## General Keybinding Decoder\n", + " if key in moveBindings.keys():\n", + " x = float(moveBindings[key][0])\n", + " y = float(moveBindings[key][1])\n", + " z = float(moveBindings[key][2])\n", + " a = float(moveBindings[key][3])\n", + " b = float(moveBindings[key][4])\n", + " g = float(moveBindings[key][5])\n", + " \n", + " else:\n", + " x = 0.0\n", + " y = 0.0\n", + " z = 0.0\n", + " a = 0.0\n", + " b = 0.0\n", + " g = 0.0\n", + " \n", + "\n", + " \n", + " twist = Twist()\n", + " twist.linear.x = x\n", + " twist.angular.z = g \n", + "\n", + " move_turtles(twist)\n", + "\n", + "\n", + "turtle_control = jr2.Subscriber(keyInput, String, topic_name, cb)\n", + "turtle_control.display()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0cd916b-41a7-4832-9470-328c1d30689b", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 1366d2a5956b6eaffee3e89653d9feec0f5eefb8 Mon Sep 17 00:00:00 2001 From: ldania Date: Mon, 28 Nov 2022 10:16:11 +0000 Subject: [PATCH 2/7] Functional Keyboard Input for Turtlesim --- jupyros/ros2/__init__.py | 2 + jupyros/ros2/ipy.py | 26 ++ notebooks/ROS2_Keyboard_Input.ipynb | 41 ++- notebooks/ROS2_Turtlesim.ipynb | 310 ++++++++++++++++++ .../ROS2_Turtlesim_KeyboardControl.ipynb | 35 +- notebooks/ROS_Turtlesim.ipynb | 2 +- 6 files changed, 392 insertions(+), 24 deletions(-) create mode 100644 jupyros/ros2/ipy.py create mode 100644 notebooks/ROS2_Turtlesim.ipynb diff --git a/jupyros/ros2/__init__.py b/jupyros/ros2/__init__.py index 67a25ae..63f22db 100644 --- a/jupyros/ros2/__init__.py +++ b/jupyros/ros2/__init__.py @@ -17,3 +17,5 @@ from ..ros2.ros_widgets import * from ..ros2.subscriber import * from ..ros2.key_input import * +from ..ros2.turtle_sim import * +from ..ros2.ipy import * diff --git a/jupyros/ros2/ipy.py b/jupyros/ros2/ipy.py new file mode 100644 index 0000000..ed29c2e --- /dev/null +++ b/jupyros/ros2/ipy.py @@ -0,0 +1,26 @@ +############################################################################# +# Copyright (c) Wolf Vollprecht, QuantStack # +# # +# Distributed under the terms of the BSD 3-Clause License. # +# # +# The full license is in the file LICENSE, distributed with this software. # +############################################################################# +import sys +from threading import Thread + +import ipywidgets as widgets +from IPython.core.magic import register_cell_magic + +def executor(cell, gbls, lcls): + exec(cell, gbls, lcls) + +# @register_cell_magic is not available during jupyter nbextension enable ... +try: + @register_cell_magic + def thread_cell(line, cell, local_ns=None): + t = Thread(target=executor, args=(cell, globals(), sys._getframe(2).f_locals)) + out = widgets.Output(layout={'border': '1px solid gray'}) + t.start() + return out +except: + pass \ No newline at end of file diff --git a/notebooks/ROS2_Keyboard_Input.ipynb b/notebooks/ROS2_Keyboard_Input.ipynb index 3169a56..cfc764f 100644 --- a/notebooks/ROS2_Keyboard_Input.ipynb +++ b/notebooks/ROS2_Keyboard_Input.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -62,9 +62,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bbc3405979ce48918e210c79dbe99979", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "918427091a334342b8673302f787ab75", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "key_send = jr2.KeyInput(key_node, String, '/keyboard_stream')\n", "key_send.display_inputs()" diff --git a/notebooks/ROS2_Turtlesim.ipynb b/notebooks/ROS2_Turtlesim.ipynb new file mode 100644 index 0000000..786a84f --- /dev/null +++ b/notebooks/ROS2_Turtlesim.ipynb @@ -0,0 +1,310 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7259a8b6", + "metadata": {}, + "outputs": [], + "source": [ + "import rclpy as rp\n", + "import jupyros.ros2 as jr2\n", + "import jupyros.ros2.turtle_sim as turtle\n", + "from turtlesim.srv import Spawn\n", + "from turtlesim.msg import Pose\n", + "from time import time\n", + "import os\n", + "from std_msgs.msg import String\n", + "from geometry_msgs.msg import Twist\n", + "from sidecar import Sidecar\n", + "from time import time, sleep\n", + "import math\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize ROS communications for a given context\n", + "if(rp.ok() == False):\n", + " rp.init()\n", + "else:\n", + " print(\"rclpy already initiated\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", + "metadata": {}, + "outputs": [], + "source": [ + "superturtle = rp.create_node(\"superturtle\")\n", + "moveNode = rp.create_node(\"moveNode\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3bdbfe05-c4d3-4fd3-abfa-f38b039d4541", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b70f8496aa1448781cef2961bd82ece", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "033a9ba0baa343b698dbe87473412d33", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "key_send = jr2.KeyInput(keyInput, String, '/keyboard_stream')\n", + "key_send.display_inputs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2dbf024d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "turtle1 has spawned.\n" + ] + } + ], + "source": [ + "\n", + "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9af6794a92c742ea8f91a2aa125650ba", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MultiCanvas(height=1600, layout=Layout(width='100%'), width=1600)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "display(turtlesim.canvas)" + ] + }, + { + "cell_type": "markdown", + "id": "ece1ece3-54f6-4df8-be79-42d7f37f6e08", + "metadata": {}, + "source": [ + "**TIP:** When using JupyterLab, you can right-click on the canvas and select *Create New View from Output*" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", + "metadata": { + "jupyter": { + "source_hidden": true + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'x': 800, 'y': 800, 'theta': 0}\n" + ] + } + ], + "source": [ + "poses = {}\n", + "\n", + "for name in turtlesim.turtles.keys():\n", + " poses[name] = turtlesim.turtles[name].pose\n", + " \n", + "print(poses[\"turtle1\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ac63dbbb-b388-4b18-890c-e3bcada044a9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x': 800, 'y': 800, 'theta': 0}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cd2e66dc", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3523d845c79946de8b5259f5aa32a923", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "topic_name = '/keyboard_stream'\n", + "def move_turtles(msg):\n", + " scale = 0.01\n", + " name = \"turtle1\"\n", + "\n", + " poses[name] = {\"x\": turtlesim.turtles[name].pose[\"x\"] + msg.linear.x*math.cos(turtlesim.turtles[name].pose[\"theta\"])/scale,\n", + " \"y\": turtlesim.turtles[name].pose[\"y\"] - msg.linear.x*math.sin(turtlesim.turtles[name].pose[\"theta\"] )/scale,\n", + " \"theta\": turtlesim.turtles[name].pose[\"theta\"] + msg.angular.z/ 180 * math.pi}\n", + " \n", + " \n", + " turtlesim.move_turtles(new_poses=poses)\n", + "\n", + "\n", + "\n", + "\n", + "def cb(msg):\n", + " name = \"turtle1\"\n", + " x, y = convert_xy_units(msg.x, msg.y)\n", + " poses[name] = {\"x\": x,\n", + " \"y\": y,\n", + " \"theta\": msg.theta}\n", + " \n", + " turtlesim.move_turtles(new_poses=poses)\n", + "\n", + "\n", + "turtle_control = jr2.Subscriber(keyInput, String, topic_name, cb)\n", + "turtle_control.display()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c9e44409-1f96-426f-9826-95f2ddff5119", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UsageError: Cell magic `%%thread_cell` not found.\n" + ] + } + ], + "source": [ + "%%thread_cell\n", + "\n", + "i = 0\n", + "pub = jr2.Publisher(test_node, Pose, '/Pose')\n", + "\n", + "while run:\n", + " msg = Pose()\n", + " msg.x = (i/1800*5)*math.sin(i / 180 * math.pi) + 11.08 / 2\n", + " msg.y = (i/1800*5)*math.cos(i / 180 * math.pi) + 11.08 / 2\n", + " msg.theta = - i / 180 * math.pi\n", + " pub.publish(msg)\n", + " rate.sleep()\n", + " i += 1\n", + "print(\"Done\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "606db6b1-f505-41b7-99d1-525b09cf662e", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb index f45dd4d..eef6d87 100644 --- a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb +++ b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb @@ -2,26 +2,14 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "7259a8b6", "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'turtle_sim'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn [1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mrclpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mrp\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mjupyros\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mros2\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mjr2\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mturtle_sim\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mturtle\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mturtlesim\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msrv\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Spawn\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mturtlesim\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmsg\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Pose\n", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'turtle_sim'" - ] - } - ], + "outputs": [], "source": [ "import rclpy as rp\n", "import jupyros.ros2 as jr2\n", - "import turtle_sim as turtle\n", + "import jupyros.ros2.turtle_sim as turtle\n", "from turtlesim.srv import Spawn\n", "from turtlesim.msg import Pose\n", "from time import time\n", @@ -82,7 +70,18 @@ }, "outputs": [], "source": [ - "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n", + "\n", + "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", + "metadata": {}, + "outputs": [], + "source": [ + "\n", "display(turtlesim.canvas)" ] }, @@ -94,7 +93,9 @@ "tags": [] }, "outputs": [], - "source": [] + "source": [ + "!jupyter labextension install js" + ] }, { "cell_type": "markdown", diff --git a/notebooks/ROS_Turtlesim.ipynb b/notebooks/ROS_Turtlesim.ipynb index f784c45..7f7e1a5 100644 --- a/notebooks/ROS_Turtlesim.ipynb +++ b/notebooks/ROS_Turtlesim.ipynb @@ -245,7 +245,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.8.10" } }, "nbformat": 4, From 9c00b2eae453b968bd00b30afb1f6ec9aab1bae2 Mon Sep 17 00:00:00 2001 From: ldania Date: Mon, 28 Nov 2022 10:34:54 +0000 Subject: [PATCH 3/7] Adjustestment of thread_cell --- jupyros/ros2/ipy.py | 4 +- notebooks/ROS2_Turtlesim.ipynb | 127 ++++++++++++++++----------------- 2 files changed, 64 insertions(+), 67 deletions(-) diff --git a/jupyros/ros2/ipy.py b/jupyros/ros2/ipy.py index ed29c2e..4ba033b 100644 --- a/jupyros/ros2/ipy.py +++ b/jupyros/ros2/ipy.py @@ -5,6 +5,8 @@ # # # The full license is in the file LICENSE, distributed with this software. # ############################################################################# + +## Modified by Luigi Dania for Jupyter-Ros2 import sys from threading import Thread @@ -17,7 +19,7 @@ def executor(cell, gbls, lcls): # @register_cell_magic is not available during jupyter nbextension enable ... try: @register_cell_magic - def thread_cell(line, cell, local_ns=None): + def thread_cell2(line, cell, local_ns=None): t = Thread(target=executor, args=(cell, globals(), sys._getframe(2).f_locals)) out = widgets.Output(layout={'border': '1px solid gray'}) t.start() diff --git a/notebooks/ROS2_Turtlesim.ipynb b/notebooks/ROS2_Turtlesim.ipynb index 786a84f..1c92d4d 100644 --- a/notebooks/ROS2_Turtlesim.ipynb +++ b/notebooks/ROS2_Turtlesim.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 8, "id": "7259a8b6", "metadata": {}, "outputs": [], @@ -24,10 +24,18 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 9, "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "rclpy already initiated\n" + ] + } + ], "source": [ "# Initialize ROS communications for a given context\n", "if(rp.ok() == False):\n", @@ -38,58 +46,27 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 10, "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", "metadata": {}, - "outputs": [], - "source": [ - "superturtle = rp.create_node(\"superturtle\")\n", - "moveNode = rp.create_node(\"moveNode\")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "3bdbfe05-c4d3-4fd3-abfa-f38b039d4541", - "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3b70f8496aa1448781cef2961bd82ece", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "033a9ba0baa343b698dbe87473412d33", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stderr", + "output_type": "stream", + "text": [ + "[WARN] [1669631239.172912305] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.\n", + "[WARN] [1669631239.175681966] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.\n" + ] } ], "source": [ - "key_send = jr2.KeyInput(keyInput, String, '/keyboard_stream')\n", - "key_send.display_inputs()" + "superturtle = rp.create_node(\"superturtle\")\n", + "moveNode = rp.create_node(\"moveNode\")" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "2dbf024d", "metadata": { "tags": [] @@ -104,13 +81,12 @@ } ], "source": [ - "\n", - "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n" + "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", "metadata": { "collapsed": true, @@ -123,7 +99,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9af6794a92c742ea8f91a2aa125650ba", + "model_id": "c0e89d7ae29445dbb0a405c14c99d2b5", "version_major": 2, "version_minor": 0 }, @@ -136,7 +112,6 @@ } ], "source": [ - "\n", "display(turtlesim.canvas)" ] }, @@ -197,23 +172,20 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 13, "id": "cd2e66dc", "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3523d845c79946de8b5259f5aa32a923", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "NameError", + "evalue": "name 'keyInput' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn [13], line 26\u001b[0m\n\u001b[1;32m 19\u001b[0m poses[name] \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx\u001b[39m\u001b[38;5;124m\"\u001b[39m: x,\n\u001b[1;32m 20\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my\u001b[39m\u001b[38;5;124m\"\u001b[39m: y,\n\u001b[1;32m 21\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtheta\u001b[39m\u001b[38;5;124m\"\u001b[39m: msg\u001b[38;5;241m.\u001b[39mtheta}\n\u001b[1;32m 23\u001b[0m turtlesim\u001b[38;5;241m.\u001b[39mmove_turtles(new_poses\u001b[38;5;241m=\u001b[39mposes)\n\u001b[0;32m---> 26\u001b[0m turtle_control \u001b[38;5;241m=\u001b[39m jr2\u001b[38;5;241m.\u001b[39mSubscriber(\u001b[43mkeyInput\u001b[49m, String, topic_name, cb)\n\u001b[1;32m 27\u001b[0m turtle_control\u001b[38;5;241m.\u001b[39mdisplay()\n", + "\u001b[0;31mNameError\u001b[0m: name 'keyInput' is not defined" + ] } ], "source": [ @@ -248,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 15, "id": "c9e44409-1f96-426f-9826-95f2ddff5119", "metadata": {}, "outputs": [ @@ -256,15 +228,38 @@ "name": "stderr", "output_type": "stream", "text": [ - "UsageError: Cell magic `%%thread_cell` not found.\n" + "Exception in thread Thread-6:\n", + "Traceback (most recent call last):\n", + " File \"/usr/lib/python3.8/threading.py\", line 932, in _bootstrap_inner\n", + " self.run()\n", + " File \"/usr/lib/python3.8/threading.py\", line 870, in run\n", + " self._target(*self._args, **self._kwargs)\n", + " File \"/usr/local/lib/python3.8/dist-packages/jupyros/ros2/ipy.py\", line 15, in executor\n", + " exec(cell, gbls, lcls)\n", + " File \"\", line 5, in \n", + "NameError: name 'run' is not defined\n" ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bf6dda043fef4730adea4dfa192377a7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output(layout=Layout(border='1px solid gray'))" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "%%thread_cell\n", + "%%thread_cell2\n", "\n", "i = 0\n", - "pub = jr2.Publisher(test_node, Pose, '/Pose')\n", + "pub = jr2.Publisher(moveNode, Pose, '/Pose')\n", "\n", "while run:\n", " msg = Pose()\n", From 953652e33537bc9faccfadb516e117c3b0823f46 Mon Sep 17 00:00:00 2001 From: ldania Date: Mon, 28 Nov 2022 11:17:59 +0000 Subject: [PATCH 4/7] Adjusted Publisher --- jupyros/ros2/publisher.py | 2 +- notebooks/ROS2_Publisher_Subscriber.ipynb | 74 ++++++++++- notebooks/ROS2_Turtlesim.ipynb | 117 +++++------------- .../ROS2_Turtlesim_KeyboardControl.ipynb | 88 +++++++++++-- notebooks/ROS_Turtlesim_tf2.ipynb | 2 +- 5 files changed, 185 insertions(+), 98 deletions(-) diff --git a/jupyros/ros2/publisher.py b/jupyros/ros2/publisher.py index 9d06d68..0657f29 100644 --- a/jupyros/ros2/publisher.py +++ b/jupyros/ros2/publisher.py @@ -139,7 +139,7 @@ def __send_msg(self, args): """ Generic call to send message. """ self.msg_inst = self.msg_type() - if(self.widget_list): + if(self.__widget_list): self.widget_dict_to_msg() self.__publisher.publish(self.msg_inst) else: diff --git a/notebooks/ROS2_Publisher_Subscriber.ipynb b/notebooks/ROS2_Publisher_Subscriber.ipynb index 9466261..7d1ebde 100644 --- a/notebooks/ROS2_Publisher_Subscriber.ipynb +++ b/notebooks/ROS2_Publisher_Subscriber.ipynb @@ -53,7 +53,22 @@ "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0abfdd19ee5046a6b1ee60f6a50d2810", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#Method 1 of subscribing and printing data\n", "sub = jr2.Subscriber(test_node, Pose, '/Pose', cb, print_incoming_msg=True)\n", @@ -73,13 +88,68 @@ "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "90d8e251e05e4d68b62efce7f0456b1a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Label(value='position'), HBox(children=(Label(value='x', layout=Layout(width='100px')), FloatTe…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#Method 1 of publishing to node\n", "pub = jr2.Publisher(test_node, Pose, '/Pose')\n", "pub.display()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b364f7b6729b471d85c42a0c02fe79c8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Method 1 of subscribing and printing data\n", + "sub = jr2.Subscriber(test_node, String, '/pose_stream', cb, print_incoming_msg=True)\n", + "sub.display()" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/ROS2_Turtlesim.ipynb b/notebooks/ROS2_Turtlesim.ipynb index 1c92d4d..f071625 100644 --- a/notebooks/ROS2_Turtlesim.ipynb +++ b/notebooks/ROS2_Turtlesim.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 8, + "execution_count": 1, "id": "7259a8b6", "metadata": {}, "outputs": [], @@ -24,18 +24,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 2, "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "rclpy already initiated\n" - ] - } - ], + "outputs": [], "source": [ "# Initialize ROS communications for a given context\n", "if(rp.ok() == False):\n", @@ -46,19 +38,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 3, "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[WARN] [1669631239.172912305] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.\n", - "[WARN] [1669631239.175681966] [rcl.logging_rosout]: Publisher already registered for provided node name. If this is due to multiple nodes with the same name then all logs for that logger name will go out over the existing publisher. As soon as any node with that name is destructed it will unregister the publisher, preventing any further logs for that name from being published on the rosout topic.\n" - ] - } - ], + "outputs": [], "source": [ "superturtle = rp.create_node(\"superturtle\")\n", "moveNode = rp.create_node(\"moveNode\")" @@ -66,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "id": "2dbf024d", "metadata": { "tags": [] @@ -86,20 +69,16 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", "metadata": { - "collapsed": true, - "jupyter": { - "outputs_hidden": true - }, "tags": [] }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c0e89d7ae29445dbb0a405c14c99d2b5", + "model_id": "77f04f8ef9634ee590f4c6d02026d8b8", "version_major": 2, "version_minor": 0 }, @@ -125,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", "metadata": { "jupyter": { @@ -153,45 +132,37 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "ac63dbbb-b388-4b18-890c-e3bcada044a9", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'x': 800, 'y': 800, 'theta': 0}" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 7, "id": "cd2e66dc", "metadata": {}, "outputs": [ { - "ename": "NameError", - "evalue": "name 'keyInput' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn [13], line 26\u001b[0m\n\u001b[1;32m 19\u001b[0m poses[name] \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx\u001b[39m\u001b[38;5;124m\"\u001b[39m: x,\n\u001b[1;32m 20\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my\u001b[39m\u001b[38;5;124m\"\u001b[39m: y,\n\u001b[1;32m 21\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtheta\u001b[39m\u001b[38;5;124m\"\u001b[39m: msg\u001b[38;5;241m.\u001b[39mtheta}\n\u001b[1;32m 23\u001b[0m turtlesim\u001b[38;5;241m.\u001b[39mmove_turtles(new_poses\u001b[38;5;241m=\u001b[39mposes)\n\u001b[0;32m---> 26\u001b[0m turtle_control \u001b[38;5;241m=\u001b[39m jr2\u001b[38;5;241m.\u001b[39mSubscriber(\u001b[43mkeyInput\u001b[49m, String, topic_name, cb)\n\u001b[1;32m 27\u001b[0m turtle_control\u001b[38;5;241m.\u001b[39mdisplay()\n", - "\u001b[0;31mNameError\u001b[0m: name 'keyInput' is not defined" - ] + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2aff5baab18c49bb8af3faed876a372a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ "topic_name = '/keyboard_stream'\n", "def move_turtles(msg):\n", - " scale = 0.01\n", + " scale = 1\n", " name = \"turtle1\"\n", "\n", " poses[name] = {\"x\": turtlesim.turtles[name].pose[\"x\"] + msg.linear.x*math.cos(turtlesim.turtles[name].pose[\"theta\"])/scale,\n", @@ -205,45 +176,24 @@ "\n", "\n", "def cb(msg):\n", - " name = \"turtle1\"\n", - " x, y = convert_xy_units(msg.x, msg.y)\n", - " poses[name] = {\"x\": x,\n", - " \"y\": y,\n", - " \"theta\": msg.theta}\n", - " \n", - " turtlesim.move_turtles(new_poses=poses)\n", + " print(msg)\n", + " move_turtles(msg)\n", "\n", "\n", - "turtle_control = jr2.Subscriber(keyInput, String, topic_name, cb)\n", + "turtle_control = jr2.Subscriber(moveNode, Pose, topic_name, cb)\n", "turtle_control.display()" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 8, "id": "c9e44409-1f96-426f-9826-95f2ddff5119", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Exception in thread Thread-6:\n", - "Traceback (most recent call last):\n", - " File \"/usr/lib/python3.8/threading.py\", line 932, in _bootstrap_inner\n", - " self.run()\n", - " File \"/usr/lib/python3.8/threading.py\", line 870, in run\n", - " self._target(*self._args, **self._kwargs)\n", - " File \"/usr/local/lib/python3.8/dist-packages/jupyros/ros2/ipy.py\", line 15, in executor\n", - " exec(cell, gbls, lcls)\n", - " File \"\", line 5, in \n", - "NameError: name 'run' is not defined\n" - ] - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "bf6dda043fef4730adea4dfa192377a7", + "model_id": "1f92a4ad257146fca78c363671b8181b", "version_major": 2, "version_minor": 0 }, @@ -257,17 +207,16 @@ ], "source": [ "%%thread_cell2\n", - "\n", + "run = True\n", "i = 0\n", - "pub = jr2.Publisher(moveNode, Pose, '/Pose')\n", + "pub = jr2.Publisher(moveNode, Pose, topic_name)\n", "\n", "while run:\n", " msg = Pose()\n", " msg.x = (i/1800*5)*math.sin(i / 180 * math.pi) + 11.08 / 2\n", " msg.y = (i/1800*5)*math.cos(i / 180 * math.pi) + 11.08 / 2\n", " msg.theta = - i / 180 * math.pi\n", - " pub.publish(msg)\n", - " rate.sleep()\n", + " pub.send_msg(msg)\n", " i += 1\n", "print(\"Done\")" ] diff --git a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb index eef6d87..53729f0 100644 --- a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb +++ b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "7259a8b6", "metadata": {}, "outputs": [], @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", "metadata": {}, "outputs": [], @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", "metadata": {}, "outputs": [], @@ -52,10 +52,39 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "3bdbfe05-c4d3-4fd3-abfa-f38b039d4541", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fc8ee6a25ba64a3bb7d88184717a5672", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4b231f376d4145c3a3086ae7ea55bb62", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "key_send = jr2.KeyInput(keyInput, String, '/keyboard_stream')\n", "key_send.display_inputs()" @@ -63,12 +92,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "2dbf024d", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "turtle1 has spawned.\n" + ] + } + ], "source": [ "\n", "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n" @@ -76,10 +113,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d4a4365909444d9495776ffc4f282e02", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MultiCanvas(height=1600, layout=Layout(width='100%'), width=1600)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "\n", "display(turtlesim.canvas)" @@ -203,9 +255,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "c0cd916b-41a7-4832-9470-328c1d30689b", "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UsageError: %%thread_cell is a cell magic, but the cell body is empty.\n" + ] + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69fbd5a8-f709-4782-9d46-f7dfc5a27fbc", + "metadata": {}, "outputs": [], "source": [] } diff --git a/notebooks/ROS_Turtlesim_tf2.ipynb b/notebooks/ROS_Turtlesim_tf2.ipynb index 3b3afc1..4cc25b6 100644 --- a/notebooks/ROS_Turtlesim_tf2.ipynb +++ b/notebooks/ROS_Turtlesim_tf2.ipynb @@ -153,7 +153,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.8.10" } }, "nbformat": 4, From 5148ba5dbba8b510bede029295faf40d50e35b04 Mon Sep 17 00:00:00 2001 From: ldania Date: Mon, 28 Nov 2022 12:08:46 +0000 Subject: [PATCH 5/7] Adjusting publisher to allow direct messaging --- jupyros/ros2/publisher.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jupyros/ros2/publisher.py b/jupyros/ros2/publisher.py index 0657f29..9c51cf9 100644 --- a/jupyros/ros2/publisher.py +++ b/jupyros/ros2/publisher.py @@ -86,6 +86,7 @@ def __init__(self, node: Node, msg_type: MsgType, topic: str, rate = None ) -> N "send_btn": widgets.Button(description="Send Message"), "txt_input": widgets.Text(description="Message", value="Something") } + self.vbox = None if(rate): self.node.create_timer(rate, self.__send_msg) self.widget_dict, self.widget_list = add_widgets(self.msg_type, self.__widget_dict, self.__widget_list) @@ -126,7 +127,7 @@ def display(self) -> widgets.VBox: )) self.__widget_list.append(btm_box) vbox = widgets.VBox(children=self.__widget_list) - + self.vbox = vbox return vbox def send_msg(self, args): @@ -139,7 +140,7 @@ def __send_msg(self, args): """ Generic call to send message. """ self.msg_inst = self.msg_type() - if(self.__widget_list): + if(self.vbox): self.widget_dict_to_msg() self.__publisher.publish(self.msg_inst) else: From fed4ae48efe609f81f8cc1fbde6118fc0af862bd Mon Sep 17 00:00:00 2001 From: ldania Date: Mon, 28 Nov 2022 13:48:06 +0000 Subject: [PATCH 6/7] Cicular Movement --- jupyros/ros2/turtle_sim.py | 123 ++++++++++++++++++ notebooks/ROS2_Turtlesim.ipynb | 45 +++---- .../ROS2_Turtlesim_KeyboardControl.ipynb | 76 ++++++----- 3 files changed, 186 insertions(+), 58 deletions(-) create mode 100644 jupyros/ros2/turtle_sim.py diff --git a/jupyros/ros2/turtle_sim.py b/jupyros/ros2/turtle_sim.py new file mode 100644 index 0000000..964ab77 --- /dev/null +++ b/jupyros/ros2/turtle_sim.py @@ -0,0 +1,123 @@ +import os +import time +import math +import random + +import ipycanvas +import ipywidgets + +from ament_index_python.packages import get_package_share_directory + + +class TurtleSim: + def __init__(self, width=1600, height=1600, turtle_size=100, background_color="#4556FF"): + self.turtles = {} + self.turtle_size = turtle_size + self.canvas_middle = {"x": width // 2, + "y": height // 2, + "theta": 0} + + # Three layers for the canvas: 0-background, 1-paths, 2-turtles + self.canvas = ipycanvas.MultiCanvas(3, + width=width, height=height, + layout={"width": "100%"}) + + # Water background + self.canvas[0].fill_style = background_color + self.canvas[0].fill_rect(0, 0, width, height) + + # Turtle path width + self.canvas[1].line_width = 8 + + self.last_move_time = time.time() + self.spawn() + + def spawn(self, name=None, pose=None): + + if (name is None) or (name in self.turtles.keys()): + name = "turtle" + str(len(self.turtles) + 1) + + self.turtles[name] = self.Turtle(name, self.turtle_size) + + if pose is None: + # Spawn to middle of canvas + self.turtles[name].pose = self.canvas_middle + else: + self.turtles[name].pose = pose + + with ipycanvas.hold_canvas(self.canvas): + self.draw_turtle(name) + + print(name + " has spawned.") + + def move_turtles(self, new_poses): + elapsed_time = time.time() - self.last_move_time + + + + if elapsed_time > 0.08: # seconds + self.last_move_time = time.time() + + with ipycanvas.hold_canvas(self.canvas): + self.canvas[2].clear() + + for name in self.turtles.keys(): + # Draw line path + self.canvas[1].stroke_style = self.turtles[name].path_color + self.canvas[1].stroke_line(self.turtles[name].pose["x"], + self.turtles[name].pose["y"], + new_poses[name]["x"], + new_poses[name]["y"]) + # Update + self.turtles[name].pose["x"] = new_poses[name]["x"] + self.turtles[name].pose["y"] = new_poses[name]["y"] + self.turtles[name].pose["theta"] = new_poses[name]["theta"] + + + + self.draw_turtle(name) + + def draw_turtle(self, name="turtle1", n=2): + # Offsets for turtle center and orientation + x_offset = - self.turtle_size / 2 + y_offset = - self.turtle_size / 2 + theta_offset = self.turtles[name].pose["theta"] - math.radians(90) # to face right side + + # Transform canvas + self.canvas[n].save() + self.canvas[n].translate(self.turtles[name].pose["x"], self.turtles[name].pose["y"]) + self.canvas[n].rotate(-theta_offset) + + self.canvas[n].draw_image(self.turtles[name].canvas, + x_offset, y_offset, + self.turtle_size) + + # Revert transformation + self.canvas[n].restore() + + class Turtle: + def __init__(self, name, size=100): + self.name = name + self.size = size + self.canvas = None + self.randomize() + self.pose = {"x": 0, + "y": 0, + "theta": 0} + self.path_color = '#B3B8FF' # Light blue + + def randomize(self): + img_path = str(get_package_share_directory("turtlesim")) + "/images/" + images = os.listdir(img_path) + turtle_pngs = [img for img in images if ('.png' in img and 'palette' not in img)] + random_png = turtle_pngs[random.randint(0, len(turtle_pngs) - 1)] + turtle_img = ipywidgets.Image.from_file(img_path + random_png) + turtle_canvas = ipycanvas.Canvas(width=self.size, height=self.size) + + with ipycanvas.hold_canvas(turtle_canvas): + turtle_canvas.draw_image(turtle_img, 0, 0, self.size) + + time.sleep(0.1) # Drawing time + self.canvas = turtle_canvas + + return self diff --git a/notebooks/ROS2_Turtlesim.ipynb b/notebooks/ROS2_Turtlesim.ipynb index f071625..46ed202 100644 --- a/notebooks/ROS2_Turtlesim.ipynb +++ b/notebooks/ROS2_Turtlesim.ipynb @@ -12,7 +12,6 @@ "import jupyros.ros2.turtle_sim as turtle\n", "from turtlesim.srv import Spawn\n", "from turtlesim.msg import Pose\n", - "from time import time\n", "import os\n", "from std_msgs.msg import String\n", "from geometry_msgs.msg import Twist\n", @@ -78,7 +77,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "77f04f8ef9634ee590f4c6d02026d8b8", + "model_id": "f7e9060702e74556b7652d4a783d9768", "version_major": 2, "version_minor": 0 }, @@ -107,9 +106,6 @@ "execution_count": 6, "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", "metadata": { - "jupyter": { - "source_hidden": true - }, "tags": [] }, "outputs": [ @@ -147,7 +143,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "2aff5baab18c49bb8af3faed876a372a", + "model_id": "9a96ef62b2b440e0a6edd111a08f2a22", "version_major": 2, "version_minor": 0 }, @@ -160,15 +156,20 @@ } ], "source": [ - "topic_name = '/keyboard_stream'\n", + "topic_name = '/Pose'\n", "def move_turtles(msg):\n", - " scale = 1\n", + " scale = 0.0015\n", " name = \"turtle1\"\n", - "\n", - " poses[name] = {\"x\": turtlesim.turtles[name].pose[\"x\"] + msg.linear.x*math.cos(turtlesim.turtles[name].pose[\"theta\"])/scale,\n", - " \"y\": turtlesim.turtles[name].pose[\"y\"] - msg.linear.x*math.sin(turtlesim.turtles[name].pose[\"theta\"] )/scale,\n", - " \"theta\": turtlesim.turtles[name].pose[\"theta\"] + msg.angular.z/ 180 * math.pi}\n", " \n", + " def angle_slope():\n", + " d_y = (math.sin(msg.theta+1/180)*math.cos(msg.theta+1/180)-math.sin(msg.theta)*math.cos(msg.theta))\n", + " d_x = (math.cos(msg.theta+1/180) - math.cos(msg.theta))\n", + " return math.atan2(d_y,d_x)\n", + " \n", + " poses[name] = {\"x\": 1/scale * math.cos(msg.theta) + 800,\n", + " \"y\": -1/scale * math.sin(msg.theta)*math.cos(msg.theta) + 800,\n", + " \"theta\": angle_slope()}\n", + " ##msg.theta - math.atan2((-1/scale * math.sin(msg.theta)*math.cos(msg.theta) + 800),(1/scale * math.cos(msg.theta) + 800))\n", " \n", " turtlesim.move_turtles(new_poses=poses)\n", "\n", @@ -176,7 +177,6 @@ "\n", "\n", "def cb(msg):\n", - " print(msg)\n", " move_turtles(msg)\n", "\n", "\n", @@ -193,7 +193,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1f92a4ad257146fca78c363671b8181b", + "model_id": "b9d3b46917c34d3097c23523095f14df", "version_major": 2, "version_minor": 0 }, @@ -208,26 +208,17 @@ "source": [ "%%thread_cell2\n", "run = True\n", - "i = 0\n", + "i = 90\n", "pub = jr2.Publisher(moveNode, Pose, topic_name)\n", "\n", "while run:\n", " msg = Pose()\n", - " msg.x = (i/1800*5)*math.sin(i / 180 * math.pi) + 11.08 / 2\n", - " msg.y = (i/1800*5)*math.cos(i / 180 * math.pi) + 11.08 / 2\n", - " msg.theta = - i / 180 * math.pi\n", - " pub.send_msg(msg)\n", + " msg.theta = i / 180 * math.pi\n", + " pub.send_msg( msg)\n", + " sleep(0.01)\n", " i += 1\n", "print(\"Done\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "606db6b1-f505-41b7-99d1-525b09cf662e", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb index 53729f0..1e9c241 100644 --- a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb +++ b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb @@ -59,7 +59,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fc8ee6a25ba64a3bb7d88184717a5672", + "model_id": "33726261d3ca48cfb41d862e9386ed5e", "version_major": 2, "version_minor": 0 }, @@ -73,7 +73,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4b231f376d4145c3a3086ae7ea55bb62", + "model_id": "62f02b8ea884432a85024d49449446dd", "version_major": 2, "version_minor": 0 }, @@ -120,7 +120,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "d4a4365909444d9495776ffc4f282e02", + "model_id": "32c59818a7cd4fdfa129eca3b0cb238f", "version_major": 2, "version_minor": 0 }, @@ -137,18 +137,6 @@ "display(turtlesim.canvas)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "347b508d-4568-4cc2-b8da-c05f26b6f606", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "!jupyter labextension install js" - ] - }, { "cell_type": "markdown", "id": "ece1ece3-54f6-4df8-be79-42d7f37f6e08", @@ -159,10 +147,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'x': 800, 'y': 800, 'theta': 0}\n" + ] + } + ], "source": [ "poses = {}\n", "\n", @@ -174,20 +170,46 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "ac63dbbb-b388-4b18-890c-e3bcada044a9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'x': 800, 'y': 800, 'theta': 0}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "turtlesim.turtles[name].pose" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "cd2e66dc", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7806c8d4a3f04f5f8f6f64d0043ca113", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "topic_name = '/keyboard_stream'\n", "def move_turtles(msg):\n", @@ -255,18 +277,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "c0cd916b-41a7-4832-9470-328c1d30689b", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "UsageError: %%thread_cell is a cell magic, but the cell body is empty.\n" - ] - } - ], + "outputs": [], "source": [] }, { From 51718642719a5d7d2bba915501f9fb39d67e9b18 Mon Sep 17 00:00:00 2001 From: ldania Date: Wed, 7 Dec 2022 11:31:29 +0000 Subject: [PATCH 7/7] Cleanup for PR File Cleanup for PR, resetting irrelevant notebooks File Cleanup for PR Cleanup --- notebooks/ROS2_Keyboard_Input.ipynb | 41 +------ notebooks/ROS2_Publisher_Subscriber.ipynb | 74 +---------- notebooks/ROS2_Turtlesim.ipynb | 95 ++++---------- .../ROS2_Turtlesim_KeyboardControl.ipynb | 116 +++--------------- notebooks/ROS_Turtlesim.ipynb | 2 +- notebooks/ROS_Turtlesim_tf2.ipynb | 2 +- 6 files changed, 46 insertions(+), 284 deletions(-) diff --git a/notebooks/ROS2_Keyboard_Input.ipynb b/notebooks/ROS2_Keyboard_Input.ipynb index cfc764f..3169a56 100644 --- a/notebooks/ROS2_Keyboard_Input.ipynb +++ b/notebooks/ROS2_Keyboard_Input.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -62,38 +62,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bbc3405979ce48918e210c79dbe99979", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "918427091a334342b8673302f787ab75", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "key_send = jr2.KeyInput(key_node, String, '/keyboard_stream')\n", "key_send.display_inputs()" diff --git a/notebooks/ROS2_Publisher_Subscriber.ipynb b/notebooks/ROS2_Publisher_Subscriber.ipynb index 7d1ebde..9466261 100644 --- a/notebooks/ROS2_Publisher_Subscriber.ipynb +++ b/notebooks/ROS2_Publisher_Subscriber.ipynb @@ -53,22 +53,7 @@ "metadata": { "scrolled": true }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0abfdd19ee5046a6b1ee60f6a50d2810", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#Method 1 of subscribing and printing data\n", "sub = jr2.Subscriber(test_node, Pose, '/Pose', cb, print_incoming_msg=True)\n", @@ -88,68 +73,13 @@ "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "90d8e251e05e4d68b62efce7f0456b1a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Label(value='position'), HBox(children=(Label(value='x', layout=Layout(width='100px')), FloatTe…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#Method 1 of publishing to node\n", "pub = jr2.Publisher(test_node, Pose, '/Pose')\n", "pub.display()" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b364f7b6729b471d85c42a0c02fe79c8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#Method 1 of subscribing and printing data\n", - "sub = jr2.Subscriber(test_node, String, '/pose_stream', cb, print_incoming_msg=True)\n", - "sub.display()" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/ROS2_Turtlesim.ipynb b/notebooks/ROS2_Turtlesim.ipynb index 46ed202..6facf1e 100644 --- a/notebooks/ROS2_Turtlesim.ipynb +++ b/notebooks/ROS2_Turtlesim.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "7259a8b6", "metadata": {}, "outputs": [], @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", "metadata": {}, "outputs": [], @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", "metadata": {}, "outputs": [], @@ -48,47 +48,24 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "2dbf024d", "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "turtle1 has spawned.\n" - ] - } - ], + "outputs": [], "source": [ "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f7e9060702e74556b7652d4a783d9768", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MultiCanvas(height=1600, layout=Layout(width='100%'), width=1600)" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display(turtlesim.canvas)" ] @@ -103,20 +80,12 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'x': 800, 'y': 800, 'theta': 0}\n" - ] - } - ], + "outputs": [], "source": [ "poses = {}\n", "\n", @@ -136,25 +105,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "cd2e66dc", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9a96ef62b2b440e0a6edd111a08f2a22", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "topic_name = '/Pose'\n", "def move_turtles(msg):\n", @@ -186,25 +140,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "c9e44409-1f96-426f-9826-95f2ddff5119", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b9d3b46917c34d3097c23523095f14df", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output(layout=Layout(border='1px solid gray'))" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "%%thread_cell2\n", "run = True\n", @@ -219,6 +158,14 @@ " i += 1\n", "print(\"Done\")" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fd093f5-122e-4006-8ad8-813428356fbe", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb index 1e9c241..fd0fa0b 100644 --- a/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb +++ b/notebooks/ROS2_Turtlesim_KeyboardControl.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "7259a8b6", "metadata": {}, "outputs": [], @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "1964ecfc-67ee-47bf-aad3-824315c4418d", "metadata": {}, "outputs": [], @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "47354d6d-8c92-47ce-9f85-c0c1e403d8bf", "metadata": {}, "outputs": [], @@ -52,39 +52,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "3bdbfe05-c4d3-4fd3-abfa-f38b039d4541", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "33726261d3ca48cfb41d862e9386ed5e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Canvas()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "62f02b8ea884432a85024d49449446dd", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "key_send = jr2.KeyInput(keyInput, String, '/keyboard_stream')\n", "key_send.display_inputs()" @@ -92,20 +63,12 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "2dbf024d", "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "turtle1 has spawned.\n" - ] - } - ], + "outputs": [], "source": [ "\n", "turtlesim = turtle.TurtleSim(background_color=\"#0000FF\")\n" @@ -113,25 +76,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "2bfe401a-2a01-4f75-839a-411b221bac8e", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "32c59818a7cd4fdfa129eca3b0cb238f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MultiCanvas(height=1600, layout=Layout(width='100%'), width=1600)" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "\n", "display(turtlesim.canvas)" @@ -147,18 +95,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "497db1e0-8c21-4ec0-b620-1607ab34d685", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'x': 800, 'y': 800, 'theta': 0}\n" - ] - } - ], + "outputs": [], "source": [ "poses = {}\n", "\n", @@ -170,46 +110,20 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "ac63dbbb-b388-4b18-890c-e3bcada044a9", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'x': 800, 'y': 800, 'theta': 0}" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "turtlesim.turtles[name].pose" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "cd2e66dc", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7806c8d4a3f04f5f8f6f64d0043ca113", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Button(description='Start', style=ButtonStyle()), Button(description='Stop', sty…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "topic_name = '/keyboard_stream'\n", "def move_turtles(msg):\n", diff --git a/notebooks/ROS_Turtlesim.ipynb b/notebooks/ROS_Turtlesim.ipynb index 7f7e1a5..f784c45 100644 --- a/notebooks/ROS_Turtlesim.ipynb +++ b/notebooks/ROS_Turtlesim.ipynb @@ -245,7 +245,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/notebooks/ROS_Turtlesim_tf2.ipynb b/notebooks/ROS_Turtlesim_tf2.ipynb index 4cc25b6..3b3afc1 100644 --- a/notebooks/ROS_Turtlesim_tf2.ipynb +++ b/notebooks/ROS_Turtlesim_tf2.ipynb @@ -153,7 +153,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.9.13" } }, "nbformat": 4,