diff --git a/wiki/common-platforms/kinova-setup-and-apis.md b/wiki/common-platforms/kinova-setup-and-apis.md index 57d1052b..d1d42b1f 100644 --- a/wiki/common-platforms/kinova-setup-and-apis.md +++ b/wiki/common-platforms/kinova-setup-and-apis.md @@ -44,11 +44,11 @@ The arm should be resting as in the position below: ![Kinova starting position](/assets/images/common-platforms/kinova_start.png) -It is essential that the *gripper is not blocked*, as the arm will open and close the gripper upon startup. If the arm is in a position where the gripper is blocked, move the arm gently until it reaches a *stable* position where the gripper is free to open and close. +It is essential that the **gripper is not blocked**, as the arm will open and close the gripper upon startup. If the arm is in a position where the gripper is blocked, move the arm gently until it reaches a **stable** position where the gripper is free to open and close. -Once the arm is in a safe position, check that the power supply is connected and turned on. *Localize the red e-stop button and keep it within reach at all times*. Unlock the robot by twisting the e-stop button in the same sense as the arrow on it. The button should pop out. +Once the arm is in a safe position, check that the power supply is connected and turned on. **Localize the red e-stop button and keep it within reach at all times**. Unlock the robot by twisting the e-stop button in the same sense as the arrow on it. The button should pop out. -Then press the silver button on the back of the arm until a blue LED lights up and release it. *DO NOT* press the button for more than 10 seconds, as that will factory reset the arm. The lights will then show blue and yellow during startup. *Once the gripper closes and opens and the light turns to solid green, the arm will be ready for use.* +Then press the silver button on the back of the arm until a blue LED lights up and release it. **DO NOT** press the button for more than 10 seconds, as that will factory reset the arm. The lights will then show blue and yellow during startup. **Once the gripper closes and opens and the light turns to solid green, the arm will be ready for use.** #### Using diff --git a/wiki/common-platforms/ros/ros-lifecycle.md b/wiki/common-platforms/ros/ros-lifecycle.md index 69bdb763..7729ad73 100644 --- a/wiki/common-platforms/ros/ros-lifecycle.md +++ b/wiki/common-platforms/ros/ros-lifecycle.md @@ -10,7 +10,7 @@ title: ROS 2 Node Lifecycle # and used in other parts of the site. --- ## Introduction -Many robotics platforms implement state machines as part of their functionality. ROS 2 offers a convenient way of working with state machines in the form of `managed nodes`, also called `lifecycle nodes`. These nodes can be turned on/off, configured/unconfigured, etc. In a nutshell, lifecycle nodes can be activated or deactivated based on the current state of a robot's state machine. +Many robotics platforms implement state machines as part of their functionality. ROS 2 offers a convenient way of working with state machines in the form of `managed nodes`, also called `lifecycle nodes`. These nodes can be turned on/off, configured/unconfigured, etc. In a nutshell, lifecycle nodes can be activated or deactivated based on the current state of a robot's state machine. Before ROS 2, state machine implementations basically relied on ignoring nodes when they were not useful to the current state. While this is still possible in ROS 2, lifecycle nodes offer significant advantages from an efficiency standpoint: @@ -41,6 +41,7 @@ Please note that ROS offers a lot of freedom when implementing these states (eve Secondary states: also known as "transition states", these states serve as buffers between primary states, where the node will be doing some internal operation relating to a corresponding `transition` function. These states are: + + `Configuring` + `CleaningUp` + `ShuttingDown` @@ -48,7 +49,7 @@ Secondary states: also known as "transition states", these states serve as buffe + `Deactivating` + `ErrorProcessing` -While almost all these states' functionalities and their corresponding transition functions can be easily inferred from the lifecycle diagram, `ErrorProcessing` deserves some extra explanation. As you can see from the diagram, sometimes transition states can fail, returning to the previous primary state. This is *not* the purpose of `ErrorProcessing`. The transition state will return to the original primary state when it's function fails "logically", e.g. the program has to be running for 10 minutes before the node activates, checked for inside an if-loop. The `ErrorProcessing`, on the other hand, is reached when an error is *raised*, e.g. you tried dividing something by zero. +While almost all these states' functionalities and their corresponding transition functions can be easily inferred from the lifecycle diagram, `ErrorProcessing` deserves some extra explanation. As you can see from the diagram, sometimes transition states can fail, returning to the previous primary state. This is **not** the purpose of `ErrorProcessing`. The transition state will return to the original primary state when it's function fails "logically", e.g. the program has to be running for 10 minutes before the node activates, checked for inside an if-loop. The `ErrorProcessing`, on the other hand, is reached when an error is **raised**, e.g. you tried dividing something by zero. ## Triggering Transitions @@ -63,21 +64,25 @@ With all this in mind, changing a node state can happen in two ways: either thro ### CLI Lifecycle For CLI commands, you can run: + ```bash ros2 lifecycle ``` Start the lifecycle talker node provided with ROS: + ```bash ros2 run lifecycle lifecycle_talker ``` To get the state the node is in, run + ```bash ros2 lifecycle get /lc_talker ``` Which should return + ```bash unconfigured [1] ``` @@ -85,11 +90,13 @@ unconfigured [1] As expected. The number in brackets is the id of the node state. This is not super relevant for node states, as these ids are not really used for commands. Much more interesting are the ids for transitions. If you run: + ```bash ros2 lifecycle list /lc_talker ``` You should get as output: + ```bash - configure [1] Start: unconfigured @@ -102,11 +109,13 @@ You should get as output: These are the possible transitions from primary state `Unconfigured`, as shown in the lifecycle diagram. Note the ids here, as they will be useful when discussing services. To change states, you should call the command `set` with the transition function name e.g.: + ```bash ros2 lifecycle set /lc_talker configure ``` Returning to the `lc_talker` terminal should reveal the messages: + ```bash [INFO] [1732664038.655707440] [lc_talker]: on_configure() is called. [INFO] [1732664039.655992380] [lc_talker]: Lifecycle publisher is currently inactive. Messages are not published. @@ -119,6 +128,7 @@ Returning to the `lc_talker` terminal should reveal the messages: All these lifecycle commands are basically services. For example, we can make a standard service call to get the current state of the node: + ```bash ros2 service call /lc_talker/get_state lifecycle_msgs/GetState ``` @@ -129,6 +139,7 @@ lifecycle_msgs.srv.GetState_Response(current_state=lifecycle_msgs.msg.State(id=2 ``` See the id field? This is where they become important. For service calls requesting state transitions, you need to know the id of the transition (not to be confused with the id of the state itself). To get those, you could run, for example: + ```bash ros2 service call /lc_talker/get_available_transitions lifecycle_msgs/srv/GetAvailableTransitions ``` @@ -139,11 +150,13 @@ lifecycle_msgs.srv.GetAvailableTransitions_Response(available_transitions=[lifec ``` The output is a bit confusing (and better seen in RQt), but we can notice that the id for `activate` is 3. If we want to move to that state, a service call is also possible: + ```bash ros2 service call /lc_talker/change_state lifecycle_msgs/ChangeState "{transition: {id: 3}}" ``` This service also has a `label` field, which is not required (but highly recommended). Back in the talker terminal: + ```bash [INFO] [1732664498.641014385] [lc_talker]: Lifecycle publisher is active. Publishing: [Lifecycle HelloWorld #459] ``` @@ -152,9 +165,10 @@ When inside the code, all lifecycle changes are done through service calls. More ## In Code -You can find the lifecycle examples at the ROS demo [github](https://github.com/ros2/demos/tree/rolling/lifecycle/src). This guide will comment just a few key points on that code. +You can find the lifecycle examples at the ROS demo [github](https://github.com/ros2/demos/tree/rolling/lifecycle/src).This guide will comment just a few key points on that code. Right at the definition of the talker node, we see: + ```cpp class LifecycleTalker : public rclcpp_lifecycle::LifecycleNode ``` @@ -162,6 +176,7 @@ class LifecycleTalker : public rclcpp_lifecycle::LifecycleNode Note that the node doesn't inherit from the typical `rclcpp:Node` class. Not all node capabilities are available for a lifecycle node (and vice-versa, obviously). As for the callback functions, you can see that they have special signatures and return values: + ```cpp rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_configure(const rclcpp_lifecycle::State &) @@ -192,7 +207,8 @@ rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn From the code, you can also see that `on_configure()` (and the other callbacks) are never explicitly defined as service callbacks. The lifecycle framework takes care of that. -The last point that should be highlighted is in `main`. Notice the node is note run as a regular node: +The last point that should be highlighted is in `main`. Notice the node is not run as a regular node: + ```cpp rclcpp::init(argc, argv); @@ -211,6 +227,7 @@ rclcpp::shutdown(); Executors are beyond the scope of this document, but you can read more about them [here](https://docs.ros.org/en/foxy/Concepts/About-Executors.html). Finally, as kind of a side note, you can also launch and trigger lifecycle nodes from launch files, as explained in [1]: + ```python from launch import LaunchDescription from launch_ros.actions import LifecycleNode diff --git a/wiki/computing/quantum.md b/wiki/computing/quantum.md index 52a86477..2d04b01b 100644 --- a/wiki/computing/quantum.md +++ b/wiki/computing/quantum.md @@ -9,7 +9,7 @@ title: Quantum Computing and the Qiskit Package # The 'title' is automatically displayed at the top of the page # and used in other parts of the site. --- -With the undeniable rise of quantum computers, future generations of roboticists must be versed in the functioning and applications of this technology. However, very few concise guides exist that explain quantum computing in introductory terms for a techincal audience. This article shows some basic principles of quantum computing together with the Python package Qiskit, developed by IBM. +With the undeniable rise of quantum computers, future generations of roboticists must be versed in the functioning and applications of this technology. However, very few concise guides exist that explain quantum computing in introductory terms for a technical audience. This article shows some basic principles of quantum computing together with the Python package Qiskit, developed by IBM. ## Fundamentals of Quantum Computing - Single Qubit Systems @@ -28,7 +28,7 @@ $$ We can use the electron’s spin (or some other physical entity bound by quantum mechanics) as a means of transmitting information, therefore stepping into the world of quantum computing (QC). -Any quantum signal whose state can be written as a superposition of two binary states is a "quibt". In our example, the spin of a single electron is a qubit. The pair $\{|0\rangle, |1\rangle\}$ represents an orthonormal basis, called the computational basis, which can be used to perform measurements. These measurements allow us to access the information stored in a qubit and transform it into a classical signal, or "cbit" (classical bit). This is generally done by assigning $|0\rangle \rightarrow 0$ and $|1\rangle \rightarrow 1$. +Any quantum signal whose state can be written as a superposition of two binary states is a "qubit". In our example, the spin of a single electron is a qubit. The pair $\{|0\rangle, |1\rangle\}$ represents an orthonormal basis, called the computational basis, which can be used to perform measurements. These measurements allow us to access the information stored in a qubit and transform it into a classical signal, or "cbit" (classical bit). This is generally done by assigning $|0\rangle \rightarrow 0$ and $|1\rangle \rightarrow 1$. Some differences in relation to classical computing already start to appear. Consider, for example, the qubit whose state is given by $|\psi\rangle = \frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle$. If we measure this signal with respect to the computational basis, we get $Pr[|0\rangle] = Pr[|1\rangle] = \frac{1}{2}$, meaning that the same signal, when converted to a classical bit (using the equivalence previously established) will yield bit 0 50% of the time and bit 1 50% of the time. Therefore, the same signal can result in different values when measured. This property is what makes QC different than classical computing. While a classical bit can be either 0 or 1, a quantum bit exists as a whole range of superpositions, and its measured value is probabilistic. @@ -54,7 +54,7 @@ Back to the technical bit. We previously mentioned the computational basis $\{|0 There are several ways to represent a single qubit. One of them is the vector representation, which is particularly useful when we wish to represent operators/gates as matrices. In this representation, a state such is written as $|\psi\rangle = \begin{bmatrix} \alpha \\ \beta \end{bmatrix}$. Henceforth, whenever a vector notation is used, we'll assume it is with respect to the computational basis. -Another representation of a single qubit system relates to the concepts of global phase and relative phase. Two qubit states $|\psi\rangle$ and $|\psi'\rangle$ are considered equivalent ($|\psi\rangle \sim |\psi'\rangle$) if there exists a value $\alpha \in [0, 2\pi)$ such that $|\psi\rangle = e^{i \alpha} |\psi'\rangle$. The angle $\alpha$ is called the global phase of the state. By manipulating the global phase of the state, it is possible to see that any qubit state can be written as $|\psi\rangle = \begin{bmatrix} \cos{\frac{\theta}{2}} \\ e^{i\varphi} \sin{\frac{\theta}{2}}\end{bmatrix}$, with $\theta \in [0, \pi]$ and $\varphi \in [0, 2\pi)$. The angle $\varphi$ is called the relative phase. The angle pair $(\theta, \varphi)$ can be used to represent the qubit using the so-called "Bloch sphere", which is shown below. In the Bloch sphere, we represent the state $|\psi\rangle$ as a unit vector from the origin, with $\theta$ being its polar angle and $\varphi$ its azimuth angle. Another feature of the Bloch sphere is that it maps the special states previosuly described to key points on the sphere's surface. +Another representation of a single qubit system relates to the concepts of global phase and relative phase. Two qubit states $|\psi\rangle$ and $|\psi'\rangle$ are considered equivalent ($|\psi\rangle \sim |\psi'\rangle$) if there exists a value $\alpha \in [0, 2\pi)$ such that $|\psi\rangle = e^{i \alpha} |\psi'\rangle$. The angle $\alpha$ is called the global phase of the state. By manipulating the global phase of the state, it is possible to see that any qubit state can be written as $|\psi\rangle = \begin{bmatrix} \cos{\frac{\theta}{2}} \\ e^{i\varphi} \sin{\frac{\theta}{2}}\end{bmatrix}$, with $\theta \in [0, \pi]$ and $\varphi \in [0, 2\pi)$. The angle $\varphi$ is called the relative phase. The angle pair $(\theta, \varphi)$ can be used to represent the qubit using the so-called "Bloch sphere", which is shown below. In the Bloch sphere, we represent the state $|\psi\rangle$ as a unit vector from the origin, with $\theta$ being its polar angle and $\varphi$ its azimuth angle. Another feature of the Bloch sphere is that it maps the special states previously described to key points on the sphere's surface. ![Representing a state on the Bloch sphere](/assets/images/computing/bloch.png) @@ -153,7 +153,7 @@ As a general formula for the Bell states, we can write $|\Psi^{ij}\rangle = \fra ## Operators and Quantum Ports -Operators will be defined as transformations from the state space of a quantum system to itself \cite{rieffel2011quantum}. Not all operators imaginable are permissible, for they must satisfy the rules of quantum mechanics. Namely, the operators, once defined in their vector spaces, need to satisfy the requirements of linearity, for the principle of superposition to hold, and the preservation of the inner product, so that no contradictions arise in terms of measurement. In these equations, $U$ is an operator and $U^\dag$ means the complex conjugate transpose of $U$. Operators can be represented as both matrices or bra-ket entities. +Operators will be defined as transformations from the state space of a quantum system to itself [1]. Not all operators imaginable are permissible, for they must satisfy the rules of quantum mechanics. Namely, the operators, once defined in their vector spaces, need to satisfy the requirements of linearity, for the principle of superposition to hold, and the preservation of the inner product, so that no contradictions arise in terms of measurement. In these equations, $U$ is an operator and $U^\dag$ means the complex conjugate transpose of $U$. Operators can be represented as both matrices or bra-ket entities. Linearity: @@ -234,7 +234,7 @@ Gates can be combined into circuits. The circuits shown in this work, such as th 1. Information flows from left to right; 2. Qubit registers, which are represented by single lines, are numbered, and the higher the value, the more signification the qubit; 3. Double lines represent classical bits, It is possible to have either many double lines, each one representing a bit, or a single double line representing a bit string; -4. Measurements, which are always done against the computational basis, take a 1-qubit state to a classical bit in accordance to the encoding in section \ref{sec:single_qubit}. If measuring into a bit string, significance is preserved; +4. Measurements, which are always done against the computational basis, take a 1-qubit state to a classical bit in accordance to the encoding in the section on Single Qubit Systems. If measuring into a bit string, significance is preserved; 5. Gates are represented by squares, with the operator involved represented by letters. diff --git a/wiki/tools/usb-compute-sticks.md b/wiki/tools/usb-compute-sticks.md index 60b1a103..fd25a492 100644 --- a/wiki/tools/usb-compute-sticks.md +++ b/wiki/tools/usb-compute-sticks.md @@ -20,12 +20,12 @@ As of the time of writing, we have found at CMU: ![NCS2 (top) and Plai Plug 2803 (bottom)](/assets/images/tools/sticks.png) -In terms of usefulness, these sticks don’t add that much power to most modern computers. Your typical notebook GPU (and even CPU) will generally be able to handle more visual processing than the sticks, especially considering real-time applications. *These sticks are useful, however, when you have to do visual inference on low-power hardware, such as running object detection using a Raspberry Pi, for example. Or when the CPU/GPU of your system will already be in full demand, such as in autonomous drone flight. In these cases, the sticks can increase the speed of your program.* +In terms of usefulness, these sticks don’t add that much power to most modern computers. Your typical notebook GPU (and even CPU) will generally be able to handle more visual processing than the sticks, especially considering real-time applications. **These sticks are useful, however, when you have to do visual inference on low-power hardware, such as running object detection using a Raspberry Pi, for example. Or when the CPU/GPU of your system will already be in full demand, such as in autonomous drone flight. In these cases, the sticks can increase the speed of your program.** ![Stick with Raspberry Pi](/assets/images/tools/stick-raspi.png) ### Pros and cons of each stick -*Intel NCS2*: +**Intel NCS2**: +Documentation provided by intel @@ -39,7 +39,7 @@ In terms of usefulness, these sticks don’t add that much power to most modern -Getting the stick to work is not trivial -*Gyrfalcon Tech Plai Plug 2803*: +**Gyrfalcon Tech Plai Plug 2803**: +Honestly, I didn’t find any… but please feel free to use this stick and prove me wrong @@ -145,8 +145,8 @@ $ omz_converter --name human-pose-estimation-3d-0001 --precisions FP16 -d . -o . If you do run the conversion command, make sure you have installed the framework (torch, tensorflow, etc.) used by the original model. -Now that the model has been downloaded and converted, *copy the .bin and .xml files into the -computer where you will run the application*. +Now that the model has been downloaded and converted, **copy the .bin and .xml files into the +computer where you will run the application**. ### Installing OpenVINO runtime in your computer