# 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:

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:

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.

### 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:

---
**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:

## 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

> O erro indica que não foi possível encontrar uma biblioteca padrão de interação com os pinos
ou

> 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
```