{ "cells": [ { "cell_type": "markdown", "id": "611b7e76", "metadata": {}, "source": [ "\n", "## Setting up the Environment\n", "\n", "This step involves importing the required modules and initializing key components for our tasks.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "615cb805", "metadata": { "ExecuteTime": { "end_time": "2023-09-08T16:51:08.901104329Z", "start_time": "2023-09-08T16:51:08.139879012Z" } }, "outputs": [], "source": [ "from pycram.bullet_world import BulletWorld, Object\n", "from pycram.pose import Transform\n", "from pycram.local_transformer import LocalTransformer" ] }, { "cell_type": "markdown", "id": "6d4dc619", "metadata": {}, "source": [ "\n", "## Initializing the World\n", "\n", "Every robot simulation requires a world where it can interact. This world serves as the playground where the robot performs tasks. \n", "Let's start by creating this world.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "7a3222c2", "metadata": { "ExecuteTime": { "end_time": "2023-09-08T16:51:11.202198685Z", "start_time": "2023-09-08T16:51:10.916529902Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Unknown tag \"material\" in /robot[@name='plane']/link[@name='planeLink']/collision[1]\n", "Unknown tag \"contact\" in /robot[@name='plane']/link[@name='planeLink']\n", "Unknown tag \"material\" in /robot[@name='plane']/link[@name='planeLink']/collision[1]\n", "Unknown tag \"contact\" in /robot[@name='plane']/link[@name='planeLink']\n" ] } ], "source": [ "# Create an instance of the BulletWorld\n", "world = BulletWorld()\n" ] }, { "cell_type": "markdown", "id": "b27205e4", "metadata": {}, "source": [ "The world can be closed by calling the exit method of the world, but don't call this method yet since it would close the world." ] }, { "cell_type": "code", "execution_count": 9, "id": "c019c259", "metadata": {}, "outputs": [], "source": [ "world.exit()" ] }, { "cell_type": "markdown", "id": "a183eaae", "metadata": {}, "source": [ "\n", "## Adding Objects to the World\n", "\n", "For our robot to perform meaningful tasks, we need to populate its world with objects. \n", "In this section, we'll add a variety of objects, from a simple floor plane to kitchen setups and items like milk and bowls. \n", "These objects will be used in subsequent tasks.\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "14494539", "metadata": { "ExecuteTime": { "end_time": "2023-09-08T16:51:38.439962987Z", "start_time": "2023-09-08T16:51:33.675944073Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Unknown tag \"material\" in /robot[@name='plane']/link[@name='planeLink']/collision[1]\n", "Unknown tag \"contact\" in /robot[@name='plane']/link[@name='planeLink']\n", "Scalar element defined multiple times: limit\n", "Unknown tag \"material\" in /robot[@name='plane']/link[@name='planeLink']/collision[1]\n", "Unknown tag \"contact\" in /robot[@name='plane']/link[@name='planeLink']\n", "Scalar element defined multiple times: limit\n" ] } ], "source": [ "from pycram.bullet_world import Object\n", "from pycram.enums import ObjectType\n", "\n", "plane = Object(\"floor\", ObjectType.ENVIRONMENT, \"plane.urdf\", world=world)\n", "\n", "kitchen = Object(\"kitchen\", ObjectType.ENVIRONMENT, \"kitchen.urdf\")\n", "milk = Object(\"milk\", ObjectType.MILK, \"milk.stl\", Pose([0.9, 1, 0.95]))\n", "bowl = Object(\"bowl\", ObjectType.BOWL, \"bowl.stl\", Pose([1.6, 1, 0.90]))" ] }, { "cell_type": "markdown", "id": "d48d292b", "metadata": {}, "source": [ "## Creating a Local Transfomer\n", "The local transformer is implemented as a singelton, meaing regardless of how much and where an instance is created it will always be the same instance. This is done since the local transfomer collects all transformations between frames and would there always be a new instance, all transformations woulb need to be re-collected. " ] }, { "cell_type": "code", "execution_count": 4, "id": "708606eb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n" ] } ], "source": [ "from pycram.local_transformer import LocalTransformer\n", "\n", "local_transformer = LocalTransformer()\n", "print(local_transformer)\n", "\n", "new_local_transformer = LocalTransformer()\n", "print(new_local_transformer)" ] }, { "cell_type": "markdown", "id": "fb97d61e", "metadata": {}, "source": [ "## Transformations with LocalTransformer\n", "Now that we have our world set up, let's perform some transformations. We'll use the LocalTransformer to transform poses relative to our objects." ] }, { "cell_type": "code", "execution_count": 5, "id": "988ffda1", "metadata": { "ExecuteTime": { "end_time": "2023-09-08T16:42:15.478051994Z", "start_time": "2023-09-08T16:42:15.472743693Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "header: \n", " seq: 0\n", " stamp: \n", " secs: 1699448290\n", " nsecs: 552922010\n", " frame_id: \"milk_4\"\n", "pose: \n", " position: \n", " x: 0.09999999999999998\n", " y: 0.0\n", " z: 0.050000000000000044\n", " orientation: \n", " x: 0.0\n", " y: 0.0\n", " z: 0.0\n", " w: 1.0\n", "header: \n", " seq: 0\n", " stamp: \n", " secs: 1699448290\n", " nsecs: 553559541\n", " frame_id: \"map\"\n", "pose: \n", " position: \n", " x: 1.0\n", " y: 1.0\n", " z: 1.0\n", " orientation: \n", " x: 0.0\n", " y: 0.0\n", " z: 0.0\n", " w: 1.0\n" ] } ], "source": [ "from pycram.local_transformer import LocalTransformer\n", "from pycram.pose import Pose\n", "\n", "l = LocalTransformer()\n", "test_pose = Pose([1, 1, 1], [0, 0, 0, 1], \"map\")\n", "\n", "transformed_pose = l.transform_to_object_frame(test_pose, milk)\n", "print(transformed_pose)\n", "\n", "new_pose = l.transform_pose(transformed_pose, \"map\")\n", "print(new_pose)" ] }, { "cell_type": "markdown", "id": "72716743", "metadata": {}, "source": [ "In the above code, we first transformed a pose to the object frame of the milk object, and then we transformed it back to the map frame. This demonstrates how we can easily manipulate poses relative to objects in our environment.\n", "You can also transform poses relative to other poses. by using the transform_pose method. Further u can set a Transform." ] }, { "cell_type": "code", "execution_count": 6, "id": "dd2bafc5", "metadata": {}, "outputs": [], "source": [ "from pycram.pose import Transform\n", "\n", "l.setTransform(Transform([1, 1, 1], [0, 0, 0, 1], \"map\", \"test_frame\"))\n", "p = Pose()\n", "\n", "transformed_pose = l.transform_pose(p, \"test_frame\")" ] }, { "cell_type": "markdown", "id": "8af90783", "metadata": {}, "source": [ "You can also set a Pose to an object and update the transforms for that object. However, this is usually done in the background when necessary so you should only use this method if there is something wrong with the Transformation." ] }, { "cell_type": "code", "execution_count": 7, "id": "6b23f540", "metadata": { "ExecuteTime": { "end_time": "2023-09-08T16:47:16.375950749Z", "start_time": "2023-09-08T16:47:16.332420624Z" } }, "outputs": [], "source": [ "milk.set_pose(Pose([1, 2, 1]))\n", "l.update_transforms_for_object(milk)" ] }, { "cell_type": "markdown", "id": "26545569", "metadata": {}, "source": [ "## Transformation frames\n", "As you can see in the example above the frame_id of the object is not 'milk' but 'milk_4'. This is done since frame_ids need to be unique, however, the name of an Object does not. To solve this problem the name of an Object is concatenated with a unique id therefore making it unique. \n", "\n", "Furthermore, links of an Object are represented by the Object frame_id + '/' + link name. Since link names need to be unique for an URDF this is no problem.\n", "\n", "These frames need to be used in whenever you are transforming something with the local transformer. To get the base frame of an Object, meaning the frame name without any link there is the attribute tf_frame and for the frame of a link there is the method get_link_tf_frame. " ] }, { "cell_type": "code", "execution_count": 8, "id": "bd619710", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "milk_4\n", "kitchen_3/kitchen_island_surface\n" ] } ], "source": [ "print(milk.tf_frame)\n", "\n", "print(kitchen.get_link_tf_frame(\"kitchen_island_surface\"))" ] } ], "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.8.10" } }, "nbformat": 4, "nbformat_minor": 5 }