Repository: pollen-robotics/reachy2-sdk (language: python)

Issue:
Integrate Orbbec



Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index 36d8a50e..b27ed644 100644
--- a/README.md
+++ b/README.md
@@ -37,10 +37,10 @@ Note that only **offline tests** are executed by the Continuous Integration/Cont
 
 ### Camera tests
 
-Camera tests have their own marks because it requires the camera to be plugged to the sdk server (*sr_camera* and/or *teleop_camera*). 
+Camera tests have their own marks because it requires the cameras to be plugged to the sdk server 
 
 ```console
-$ pytest -m [sr_camera | teleop_camera]
+$ pytest -m cameras
 ```
 
 ## Logs
diff --git a/setup.cfg b/setup.cfg
index fe6ea362..f9c0fcce 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,7 +20,7 @@ install_requires =
     grpcio>=1.59.0, <=1.62.2
     pyquaternion==0.9.9
     opencv-python>=4.8.0, <4.9.0
-    reachy2-sdk-api>=1.0.8,  <1.1.0
+    reachy2-sdk-api>=1.0.9,  <1.1.0
 
 [options.packages.find]
 where = src
@@ -60,8 +60,8 @@ testpaths = tests/units
 markers = 
     online: test connected to simulated robot
     offline: no grpc connection required
-    sr_camera : test for SR sr_camera
-    teleop_camera : test for teleop_camera
+    cameras : tests for teleop and depth cameras
+
 
 [mypy]
 ignore_missing_imports = True
