{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How-To: Control a PoppyCreature using the  visual programming language [Snap!](http://snap.berkeley.edu) *(a variant of Scratch)*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![alt text](image/snap-header.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook will describe how:\n",
    "* you can **connect the visual programming language [Snap!](http://snap.berkeley.edu)** to a Poppy Creature \n",
    "* and how you can **control it in real time** using poppy's custom blocks."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Snap!](http://snap.berkeley.edu/) is a *\"very powerful visual, drag-and-drop programming language. It is an extended reimplementation of [Scratch](http://scratch.mit.edu) (a project of the Lifelong Kindergarten Group at the MIT Media Lab) that allows you to Build Your Own Blocks\"*. It is an extremely efficient tool to learn how to program for kids or even college students and also a powerful prototyping method for artists."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Snap!](http://snap.berkeley.edu/) is open-source and it is entirelly written in javascript, you only need a browser connected to the Poppy Creature webserver. **No installation is required on your computer!**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note: We assume in this tutorial that you are familiar with the basic of Snap! or Scratch. If it's not the case you can find a lot of documentation online. We especially recommand the very good [Snap! reference manual](http://snap.berkeley.edu/SnapManual.pdf).*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An example of the [Snap!](http://snap.berkeley.edu/) interface:\n",
    "\n",
    "![alt text](image/snap.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Comments, issues, improvements and updates can be sent directly on the dedicated section of the [github issue tracker](https://github.com/poppy-project/pypot/labels/Notebooks).**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### What's needed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**First, if you do not know how to run an IPython Notebook please refer to [our readme](https://github.com/poppy-project/pypot/blob/master/samples/notebooks/readme.md#notebooks-everywhere).**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To follow this tutorial you will need:\n",
    "\n",
    "* a poppy creature (real or simulated)\n",
    "* the python [pypot](https://github.com/poppy-project/pypot) library version >= 2.1 (only if you are working with a simulated creature, otherwise you can [directly connect to your poppy creature](https://github.com/poppy-project/pypot/blob/master/samples/notebooks/readme.md#connecting-to-a-remote-notebook))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note: for this notebook we will use a simulated poppy humanoid in V-REP (see [this v-rep notebook](http://nbviewer.ipython.org/github/poppy-project/pypot/blob/master/samples/notebooks/Controlling%20a%20Poppy%20humanoid%20in%20V-REP%20using%20pypot.ipynb) for details on how they can be installed and connected) but you can use any other creature (e.g. a real poppy ergo for instance). Only the configuration of the robot host will change (see details below).*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Please refer to [the install section](https://github.com/poppy-project/pypot#installation) if you don't know how to install these libraries or how to connect to your Poppy Creature.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Connect [Snap!](http://snap.berkeley.edu) to a Poppy Creature"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before being able to control a simulated Poppy Creature with [Snap!](http://snap.berkeley.edu) blocks a few steps are required:\n",
    "* First, we need to connect to a Poppy Creature (real or simulated).\n",
    "* Then, we need to tell [pypot](https://github.com/poppy-project/pypot) that we wan't to control it through Snap!.\n",
    "* Finally, connect to [Snap!](http://snap.berkeley.edu) web interface (locally or online) and import the Poppy specific blocks."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note: If you want to control a real Poppy Creature this is even simpler. As Poppy Creatures come with an embedded board with everything configured, you only need to connect to their webserver. Assuming that you are working with a Poppy-ErgoJr and that you are on the same network that your creature, you only have to connect to http://poppy-ergojr:8080/snap (see [here](https://github.com/poppy-project/pypot#pypot-a-python-lib-for-dynamixel-motors-control) for details).*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a simulated Poppy Creature and connect it to [Snap!](http://poppy-project.github.io/pypot/pypot.server.html#pypot.server.snap.SnapRobotServer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So, first we will create and launch the Robot Snap Server. In more details, we will:\n",
    "* instantiate a [Poppy Creature](https://github.com/poppy-project/Poppy-Creature)\n",
    "* connect it the [SnapRobotServer](http://poppy-project.github.io/pypot/pypot.server.html#pypot.server.snap.SnapRobotServer) and run it"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We create a [Poppy Humanoid](https://github.com/poppy-project/Poppy-Humanoid) using the approach discribed in [here](http://nbviewer.ipython.org/github/poppy-project/pypot/blob/master/samples/notebooks/Controlling%20a%20Poppy%20humanoid%20in%20V-REP%20using%20pypot.ipynb) and specifies that we want to use [Snap!](http://snap.berkeley.edu) to control it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pypot.creatures import PoppyHumanoid\n",
    "\n",
    "poppy = PoppyHumanoid(simulator='vrep', use_snap=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note for advanced users: setting the use_snap arg to True basically creates a webserver which allows [Snap!](http://snap.berkeley.edu) to get/post values from/to a Poppy Creature through [pypot REST API](https://github.com/poppy-project/pypot/blob/master/REST-APIs.md). Then we use the *http* block to connect Snap! with the robot (you can refer to the section [The Outside World](http://snap.berkeley.edu/SnapManual.pdf) from Snap! reference manual for more details). You can manually specify the host and port to which the server will be attached using snap_host and snap_port args. Here, we use the default values which bind the server to the *localhost*. Yet, this will not allow for external connections. You can use *snap_host='0.0.0.0'* to automatically attach the webserver to the IP of your machine. Hostnames can also be used, for instance Poppy Creatures usually provide an hostname such as *host='poppy-humanoid.local'*.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "poppy.snap.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note for advanced user: the run method will run the server forever and thus block the main thread. This is here not a problem as you do not need to execute extra code for this tutorial. If you need to run other python code after, you can run this method inside a thread.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can create a poppy creature from python with the above code, but you can also use a simple command on your terminal: \n",
    "``` \n",
    "poppy-snap --vrep poppy-humanoid \n",
    "```\n",
    "If you want to try other configurations, look at the help of poppy-snap:\n",
    "``` \n",
    "poppy-snap --help \n",
    "``` "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"image/vrep-poppy.png\" alt=\"V-REP Poppy Humanoid Scene\" style=\"height: 500px;\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Use [Snap!](http://snap.berkeley.edu/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we have anything we need to control our Poppy Creature, we just need to run [Snap!](http://snap.berkeley.edu/) on a web browser."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As stated above, [Snap!](http://snap.berkeley.edu/) is entirelly written in javascript and thus the only things needed to run it is a (not too old) web browser! You can run [Snap!](http://snap.berkeley.edu/) in two modes:\n",
    "* **online**: you just need to go to http://snap.berkeley.edu/snapsource/snap.html\n",
    "* **locally**: you have to first download [Snap! sources](https://github.com/jmoenig/Snap--Build-Your-Own-Blocks) and then open the *snap.html* file. No internet connection is required after downloading the source.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now detail on you can control your Poppy Creature via the two approaches:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note that the online one is more straightforward and should thus be privileged except if you do not have an internet connection.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alternative 1: Run [Snap!](http://snap.berkeley.edu/snapsource/snap.html) Online"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last step required before actually making your robot moves in [Snap!](http://snap.berkeley.edu/snapsource/snap.html) is to import our predefined blocks. [Snap!](http://snap.berkeley.edu/snapsource/snap.html) provides a really simple way to do that: you just have to go to this url: http://snap.berkeley.edu/snapsource/snap.html#open:http://127.0.0.1:6969/snap-blocks.xml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note the **#open:http://...** at the end of the url. It tells [Snap!](http://snap.berkeley.edu) to automatically loads the blocks that can be found at the url: http://127.0.0.1:6969/snap-blocks.xml."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "*Note: if you changed the web server host, you need to change it in here as well. For instance if you use the Poppy Ergo default hostname you need to go to http://snap.berkeley.edu/snapsource/snap.html#open:http://poppy-ergojr.local:6969/snap-blocks.xml instead.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should now see something like this in your browser (note importing the blocks may take a few seconds):\n",
    "\n",
    "![alt text](image/snap-ready.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alternative 2: Run [Snap!](http://snap.berkeley.edu/snapsource/snap.html) locally"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you use [Snap!](http://snap.berkeley.edu) locally instead, you will have to first:\n",
    "* launch [Snap!](http://snap.berkeley.edu/) by opening the **snap.html** file from you snap local folder\n",
    "* import the project with our specific blocks via the snap menu\n",
    "\n",
    "![alt text](image/snap-import.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Poppy's specific blocks can be found on pypot/server/snap_projects/pypot-snap-blocks.xml directory in the pypot installation folder (its location will depend on your operating system and how you installed it). You can use the explorer/finder to find it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively you can directly download it from the [github repository](https://raw.githubusercontent.com/poppy-project/pypot/master/pypot/server/snap_projects/pypot-snap-blocks.xml). For instance:\n",
    "\n",
    "```bash\n",
    "wget https://raw.githubusercontent.com/poppy-project/pypot/master/pypot/server/snap_projects/pypot-snap-blocks.xml\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once imported you should see something like:\n",
    "\n",
    "![alt text](image/snap-ready.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using [Snap!](http://snap.berkeley.edu) to make your Poppy Creature moves"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can see that our base project comes with a few specific blocks such as:\n",
    "\n",
    "<img src=\"image/snap-basic-blocks.png\" alt=\"Drawing\" style=\"height: 700px;\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Those blocks can be used to respectively:\n",
    "* test if connection with poppy robot is working well\n",
    "* get a list of all motors name\n",
    "* get a list of all motors refered by an alias\n",
    "* get the value of a register motor (e.g. get motor \"head_z\" register \"present_load\")\n",
    "* get the index of a motor\n",
    "* get all alias avaible for the current robot\n",
    "* set a motor position in a specified time\n",
    "* turn a motor compliant or not\n",
    "* set a register of a motor (e.g. set motor \"head_z\" register \"present_load\" to 10)\n",
    "* create/attach a move to some motors (you have to create a move before to record or replay it)\n",
    "* stop the record of a move\n",
    "* start the record of a move\n",
    "* play a move at a defined speed\n",
    "* play a move in reverse at a defined speed\n",
    "* play concurently many moves\n",
    "* play sequentialy many moves\n",
    "\n",
    "Other blocks are also available. Their behavior should be easily deduced from their name."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can easily see all blocks relative to poppy in Snap! with the \"find blocks\" feature.\n",
    "You have to right-click in the left part of Snap! page and select \"find blocks\":\n",
    "<img src=\"image/snap-right-click.png\" alt=\"Drawing\" style=\"height: 250px;\"/>\n",
    "\n",
    "If you type **robot** on the search input, you will select all poppy blocks:\n",
    "<img src=\"image/snap-find-pypot-blocks.png\" alt=\"Drawing\" style=\"height: 700px;\" text-align=\"left\"/>\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To control a motor via a slider you need to:\n",
    "* first, make a variable - we will call it **head position**\n",
    "* right click on it and use the slider option\n",
    "* change the slider min/max to (-50, 50)\n",
    "\n",
    "![alt text](image/snap-slider.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, connect it to a motor:\n",
    "* use the *motor(s) goto position* block\n",
    "* put it inside a forever loop\n",
    "* add a wait for performance issue\n",
    "\n",
    "<img src=\"image/snap-slider-example.png\" alt=\"Drawing\" style=\"height: 100px;\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Project example: orchestration of move records"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On the pypot install directory pypot/server/pypot-snap-record-orchestration-demo.xml (its location will depend on your operating system and how you installed it), you can find a project tutorial of how to make orchestration of move record.\n",
    "Alternatively you can directly download it from the [github repository](https://raw.githubusercontent.com/poppy-project/pypot/master/pypot/server/snap_projects/pypot-snap-blocks.xml):\n",
    "```bash\n",
    "wget https://raw.githubusercontent.com/poppy-project/pypot/master/pypot-snap-record-orchestration-demo.xml\n",
    "```\n",
    "or getting it from [Snap! cloud](http://snap.berkeley.edu/snapsource/snap.html#cloud:Username=showok&ProjectName=pypot_orchestration_demo).\n",
    "\n",
    "\n",
    "This project will guide you step by step on how to use Snap! to record and play many nested move.\n",
    "\n",
    "<img src=\"image/snap-orchestration-demo.png\" alt=\"Drawing\" style=\"height: 700px;\" text-align=\"left\"/>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Project example: apply a sinus on a few motors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![alt text](image/snap-sinus.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Demonstration Video"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
