From 2daa17c43b693a6b841ae436346d256dd29e4fd0 Mon Sep 17 00:00:00 2001 From: Nevin Valsaraj Date: Thu, 24 Sep 2026 00:28:45 -0700 Subject: [PATCH 1/2] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0c3ded0a1df16cba8a89e9004fc6664d4f246880 Author: Nevin Valsaraj Date: Thu Sep 24 00:21:15 2026 -0700 PR review remediation: centralize images, fix paths, typos, and links - Move 27 images from wiki/*/assets/ to assets/images// - Update all image references to absolute /assets/images/ paths - Fix empty link [ROS Design Website]() in ros-lifecycle.md - Fix typos: quibt→qubit, techincal→technical, previosuly→previously, note→not - Remove LaTeX artifacts (\cite, \ref) from quantum.md - Add missing language tag to xenial repos code block in usb-compute-sticks.md commit cabebcca68bd02dc9ec437901da02093aade3226 Merge: 742965d 23696b8 Author: Leo Mouta Date: Tue Nov 26 19:36:09 2024 -0500 Merge remote-tracking branch 'origin/F24_TeamA' commit 23696b8f21d358028289b3aaafcf23d9f440858a Author: Leo Mouta Date: Tue Nov 26 19:16:23 2024 -0500 Images commit a474285cbbbdc9f409f3cb23ce7c5a221656ba16 Author: Leo Mouta Date: Tue Nov 26 19:14:25 2024 -0500 Team A F24 wiki draft commit 742965df2cf9a620cd87f0b6a28b2ba638268280 Author: Leonardo Mouta Date: Mon May 6 00:40:30 2024 -0400 Extra credit entries commit a2e9f6e0f7645317df146683887025cd1fc14812 Author: Leonardo Mouta Date: Wed May 1 00:21:49 2024 -0400 MRSD 2025 team A CreoClean wiki entry - USB Compute Sticks commit c829c7b7cd7fb613c96b46048143ef95ade1fa51 Author: Leonardo Mouta Date: Wed May 1 00:18:12 2024 -0400 MRSD 2025 team A CreoClean wiki entry - USB Compute Sticks # Conflicts: # _data/navigation.yml # wiki/common-platforms/kinova-setup-and-apis.md # wiki/common-platforms/ros/ros-lifecycle.md # wiki/computing/quantum.md # wiki/tools/usb-compute-sticks.md --- .../common-platforms/kinova-setup-and-apis.md | 6 +- wiki/common-platforms/ros/ros-lifecycle.md | 69 ++++++++++++------- wiki/computing/quantum.md | 10 +-- wiki/tools/usb-compute-sticks.md | 10 +-- 4 files changed, 56 insertions(+), 39 deletions(-) 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..73caedc1 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: @@ -32,52 +32,57 @@ There are two types of states a node can be in: Primary states: these are the steady states, represented in blue in the picture. A node can be in a primary state indeterminately. These states are: -+ `unconfigured`: this is the state the node will be in as soon as it is instantiated. If a non-fatal error is raised during operation, the node can come back to this state. -+ `inactive`: the node has been been configured, but it is not running any process. Beware: the node can still queue data (e.g. from subscribed topics) while in this state. It will just not perform anything. -+ `active`: this is where the node behaves as a "traditional" node, performing it's operations regularly. -+ `finalized`: this is where nodes go when they fail or are terminated. The node will still exist for debugging purposes, but cannot be re-run. For the node to vanish, a `destroy()` function has to be called. ++ ```unconfigured```: this is the state the node will be in as soon as it is instantiated. If a non-fatal error is raised during operation, the node can come back to this state. ++ ```inactive```: the node has been been configured, but it is not running any process. Beware: the node can still queue data (e.g. from subscribed topics) while in this state. It will just not perform anything. ++ ```active```: this is where the node behaves as a "traditional" node, performing it's operations regularly. ++ ```finalized```: this is where nodes go when they fail or are terminated. The node will still exist for debugging purposes, but cannot be re-run. For the node to vanish, a ```destroy()``` function has to be called. Please note that ROS offers a lot of freedom when implementing these states (even their demo strays a bit from the convention above). Try to keep your use reasonable for other developers. -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: +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` -+ `Activating` -+ `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. ++ ```Configuring``` ++ ```CleaningUp``` ++ ```ShuttingDown``` ++ ```Activating``` ++ ```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. ## Triggering Transitions -As the diagram shows, there are transitions between the states. It is possible to see that they usually come in pairs. For example, there is transition function `configure()` and there is also a `onConfigure()` function inside the node secondary state `Configuring`. The nomenclature can be a bit confusing, so here is a brief explanation: +As the diagram shows, there are transitions between the states. It is possible to see that they usually come in pairs. For example, there is transition function ```configure()``` and there is also a ```onConfigure()``` function inside the node secondary state ```Configuring```. The nomenclature can be a bit confusing, so here is a brief explanation: -+ `function()`: This is the name used by the lifecycle framework to trigger transitions. When you want to tell a node to move into another state (more in a sec), this is the name you use. These names come with ROS and don't need additional programming. -+ `onFunction()`: This is a callback function, defined inside the node, that will be actually responsible for performing the state transition. In other words, this is the function that is actually aware of what the node is. When the lifecycle manager calls `node1 configure`, it is the function `onConfigure()`, inside `node1` that will be executed. -+ `Functioning`: This is the (transient) state the node is at while executing callback function `onFunction()`. ++ ```function()```: This is the name used by the lifecycle framework to trigger transitions. When you want to tell a node to move into another state (more in a sec), this is the name you use. These names come with ROS and don't need additional programming. ++ ```onFunction()```: This is a callback function, defined inside the node, that will be actually responsible for performing the state transition. In other words, this is the function that is actually aware of what the node is. When the lifecycle manager calls ```node1 configure```, it is the function ```onConfigure()```, inside ```node1``` that will be executed. ++ ```Functioning```: This is the (transient) state the node is at while executing callback function ```onFunction()```. With all this in mind, changing a node state can happen in two ways: either through CLI tools or through a service call. ### 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 @@ -99,14 +106,16 @@ You should get as output: Goal: shuttingdown ``` -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. +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.: -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: +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 ``` @@ -138,12 +149,14 @@ response: lifecycle_msgs.srv.GetAvailableTransitions_Response(available_transitions=[lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=2, label='cleanup'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=11, label='cleaningup')), lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=3, label='activate'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=13, label='activating')), lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=6, label='shutdown'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=12, label='shuttingdown'))]) ``` -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: +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: +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,16 +165,18 @@ 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 ``` -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). +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 &) @@ -190,9 +205,10 @@ 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. +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 not run as a regular node: -The last point that should be highlighted is in `main`. Notice the node is note 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 From 3f136f6a17006a5ace883d9aa5f1cd2f56d19289 Mon Sep 17 00:00:00 2001 From: Nevin Valsaraj Date: Thu, 24 Sep 2026 00:37:31 -0700 Subject: [PATCH 2/2] Fix inline code blocks: use single backticks instead of triple backticks Triple backticks (). This was breaking markdown parsing of the ros-lifecycle.md page. --- wiki/common-platforms/ros/ros-lifecycle.md | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/wiki/common-platforms/ros/ros-lifecycle.md b/wiki/common-platforms/ros/ros-lifecycle.md index 73caedc1..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: @@ -32,32 +32,32 @@ There are two types of states a node can be in: Primary states: these are the steady states, represented in blue in the picture. A node can be in a primary state indeterminately. These states are: -+ ```unconfigured```: this is the state the node will be in as soon as it is instantiated. If a non-fatal error is raised during operation, the node can come back to this state. -+ ```inactive```: the node has been been configured, but it is not running any process. Beware: the node can still queue data (e.g. from subscribed topics) while in this state. It will just not perform anything. -+ ```active```: this is where the node behaves as a "traditional" node, performing it's operations regularly. -+ ```finalized```: this is where nodes go when they fail or are terminated. The node will still exist for debugging purposes, but cannot be re-run. For the node to vanish, a ```destroy()``` function has to be called. ++ `unconfigured`: this is the state the node will be in as soon as it is instantiated. If a non-fatal error is raised during operation, the node can come back to this state. ++ `inactive`: the node has been been configured, but it is not running any process. Beware: the node can still queue data (e.g. from subscribed topics) while in this state. It will just not perform anything. ++ `active`: this is where the node behaves as a "traditional" node, performing it's operations regularly. ++ `finalized`: this is where nodes go when they fail or are terminated. The node will still exist for debugging purposes, but cannot be re-run. For the node to vanish, a `destroy()` function has to be called. Please note that ROS offers a lot of freedom when implementing these states (even their demo strays a bit from the convention above). Try to keep your use reasonable for other developers. -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: +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``` -+ ```Activating``` -+ ```Deactivating``` -+ ```ErrorProcessing``` ++ `Configuring` ++ `CleaningUp` ++ `ShuttingDown` ++ `Activating` ++ `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 -As the diagram shows, there are transitions between the states. It is possible to see that they usually come in pairs. For example, there is transition function ```configure()``` and there is also a ```onConfigure()``` function inside the node secondary state ```Configuring```. The nomenclature can be a bit confusing, so here is a brief explanation: +As the diagram shows, there are transitions between the states. It is possible to see that they usually come in pairs. For example, there is transition function `configure()` and there is also a `onConfigure()` function inside the node secondary state `Configuring`. The nomenclature can be a bit confusing, so here is a brief explanation: -+ ```function()```: This is the name used by the lifecycle framework to trigger transitions. When you want to tell a node to move into another state (more in a sec), this is the name you use. These names come with ROS and don't need additional programming. -+ ```onFunction()```: This is a callback function, defined inside the node, that will be actually responsible for performing the state transition. In other words, this is the function that is actually aware of what the node is. When the lifecycle manager calls ```node1 configure```, it is the function ```onConfigure()```, inside ```node1``` that will be executed. -+ ```Functioning```: This is the (transient) state the node is at while executing callback function ```onFunction()```. ++ `function()`: This is the name used by the lifecycle framework to trigger transitions. When you want to tell a node to move into another state (more in a sec), this is the name you use. These names come with ROS and don't need additional programming. ++ `onFunction()`: This is a callback function, defined inside the node, that will be actually responsible for performing the state transition. In other words, this is the function that is actually aware of what the node is. When the lifecycle manager calls `node1 configure`, it is the function `onConfigure()`, inside `node1` that will be executed. ++ `Functioning`: This is the (transient) state the node is at while executing callback function `onFunction()`. With all this in mind, changing a node state can happen in two ways: either through CLI tools or through a service call. @@ -106,15 +106,15 @@ You should get as output: Goal: shuttingdown ``` -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. +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.: +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: +Returning to the `lc_talker` terminal should reveal the messages: ```bash [INFO] [1732664038.655707440] [lc_talker]: on_configure() is called. @@ -149,13 +149,13 @@ response: lifecycle_msgs.srv.GetAvailableTransitions_Response(available_transitions=[lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=2, label='cleanup'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=11, label='cleaningup')), lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=3, label='activate'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=13, label='activating')), lifecycle_msgs.msg.TransitionDescription(transition=lifecycle_msgs.msg.Transition(id=6, label='shutdown'), start_state=lifecycle_msgs.msg.State(id=2, label='inactive'), goal_state=lifecycle_msgs.msg.State(id=12, label='shuttingdown'))]) ``` -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: +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: +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] @@ -173,7 +173,7 @@ Right at the definition of the talker node, we see: 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). +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: @@ -205,9 +205,9 @@ 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. +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 not 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);