diff --git a/src/examples/1_getting_started.ipynb b/src/examples/1_getting_started.ipynb
index ea1c4c82..9fc64d5f 100644
--- a/src/examples/1_getting_started.ipynb
+++ b/src/examples/1_getting_started.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "0c52fc2b",
+   "id": "0",
    "metadata": {},
    "source": [
     "# Getting started with Reachy 2"
@@ -10,7 +10,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "b3b79886",
+   "id": "1",
    "metadata": {},
    "source": [
     "In this first tutorial, we will familiarize ourselves with Reachy. We will cover how to connect to the robot and obtain basic information."
@@ -18,7 +18,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "1f35ddce",
+   "id": "2",
    "metadata": {},
    "source": [
     "## Connect to Reachy"
@@ -26,7 +26,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "f226e41b",
+   "id": "3",
    "metadata": {},
    "source": [
     "First, establish a connection to your robot:"
@@ -35,7 +35,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f2d8265b",
+   "id": "4",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -46,7 +46,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "245fc9b2",
+   "id": "5",
    "metadata": {},
    "source": [
     "You can check the connection status at any time with:"
@@ -55,7 +55,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1e218be1",
+   "id": "6",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -64,7 +64,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "a7196684",
+   "id": "7",
    "metadata": {},
    "source": [
     "Reachy is now ready for use. By default, all motors are turned off. In the next tutorial, we will learn how to move Reachy. The overall status of Reachy's motors can be checked as follows:"
@@ -73,7 +73,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "c1d988af",
+   "id": "8",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -83,7 +83,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "28adc5a8",
+   "id": "9",
    "metadata": {},
    "source": [
     "Let's retrieve information about the robot, including hardware and software versions, configuration, and battery level:"
@@ -92,7 +92,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a86fc2dc",
+   "id": "10",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -101,7 +101,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "d155f27d",
+   "id": "11",
    "metadata": {},
    "source": [
     "You can also access this information independently, for example:"
@@ -110,7 +110,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "8ca98240",
+   "id": "12",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -119,7 +119,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "eb784543",
+   "id": "13",
    "metadata": {},
    "source": [
     "## Body parts"
@@ -127,7 +127,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "9787373a",
+   "id": "14",
    "metadata": {},
    "source": [
     "Let's take a look at Reachy's body. Reachy's arm has 7 degrees of freedom and one joint for the gripper.\n",
@@ -148,7 +148,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "c1116bf8",
+   "id": "15",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -157,7 +157,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "dbb73dd7",
+   "id": "16",
    "metadata": {},
    "source": [
     "The current and goal positions are also listed (i.e., the present and target angles of the joints).\n",
@@ -167,7 +167,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f135ac9a",
+   "id": "17",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -178,7 +178,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "07156e26",
+   "id": "18",
    "metadata": {},
    "source": [
     "## Mobile Base"
@@ -186,7 +186,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "8f38abb4",
+   "id": "19",
    "metadata": {},
    "source": [
     "The mobile base can be accessed in the same way as the body parts:"
@@ -195,7 +195,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "72aebe9b",
+   "id": "20",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -204,7 +204,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "ddbbcb67",
+   "id": "21",
    "metadata": {},
    "source": [
     "## Disconnect"
@@ -212,7 +212,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "1b0a56d2",
+   "id": "22",
    "metadata": {},
    "source": [
     "No action is required; simply close your terminal or notebook!\n",
@@ -224,7 +224,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "0cb3f2c0",
+   "id": "23",
    "metadata": {},
    "outputs": [],
    "source": [
diff --git a/src/examples/2_moves_introduction.ipynb b/src/examples/2_moves_introduction.ipynb
index cbbb9a46..c7230949 100644
--- a/src/examples/2_moves_introduction.ipynb
+++ b/src/examples/2_moves_introduction.ipynb
@@ -3,7 +3,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f2d8265b",
+   "id": "0",
    "metadata": {},
    "source": [
     "# Moves introduction"
@@ -12,7 +12,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "cd48baf0",
+   "id": "1",
    "metadata": {},
    "source": [
     "ReachySDK for Reachy 2 offers you methods to make movements with the arms and head, controlling the target position in several ways, choosing the duration of the movement, or even the interpolation mode. We called them **Moves**.\n",
@@ -32,7 +32,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "923aca0f",
+   "id": "2",
    "metadata": {},
    "source": [
     "## Initialize to your robot"
@@ -41,7 +41,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "d675839b",
+   "id": "3",
    "metadata": {},
    "source": [
     "Connect to your robot:"
@@ -50,7 +50,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a0c2d4ab",
+   "id": "4",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -63,7 +63,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "5e2936a7",
+   "id": "5",
    "metadata": {},
    "source": [
     "Turn on Reachy so the motors can be controlled, and set in the zero pose:"
@@ -72,7 +72,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "0377f13d",
+   "id": "6",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -84,7 +84,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "28592b1a",
+   "id": "7",
    "metadata": {},
    "source": [
     "`set_pose('default')` is a convenient function to reset all motors position at once. It also accepts the parameter elbow_90 (i.e. `set_pose('elbow_90')`), Reachy has the two forearms parallel to the ground. These standard poses can be useful when you want to start a new task from a known position."
@@ -93,7 +93,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b1a4a4a3",
+   "id": "8",
    "metadata": {},
    "source": [
     "> This example is available in [set_zero_pose.py](set_zero_pose.py)"
@@ -102,7 +102,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "edf24ed3",
+   "id": "9",
    "metadata": {},
    "source": [
     "## The Moves"
@@ -111,7 +111,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "a9ba27c0",
+   "id": "10",
    "metadata": {},
    "source": [
     "### First move"
@@ -120,7 +120,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "901a252d",
+   "id": "11",
    "metadata": {},
    "source": [
     "Let's move Reachy's right arm. The *goto_joints* allows to control the 7 degrees of freedom of the arm at once (see [getting_started](1_getting_started.ipynb))"
@@ -129,7 +129,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f135ac9a",
+   "id": "12",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -141,7 +141,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b087287f",
+   "id": "13",
    "metadata": {},
    "source": [
     "This method returns an id, that you can use to get information on this movement or to cancel this movement. Store this id in a variable (*move_1* here) to be able to use it further. All the move methods return an id."
@@ -150,7 +150,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b9402c92",
+   "id": "14",
    "metadata": {},
    "source": [
     "### Moves execution"
@@ -159,7 +159,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "3297d489",
+   "id": "15",
    "metadata": {},
    "source": [
     "Move commands can only be sent on parts:\n",
@@ -173,7 +173,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "6e35fb9f",
+   "id": "16",
    "metadata": {},
    "source": [
     "#### Moves are non-blocking for other parts "
@@ -182,7 +182,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "8d303968",
+   "id": "17",
    "metadata": {},
    "source": [
     "It means you can send a move command on different parts, it won't wait for the movement to be executed on the first part to execute the other one, but will follow the timing of your code.\n",
@@ -193,7 +193,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "6744e69c",
+   "id": "18",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -206,7 +206,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "ed014768",
+   "id": "19",
    "metadata": {},
    "source": [
     "This sequence will take 3 seconds to execute, as the right arm will start its movement 1 second after the left arm has started its own movement. They will finish at the same time."
@@ -215,7 +215,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "58ee1529",
+   "id": "20",
    "metadata": {},
    "source": [
     "#### Moves are blocking and stacked for a part"
@@ -224,7 +224,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "123a4c45",
+   "id": "21",
    "metadata": {},
    "source": [
     "It means that you can send several move commands on a part one after another without any delay, they will be played in this order, but will wait for the previous move to be finished.  \n",
@@ -235,7 +235,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "3c513e13",
+   "id": "22",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -248,7 +248,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "4bddc72d",
+   "id": "23",
    "metadata": {},
    "source": [
     "This sequence will take 8 seconds to execute, as each movement on the left arm will wait for the previous before starting.  \n",
@@ -259,7 +259,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "d606d5e1",
+   "id": "24",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -274,7 +274,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c5069db7",
+   "id": "25",
    "metadata": {},
    "source": [
     "This sequence will still take 8 seconds to execute:\n",
@@ -287,7 +287,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "6d8c655e",
+   "id": "26",
    "metadata": {},
    "source": [
     "#### Wait for moves"
@@ -296,7 +296,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "5aeed3fc",
+   "id": "27",
    "metadata": {},
    "source": [
     "So how can a left arm move wait for a right arm move?\n",
@@ -306,7 +306,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "3eed45a5",
+   "id": "28",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -322,7 +322,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c49deace",
+   "id": "29",
    "metadata": {},
    "source": [
     "### Moves state"
@@ -331,7 +331,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "9d78ba20",
+   "id": "30",
    "metadata": {},
    "source": [
     "For a specific move, you may want to know its current state. You can get information on the moves given its id with 3 methods available at reachy's level:\n",
@@ -345,7 +345,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "7fcc3177",
+   "id": "31",
    "metadata": {},
    "source": [
     "First, let's wait for all the queue to be finished, in case movements are still playing:"
@@ -354,7 +354,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ecdeea71",
+   "id": "32",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -368,7 +368,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "5119cbae",
+   "id": "33",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -394,7 +394,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "6305e18b",
+   "id": "34",
    "metadata": {},
    "source": [
     "Retreive the joints request of a move command from the move ID:"
@@ -403,7 +403,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "5af5c202",
+   "id": "35",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -413,7 +413,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f2bb6457",
+   "id": "36",
    "metadata": {},
    "source": [
     "### Part execution state"
@@ -422,7 +422,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "a368ca1f",
+   "id": "37",
    "metadata": {},
    "source": [
     "As the sequence can become complex, you can get information for each part on its current status, to now which movement is being played and know which others are waiting to be played.  \n",
@@ -437,7 +437,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "354eae56",
+   "id": "38",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -459,7 +459,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "45a85811",
+   "id": "39",
    "metadata": {},
    "source": [
     "### Cancel moves"
@@ -468,7 +468,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "d3a38482",
+   "id": "40",
    "metadata": {},
    "source": [
     "If you want to modify the queue of move commands on a part, or interrupt the movement being played, you can cancel move commands at any time.  "
@@ -477,7 +477,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "310b4a78",
+   "id": "41",
    "metadata": {},
    "source": [
     "#### Single move cancellation"
@@ -486,7 +486,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "e95735ae",
+   "id": "42",
    "metadata": {},
    "source": [
     "To cancel a single movement, currently playing or stacked in a part's queue, use its id and call `cancel_move_by_id()` from reachy."
@@ -495,7 +495,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "4a825e47",
+   "id": "43",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -512,7 +512,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b966a8a6",
+   "id": "44",
    "metadata": {},
    "source": [
     "#### Multiple moves cancellation"
@@ -521,7 +521,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "087d104c",
+   "id": "45",
    "metadata": {},
    "source": [
     "To cancel all moves at once, you can call the `cancel_all_moves()` methods.  \n",
@@ -531,7 +531,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c689eaed",
+   "id": "46",
    "metadata": {},
    "source": [
     "##### All moves"
@@ -540,7 +540,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c156186a",
+   "id": "47",
    "metadata": {},
    "source": [
     "For example, if you want to cancel all moves on all parts:"
@@ -549,7 +549,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1eb4d748",
+   "id": "48",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -571,7 +571,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "7ce160b9",
+   "id": "49",
    "metadata": {},
    "source": [
     "All movements are cancelled, even the movement stacked in the left arm queue which will never be played.  "
@@ -580,7 +580,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "20e81eac",
+   "id": "50",
    "metadata": {},
    "source": [
     "##### All moves for one part"
@@ -589,7 +589,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "0c32c6b8",
+   "id": "51",
    "metadata": {},
    "source": [
     "If you only want to cancel movement on the left arm:"
@@ -598,7 +598,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1ecd0843",
+   "id": "52",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -620,7 +620,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "cc2bf8b1",
+   "id": "53",
    "metadata": {},
    "source": [
     "The movement on the head will continue, but all the movements of the left will be stopped and the left arm queue cleaned."
@@ -629,7 +629,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "d7630f64",
+   "id": "54",
    "metadata": {},
    "source": [
     "## Moves duration"
@@ -638,7 +638,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "2230b667",
+   "id": "55",
    "metadata": {},
    "source": [
     "You may have noticed that, for each methods mentioned above, you can give a custom duration for the execution of the movements. \n",
@@ -649,7 +649,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "69fd38c7",
+   "id": "56",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -670,7 +670,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "a7af163a",
+   "id": "57",
    "metadata": {},
    "source": [
     "> Default duration is **2 seconds**.\n",
@@ -681,7 +681,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f1d6d970",
+   "id": "58",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -691,7 +691,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "1eaf0d4e",
+   "id": "59",
    "metadata": {},
    "source": [
     "## Moves interpolation mode"
@@ -700,7 +700,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "e96a7f08",
+   "id": "60",
    "metadata": {},
    "source": [
     "The moves methods generates a trajectory between the present position and the goal position. This trajectory is then interpolated at a predefined frequency (100Hz) to compute all intermediary target positions that should be followed before reaching the final goal position. Depending on the interpolation mode chosen, you can have a better control over speed and acceleration.\n",
@@ -717,7 +717,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "2ec7e3dc",
+   "id": "61",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -732,7 +732,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "3e31e500",
+   "id": "62",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -745,7 +745,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "eed9670e",
+   "id": "63",
    "metadata": {},
    "source": [
     "> Default interpolation mode is **minimum_jerk**."
@@ -754,7 +754,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "cfb413f7",
+   "id": "64",
    "metadata": {},
    "outputs": [],
    "source": [
diff --git a/src/examples/3_arm_and_gripper.ipynb b/src/examples/3_arm_and_gripper.ipynb
index f5425bb9..8c439185 100644
--- a/src/examples/3_arm_and_gripper.ipynb
+++ b/src/examples/3_arm_and_gripper.ipynb
@@ -3,7 +3,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "0c52fc2b",
+   "id": "0",
    "metadata": {},
    "source": [
     "# Arm and Gripper"
@@ -12,7 +12,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "3f89c050",
+   "id": "1",
    "metadata": {},
    "source": [
     "In the previous tutorial, we explored the concept of *moves* and basic control. Now, let's delve deeper into what we can do with Reachy's arms and grippers."
@@ -21,7 +21,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "1f35ddce",
+   "id": "2",
    "metadata": {},
    "source": [
     "## Initialize Your Robot"
@@ -30,7 +30,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f226e41b",
+   "id": "3",
    "metadata": {},
    "source": [
     "First, connect to your robot:"
@@ -39,7 +39,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f2d8265b",
+   "id": "4",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -52,7 +52,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "923aca0f",
+   "id": "5",
    "metadata": {},
    "source": [
     "Next, we need to turn on the parts we want to use:"
@@ -61,7 +61,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a0c2d4ab",
+   "id": "6",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -72,7 +72,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f0549ff9",
+   "id": "7",
    "metadata": {},
    "source": [
     "Since the grippers are part of the arms, they will also be turned on. You could, of course, turn on the whole robot by calling `reachy.turn_on()` directly.\n",
@@ -82,7 +82,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "354eae56",
+   "id": "8",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -93,7 +93,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "edf24ed3",
+   "id": "9",
    "metadata": {},
    "source": [
     "## Check Arm Joints"
@@ -102,7 +102,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "d24a569e",
+   "id": "10",
    "metadata": {},
    "source": [
     "Reachy's arm offers 7 degrees of freedom. It also gives access to one joint for the gripper.\n",
@@ -120,7 +120,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "38ab4fea",
+   "id": "11",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -130,7 +130,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f9a91eed",
+   "id": "12",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -140,7 +140,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "729c9bb0",
+   "id": "13",
    "metadata": {},
    "source": [
     "You can easily access the position of each joint in one call with `get_joint_positions()`"
@@ -149,7 +149,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "6744e69c",
+   "id": "14",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -159,7 +159,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ed014768",
+   "id": "15",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -169,7 +169,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b966a8a6",
+   "id": "16",
    "metadata": {},
    "source": [
     "## Move the Arms"
@@ -178,7 +178,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "0a5a3cf5",
+   "id": "17",
    "metadata": {},
    "source": [
     "The simplest way to move an arm is to set the angle of each joint. Define a joint positions list:"
@@ -187,7 +187,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1eb4d748",
+   "id": "18",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -197,7 +197,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "7ce160b9",
+   "id": "19",
    "metadata": {},
    "source": [
     "Send the joint goal positions to the arm with `goto_joints()`"
@@ -206,7 +206,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1ecd0843",
+   "id": "20",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -219,7 +219,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c14b5ab8",
+   "id": "21",
    "metadata": {},
    "source": [
     "In order to easily move a single joint, we can use the `goto()` method on a given joint:"
@@ -228,7 +228,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "e34df82f",
+   "id": "22",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -241,7 +241,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "dbdf6d92",
+   "id": "23",
    "metadata": {},
    "source": [
     "This method works exactly like a move on the part. All gotos sent to joints are stacked on the part they belong to.\n",
@@ -251,7 +251,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "99dce0fe",
+   "id": "24",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -267,7 +267,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "4ad46437",
+   "id": "25",
    "metadata": {},
    "source": [
     "`reachy.r_arm.elbow.pitch.goto(0)` command is stacked in r_arm moves queue.\n",
@@ -277,7 +277,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "cc2bf8b1",
+   "id": "26",
    "metadata": {},
    "source": [
     "The arms should have moved in a way similar to what we saw in the [move tutorial](moves_introduction.ipynb). You already know that you can specify the duration or the interpolation mode of this kind of movement.\n",
@@ -288,7 +288,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "6adc9be3",
+   "id": "27",
    "metadata": {},
    "source": [
     "## Kinematics"
@@ -297,7 +297,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "5f4bf763",
+   "id": "28",
    "metadata": {},
    "source": [
     "The kinematic model describes the motion of a robot in mathematical form without considering the forces and torque affecting it. It only focuses on the geometric relationship between elements.\n",
@@ -312,7 +312,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "4fc61e8d",
+   "id": "29",
    "metadata": {},
    "source": [
     "### Forward Kinematics"
@@ -321,7 +321,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "e5ff1aa7",
+   "id": "30",
    "metadata": {},
    "source": [
     "Each arm has a `forward_kinematics` method that computes a 4x4 pose matrix (position and orientation of the gripper in space). For instance, the previous movement left the left elbow at 90°. The position of the gripper is:"
@@ -330,7 +330,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "70f9fb46",
+   "id": "31",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -340,7 +340,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b7dc0089",
+   "id": "32",
    "metadata": {},
    "source": [
     "It is not mandatory to move the arm to compute forward kinematics. This can be done for any set of joint positions such as:"
@@ -349,7 +349,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "2fa7129a",
+   "id": "33",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -359,7 +359,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "4159b168",
+   "id": "34",
    "metadata": {},
    "source": [
     "Reachy didn't move, but you know where it would have gone with an additional 10° applied to the shoulder joint."
@@ -368,7 +368,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "8648377a",
+   "id": "35",
    "metadata": {},
    "source": [
     "### Inverse Kinematics"
@@ -377,7 +377,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "4b069dfb",
+   "id": "36",
    "metadata": {},
    "source": [
     "Inverse kinematics works in the opposite way. Let's say you want to reach an object for which you know its position. What would be the set of joint positions to provide to `goto_joints`?"
@@ -386,7 +386,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "e571145b",
+   "id": "37",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -401,7 +401,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "aac9de48",
+   "id": "38",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -412,7 +412,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "dbcb3083",
+   "id": "39",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -422,7 +422,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b2315927",
+   "id": "40",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -433,7 +433,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "fd037ff6",
+   "id": "41",
    "metadata": {},
    "source": [
     "> All these moves are illustrated in [draw_square](draw_square.py). Check it out to see how to make Reachy draw a square with its right arm!"
@@ -442,7 +442,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "bbcc9e57",
+   "id": "42",
    "metadata": {},
    "source": [
     "## Gripper Control"
@@ -451,7 +451,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "bbd3c88d",
+   "id": "43",
    "metadata": {},
    "source": [
     "Finally, you may want to open or close a gripper to grab an object! Use the `close` or `open` method to do so:"
@@ -460,7 +460,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "93a17e38",
+   "id": "44",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -472,7 +472,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "1101041b",
+   "id": "45",
    "metadata": {},
    "source": [
     "Of course, you can partially open the gripper, and get its current state:"
@@ -481,7 +481,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b7265c1a",
+   "id": "46",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -493,7 +493,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "a4fcb002",
+   "id": "47",
    "metadata": {},
    "source": [
     "# Set robot back to compliant mode"
@@ -502,7 +502,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "e9b97de0",
+   "id": "48",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -517,7 +517,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "779ffbf1",
+   "id": "49",
    "metadata": {},
    "source": []
   }
diff --git a/src/examples/4_head_control.ipynb b/src/examples/4_head_control.ipynb
index c7369a02..25415f64 100644
--- a/src/examples/4_head_control.ipynb
+++ b/src/examples/4_head_control.ipynb
@@ -3,7 +3,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "748878af",
+   "id": "0",
    "metadata": {},
    "source": [
     "# Head control"
@@ -12,7 +12,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "9d22811e",
+   "id": "1",
    "metadata": {},
    "source": [
     "Reachy 2's head is mounted on an Orbita3D actuator, referred to as the **neck** actuator, giving 3 degrees of freedom to control the head orientation.  \n",
@@ -24,7 +24,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "923aca0f",
+   "id": "2",
    "metadata": {},
    "source": [
     "## Initialize your robot"
@@ -33,7 +33,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "5355d81b",
+   "id": "3",
    "metadata": {},
    "source": [
     "First connect to your robot:"
@@ -42,7 +42,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "588cbcb7",
+   "id": "4",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -54,7 +54,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "3e47ec7d",
+   "id": "5",
    "metadata": {},
    "source": [
     "Let's check what contains the head part:"
@@ -63,7 +63,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f2d8265b",
+   "id": "6",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -73,7 +73,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f8dc8c30",
+   "id": "7",
    "metadata": {},
    "source": [
     "The head is composed of **three joints**:\n",
@@ -89,7 +89,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a0c2d4ab",
+   "id": "8",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -99,7 +99,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c63162f5",
+   "id": "9",
    "metadata": {},
    "source": [
     "You could of course turn on the whole robot by calling `reachy.turn_on()` directly."
@@ -108,7 +108,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "edf24ed3",
+   "id": "10",
    "metadata": {},
    "source": [
     "## Head moves"
@@ -117,7 +117,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "ee5315dc",
+   "id": "11",
    "metadata": {},
    "source": [
     "There are several ways to control the head movements:\n",
@@ -128,7 +128,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b9402c92",
+   "id": "12",
    "metadata": {},
    "source": [
     "### look_at()\n",
@@ -147,7 +147,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "6744e69c",
+   "id": "13",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -157,7 +157,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f43c8934",
+   "id": "14",
    "metadata": {},
    "source": [
     "You can use multiple *look_at* to chain head movements, or even chain them with the `goto_joints()` and `orient()` functions described below. As seen in the moves tutorial, the commands on the head will be stacked.\n",
@@ -167,7 +167,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b5373062",
+   "id": "15",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -182,7 +182,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b372f164",
+   "id": "16",
    "metadata": {},
    "source": [
     "The best way to understand how to use the *look_at* is to play with it. Picture a position you would like Reachy's head to be in, guess a point which could match for the *look_at* and check if you got it right!"
@@ -191,7 +191,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "58ee1529",
+   "id": "17",
    "metadata": {},
    "source": [
     "### goto_joints()\n",
@@ -202,7 +202,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "3c513e13",
+   "id": "18",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -212,7 +212,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "f2bb6457",
+   "id": "19",
    "metadata": {},
    "source": [
     "### orient()\n",
@@ -225,7 +225,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "354eae56",
+   "id": "20",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -239,7 +239,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "c49deace",
+   "id": "21",
    "metadata": {},
    "source": [
     "## Read head position\n",
@@ -255,7 +255,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "5119cbae",
+   "id": "22",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -266,7 +266,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "45a85811",
+   "id": "23",
    "metadata": {},
    "source": [
     "### get_joints_positions()\n",
@@ -277,7 +277,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "4a825e47",
+   "id": "24",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -291,7 +291,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "b966a8a6",
+   "id": "25",
    "metadata": {},
    "source": [
     "Be careful that contrary to the quaternion that offers a unique representation of a rotation, it is not the case of the euler angles. Several angles combination can lead to the same orientation in space. For example:\n"
@@ -300,7 +300,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "1eb4d748",
+   "id": "26",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -314,7 +314,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "68833679",
+   "id": "27",
    "metadata": {},
    "source": [
     "The values are different, nevertheless it is the same final orientation. You can convince yourself doing:"
@@ -323,7 +323,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a4e4bd79",
+   "id": "28",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -333,7 +333,7 @@
   {
    "attachments": {},
    "cell_type": "markdown",
-   "id": "e17de027",
+   "id": "29",
    "metadata": {},
    "source": [
     "The head won't move."
@@ -342,7 +342,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "26c9469c",
+   "id": "30",
    "metadata": {},
    "outputs": [],
    "source": [
diff --git a/src/examples/5_cameras_images.ipynb b/src/examples/5_cameras_images.ipynb
index 324e892a..7e516f3c 100644
--- a/src/examples/5_cameras_images.ipynb
+++ b/src/examples/5_cameras_images.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "f2d8265b",
+   "id": "0",
    "metadata": {},
    "source": [
     "# Get images from cameras"
@@ -10,26 +10,26 @@
   },
   {
    "cell_type": "markdown",
-   "id": "4145d29c",
+   "id": "1",
    "metadata": {},
    "source": []
   },
   {
    "cell_type": "markdown",
-   "id": "434c4dd6",
+   "id": "2",
    "metadata": {},
    "source": [
     "Reachy 2 has 2 types of camera:\n",
     "\n",
     "- the **teleop** cameras, with a right and left cameras, located in Reachy 2’s head and used for the teleoperation\n",
-    "- the **Depth** camera, equipped with a depth sensor, located in Reachy 2’s torso and mainly useful for manipulation tasks\n",
+    "- the **depth** camera, equipped with a depth sensor, located in Reachy 2’s torso and mainly useful for manipulation tasks\n",
     "\n",
-    "Each camera can be accessed separately through reachy.cameras. They both have a right and left view, with the left and right sides considered from Reachy point of view. To be able to specify the view you want to get a frame from, you will need to import CameraView:"
+    "Each camera can be accessed separately through reachy.cameras. Teleop cameras  have a right and left view, with the left and right sides considered from Reachy point of view, while the depth camera has a left (i.e. mono RGB) and depth view. To be able to specify the view you want to get a frame from, you will need to import CameraView:"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "463fc1f2",
+   "id": "3",
    "metadata": {},
    "source": [
     "```python\n",
@@ -39,7 +39,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "37f15717",
+   "id": "4",
    "metadata": {},
    "source": [
     "## Get images"
@@ -47,7 +47,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "923aca0f",
+   "id": "5",
    "metadata": {},
    "source": [
     "First, connect to your robot.  \n",
@@ -57,7 +57,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a0c2d4ab",
+   "id": "6",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -69,7 +69,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "d94a8cbb",
+   "id": "7",
    "metadata": {},
    "source": [
     "Check the list of initialized cameras:"
@@ -78,7 +78,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "4d8b32cb",
+   "id": "8",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -87,17 +87,15 @@
   },
   {
    "cell_type": "markdown",
-   "id": "a822bd8a",
+   "id": "9",
    "metadata": {},
    "source": [
-    "The list of initialized cameras should contain both the teleop and SR camera.  \n",
-    "\n",
-    "For each camera, namely the teleop and the SR ones, you must call the `capture()`function each time you want to get an image. This captures an image from both view of the given camera at the same time. You can then access one of the image with the `get_frame()` method."
+    "The list of initialized cameras should contain both the teleop and depth cameras.  "
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "edf24ed3",
+   "id": "10",
    "metadata": {},
    "source": [
     "### Teleop cameras\n",
@@ -108,7 +106,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f135ac9a",
+   "id": "11",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -118,7 +116,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "6daf2e7d",
+   "id": "12",
    "metadata": {},
    "source": [
     "We can print the timestamp of each frame (in nanosecond)"
@@ -127,7 +125,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "56930fd0",
+   "id": "13",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -136,7 +134,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "33b015e6",
+   "id": "14",
    "metadata": {},
    "source": [
     "Let's display the captured frame with PIL:"
@@ -145,7 +143,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "643822a3",
+   "id": "15",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -155,7 +153,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ac408cd3",
+   "id": "16",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -165,7 +163,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "85b5768b",
+   "id": "17",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -174,7 +172,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "c9bad9a5",
+   "id": "18",
    "metadata": {},
    "source": [
     "The camera parameters, as defined [here](https://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/CameraInfo.html), are also available"
@@ -183,17 +181,9 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ff47d133",
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Connection with Reachy lost, check the sdk server status.\n"
-     ]
-    }
-   ],
+   "id": "19",
+   "metadata": {},
+   "outputs": [],
    "source": [
     "height, width, distortion_model, D, K, R, P =  reachy.cameras.teleop.get_parameters(CameraView.LEFT)\n",
     "print(f\"height: {height}\")\n",
@@ -207,43 +197,38 @@
   },
   {
    "cell_type": "markdown",
-   "id": "9813fac4",
+   "id": "20",
    "metadata": {},
    "source": [
-    "### SR cameras - ToDO\n",
+    "### Depth camera\n",
     "\n",
-    "The SR camera works exactly the same as the teleop camera, but you have more elements captured. In fact, it a RGBD camera, so you have both access to the RGB images and depth information.\n",
+    "The depth camera works exactly the same as the teleop camera, but you have more elements captured. In fact, it a RGBD camera, so you have both access to the RGB image and depth information.\n",
     "\n"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "4a647d9c",
+   "id": "21",
    "metadata": {},
    "source": [
     "#### RGB images\n",
     "\n",
-    "Getting RGB images from the SR camera looks the same as from the teleop one: after having called `capture()`, use `get_frame()` specifying the CameraView you want to get."
+    "Getting RGB images from the depth camera looks the same as from the teleop one:  simply use `get_frame()`, there is only one view."
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "bdafbd20",
+   "id": "22",
    "metadata": {},
    "outputs": [],
    "source": [
-    "# First call the capture()\n",
-    "reachy.cameras.SR.capture()\n",
-    "\n",
-    "# Then get the desired frames\n",
-    "l_frame = reachy.cameras.SR.get_frame(CameraView.LEFT)\n",
-    "r_frame = reachy.cameras.SR.get_frame(CameraView.RIGHT)"
+    "frame, ts = reachy.cameras.depth.get_frame()"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "d4f3f69c",
+   "id": "23",
    "metadata": {},
    "source": [
     "Let's display the captured frame with PIL:"
@@ -252,36 +237,41 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "6357ed21",
+   "id": "24",
    "metadata": {},
    "outputs": [],
    "source": [
-    "from PIL import Image"
+    "Image.fromarray(frame[:,:,::-1])"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "79ea8d53",
+   "cell_type": "markdown",
+   "id": "25",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "Image.fromarray(l_frame[:,:,::-1])"
+    "As for the teleop camera, parameters are also availables"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "88c0bebc",
+   "id": "26",
    "metadata": {},
    "outputs": [],
    "source": [
-    "Image.fromarray(r_frame[:,:,::-1])"
+    "height, width, distortion_model, D, K, R, P =  reachy.cameras.depth.get_parameters()\n",
+    "print(f\"height: {height}\")\n",
+    "print(f\"width: {width}\")\n",
+    "print(f\"distortion model: {distortion_model}\")\n",
+    "print(f\"distortion coefficients {D}\")\n",
+    "print(f\"instrinsic matrix {K}\")\n",
+    "print(f\"rectification matrix {R}\")\n",
+    "print(f\"projection matrix {P}\")"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "b4430111",
+   "id": "27",
    "metadata": {},
    "source": [
     "#### Depth information\n",
@@ -294,23 +284,16 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "9fe287fd",
+   "id": "28",
    "metadata": {},
    "outputs": [],
    "source": [
-    "# First call the capture()\n",
-    "reachy.cameras.SR.capture()\n",
-    "\n",
-    "# Then retrieve the desired frames\n",
-    "l_depth_frame = reachy.cameras.SR.get_depth_frame(CameraView.LEFT)\n",
-    "r_depth_frame = reachy.cameras.SR.get_depth_frame(CameraView.RIGHT)\n",
-    "depth = reachy.cameras.SR.get_depthmap()\n",
-    "disparity = reachy.cameras.SR.get_disparity()"
+    "depth_frame, ts = reachy.cameras.depth.get_depth_frame()"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "0305ec45",
+   "id": "29",
    "metadata": {},
    "source": [
     "Let's display the captured frame with PIL:"
@@ -319,56 +302,41 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "76f482e1",
+   "id": "30",
    "metadata": {},
    "outputs": [],
    "source": [
-    "from PIL import Image"
+    "Image.fromarray(depth_frame[:,:])"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "543f6088",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "Image.fromarray(l_depth_frame[:,:])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "bc824d95",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "Image.fromarray(r_depth_frame[:,:])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "5345e213",
+   "cell_type": "markdown",
+   "id": "31",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "Image.fromarray(depth)"
+    "If needed, camera parameters for the depth view are also available"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "20a65486",
+   "id": "32",
    "metadata": {},
    "outputs": [],
    "source": [
-    "Image.fromarray(disparity)"
+    "height, width, distortion_model, D, K, R, P =  reachy.cameras.depth.get_parameters(CameraView.DEPTH)\n",
+    "print(f\"height: {height}\")\n",
+    "print(f\"width: {width}\")\n",
+    "print(f\"distortion model: {distortion_model}\")\n",
+    "print(f\"distortion coefficients {D}\")\n",
+    "print(f\"instrinsic matrix {K}\")\n",
+    "print(f\"rectification matrix {R}\")\n",
+    "print(f\"projection matrix {P}\")"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "2b90ae6f",
+   "id": "33",
    "metadata": {},
    "source": [
     "## Live stream"
@@ -376,7 +344,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "b155140a",
+   "id": "34",
    "metadata": {},
    "source": [
     "Although we provide an optimal way to get the video stream, it is still possible to display what Reachy see through the SDK. It could be useful to feed a compute vision algorithm that do not need to run at high frequency.\n",
diff --git a/src/examples/6_mobile_base.ipynb b/src/examples/6_mobile_base.ipynb
index c995b3ce..81d8c59d 100644
--- a/src/examples/6_mobile_base.ipynb
+++ b/src/examples/6_mobile_base.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "748878af",
+   "id": "0",
    "metadata": {},
    "source": [
     "# The mobile base"
@@ -10,7 +10,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "f76b3516",
+   "id": "1",
    "metadata": {},
    "source": [
     "Reachy 2 is mounted on a mobile base!"
@@ -18,7 +18,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "923aca0f",
+   "id": "2",
    "metadata": {},
    "source": [
     "## Initialize your robot\n",
@@ -29,7 +29,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "588cbcb7",
+   "id": "3",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -40,7 +40,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "3e47ec7d",
+   "id": "4",
    "metadata": {},
    "source": [
     "Let's check what contains the mobile base part:"
@@ -49,7 +49,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "f2d8265b",
+   "id": "5",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -58,7 +58,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "3800d51e",
+   "id": "6",
    "metadata": {},
    "source": [
     "## Move around"
@@ -66,7 +66,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "d8360000",
+   "id": "7",
    "metadata": {},
    "source": [
     "Three modes are possible to control the mobile base:\n",
@@ -77,7 +77,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "332238c4",
+   "id": "8",
    "metadata": {},
    "source": [
     "### Goto and odometry"
@@ -86,7 +86,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "49ff364b",
+   "id": "9",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -100,7 +100,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "913170a6",
+   "id": "10",
    "metadata": {},
    "source": [
     "> Be careful, goto is not a *Move* method as for the arms. This goto will return once the movement is done, or the timeout expired. If you need to run this function in parallel to other processing, please check the `goto_async`"
@@ -109,7 +109,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a5b023c3",
+   "id": "11",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -120,7 +120,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b7e683a6",
+   "id": "12",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -136,7 +136,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "da0bd106",
+   "id": "13",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -146,7 +146,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "b5adf8bd",
+   "id": "14",
    "metadata": {},
    "source": [
     "The speed of the movement can be defined using"
@@ -155,7 +155,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "65931351",
+   "id": "15",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -164,7 +164,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "6b1d72d7",
+   "id": "16",
    "metadata": {},
    "source": [
     "### Free wheel"
@@ -173,7 +173,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "605009d4",
+   "id": "17",
    "metadata": {},
    "outputs": [],
    "source": [
diff --git a/src/examples/cameras.py b/src/examples/cameras.py
index 189c990b..8ed29871 100644
--- a/src/examples/cameras.py
+++ b/src/examples/cameras.py
@@ -1,3 +1,4 @@
+import argparse
 import logging
 
 import cv2
@@ -26,25 +27,34 @@ def display_teleop_cam() -> None:
         logging.info("User Interrupt")
 
 
-"""
-def display_SR_cam() -> None:
-    if reachy.cameras.SR is None:
-        exit("There is no SR camera.")
+def display_depth_cam() -> None:
+    if reachy.cameras.depth is None:
+        exit("There is no depth camera.")
 
     try:
-        while reachy.cameras.SR.capture():
-            cv2.imshow("sr_depthNode_left", reachy.cameras.SR.get_depth_frame(CameraView.LEFT))
-            cv2.imshow("sr_depthNode_right", reachy.cameras.SR.get_depth_frame(CameraView.RIGHT))
-            cv2.imshow("depth", reachy.cameras.SR.get_depthmap())
-            cv2.imshow("disparity", reachy.cameras.SR.get_disparity())
+        while True:
+            rgb, ts = reachy.cameras.depth.get_frame()
+            depth, ts_r = reachy.cameras.depth.get_depth_frame()
+            depth_map_normalized = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)  # type: ignore [attr-defined]
+            cv2.imshow("frame", rgb)
+            cv2.imshow("depthn", depth_map_normalized)
             cv2.waitKey(1)
 
     except KeyboardInterrupt:
         logging.info("User Interrupt")
-"""
+
 
 if __name__ == "__main__":
     logging.basicConfig(level=logging.INFO)
+
+    argParser = argparse.ArgumentParser(description="SDK camera example")
+    argParser.add_argument(
+        "mode",
+        type=str,
+        choices=["teleop", "depth"],
+    )
+    args = argParser.parse_args()
+
     reachy = ReachySDK(host="localhost")
 
     if not reachy.is_connected:
@@ -53,5 +63,7 @@ def display_SR_cam() -> None:
     if reachy.cameras is None:
         exit("There is no connected camera.")
 
-    display_teleop_cam()
-    # display_SR_cam()
+    if args.mode == "teleop":
+        display_teleop_cam()
+    elif args.mode == "depth":
+        display_depth_cam()
diff --git a/src/reachy2_sdk/media/camera.py b/src/reachy2_sdk/media/camera.py
index 43e2ce7a..22bf7744 100644
--- a/src/reachy2_sdk/media/camera.py
+++ b/src/reachy2_sdk/media/camera.py
@@ -18,6 +18,7 @@
 class CameraView(Enum):
     LEFT = View.LEFT
     RIGHT = View.RIGHT
+    DEPTH = View.DEPTH
 
 
 class CameraType(Enum):
@@ -71,37 +72,19 @@ def __repr__(self) -> str:
 
 class DepthCamera(Camera):
     """
-    RGBD Camera. Meant to control a Luxonis SR
+    RGBD Camera
     """
 
-    '''
-    def get_depth_frame(self, view: CameraView = CameraView.LEFT) -> Optional[npt.NDArray[np.uint8]]:
-        """Get 8bit depth view (OpenCV format)"""
-        frame = self._video_stub.GetDepthFrame(request=ViewRequest(camera_feat=self._cam_info, view=view.value))
+    def get_depth_frame(self, view: CameraView = CameraView.DEPTH) -> Optional[Tuple[npt.NDArray[np.uint16], int]]:
+        """Get 16bit depth view (OpenCV format)"""
+        frame = self._video_stub.GetDepth(request=ViewRequest(camera_feat=self._cam_info, view=view.value))
         if frame.data == b"":
             self._logger.error("No frame retrieved")
             return None
-        np_data = np.frombuffer(frame.data, np.uint8)
-        img = cv2.imdecode(np_data, cv2.IMREAD_GRAYSCALE)
-        return img  # type: ignore[no-any-return]
 
-    def get_depthmap(self) -> Optional[npt.NDArray[np.uint16]]:
-        """Get 16bit depthmap (OpenCV format)"""
-        frame = self._video_stub.GetDepthMap(request=self._cam_info)
-        if frame.data == b"":
-            self._logger.error("No frame retrieved")
-            return None
-        np_data = np.frombuffer(frame.data, np.uint8)
-        img = cv2.imdecode(np_data, cv2.IMREAD_UNCHANGED)
-        return img  # type: ignore[no-any-return]
+        if frame.encoding != "16UC1":
+            self._logger.error("Depth is not encoded in 16bit")
+        np_data = np.frombuffer(frame.data, np.uint16)
+        np_data = np_data.reshape((frame.height, frame.width))
 
-    def get_disparity(self) -> Optional[npt.NDArray[np.uint16]]:
-        """Get 16bit disparity (OpenCV format)"""
-        frame = self._video_stub.GetDisparity(request=self._cam_info)
-        if frame.data == b"":
-            self._logger.error("No frame retrieved")
-            return None
-        np_data = np.frombuffer(frame.data, np.uint8)
-        img = cv2.imdecode(np_data, cv2.IMREAD_UNCHANGED)
-        return img  # type: ignore[no-any-return]
-    '''
+        return np_data, frame.timestamp.ToNanoseconds()
diff --git a/src/reachy2_sdk/media/camera_manager.py b/src/reachy2_sdk/media/camera_manager.py
index 7f515102..3ecd7f09 100644
--- a/src/reachy2_sdk/media/camera_manager.py
+++ b/src/reachy2_sdk/media/camera_manager.py
@@ -36,6 +36,8 @@ def __repr__(self) -> str:
     def _setup_cameras(self) -> None:
         """Thread initializing cameras"""
         cams = self._video_stub.GetAvailableCameras(Empty())
+        self._teleop = None
+        self._depth = None
         if len(cams.camera_feat) == 0:
             self._logger.warning("There is no available camera.")
         else:
@@ -50,6 +52,10 @@ def _setup_cameras(self) -> None:
                 else:
                     self._logger.error(f"Camera {c.name} not defined")
 
+    def initialize_cameras(self) -> None:
+        """Manually initialize cameras"""
+        self._setup_cameras()
+
     @property
     def teleop(self) -> Optional[Camera]:
         """Get Teleop camera"""


Test patch:
diff --git a/tests/units/offline/test_camera.py b/tests/units/offline/test_camera.py
index 597ff35a..3566151e 100644
--- a/tests/units/offline/test_camera.py
+++ b/tests/units/offline/test_camera.py
@@ -10,3 +10,8 @@ def test_class() -> None:
     cam = Camera(cam_info=cam_teleop, video_stub=None)
 
     assert cam is not None
+
+    cam_depth = CameraFeatures(name="depth_torsi", stereo=False, depth=True)
+    cam = Camera(cam_info=cam_depth, video_stub=None)
+
+    assert cam is not None
diff --git a/tests/units/online/test_camera.py b/tests/units/online/test_camera.py
index f622fae5..d3ed698a 100644
--- a/tests/units/online/test_camera.py
+++ b/tests/units/online/test_camera.py
@@ -53,7 +53,7 @@ def test_sr_camera(reachy_sdk: ReachySDK) -> None:
 """
 
 
-@pytest.mark.teleop_camera
+@pytest.mark.cameras
 def test_teleop_camera(reachy_sdk: ReachySDK) -> None:
     assert reachy_sdk.cameras.teleop is not None
 
@@ -91,3 +91,45 @@ def test_teleop_camera(reachy_sdk: ReachySDK) -> None:
     assert len(K) == 9
     assert len(R) == 9
     assert len(P) == 12
+
+
+@pytest.mark.cameras
+def test_depth_camera(reachy_sdk: ReachySDK) -> None:
+    assert reachy_sdk.cameras.depth is not None
+
+    frame, ts = reachy_sdk.cameras.depth.get_frame()
+    assert frame is not None
+    assert frame.dtype == np.uint8
+    assert type(ts) == int
+    assert ts > 0
+
+    frame_right, ts_right = reachy_sdk.cameras.depth.get_frame(CameraView.RIGHT)
+
+    # there is only one view
+    assert np.array_equal(frame, frame_right)
+
+    height, width, distortion_model, D, K, R, P = reachy_sdk.cameras.depth.get_parameters()
+
+    assert height == 720
+    assert width == 1280
+    assert distortion_model == "rational_polynomial"
+    assert len(D) == 8
+    assert len(K) == 9
+    assert len(R) == 9
+    assert len(P) == 12
+
+    frame, ts = reachy_sdk.cameras.depth.get_depth_frame()
+    assert frame is not None
+    assert frame.dtype == np.uint16
+    assert type(ts) == int
+    assert ts > 0
+
+    height, width, distortion_model, D, K, R, P = reachy_sdk.cameras.depth.get_parameters(CameraView.DEPTH)
+
+    assert height == 720
+    assert width == 1280
+    assert distortion_model == "rational_polynomial"
+    assert len(D) == 8
+    assert len(K) == 9
+    assert len(R) == 9
+    assert len(P) == 12