{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Another language" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**NOTE before starting**\n", "\n", "To change the notebook which is launched by default by the \"programming with Jupyter\" tab in puppet-master interface\n", "\n", "1. Go to [My Documents/ Poppy source-code/ puppet-master/ bouteillederouge.py](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/puppet-master/bouteillederouge.py)\n", "2. Find `jupyter()` function (around line 191)\n", "3. Change the value of the variable `default_notebook`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**This notebook will guide you for connect another programmation language** *(not beginner tutorial)*\n", "\n", "What you will see in this notebook:\n", "\n", "1. Understand how your robot is programmed\n", "2. Code through API\n", "\n", " > snap server\n", " 1. Access to API to get values \n", " 2. Get value - *with single input* - and - *with multiple input* -\n", " 3. Set value - *with single input* - and - *with multiple input* -\n", " 4. Add checking inputs and use your function\n", " \n", " > http server\n", " 1. Access to API\n", " 2. Get request\n", " 3. Post request\n", " \n", "3. Add new entries in API\n", "4. Add tab in puppet-master interface" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Understand how your robot is programmed" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code source\n", "The native language of Poppy robots is the python language. In python, all of the robot's functionalities are available.\\\n", "Check notebooks «Discover your Poppy robot» and «Benchmark your Poppy robot» (in folder [My Documents/ python notebook](http://poppy.local:8888/tree/My%20Documents/Python%20notebooks)) for more information.\\\n", "You can also read [the documentation](http://poppy.local/docs) for even more information." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## API\n", "An application programming interface (API) is a computing interface which defines interactions between multiple software intermediaries.\\\n", "Show [Wikipedia](https://en.wikipedia.org/wiki/Application_programming_interface) for more informations.\n", "What interests us here is how to use a language other than Python.\n", "\n", "On the Poppy robot, you can access to the API via two server: one named \"http\", the other named \"snap\".\\\n", "These two server allow you to control your robot through some url requests\n", "\n", "**Http server**\\\n", "You can access to this server via the `8080` port (value by default).\\\n", "With this server, you can use the HTTP request of `GET` and `POST` method.\\\n", "All valid urls are visible at the root url: http://poppy.local:8080/\n", "\n", "**Snap server**\\\n", "You can access to this server via the `6969` port (value by default).\\\n", "With this server, you can use the HTTP request of only `GET` method.\\\n", "All valid urls are visible at the root url: http://poppy.local:6969/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### *Snap! Build your own Blocks* and other languages\n", "\n", "*Snap!* (formerly BYOB) is a visual, drag-and-drop programming language. It is an extended reimplementation of Scratch (a project of the Lifelong Kindergarten Group at the MIT Media Lab) that allows you to Build Your Own Blocks.\\\n", "Show [Wikipedia](https://en.wikipedia.org/wiki/Snap!_(programming_language)) and/ or [*Snap!* website](https://snap.berkeley.edu/about) for more informations. What interests us here is how *Snap!* use the robot API to control it.\n", "\n", "*Snap!* allows you to create blocks from initial blocks. These blocks correspond to functions. Among these, one of them allows you to send requests urls.\n", "On this basis, we have built a series of blocks to control the robot via the API. All these blocks have in common to end with the emission of the url request.\n", "\n", "Here, in python, we will see how to use these urls. The methodology will be the same for another language.\n", "An example applied is that of poppy-monitor ([primitive manager](http://poppy.local/monitoring/monitor)) and that of poppy-viewer ([web viewer](http://poppy.local/monitoring/visualisator)). Both are coded in JavaScript. Check the source code, respectively here: [My Documents/ Poppy Source-code/ poppy-monitor](http://poppy.local:8888/tree/My%20Documents/Poppy%20Source-code/poppy-monitor) and here: [My Documents/ Poppy Source-code/ poppy-viewer](http://poppy.local:8888/tree/My%20Documents/Poppy%20Source-code/poppy-viewer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. Code through API (snap server)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**First**\\\n", "Launch an instance of the robot with http and/or snap server.\\\n", "You can do this in two différente way:\n", "\n", "- launch API with puppet-master interface: Clicking on start API button in «[what happend?](http://poppy.local/logs)» tab.\\\n", "*By default, API auto-starting is enable (and there is no need to click on start API button), change this option in «[settings](http://poppy.local/settings)» tab.*\n", "- launch an instance of the robot directly in this notebook (show cell below)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pypot.creatures import PoppyErgoJr\n", "\n", "poppy = PoppyErgoJr(use_http=True, use_snap=True)\n", "\n", "# If you want to use another robot (humanoid, torso, ...) adapt this code\n", "#from pypot.creatures import PoppyTorso\n", "#poppy = PoppyTorso(use_http=True, use_snap=True)\n", "\n", "# If you want to use the robot with the camera unpluged, \n", "# you have to pass the argument camera='dummy\n", "#poppy = PoppyErgoJr(camera='dummy', use_http=True, use_snap=True)\n", "\n", "# If you want to use a simulated robot in the 3D web viewer aka \"poppy simu\"\n", "# you have to pass the argument simulator='poppy-simu'\n", "#poppy = PoppyErgoJr(simulator='poppy-simu', use_http=True, use_snap=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Second**\\\n", "Allow python to use url `import request` and to show HTML content inline `import HTML`" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import requests\n", "from IPython.core.display import HTML" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "All url paths available:
/
/motors/<alias>
/motor/<motor>/get/<register>
/motor/<motor>/get/list/registers
/motors/get/positions
/motors/alias
/motors/<motors>/get/<register>
/motors/set/goto/<motors_position_duration>
/motors/set/registers/<motors_register_value>
/motors/set/positions/<positions>
/motor/<motor>/set/<register>/<value>
/motor/<motor>/goto/<position>/<duration>
/snap-blocks.xml
/snap/<project>
/ip/<host>
/ip/
/reset-simulation
/primitives
/primitives/running
/primitive/<primitive>/start
/primitive/<primitive>/stop
/primitive/<primitive>/pause
/primitive/<primitive>/resume
/primitive/<primitive>/properties
/primitive/<primitive>/get/<property>
/primitive/<primitive>/set/<property>/<value>
/primitive/<primitive>/methodes
/primitive/<primitive>/call/<method>
/primitive/<primitive>/call/<method>/<args>
/primitive/MoveRecorder/<move_name>/start
/primitive/MoveRecorder/<move_name>/stop
/primitive/MoveRecorder/<move_name>/attach/<motors>
/primitive/MoveRecorder/<move_name>/get_motors
/primitive/MoveRecorder/<move_name>/start/<motors>
/primitive/MoveRecorder/<move_name>/remove
/primitive/MoveRecorder
/primitive/MovePlayer
/primitive/MovePlayer/<move_name>/start
/primitive/MovePlayer/<move_name>/start/<move_speed>
/primitive/MovePlayer/<move_name>/start/<move_speed>/backwards
/primitive/MovePlayer/<move_name>/stop
/detect/<marker>
/frame.png
/frame.png/saved_in_my_documents
/ik/<chain>/endeffector
/ik/<chain>/goto/<x>/<y>/<z>/<duration>" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Testing Snap API access\n", "valid_url_for_snap_server=''\n", "try:\n", " response = requests.get('http://poppy.local:6969/')\n", " if response.status_code==200:\n", " valid_url_for_snap_server=response.text\n", "except:\n", " print('http://poppy.local:6969/ is unreachable')\n", "\n", "HTML(valid_url_for_snap_server)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.a. Access to API to get values\n", "\n", "Each url execute an action on the robot (in the native langage) and return a value. \n", "All applications able to send a url request can use the snap API to interact with the robot (including your web browser). Be careful, the format of each url is different as well as the type of returned value.\n", "For exemple:\n", "- http://poppy.local:6969/ip/ return courant ip of the robot as a string\n", "- http://poppy.local:6969/motors/get/positions return all motors positions as a string split by `;`\n", "- http://poppy.local:6969/frame.png return the last frame take by the camera as png\n", "\n", "From there, we can create a function simplifying the emission of the url request. In *Snap!*, we would speak of blocks, and not of function, the idea is the same for another language." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/ip/\n", "192.168.1.100\n", "> call: http://poppy.local:6969/motors/get/positions\n", "[4.25, -39.15, 78.15, -17.74, 53.81, -4.84]\n" ] } ], "source": [ "def to_api(url, hostname='poppy.local', port='6969'):\n", " url_root='http://{}:{}/'.format(hostname, port)\n", " print('> call:',url_root+url)\n", " try:\n", " response = requests.get(url_root+url)\n", " if response.status_code==200:\n", " return response.text\n", " else:\n", " return 'ERROR'\n", " except:\n", " print('{} is unreachable'.format(url_root))\n", "\n", "def get_ip():\n", " return to_api('ip/')\n", "\n", "def get_all_positions():\n", " return [float(val) for val in to_api('motors/get/positions').split(';')]\n", "\n", "print(get_ip())\n", "print(get_all_positions())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.b. Get value - *with single input* -\n", "Some urls have variables. They are identified by the symbols `<` and `>` \n", "For exemple in url :\n", "- `http://poppy.local:6969/motor/`\\\n", "Replace `` by the name of the motor group" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/alias\n", "['base', 'tip']\n", "> call: http://poppy.local:6969/motors/motors\n", "['m1', 'm2', 'm3', 'm4', 'm5', 'm6']\n", "> call: http://poppy.local:6969/motors/alias\n", "> call: http://poppy.local:6969/motors/base\n", "> call: http://poppy.local:6969/motors/alias\n", "these motors: ['m1', 'm2', 'm3'], are in group of motors named: base.\n" ] } ], "source": [ "def get_motors_alias():\n", " return to_api('motors/alias').split('/')\n", "\n", "def get_motors_name(alias='motors'):\n", " return to_api('motors/'+alias).split('/')\n", "\n", "print(get_motors_alias())\n", "print(get_motors_name())\n", "\n", "print('these motors: {}, are in group of motors named: {}.'.format(\n", " get_motors_name(get_motors_alias()[0]),\n", " get_motors_alias()[0])\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- `http://poppy.local:6969/motor//get/`\\\n", "Replace `` by the name of the motor, and `` by name of register:\n", " - http://poppy.local:6969/motor/m1/get/present_position return the value of present_position for m1 motor\n", " - http://poppy.local:6969/motor/m5/get/present_speed return the value of present_speed for m5 motor\n", " - http://poppy.local:6969/motor/m3/get/led return the value of led for m3 motor" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motor/m1/get/registers\n", "all avalible register are: registers, goal_speed, compliant, safe_compliant, angle_limit, id, name, model, present_position, goal_position, present_speed, moving_speed, present_load, torque_limit, lower_limit, upper_limit, present_voltage, present_temperature, pid, led, control_mode\n", "> call: http://poppy.local:6969/motor/m1/get/present_position\n", "m1 is in position 4.25°\n", "> call: http://poppy.local:6969/motor/m1/get/present_position\n", "m1 is in position 4.25°\n", "> call: http://poppy.local:6969/motor/m1/get/compliant\n", "m1 compliant register is True\n", "> call: http://poppy.local:6969/motor/m1/get/compliant\n", "m1 compliant register is True\n", "> call: http://poppy.local:6969/motor/m1/get/led\n", "led of m1 is off\n", "> call: http://poppy.local:6969/motor/m1/get/led\n", "led of m1 is off\n" ] } ], "source": [ "def get_register(motor_id, register):\n", " url='motor/m{}/get/{}'.format(motor_id, register)\n", " return to_api(url)\n", "\n", "def get_register_list(motor_id=1):\n", " out=get_register(motor_id, 'registers')\n", " if 'ERROR' in out: return out\n", " else: return eval(out) #type == list\n", "\n", "def get_position(motor_id):\n", " out=get_register(motor_id, 'present_position')\n", " if 'ERROR' in out: return out\n", " else: return float(out)\n", " \n", "def get_compliant(motor_id):\n", " out=get_register(motor_id, 'compliant')\n", " if 'ERROR' in out: return out\n", " else: return bool(out)\n", " \n", "def get_color(motor_id):\n", " return get_register(motor_id, 'led') #type == str\n", "\n", "print('all avalible register are: {}'.format(', '.join(get_register_list())))\n", "print('m1 is in position {}°'.format(get_register(1, 'present_position')))\n", "print('m1 is in position {}°'.format(get_position(1)))\n", "print('m1 compliant register is {}'.format(get_register(1, 'compliant')))\n", "print('m1 compliant register is {}'.format(get_compliant(1)))\n", "print('led of m1 is {}'.format(get_register(1, 'led')))\n", "print('led of m1 is {}'.format(get_color(1)))\n", "#print('motor sensitivity {}'.format([get_position(2)==get_position(2) for _ in range(10)]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.b Get value - *with multiple inputs* -\n", "Some urls have multiple input. They are identified by the letter `s` For exemple in url, where motor variable have an `s`:\n", "\n", "- `http://poppy.local:6969/motors//get/`\\\n", "Replace `` by the name of one or multiple motors (split by `;`), and `` by name of register:\n", " - http://poppy.local:6969/motors/m1;m2;m3/get/present_temperature return the value of present_temperature for m1, m2 and m3 motors split by `;`\n", " - http://poppy.local:6969/motors/m1;m5/get/present_load return the value of present_load for m1 m5 motors" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/m1;m2/get/present_position\n", "m1 and m2 are respectively in position ['4.25', '-39.15']\n", "> call: http://poppy.local:6969/motors/m1;m2/get/present_position\n", "m1 and m2 are respectively in position [4.25, -39.15]\n", "> call: http://poppy.local:6969/motors/m1;m2/get/compliant\n", "m1 and m2 compliant register are respectively ['True', 'True']\n", "> call: http://poppy.local:6969/motors/m1;m2/get/compliant\n", "m1 and m2 compliant register are respectively [True, True]\n", "> call: http://poppy.local:6969/motors/m1;m2/get/led\n", "led of m1 and m2 are respectively ['off', 'off']\n", "> call: http://poppy.local:6969/motors/m1;m2/get/led\n", "led of m1 and m2 are respectively ['off', 'off']\n" ] } ], "source": [ "def get_registers(motors_id, register):\n", " if type(motors_id)!=list: return 'Type ERROR'\n", " targets=[]\n", " for motor_id in motors_id:\n", " targets.append('m'+str(motor_id))\n", " url='motors/{}/get/{}'.format(';'.join(targets), register)\n", " return to_api(url).split(';')\n", "\n", "def get_positions(motors_id):\n", " out=get_registers(motors_id, 'present_position')\n", " if 'ERROR' in out: return out\n", " else: return [float(val) for val in out]\n", "def get_compliants(motors_id):\n", " out=get_registers(motors_id, 'compliant')\n", " if 'ERROR' in out: return out\n", " else: return [bool(val) for val in out]\n", "def get_colors(motors_id):\n", " out=get_registers(motors_id, 'led')\n", " if 'ERROR' in out: return out\n", " else: return [str(val) for val in out]\n", "\n", "print('m1 and m2 are respectively in position {}'.format(get_registers([1,2], 'present_position')))\n", "print('m1 and m2 are respectively in position {}'.format(get_positions([1,2])))\n", "print('m1 and m2 compliant register are respectively {}'.format(get_registers([1,2], 'compliant')))\n", "print('m1 and m2 compliant register are respectively {}'.format(get_compliants([1,2])))\n", "print('led of m1 and m2 are respectively {}'.format(get_registers([1,2], 'led')))\n", "print('led of m1 and m2 are respectively {}'.format(get_colors([1,2])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.c. Set value - *with single input* -\n", "For these previous urls, the Snap API only returns the requested value(s). The following urls performs an action on the robot and return always 'Done!':\n", "- `http://poppy.local:6969/motor//set//`\n", " - http://poppy.local:6969/motor/m1/set/goal_position/15 motor m1 started from where it was and arrived in position 15°\n", " - http://poppy.local:6969/motor/m1/set/goal_position/-15 motor m1 started from where it was and arrived in position -15°" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motor/m1/set/compliant/0 \n", "set m1 compliant state to false: Done!\n", "> call: http://poppy.local:6969/motor/m1/set/goal_position/15 \n", "set m1 position to 15°: Done!\n", "> call: http://poppy.local:6969/motor/m1/set/compliant/1 \n", "set m1 compliant state to true: Done!\n" ] } ], "source": [ "def set_register(motor_id, register, value):\n", " url='motor/m{}/set/{}/{} '.format(motor_id, register, value)\n", " return to_api(url)\n", "\n", "def set_position(motor_id, position):\n", " return set_register(motor_id, 'goal_position', position)\n", "def set_compliant(motor_id, state):\n", " return set_register(motor_id, 'compliant', state)\n", "def set_color(motor_id, color):\n", " return set_register(motor_id, 'led', color)\n", "\n", "#note: the motor must be in the non-compliant state to be control it in position\n", "print('set m1 compliant state to false: {}'.format(set_compliant(1,0)))\n", "print('set m1 position to 15°: {}'.format(set_position(1,15)))\n", "print('set m1 compliant state to true: {}'.format(set_compliant(1,1)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.c. Set value - *with multiple inputs* -\n", "- `http://poppy.local:6969/motors/set/registers/`\\\n", "Replace `` by the name of motors, name of register, value to give to the register (split by `:` like this: `m1:led:pink`) then iterate for each moteurs (split by `;` like this: `m1:led:pink;m2:led:pink`)\n", " - http://poppy.local:6969/motors/set/registers/m1:present_position:15;m1:led:green;m6:led:yellow \\\n", " motor m1 started from where it was and arrived in position 15° ; motor m1 lit green ; motor m6 lit yellow" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:1;m2:compliant:1\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:yellow;m1:goal_position:45;m2:goal_position:25;m3:led:blue\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:goal_position:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:0;m2:compliant:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:green;m2:led:green;m3:led:green\n", "Done!\n" ] } ], "source": [ "def valid_registers_input(motors_id, registers, values):\n", " if type(motors_id)!=list or type(registers)!=list or type(values)!=list:\n", " return 'Type ERROR'\n", " if len(motors_id) != len(registers) or len(motors_id) != len(values):\n", " return 'Size ERROR'\n", " return motors_id, registers, values\n", "\n", "def set_registers(motors_id, registers, values):\n", " registers_input = valid_registers_input(motors_id, registers, values)\n", " if 'ERROR' in registers_input:\n", " return registers_input\n", " else:\n", " motors_id, registers, values = registers_input\n", " cmd=[]\n", " for i, motor_id in enumerate(motors_id):\n", " cmd.append('m{}:{}:{}'.format(motor_id, registers[i], values[i]))\n", " cmd=';'.join(cmd)\n", " url='motors/set/registers/'+cmd\n", " return to_api(url)\n", "\n", "def set_positions(motors_id, positions):\n", " return set_registers(motors_id, ['goal_position']*len(motors_id), positions)\n", "def set_compliants(motors_id, states):\n", " return set_registers(motors_id, ['compliant']*len(motors_id), states)\n", "def set_colors(motors_id, colors):\n", " return set_registers(motors_id, ['led']*len(motors_id), colors)\n", "\n", "print(set_compliants([1,2],[1,1]))\n", "print(set_registers([1,1,2,3],['led', 'goal_position', 'goal_position', 'led'],['yellow', 45, 25, 'blue']))\n", "print(set_positions([1],[0]))\n", "print(set_compliants([1,2],[0,0]))\n", "print(set_colors([1,2,3],['green']*3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.d. Add checking inputs and use your function" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/motors\n", "> call: http://poppy.local:6969/motor/m1/get/registers\n" ] } ], "source": [ "'''\n", "prepare input for set_register function:\n", " accept:\n", " python list of values,\n", " str list of values (split by space),\n", " int, float, bool\n", " return: python list of str values\n", "'''\n", "def set_type(value):\n", " if type(value)==str:\n", " value=value.split(' ')\n", " elif type(value) in (float, int, bool):\n", " value=[str(value)]\n", " elif type(value)!=list:\n", " return 'Type ERROR'\n", " else:\n", " for i, v in enumerate(value): value[i]=str(v)\n", " return value\n", "'''\n", "re-write valid_registers_input function\n", "valid_registers_input is use by set_registers function\n", "add set_type function\n", "add check size, accept one value for default for each motor\n", "return couple of tree values, each is a list of str values\n", "'''\n", "number_of_all_motors=len(get_motors_name())\n", "all_valid_register=get_register_list()\n", "\n", "def valid_registers_input(motors_id, registers, values):\n", "\n", " motors_id, registers, values = set_type(motors_id), set_type(registers), set_type(values)\n", " if 'ERROR' in (motors_id or registers or values):\n", " return 'Type ERROR'\n", "\n", " if len(registers) == 1:\n", " registers=registers*len(motors_id)\n", " elif len(motors_id) != len(registers):\n", " return 'Size ERROR'\n", "\n", " if len(values) == 1:\n", " values=values*len(motors_id)\n", " elif len(motors_id) != len(values):\n", " return 'Size ERROR'\n", " \n", " number_of_motors=number_of_all_motors\n", " valid_register=all_valid_register\n", " #assume that value of values variable are check before\n", " for i, motor_id in enumerate(motors_id):\n", " if int(motor_id) <1 or int(motor_id) > number_of_motors or registers[i] not in valid_register:\n", " return 'Value ERROR'\n", " \n", " return motors_id, registers, values\n", "'''\n", "No need to re-write set_registers function\n", "but get_registers function need to:\n", "add set_type function to avoid error\n", "add check values\n", "'''\n", "def get_registers(motors_id, register):\n", " motors_id=set_type(motors_id)\n", " if 'ERROR' in motors_id: return motors_id\n", " \n", " valid_register=all_valid_register\n", " if register not in valid_register: return 'Value ERROR'\n", " \n", " number_of_motors=number_of_all_motors\n", " targets=[]\n", " for i, motor_id in enumerate(motors_id):\n", " if int(motor_id) <1 or int(motor_id) > number_of_motors:\n", " return 'Value ERROR'\n", " else:\n", " targets.append('m'+motor_id)\n", " \n", " url='motors/{}/get/{}'.format(';'.join(targets), register)\n", " return to_api(url).split(';')" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "'''\n", "re-write function\n", "add check value\n", "'''\n", "def set_positions(motors_id, positions):\n", " positions=set_type(positions)\n", " if 'ERROR' in positions: return positions\n", " for position in positions:\n", " if float(position) < -90 or float(position) > 90:\n", " return 'Value ERROR'\n", " return set_registers(motors_id, 'goal_position', positions)\n", "\n", "def set_compliants(motors_id, states):\n", " states=set_type(states)\n", " if 'ERROR' in states: return states\n", " for state in states:\n", " if state == 'True': state='1'\n", " elif state == 'False': state='0'\n", " elif state not in ('0', '1'): return 'Value ERROR'\n", " return set_registers(motors_id, 'compliant', states)\n", "\n", "def set_colors(motors_id, colors):\n", " colors=set_type(colors)\n", " if 'ERROR' in colors: return colors\n", " for color in colors:\n", " if color not in ['red','green','pink','blue','yellow','off']:\n", " return 'Value ERROR'\n", " return set_registers(motors_id, 'led', colors)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:0;m2:compliant:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:yellow;m1:goal_position:45;m2:goal_position:25;m3:led:blue\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:goal_position:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:1;m2:compliant:1\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:green;m2:led:green;m3:led:green\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:0;m2:compliant:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:yellow;m1:goal_position:45;m2:goal_position:25;m3:led:blue\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:goal_position:0\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:1;m2:compliant:1\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:green;m2:led:green;m3:led:green\n", "Done!\n" ] } ], "source": [ "#before syntaxe, work always + check values\n", "print(set_compliants([1,2],[0,0]))\n", "print(set_registers([1,1,2,3],['led', 'goal_position', 'goal_position', 'led'],['yellow', 45, 25, 'blue']))\n", "print(set_positions([1],[0]))\n", "print(set_compliants([1,2],[1,1]))\n", "print(set_colors([1,2,3],['green']*3))\n", "# + more flxible syntaxe \n", "print(set_compliants('1 2',0))\n", "print(set_registers('1 1 2 3','led goal_position goal_position led','yellow 45 25 blue'))\n", "print(set_positions(1,0))\n", "print(set_compliants([1,2],1))\n", "print(set_colors('1 2 3','green'))" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/set/registers/m1:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m2:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m2/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m2:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m2/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m3:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m3/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m3:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m3/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m4:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m4/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m4:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m4/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m5:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m5/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m5:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m5/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m6:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m6/get/led\n", "['pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m6/get/led\n", "['off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:red;m2:led:red;m3:led:red;m4:led:red;m5:led:red;m6:led:red\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['red', 'red', 'red', 'red', 'red', 'red']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:green;m2:led:green;m3:led:green;m4:led:green;m5:led:green;m6:led:green\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['green', 'green', 'green', 'green', 'green', 'green']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:pink;m2:led:pink;m3:led:pink;m4:led:pink;m5:led:pink;m6:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['pink', 'pink', 'pink', 'pink', 'pink', 'pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:blue;m2:led:blue;m3:led:blue;m4:led:blue;m5:led:blue;m6:led:blue\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['blue', 'blue', 'blue', 'blue', 'blue', 'blue']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:yellow;m2:led:yellow;m3:led:yellow;m4:led:yellow;m5:led:yellow;m6:led:yellow\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['yellow', 'yellow', 'yellow', 'yellow', 'yellow', 'yellow']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:red;m2:led:red;m3:led:red;m4:led:red;m5:led:red;m6:led:red\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['red', 'red', 'red', 'red', 'red', 'red']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:green;m2:led:green;m3:led:green;m4:led:green;m5:led:green;m6:led:green\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['green', 'green', 'green', 'green', 'green', 'green']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:pink;m2:led:pink;m3:led:pink;m4:led:pink;m5:led:pink;m6:led:pink\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['pink', 'pink', 'pink', 'pink', 'pink', 'pink']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:blue;m2:led:blue;m3:led:blue;m4:led:blue;m5:led:blue;m6:led:blue\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['blue', 'blue', 'blue', 'blue', 'blue', 'blue']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:yellow;m2:led:yellow;m3:led:yellow;m4:led:yellow;m5:led:yellow;m6:led:yellow\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['yellow', 'yellow', 'yellow', 'yellow', 'yellow', 'yellow']\n", "> call: http://poppy.local:6969/motors/set/registers/m1:led:off;m2:led:off;m3:led:off;m4:led:off;m5:led:off;m6:led:off\n", "Done!\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/led\n", "['off', 'off', 'off', 'off', 'off', 'off']\n" ] } ], "source": [ "#use your function\n", "import time\n", "\n", "for i in range(1,7):\n", " print(set_colors(i,'pink'))\n", " print(get_colors(i))\n", " time.sleep(0.5)\n", " print(set_colors(i,'off'))\n", " print(get_colors(i))\n", " #time.sleep(0.5)\n", "\n", "for _ in range(2):\n", " for c in ['red','green','pink','blue','yellow']:\n", " print(set_colors('1 2 3 4 5 6', c))\n", " print(get_colors('1 2 3 4 5 6'))\n", " time.sleep(0.5)\n", " print(set_colors('1 2 3 4 5 6','off'))\n", " print(get_colors('1 2 3 4 5 6'))\n", " time.sleep(0.5)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:0;m2:compliant:0;m3:compliant:0;m4:compliant:0;m5:compliant:0;m6:compliant:0\n", "> call: http://poppy.local:6969/motors/set/registers/m1:goal_position:0;m2:goal_position:10;m3:goal_position:-15;m4:goal_position:10;m5:goal_position:0;m6:goal_position:0\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/present_position\n", "motors in position: [0.73, 41.5, 30.06, -13.05, 55.57, -4.84]\n", "> call: http://poppy.local:6969/motors/set/registers/m1:goal_position:-10;m2:goal_position:-10;m3:goal_position:-10;m4:goal_position:-10;m5:goal_position:-10;m6:goal_position:-10\n", "> call: http://poppy.local:6969/motors/m1;m2;m3;m4;m5;m6/get/present_position\n", "motors in position: [0.73, 41.5, 30.06, -13.05, 55.57, -4.84]\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:1;m2:compliant:1;m3:compliant:1;m4:compliant:1;m5:compliant:1;m6:compliant:1\n", "> call: http://poppy.local:6969/motors/m1/get/present_position\n", "m1 in position [-10.7]°\n", "> call: http://poppy.local:6969/motors/m2/get/present_position\n", "m2 in position [-11.88]°\n", "> call: http://poppy.local:6969/motors/m3/get/present_position\n", "m3 in position [-10.7]°\n", "> call: http://poppy.local:6969/motors/m4/get/present_position\n", "m4 in position [-10.7]°\n", "> call: http://poppy.local:6969/motors/m5/get/present_position\n", "m5 in position [-8.36]°\n", "> call: http://poppy.local:6969/motors/m6/get/present_position\n", "m6 in position [-5.43]°\n" ] } ], "source": [ "set_compliants('1 2 3 4 5 6', 0)\n", "\n", "set_positions('1 2 3 4 5 6', '0 10 -15 10 0 0')\n", "time.sleep(1.5)\n", "print('motors in position: ', get_positions([1, 2, 3, 4, 5, 6]))\n", "\n", "set_positions('1 2 3 4 5 6', -10)\n", "time.sleep(.5)\n", "print('motors in position: ', get_positions('1 2 3 4 5 6'))\n", "\n", "set_compliants('1 2 3 4 5 6', 1)\n", "\n", "time.sleep(.5)\n", "for i in range(1,7): print('m{} in position {}°'.format(i, get_positions(i)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Another URL**\n", "- `http://poppy.local:6969/motors/set/goto/`\n", " - http://poppy.local:6969/motors/set/goto/m1:0:1;m2:15:2;m6:45:1.5 \\\n", "motor m1 started from where it was and arrived in position 0° in 1 seconde ;\\\n", "motor m2 started from where it was and arrived in position 15° in 2 secondes ;\\\n", "motor m6 started from where it was and arrived in position 45° in 1.5 secondes" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> call: http://poppy.local:6969/motors/motors\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:False;m2:compliant:False;m3:compliant:False;m4:compliant:False;m5:compliant:False;m6:compliant:False\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/goto/m1:10:1;m2:10:1;m3:10:1;m4:10:1;m5:10:1;m6:10:1\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/goto/m1:-10:2;m2:-10:2;m3:-10:2;m4:-10:2;m5:-10:2;m6:-10:2\n", "Done!\n", "> call: http://poppy.local:6969/motors/set/registers/m1:compliant:True;m2:compliant:True;m3:compliant:True;m4:compliant:True;m5:compliant:True;m6:compliant:True\n", "Done!\n" ] } ], "source": [ "number_of_all_motors=len(get_motors_name())\n", "\n", "def valid_goto_input(motors_id, positions, durations):\n", "\n", " motors_id, positions, durations = set_type(motors_id), set_type(positions), set_type(durations)\n", " if 'ERROR' in (motors_id or positions or durations):\n", " return 'Type ERROR'\n", "\n", " if len(positions) == 1:\n", " positions=positions*len(motors_id)\n", " elif len(motors_id) != len(positions):\n", " return 'Size ERROR'\n", "\n", " if len(durations) == 1:\n", " durations=durations*len(motors_id)\n", " elif len(durations) != len(durations):\n", " return 'Size ERROR'\n", " \n", " number_of_motors=number_of_all_motors\n", " for i, motor_id in enumerate(motors_id):\n", " if int(motor_id) <1 or int(motor_id) > number_of_motors:\n", " return 'Value ERROR'\n", " if float(positions[i]) < -90 or float(positions[i]) > 90:\n", " return 'Value ERROR'\n", " if float(durations[i]) < 0:\n", " return 'Value ERROR'\n", " \n", " return motors_id, positions, durations\n", "\n", "def set_goto(motors_id, positions, durations):\n", " goto_input = valid_goto_input(motors_id, positions, durations)\n", " if 'ERROR' in goto_input:\n", " return goto_input\n", " else:\n", " motors_id, positions, durations = goto_input\n", " cmd=[]\n", " for i, motor_id in enumerate(motors_id):\n", " cmd.append('m{}:{}:{}'.format(motor_id, positions[i], durations[i]))\n", " cmd=';'.join(cmd)\n", " url='motors/set/goto/'+cmd\n", "\n", " return to_api(url)\n", "\n", "print(set_compliants('1 2 3 4 5 6', False))\n", "print(set_goto('1 2 3 4 5 6', 10, 1))\n", "time.sleep(1.5)\n", "print(set_goto('1 2 3 4 5 6', -10, 2))\n", "time.sleep(2.5)\n", "print(set_compliants('1 2 3 4 5 6', True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Recap: function define here:\n", "to_api(url)\n", "\n", "get_ip() \\\n", "get_all_positions() \\\n", "get_motors_alias() \\\n", "get_motors_name()\n", "\n", "get_register(motor_id, register) \\\n", "get_register_list() \\\n", "get_position(motor_id) \\\n", "get_compliant(motor_id) \\\n", "get_color(motor_id)\n", "\n", "get_registers(motors_id, register) \\\n", "get_positions(motors_id) \\\n", "get_compliants(motors_id) \\\n", "get_colors(motors_id)\n", "\n", "set_register(motor_id, register, value) \\\n", "set_position(motor_id, value) \\\n", "set_compliant(motor_id, value) \\\n", "set_color(motor_id, value)\n", "\n", "set_type(value)\n", "\n", "valid_registers_input(motors_id, registers, values) \\\n", "set_registers(motors_id, registers, values) \\\n", "set_positions(motors_id values) \\\n", "set_compliants(motors_id, values) \\\n", "set_colors(motors_id, values)\n", "\n", "valid_goto_input(motors_id, positions, durations) \\\n", "set_goto(motors_id, positions, durations)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2*. Code through API (http server)\n", "## 2*.a. Access to API" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/\n" ] }, { "data": { "text/html": [ "All url paths available:

Get method url:
/
/robot.json
/motor/alias/list.json
/motor/<alias>/list.json
/sensor/list.json
/motor/<motor_name>/register/list.json
/sensor/<motor_name>/register/list.json
/motor/<motor_name>/register/<register_name>/list.json
/sensor/<motor_name>/register/<register_name>/list.json
/motor/<motor_name>/register/<register_name>
/sensor/<motor_name>/register/<register_name>
/primitive/list.json
/primitive/running/list.json
/primitive/<primitive_name>/start.json
/primitive/<primitive_name>/stop.json
/primitive/<primitive_name>/pause.json
/primitive/<primitive_name>/resume.json
/primitive/<primitive_name>/property/list.json
/primitive/<primitive_name>/property/<prop>
/primitive/<primitive_name>/method/list.json
/motors/register/<register_name>

Post method url:
/motor/<motor_name>/register/<register_name>/value.json
/sensor/<motor_name>/register/<register_name>/value.json
/primitive/<primitive_name>/property/<prop>/value.json
/primitive/<primitive_name>/method/<method_name>/args.json
" ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def get_api(url, hostname='poppy.local', port='8080'):\n", " url_root='http://{}:{}/'.format(hostname, port)\n", " print('> get:',url_root+url)\n", " try:\n", " response = requests.get(url_root+url)\n", " if response.status_code==200:\n", " return response\n", " else:\n", " return 'ERROR {}!'.format(response.status_code)\n", " except:\n", " print('{} is unreachable'.format(url_root))\n", "\n", "def post_api(url, value, hostname='poppy.local', port='8080'):\n", " url_root='http://{}:{}/'.format(hostname, port)\n", " print('> post: url=', url_root+url, ' ; value=', value)\n", " try:\n", " response = requests.post(url_root+url, json=value)\n", " if response.status_code==200:\n", " return 'Done!'\n", " else:\n", " return 'ERROR {}!'.format(response.status_code)\n", " except:\n", " print('{} is unreachable'.format(url_root))\n", " \n", "HTML(get_api('').text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2*.b. Get request" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/motor/motors/list.json\n", "{'motors': ['m1', 'm2', 'm3', 'm4', 'm5', 'm6']}\n", "> get: http://poppy.local:8080/motor/m1/register/list.json\n", "{'registers': ['registers', 'goal_speed', 'compliant', 'safe_compliant', 'angle_limit', 'id', 'name', 'model', 'present_position', 'goal_position', 'present_speed', 'moving_speed', 'present_load', 'torque_limit', 'lower_limit', 'upper_limit', 'present_voltage', 'present_temperature', 'pid', 'led', 'control_mode']}\n", "> get: http://poppy.local:8080/motor/m1/register/name\n", "m1\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-10.7\n", "> get: http://poppy.local:8080/motor/m1/register/compliant\n", "True\n", "> get: http://poppy.local:8080/motor/m1/register/angle_limit\n", "[-150.0, 150.0]\n", "> get: http://poppy.local:8080/motor/m1/register/led\n", "off\n" ] } ], "source": [ "def get_motor_list(alias='motors'):\n", " url='motor/{}/list.json'.format(alias)\n", " return get_api(url).json()\n", "def get_motor_register_list(motor_id=1):\n", " url = 'motor/m{}/register/list.json'.format(motor_id)\n", " return get_api(url).json()\n", "def get_motor_register_value(motor_id, register):\n", " url = 'motor/m{}/register/{}'.format(motor_id, register)\n", " return get_api(url).json()[register]\n", "\n", "print(get_motor_list())\n", "print(get_motor_register_list())\n", "print(get_motor_register_value(1, 'name'))\n", "print(get_motor_register_value(1, 'present_position'))\n", "print(get_motor_register_value(1, 'compliant'))\n", "print(get_motor_register_value(1, 'angle_limit'))\n", "print(get_motor_register_value(1, 'led'))" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/sensor/list.json\n", "{'sensors': ['camera', 'marker_detector']}\n", "> get: http://poppy.local:8080/sensor/camera/register/list.json\n", "{'registers': ['frame', 'resolution', 'fps', 'index']}\n", "> get: http://poppy.local:8080/sensor/camera/register/fps\n", "20.0\n", "> get: http://poppy.local:8080/sensor/camera/register/resolution\n", "[640, 480]\n", "> get: http://poppy.local:8080/sensor/camera/register/frame\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "IOPub data rate exceeded.\n", "The notebook server will temporarily stop sending output\n", "to the client in order to avoid crashing it.\n", "To change this limit, set the config variable\n", "`--NotebookApp.iopub_data_rate_limit`.\n", "\n", "Current values:\n", "NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n", "NotebookApp.rate_limit_window=3.0 (secs)\n", "\n" ] } ], "source": [ "def get_sensor_list():\n", " return get_api('sensor/list.json').json()\n", "def get_sensor_register_list(sensor):\n", " url = 'sensor/{}/register/list.json'.format(sensor)\n", " return get_api(url).json()\n", "def get_sensor_register_value(sensor, register):\n", " url = 'sensor/{}/register/{}'.format(sensor, register)\n", " return get_api(url).json()[register]\n", "\n", "print(get_sensor_list())\n", "print(get_sensor_register_list('camera'))\n", "print(get_sensor_register_value('camera', 'fps'))\n", "print(get_sensor_register_value('camera', 'resolution'))\n", "print(get_sensor_register_value('camera', 'frame'))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/primitive/list.json\n", "{'primitives': ['safe_power_up', 'dance', 'base_posture', 'rest_posture', 'curious_posture', 'tetris_posture', 'tracking_feedback']}\n", "> get: http://poppy.local:8080/primitive/list.json\n", "> get: http://poppy.local:8080/primitive/safe_power_up/property/list.json\n", "{'property': []}\n", "> get: http://poppy.local:8080/primitive/list.json\n", "> get: http://poppy.local:8080/primitive/safe_power_up/method/list.json\n", "{'methods': ['start', 'stop', 'pause', 'resume']}\n" ] } ], "source": [ "def get_primitive_list():\n", " return get_api('primitive/list.json').json()\n", "def get_primitive_property(primitive_name):\n", " url='primitive/{}/property/list.json'.format(primitive_name)\n", " return get_api(url).json()\n", "def get_primitive_method(primitive_name):\n", " url='primitive/{}/method/list.json'.format(primitive_name)\n", " return get_api(url).json()\n", "\n", "print(get_primitive_list())\n", "print(get_primitive_property(get_primitive_list()['primitives'][0]))\n", "print(get_primitive_method(get_primitive_list()['primitives'][0]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2*.c. Post request" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> post: url= http://poppy.local:8080/motor/m1/register/compliant/value.json ; value= False\n", "Done!\n", "> get: http://poppy.local:8080/motor/m1/register/compliant\n", "False\n", "> post: url= http://poppy.local:8080/motor/m1/register/goal_speed/value.json ; value= 25\n", "Done!\n", "> post: url= http://poppy.local:8080/motor/m1/register/goal_position/value.json ; value= 25\n", "Done!\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-10.7\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-6.6\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-2.79\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "1.32\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "5.13\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "8.94\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "13.05\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "16.57\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "21.26\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "25.07\n", "> post: url= http://poppy.local:8080/motor/m1/register/goal_position/value.json ; value= 0\n", "Done!\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "25.37\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "21.85\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "18.04\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "13.64\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "9.82\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "5.13\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "0.15\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-0.15\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-0.15\n", "> get: http://poppy.local:8080/motor/m1/register/present_position\n", "-0.15\n", "> post: url= http://poppy.local:8080/motor/m1/register/comlpiant/value.json ; value= True\n", "Done!\n" ] } ], "source": [ "def post_motor_value(motor, register, value):\n", " url = 'motor/m{}/register/{}/value.json'.format(motor, register)\n", " return post_api(url, value)\n", "\n", "import time\n", "print(post_motor_value(1, 'compliant', False))\n", "print(get_motor_register_value(1, 'compliant'))\n", "print(post_motor_value(1, 'goal_speed', 25))\n", "print(post_motor_value(1, 'goal_position', 25))\n", "for _ in range(10):\n", " print(get_motor_register_value(1, 'present_position'))\n", " time.sleep(0.1)\n", "print(post_motor_value(1, 'goal_position', 0))\n", "for _ in range(10):\n", " print(get_motor_register_value(1, 'present_position'))\n", " time.sleep(0.1)\n", "print(post_motor_value(1, 'comlpiant', True))" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/sensor/list.json\n", "{'sensors': ['camera', 'marker_detector']}\n", "> get: http://poppy.local:8080/sensor/camera/register/list.json\n", "{'registers': ['frame', 'resolution', 'fps', 'index']}\n", "> get: http://poppy.local:8080/sensor/camera/register/fps\n", "20.0\n", "> post: url= http://poppy.local:8080/sensor/caemra/register/fps/value.json ; value= 15.0\n", "ERROR 500!\n", "> get: http://poppy.local:8080/sensor/camera/register/fps\n", "20.0\n" ] } ], "source": [ "def post_sensor_value(sensor, register, value):\n", " url = 'sensor/{}/register/{}/value.json'.format(sensor, register)\n", " return post_api(url, value)\n", "\n", "print(get_sensor_list())\n", "print(get_sensor_register_list('camera'))\n", "print(get_sensor_register_value('camera', 'fps'))\n", "print(post_sensor_value('caemra', 'fps', 15.0))\n", "print(get_sensor_register_value('camera', 'fps'))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/primitive/list.json\n", "{'primitives': ['safe_power_up', 'dance', 'base_posture', 'rest_posture', 'curious_posture', 'tetris_posture', 'tracking_feedback']}\n", "> get: http://poppy.local:8080/primitive/rest_posture/property/list.json\n", "{'property': []}\n", "> get: http://poppy.local:8080/primitive/rest_posture/method/list.json\n", "{'methods': ['start', 'stop', 'pause', 'resume']}\n", "> post: url= http://poppy.local:8080/primitive/rest_posture/method/start/args.json ; value= start\n", "ERROR 500!\n", "> post: url= http://poppy.local:8080/primitive/rest_posture/method/stop/args.json ; value= stop\n", "ERROR 500!\n" ] } ], "source": [ "def post_primitive_property(primitive, prop, value):\n", " url = 'primitive/{}/property/{}/value.json'.format(primitive, prop)\n", " return post_api(url, value)\n", "\n", "def post_primitive_method(primitive, meth, value):\n", " url = 'primitive/{}/method/{}/args.json'.format(primitive, meth)\n", " return post_api(url, value)\n", "\n", "print(get_primitive_list())\n", "print(get_primitive_property('rest_posture'))\n", "print(get_primitive_method('rest_posture'))\n", "print(post_primitive_method('rest_posture', 'start', 'start'))\n", "time.sleep(2)\n", "print(post_primitive_method('rest_posture', 'stop', 'stop'))" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> get: http://poppy.local:8080/primitive/list.json\n", "{'primitives': ['safe_power_up', 'dance', 'base_posture', 'rest_posture', 'curious_posture', 'tetris_posture', 'tracking_feedback']}\n", "> get: http://poppy.local:8080/primitive/rest_posture/start.json\n", "start of rest_posture Done!\n", "> get: http://poppy.local:8080/primitive/rest_posture/stop.json\n", "stop of rest_posture Done!\n" ] } ], "source": [ "def set_primitive_action(primitive, action):\n", " if action not in ['start','stop','pause','resume']:\n", " return 'Value ERROR'\n", " url = 'primitive/{}/{}.json'.format(primitive, action)\n", " if get_api(url).status_code==200:\n", " return '{} of {} Done!'.format(action, primitive)\n", " else:\n", " return '{} of {} Fail! Error {}'.format(action, primitive, get_api(url).status_code)\n", "\n", "print(get_primitive_list())\n", "print(set_primitive_action('rest_posture', 'start'))\n", "time.sleep(2)\n", "print(set_primitive_action('rest_posture', 'stop'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. Add new entries in API\n", "\n", "Add an specific url, in the good file, with the good syntaxe, and do everything python can be do.\n", "Both server have access to the RESTRobot class to munipulate the robot. If you need, add an entries here as well \n", "[My Documents/ Poppy Source-code/ pypotserver/ rest.py](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/pypot/server/rest.py)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.1 snap server\n", "\n", "Snap server are define here: [My Documents/ Poppy Source-code/ pypotserver/ snap.py](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/pypot/server/snap.py)\n", "\n", "Standard entry is written like this:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "#~/pypot/server/snap.py\n", "class SnapRobotServer(AbstractServer):\n", " def __init__(self, robot, host='0.0.0.0', port='6969', quiet=True):\n", " ...\n", " @self.app.get('/specific/url/with//and/')\n", " def what_will_be_done(var_1, var_2):\n", " rr.what_the_robot_do(var_1)\n", " return 'what you want'\n", "#wherre rr is the restfuul_robot intitiate by RESTRobot class\n", "\n", "#An exemple, ligne 202:\n", " @self.app.get('/motors//get/')\n", " def get_motors_registers(motors, register):\n", " motors = motors.split(';')\n", " return ';'.join(str(rr.get_register_value(m, register)) for m in motors)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.2 http server\n", "\n", "Http server are define here: [My Documents/ Poppy Source-code/ pypotserver/ httpserver.py](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/pypot/server/httpserver.py)\n", "\n", "Standard entry is written like this:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "#add specific url in url_path ligne 234 and write associate function\n", "\n", "(r'/specific/url/with/(?P[a-zA-Z0-9_]+)/and/(?P[a-zA-Z0-9_]+)/value\\.json', what_will_be_done_1),\n", "class what_will_be_done_when_post_here(PoppyRequestHandler):\n", " def post(self, var_1, var_2):\n", " data = json.loads(self.request.body.decode())\n", " self.restful_robot.what_the_robot_do(var_1, var_2, data)\n", " self.write_json({})\n", "\n", "(r'/primitive/list\\.json', what_will_be_done_2),\n", "class what_will_be_done_when_get_here(PoppyRequestHandler):\n", " def get(self):\n", " self.write_json({\n", " 'key': self.restful_robot.value()\n", " })\n", "#where self.restful_robot is the restfull_robot intitiate by RESTRobot class\n", "\n", "#An exemple, ligne 86, get methode:\n", "(r'/motor/(?P[a-zA-Z0-9_]+)/?list\\.json', MotorsListHandler)\n", "class MotorsListHandler(PoppyRequestHandler):\n", " def get(self, alias='motors'):\n", " self.write_json({\n", " alias: self.restful_robot.get_motors_list(alias)\n", " })\n", "#An exemple, ligne 121, post methode:\n", "(r'/motor/(?P[a-zA-Z0-9_]+)/register/(?P[a-zA-Z0-9_]+)/value\\.json', UpdateMotorRegisterHandler)\n", "class UpdateMotorRegisterHandler(PoppyRequestHandler):\n", " def post(self, motor_name, register_name):\n", " data = json.loads(self.request.body.decode())\n", " self.restful_robot.set_motor_register_value(motor_name, register_name, data)\n", " self.write_json({}) \n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4. Add tab in puppet-master interface\n", "\n", "In [My Documents/ Poppy Source-code/ puppet-master/ templates/ programming.html](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/puppet-master/templates/programming.html) add a tab:\n", "\n", "Standard entry is written like this:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", " \n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where svg icon are define in [My Documents/ Poppy Source-code/ puppet-master/ templates/ defs-svg.html](http://poppy.local:8888/edit/My%20Documents/Poppy%20Source-code/puppet-master/templates/defs-svg.html)\n", "\n", "You can also add a simple png file in folder: [My Documents/ Poppy Source-code/ puppet-master/ static/ img](http://poppy.local:8888/tree/My%20Documents/Poppy%20Source-code/puppet-master/static/img) and use this Standard entry:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", " \n", "```" ] } ], "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.7.3" } }, "nbformat": 4, "nbformat_minor": 1 }