---
# System prepended metadata

title: Capítulo 1 - Artigo 6 - Raspberry Pi
tags: [Apostila de Introdução Geral no LEAD - 2024]

---

# Capítulo 1 - Artigo 6 - Raspberry Pi

## 6.0 - Introdução
O presente artigo tem como objetivo configurar o Raspberry Pi 4,presente no laboratório, para rodar o ROS2 seja em um container dentro do Raspberry Pi OS (64-bit), seja no Ubuntu 22.04 LTS (64-bit) e posteriormente rodar os pacotes que visam interagir com o LED que serão apresentados abaixo.

## 6.0.1 - Sumário Geral do capitulo 1
1. Introdução do Capítulo
2. Instalando o ROS
3. Nó
4. Publicador
5. Subscritor       
6. Raspberry Pi   < Estamos aqui
7. Nó Raspberry
8. Launch

## 6.0.2 - Sumário Local
[TOC]

## 6.1 - Conhecendo o Raspberry Pi 4

O Raspberry Pi 4 possui como entradas de periférico mais relevantes 2 entradas mini HDMI, 1 entrada de alimentação USB-C, 4 entradas USB e uma entrada micro-SD conforme foto abaixo:

![image](https://hackmd.io/_uploads/BJNZnfd5T.png)

O Raspberry em si não possui interface inicial de configuração e faz-se necessário a instalação de um sistema operacional no micro-SD através do [Raspberry Pi Imager](https://www.raspberrypi.com/software/), interface gráfica simples e oficial para isso, onde destrincharemos o passo a passo a seguir.


## 6.2 - Instalação do Sistema Operacional

Antes de qualquer instalação é **IMPRESCINDíVEL** verificar o conteúdo presente no micro-SD uma vez que o processo de instalação da imagem deleta todo e qualquer arquivo presente no mesmo. Se houver algo no SD entrar em contato com o professor Jacoud ou outro responsável do laboratório.

A interface gráfica do Raspberry Pi Imager tem às seguintes opções:

![image](https://hackmd.io/_uploads/HyfGCMO5a.png)

No botão `Choose Device` você escolhe `Raspberry Pi 4` e em `Choose OS` o sistema operacional desejado, no caso, pode ser o `Raspberry Pi OS (64-bit)` ou em `Other general-purpose OS` e depois em `Ubuntu` e por último`Ubuntu Desktop 22.04.03 LTS (64-bit)`. Depois disso basta selecionar `NEXT` até que o processo de instalação comece e basta aguardar até o fim do processo para poder inicializar o raspberry e fazer as configurações iniciais do SO.

Antes de acessarmos o SO se faz necessário o uso de um teclado, mouse e monitor para acessarmos o sistema operacioal e posteriormente habilitarmos o ssh (acesso remoto por terminal). Como mencionado anteriormente, recomendamos 2 opões de sistema operacional e iremos destrinchar o tutorial nas 2 opções propostas.

## 6.3 - Configuração inicial do Raspberry Pi OS
A configuração do Raspberry Pi OS é bastante intuitiva no menu principal basta selecionar país, língua, fuso horário. Depois criar o usuário padrão, a rede wifi. Além disso, é necessário habilitar o ssh para conseguirmos acessar o raspberry através da rede direto do seu computador.

### 6.3.1 - Configurando ssh

Para habilitar o ssh é necessário abrir a aba com o icone do raspberry, depois ir em `Preferences`, depois `Raspberry Pi Configuration`. Na aba que abriu ir em `Interfaces` e habilitar a opção de ssh.

### 6.3.2 - Conectando via ssh

Para acessar o raspberry via ssh é necessário realizar o seguinte comando no computador:
```bash!
ssh nomeDoUsuarioDoRaspberry@ip
```
Note que o `ip` é obtido utilizando o comando abaixo no raspberry:
```bash!
hostname -I
```

### 6.3.3 - Configurando um container com ROS2 Humble

Como o ROS2 Humble roda nativamente no Ubuntu 22.04 o ideal é rodar nesse SO portanto vamos utilizar o distrobox que é um gerenciador de containers de distribuições que utiliza o docker ou o podman por baixo dos panos para criar um container isolado e seguro para rodarmos o ROS2 Humble.

Para isso é necessário seguir os seguintes passos:
```bash!
sudo apt-get install podman curl -y # Instala o podman e o curl
sudo systemctl enable --now podman # Habilita o funcionamento do podman
sudo reboot # Reinicia o raspberry
ssh nomeDoUsuarioDoRaspberry@ip # faz ssh com o raspberry novamente
curl https://raw.githubusercontent.com/89luca89/distrobox/main/install | sudo sh # Baixa o script que instala o Distrobox com o curl e o executa
cd && mkdir containers # Criar a pasta containers na raiz do usuario
cd containers && mkdir humbleV1 # Cria a pasta que guardaremos nosso container
distrobox-create --root --image docker.io/library/ros:humble-ros-base-jammy --name humbleV1 --home ~/containers/humbleV1 # Cria o container humbleV1 com volume em ~/containers/humbleV1 
distrobox enter --root humbleV1 # Entra no container criado 
sudo apt update | sudo apt upgrade -y # Atualiza o container
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc # Configura os terminais para reconhecer os comandos do ROS2 sempre que inicializar um terminal
echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> ~/.bashrc # Configura os terminais para reconhecer os comandos do colcon sempre que inicializar um terminal
source ~/.bashrc # "Reinicializando" o terminal
```



## 6.3 - Configuração inicial do Ubuntu 22.04 LTS

A configuração do Ubuntu no raspberry segue o mesmo padrão que a configuração em outros PCs. Depois de configurados o idioma, teclado, rede, região e usuário padrão conforme preferir, atualize os programas através dos comandos:
```bash!
sudo apt update
sudo apt upgrade
```

### 6.3.1 - Configurando ssh

Após as etapas anteriores é necessário habilitar o ssh para conseguirmos acessar o raspberry através da rede direto do seu computador.

Para isso é necessário o seguinte conjunto de comandos:
```bash!
sudo apt update # Verifica e atualiza os repostiórios dos programas do sistema 
sudo apt install openssh-server # Baixa o gerenciador do ssh
sudo systemctl start ssh # Habilita o ssh 
sudo systemctl enable ssh # Habilita o ssh toda vez que o computador iniciar
```
Para verificar se tudo foi configurado corretamente basta usar o seguinte comando:

```bash!
sudo systemctl status ssh # Verifica o status do ssh
```

Caso apareça algo parecido com a imagem abaxo, está tudo correto e basta precionar `q` para continuar.

![image](https://hackmd.io/_uploads/BJ3sBglj6.png)


### 6.3.2 - Conectando via ssh

Feito oque foi descrito acima para acessar o raspberry via ssh é necessário realizar o seguinte comando no computador:
```bash!
ssh nomeDoUsuarioDoRaspberry@ip
```
Note que o `ip` é obtido utilizando o comando abaixo no raspberry:
```bash!
hostname -I
```

### 6.4 - Instalando ROS2 e Colcon

Agora só nos resta instalar o ROS2 Humble e suas dependências com os seguintes comandos:
```bash!
sudo apt update && sudo apt install curl -y # Verifica os repositórios e instala o curl com a flag -y preenchendo com "yes" as possíveis perguntas
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg # Usa o curl para baixar a GPG key necessária para acessar o repositório do ROS2
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null # Adiciona o repostório na source list para atualizações futuras
sudo apt update # Verifica e atualiza os repostiórios dos programas do sistema  
sudo apt upgrade -y # Instala as versões dos respotirórios dos programas do sistema com a flag -y preenchendo com "yes" as possíveis perguntas
sudo apt install ros-humble-ros-base -y # Instala a versão base do ROS2 Humble com a flag -y preenchendo com "yes" as possíveis perguntas
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc # Configura os terminais para reconhecer os comandos do ROS2 sempre que inicializar um terminal
sudo apt install python3-colcon-common-extensions -y # Instala o colcon com a flag -y preenchendo com "yes" as possíveis perguntas
echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> ~/.bashrc # Configura os terminais para reconhecer os comandos do colcon sempre que inicializar um terminal
source ~/.bashrc # "Reinicializando" o terminal
```
Abaixo explicaremos como funciona o pacote criado para o Raspberry e suas peculiaridades em cada um dos SO's citados, mas antes é necessário fazer as ligações do LED com o Raspberry Pi.

## 6.5 - Ligação dos pinos no Raspberry 

Note o pinout do Raspberry:
![image](https://hackmd.io/_uploads/Sk8iWpyoa.png)

---

**CUIDADO!! Preste MUITA atenção nessa parte pois um descuido na hora de ligar os pinos pode levar à queima do Raspberry**

---

De acordo com os arquivos do pacote o pino inicialmente configurado para receber o sinal de liga e desliga do LED é a `GPIO17` sendo necessário a montagem do seguinte esquema:

![image](https://hackmd.io/_uploads/rJX2xakj6.png)

## 6.6 - Criação e configuração do pacote Blink Tutorial

O pacote Blink Tutorial consiste em um pacote ROS2 que faz com que o LED pisque de diferentes formas. 

De forma análoga em ambos os sistemas operacionais podemos criar o workspace e o pacote através do ROS2 com os seguintes comandos:

```bash!
sudo apt update # Verifica e atualiza os repostiórios dos programas do sistema 
cd && mkdir tutorial_ws  # À partir do diretório raiz do usuario cria a pasta tutorial_ws
cd tutorial_ws && mkdir src # Navega até a pasta tutorial_ws e cria a pasta src (source)
colcon build # Configura o Workspace ROS
echo "source ~/tutorial_ws/install/setup.bash" >> ~/.bashrc # Configura os terminais para reconhecer os comandos dos pacotes dentro do workspace
source ~/.bashrc # "Reinicializando" o terminal
sudo apt install python3-gpiozero -y # Instala a dependencia gpiozero que cuida da interface com as gpios do raspberry
cd src && ros2 pkg create blink_tutorial --build-type ament_python --dependencies rclpy std_msgs gpiozero # Navega até a pasta src e cria o pacote blink_tutorial de linguagem python com as dependencias rclpy std_msgs gpiozero
cd .. && colcon build # Retorna a pasta raiz do workspace e atualiza o workspace para incluir o pacote criado
```
Configurado o pacote podemos criar e configurar os nós como mostrado abaixo.

## 6.6 - Criação e configuração do Nó de teste de pinagens

O nó de teste de pinagens serve para verificar se as bibliotecas de acesso a gpio e o esquemático estão corretamente configurados, alternando o estado do LED de acordo com o tempo estabelecido na criação do nó.

### 6.6.1 - Criação do Nó

Para confeccionar esse nó fazemos o seguinte conjunto de comandos:

```bash!
cd ~/tutorial_ws/src/blink_tutorial/blink_tutorial/ # Navega até a pasta ~/tutorial_ws/src/blink_tutorial/blink_tutorial/ onde devemos criar os códigos dos nós desse pacote
touch blink_test.py # Criação do arquivo que conterá o código do nó de teste de pinagens
chmod +x blink_test.py # Transformando esse arquivo em um executável
```

### 6.6.2 - Configurando o Nó 

Agora precisamos editar o arquivo `~/tutorial_ws/src/blink_tutorial/setup.py` para adicionar um comando para executar esse nó. Particularmente eu gosto do vim para edição de arquivos no terminal mas se preferir pode usar o nano (o code nesse caso não abriria porque estamos por ssh e não temos acesso a interface gráfica mas se não estiver por ssh use o editor que preferir). Abaixo tem o conjunto de comandos necessários para instalar o vim e abrir esse arquivo.

```bash!
sudo apt update # Verifica e atualiza os repositórios dos programas do sistema 
sudo apt install vim -y # Instala o vim com a flag -y preenchendo com "yes" as possíveis perguntas
vim ~/tutorial_ws/src/blink_tutorial/setup.py # Abre ~/tutorial_ws/src/blink_tutorial/setup.py no vim
```
Ao executar esse comando temos a seguinte resposta:

```python=
from setuptools import find_packages, setup

package_name = 'blink_tutorial'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='leadpi4-pios',
    maintainer_email='leadpi4-pios@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)
```

>Obs: Alguns comandos úteis do vim:
>* `i` para ativar o modo de edição
>* `esc` para sair do modo de edição
>* `dd`para deletar uma linha (só funciona fora do modo de edição)
>* `u` para desfazer a ultima modificacao (só funciona fora do modo de edição)
>* `:wq` salva e sai (só funciona fora do modo de edição)
>* `:q `sai (só funciona fora do modo de edição)

Agora se quisermos adicionar esse nó como um executável de nome `blink_test` podemos editar `entry_points` da seguinte forma:

```python=
from setuptools import find_packages, setup

package_name = 'blink_tutorial'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='leadpi4-pios',
    maintainer_email='leadpi4-pios@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            "blink_test= blink_tutorial.blink_test:main"
        ],
    },
)
```
Basicamente oque fizemos foi configurar o nó executável `blink_test` como a execução da função `main` existente dentro do arquivo `blink_test` do pacote `blink_tutorial`

Além disso, no caso do Ubuntu é necessário usar os comandos abaixos para termos acesso às GPIOs:
```bash!
sudo adduser "${USER}" dialout # Adiciona o usuário ao grupo de acesso as GPIOs no Ubuntu
sudo reboot # Reinicia o raspberry
```
Agora podemos editar tranquilamente o nó editando o arquivo `~/tutorial_ws/src/blink_tutorial/blink_tutorial/blink_test.py` e a cada necessidade de execução após edição desse arquivo é necessário dar um `colcon build` em `~/tutorial_ws/` para recompilar o pacote.

### 6.6.3 - Editando o Nó

O código para esse nó está descrito abaixo, feito dessa vez com classes para termos uma outra perspectiva de implementação de um nó, sendo destrinchado em seguida:

```pyhton=
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from gpiozero import LED

class BlinkNode(Node):
    def __init__(self):
        super().__init__(node_name="blink_test")
        self.create_timer(1,self.blink_callback)
        self.led = LED(17)

    def blink_callback(self):
        self.led.toggle()


def main(args=None):
    rclpy.init(args=args)
    node = BlinkNode()
    rclpy.spin(node)
    rclpy.shutdown()
```
> . Na linha 1 configuramos o tipo de python que vamos usar
> . Na linha 2 e 3 importamos a biblioteca do ROS2 em python a `rclpy` 
> . Na linha 4 importamos a biblioteca gpiozero de interação com as GPIOs
> . Nas linhas 6 a 13 criamos uma classe `BlinkNode(Node)` que herda as características e métodos da classe `Node` do `rlcy` e criamos seu construtor `__init__()` nas linhas 7 a 10 e uma outra função `blink_callback()` nas linhas 12 a 13 que explicaremos abaixo.
    >> . Na linha 8 do construtor chamamos o construtor da classe que herdamos através do método `super().__init__()` inicializando-o com o nome do nó
    >> . Além disso na linha 9 nós criamos um timer através do método herdado `self.create_timer()` que a cada `1` segundo executará a função `blink_callback()`
    >> . Na linha 10 inicializamos um atributo chamado `led` inicializando como um objeto do tipo `LED` da lib `gpiozero` com o pino `17`
    >> . Na linha 12 e 13 criamos o método `blink_callback()` que utiliza o método `toggle()` da classe `LED` que alterna o estado anterior do led no pino 17
    >> 
> . Da linha 15 a 19 criamos a função `main` que inicializa o ROS2 e o nó
    >> . Na linha 16 inicializamos o ROS2
    >> . Na linha 17 criamos o nó à partir da classe `BlinkNode()`
    >> . Na linha 18 mantemos o nó ativo através do uso do método `spin()`
    >> . Por fim na linha 19 finalizamos o ROS2

Não se esqueça do `colcon build` em `~/tutorial_ws/` para recompilar o pacote. Se tudo der certo o LED deverá piscar de 1 em 1 segundo e se desejar mudar esse tempo basta alterar o valor `1` do primeiro argumento do método `create_timer()`.

## 6.4 - Erros comuns no Raspberry Pi OS

## 6.4 - Erros comuns no Ubuntu 22.04

### 6.4.1.Problemas com gpiozero

![image](https://hackmd.io/_uploads/BkeXuzesa.png)
> O erro indica que não foi possível encontrar uma biblioteca padrão de interação com os pinos

ou

![image](https://hackmd.io/_uploads/B1yf6GWjp.png)
> O erro indica que não foi possível ter acesso aos pinos

O gpiozero é uma lib que intermedia a interação com as gpios de maneira mais amigável e genérica que as interfaces providas pelos sistemas operacionais, portanto ela interage por debaixo dos panos com a biblioteca do SO responsável por prover interação com as gpios e normalmente essa lib precisa de acesso root, abaixo soluções para esse problema:

* Use o conjunto de comandos abaixo: 
 
```bash!
sudo adduser "${USER}" dialout # Adiciona o usuário ao grupo de     acesso as GPIOs no Ubuntu
sudo reboot # Reinicia o raspberry
```
* Caso o problema persista use o seguinte comando:

```bash!
export GPIOZERO_PIN_FACTORY=lgpio # Configura a biblioteca a ser utilizada por baixo dos panos pela gpiozero
```       







