Robótica
Como encontrar a posição final de um braço robótico com 3 servos

Como encontrar a posição final de um braço robótico com 3 servos

Um braço robótico é uma estrutura mecânica articulada que pode ser controlada por meio de servos. Cada servo é responsável por controlar o movimento em um eixo específico, como o eixo X, Y ou Z. Para encontrar a posição final do braço robótico nos eixos X e Y, é necessário utilizar uma fórmula que leve em consideração os ângulos de rotação de cada servo.

Fórmula para encontrar a posição final

A fórmula para encontrar a posição final de um braço robótico com 3 servos nos eixos X e Y é baseada na trigonometria. Vamos supor que os ângulos de rotação dos servos sejam representados por θ1, θ2 e θ3, respectivamente.

Para o eixo X:

X = L1 * cos(θ1) + L2 * cos(θ1 + θ2) + L3 * cos(θ1 + θ2 + θ3)

Para o eixo Y:

Y = L1 * sin(θ1) + L2 * sin(θ1 + θ2) + L3 * sin(θ1 + θ2 + θ3)

Onde:

  • L1, L2 e L3 são os comprimentos dos segmentos do braço robótico;
  • θ1, θ2 e θ3 são os ângulos de rotação dos servos.

Exemplo prático

Vamos supor que o braço robótico tenha os seguintes comprimentos de segmentos:

  • L1 = 10 cm
  • L2 = 15 cm
  • L3 = 20 cm

E que os ângulos de rotação dos servos sejam:

  • θ1 = 45°
  • θ2 = 30°
  • θ3 = 60°

Substituindo os valores na fórmula, temos:

X = 10 * cos(45°) + 15 * cos(45° + 30°) + 20 * cos(45° + 30° + 60°)

Y = 10 * sin(45°) + 15 * sin(45° + 30°) + 20 * sin(45° + 30° + 60°)

Calculando os valores, obtemos:

X ≈ 32,07 cm

Y ≈ 31,75 cm

Portanto, a posição final do braço robótico nos eixos X e Y é aproximadamente (32,07 cm, 31,75 cm).

Considerações finais

A fórmula apresentada permite encontrar a posição final de um braço robótico nos eixos X e Y com base nos ângulos de rotação dos servos e nos comprimentos dos segmentos do braço. É importante lembrar que essa fórmula assume que o braço robótico opera em um plano bidimensional e que não há interferências ou restrições adicionais.

Além disso, é fundamental ter em mente que a precisão da posição final depende da precisão dos ângulos de rotação dos servos e dos comprimentos dos segmentos do braço. Qualquer imprecisão ou erro na medição ou no controle dos servos pode afetar a posição final do braço robótico.

Em resumo, a fórmula apresentada é uma ferramenta útil para calcular a posição final de um braço robótico nos eixos X e Y, mas é necessário ter cuidado ao utilizar e interpretar os resultados.

C/C++ Desenvolvimento de Software Python
Desenvolvimento com KINECT

No primeiro artigo, apresentei a instalação do kinect no ubuntu.

Artigo tratando o kinect no ubuntu

Agora iremos falar e mostrar um pouco sobre seu desenvolvimento.

GITHUB do Projeto

O projeto do libfreenect fica neste repositório.

https://github.com/OpenKinect/libfreenect.git

Site do Projeto

https://openkinect.org/wiki/Low_Level

Meu GITHUB

Ja os meus conjuntos de testes, inclusive os apresentados nos artigos relacionados, podem ser vistos, neste repositório.

https://github.com/marcelomaurin/kinect

Instalação de desenvolvimento

O processo de instalação completo foi visto no artigo anterior, porem para efeito de desenvolvimento os pacotes necessários são:

sudo apt install libudev-dev
sudo apt install libglfw3-dev
sudo apt install freeglut3-dev
sudo apt install libfreenect-dev

Sendo os 3 pacotes iniciais, apenas apoio, e o libfreenect-dev realmente a lib necessária.

Hello World da Biblioteca

Neste primeiro projeto, pouca coisa faremos, apenas iremos compilar identificando o device.

#include <stdio.h>
#include <stdlib.h>
#include <libfreenect.h>

freenect_context *f_ctx;
freenect_device *f_dev;
int user_device_number = 0; // Normalmente 0 se você tiver apenas um Kinect

void depth_cb(freenect_device *dev, void *v_depth, uint32_t timestamp) {
    // Callback para dados de profundidade - não usado neste exemplo
}

void rgb_cb(freenect_device *dev, void *rgb, uint32_t timestamp) {
    // Salva uma imagem RGB capturada pelo Kinect
    FILE *image = fopen("output_image.ppm", "wb");
    if (image == NULL) {
        printf("Erro ao abrir o arquivo para escrita\n");
        return;
    }
    fprintf(image, "P6\n# Kinect RGB test\n640 480\n255\n");
    fwrite(rgb, 640*480*3, 1, image);
    fclose(image);
    printf("Imagem salva como output_image.ppm\n");

    // Depois de salvar a imagem, podemos sair do loop principal
    freenect_stop_video(dev);
    freenect_close_device(dev);
    freenect_shutdown(f_ctx);
    exit(0);
}

int main() {
    if (freenect_init(&f_ctx, NULL) < 0) {
        printf("freenect_init() falhou\n");
        return 1;
    }

    if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) {
        printf("Não foi possível abrir o dispositivo\n");
        freenect_shutdown(f_ctx);
        return 1;
    }

    freenect_set_depth_callback(f_dev, depth_cb);
    freenect_set_video_callback(f_dev, rgb_cb);
    freenect_set_video_mode(f_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB));

    freenect_start_video(f_dev);

    while (freenect_process_events(f_ctx) >= 0) {
        // Processa eventos do Kinect até que a captura de imagem seja concluída
    }

    return 0;
}

Neste exemplo o programa pega o kinect e tira uma foto, salvando na maquina local.

Vamos entender o código.

A freenect_init inicia a api.

A próxima função freenect_open_device, abre o device conforme o número que estiver descrito. Isso permite abrir mais de um kinect na mesma maquina.

As funções freenect_set_depth_callback e freenect_set_video_callback criam funções de callback, para controle, se voce não sabe o que é leia este artigo:

A função freenect_set_video_mode indica os parâmetros de resolução.

Por ultimo a função freenect_start_video, dá inicio ao kinect que aciona o callback quando pronto.

Makefile

Criamos aqui o arquivo de compilação do projeto.

CC=gcc
CFLAGS=-c -Wall -I/usr/include/libfreenect
LDFLAGS=-L/usr/lib/x86_64-linux-gnu -lfreenect
SOURCES=kinect.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=kinect

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS) 
	$(CC) $(OBJECTS) -o $@ $(LDFLAGS)

.c.o:
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -f $(OBJECTS) $(EXECUTABLE)

Perceba aqui que o pulo do gato neste makefile, é a inclusão da pasta /usr/lib/x86_64-linux-gnu que é onde a lib se encontra. Bem como a /usr/include/libfreenect que é onde o header se encontra.

Compilando o projeto

Para compilar esse projeto, é necessário apenas rodar o script na pasta src do ubuntu:

make all

Compilando o projeto

Rodando o programa

Agora iremos rodar o programa, isso é a parte mais simples.

Ao rodar, ele captura uma foto, e salva, conforme apresentado.

Foto capturada pelo kinect.

MNote2 srvFalar
MNote 2.32

Fechamos a versão 2.31 e demos inicio a versão 2.32.

Na versão 2.31 foram feitos as seguintes mudanças:

  • Melhora no tratamento das janelas
  • Correções no CHATGPT e uso da API
  • Correções no MQUERY para Windows
  • Criação de gráficos a partir dos datasets de select
  • Exportação para JSON e CSV dos datasets
  • Importação de CSV de dados para Mysql
  • Sintetização de vóz para windows e Linux.
  • Inicio da integração da ferramenta de criação de treinamento de redes neurais
  • srvFalar associado ao projeto MNote

Estas modificações já estão disponíveis em Windows e Linux, e em breve atualizadas na versão ARM.

Sintetização de Voz

Apresentação de melhorias na versão 2.31 usando o chatgpt.

Criação de Gráficos

Criação de gráficos no MNote2

C/C++ robotinics srvFalar
srvFalar

Estamos preparando os pacotes de instalação do srvFalar, com este pacote será possível rodar a aplicação como serviço.

Houve várias mudanças e outras virão.

Estamos atualizando o projeto para atender as necessidades do projeto robotinics.

Blog C/C++
ISO8583

Este material esta sendo construído.

Objetivo

O objetivo deste artigo é apresentar uma visão geral sobre este protocolo.

Histórico

Criado em 1987 a ISO8583 descreve o intercâmbio entre requisições bancárias.

Funcionamento

Sem entrar muito no detalhe do funcionamento.

Basicamente a imagem abaixo, ilustra o funcionamento do protocolo em linhas gerais.

Visão geral do protocolo

De forma geral, o PDV ou POS solicita a operadora uma dada solicitação.

Por exemplo:

inicio de pagamento com cartão de crédito.

No corpo da solicitação, irão alguns dados identificadores da solicitação.

A operadora, pode conforme o tipo da solicitação, perguntar algumas coisas, como senha, tipo de cartão entre outras coisas.

Ou mesmo solicitar a visualização de outras.

A esta solicitação (chamamos de ação), que deve ser respondida pelo PDV ou POS.

A operadora pode realizar quantas perguntas forem necessárias para atendimento de suas necessidades.

Ao fim a operadora envia a resposta final, dando por encerrado a operação.

Em linhas bem gerais é assim que funciona o protocolo ISO 8583.

Estaremos entrando em detalhes, mais adiante.

Porem para entendimento geral, é um protocolo mestre/escravo, onde após a solicitação inicial, a operadora passa a solicitar informações, que devem ser respondidas.

Identificadores de tipo de mensagens

O identificador de tipo de mensagem é um campo numérico de 4 dígitos que especifica o tipo da mensagem que deve ser processado.

Formatação do cabeçalho da solicitação
  • V: número de versão da ISO 8583 (0 indica que é ISO 8583:1987; 1 indica ISO 8583:1992).
  • n: Classe da Mensagem conforme a tabela abaixo: | 0 Reserved for ISO use | 1 Authorization | 2 Financial | | 3 File action | 4 Reversal/Chargeback | 5 Reconciliation | | 6 Administration | 7 Fee collection | 8 Network management | | 9 Reserved for ISO use | | |
  • X: Função da Mensagem conforme tabela: | 0 Request | 1 Request response | 2 Advice | | 3 Advice response | 4 Notification | 5 – 9 Reserved for ISO use |
  • Y: Origem da Transação | 0 Acquirer | 1 Acquirer repeat | 2 Card issuer | | 3 Card issuer repeat | 4 Other | 5 Other repeat | | 6 –9 Reserved for ISO use | | |

Simulando PDV e Simulando Autorizadora

Eu vasculhando a internet achei o site da neapay, conforme referência.

Baixei um download simulator_ISSUER_ISO8583_host_auth_PRO.

A aplicação trabalha com JAVA, e é uma boa pedida quem deseja testar e aprender mais sobre o protocolo.

Simulação de ISO8583

Referências

C/C++
Threads para Raiz – Parte 2 – Programação C

Neste segundo artigo, utilizaremos o exemplo apresentado e iremos desenvolver nossa aplicação em C para linux.

Github

Para ilustrar nosso exemplo criei uma pasta C no nosso projeto git.

Threads para Raiz – Parte 1

Todos os itens deste artigos estão na pasta C.

Makefile

Para quem acompanha meu canal, o nosso bem amado Makefile é o contrutor da aplicação.

PROGRAMA=threads
PROGRAMA32=threads32

LIBS= -lpthread

CC=gcc

SOURCE= threads.c

all32: clean compile32


all: clean compile

clean:
	rm -f *.o
	rm -f $(PROGRAMA)

compile32:
	$(CC) -m32  $(SOURCE) $(LIBS) -o $(PROGRAMA32)

compile:
	$(CC) $(SOURCE) $(LIBS) -o $(PROGRAMA)

Aqui criamos um construtor para ambas as arquituras 32 e 64bits.

Por padrão iremos manter o uso em 64bits que é a plataforma nativa do meu linux.

Criando a base

O primeiro passo é criar a base do nosso chamador.

Para tanto iremos no main, inicializar as variáveis e chamar os chamadores das threads.

void main(void){
	int rstatus = 0;
	srand(time(NULL));
	pthread_t  pidRecepcao = 0;
	pthread_t  pidControlador = 0;
	pthread_t  pidExecutor = 0;
	//mutex = PTHREAD_MUTEX_INITIALIZER;

	printf("\nBem vindo ao programa das threads\n");
	printf("Este programa faz parte do artigo:\n");
	printf("http://maurinsoft.com.br/index.php/2022/07/02/threads-para-raiz-parte-1/\n\n");
	printf("Inicializando vetor\n\n");
	StartVetor();
	printf("Iniciando Recepcao\n");
	pidRecepcao = Start_Recepcao();
	printf("Iniciando Controlador\n");
	pidControlador = Start_Controlador();
	printf("Iniciando Executor\n");
	pidExecutor = Start_Executor();
	//bool flag = ((pidRecepcao!=0)||(pidControlador!=0)||(pidExecutor!=0));
	flgTerminou = false;
	while(!flgTerminou){
		printf("Status:");

		if(rstatus != 0)
		{
			printf ("Erro ao aguardar finalização do thread A.\n");

		}

		flgTerminou = flgTerminouRecepcao && flgTerminouExecucao;
		sleep(1);
	}
	printf("\n\nFila ordenada:");
	for(int cont = 0;cont<=MAXITEMS-1;cont++)
	{
	  printf("%i ",fila[cont]);
	}
	printf("\n\n");

	printf("\n\nFila executada:");
	for(int cont = 0;cont<=MAXITEMS-1;cont++)
	{
	  printf("%i ",executada[cont]);
	}
	printf("\n\n");

}

As funcoes Start_Recepcao, Start_Controlador, Start_Executor chamam as threads, que serão apresentadas em um próximo momento.

A variavel pidRecepcao , do tipo pthread_t que indica cada uma das threads criadas.

Inicialização de variáveis

A inicialização da fila é feita pela função StartVetor, conforme fonte abaixo:

void StartVetor(){
		for (int cont = 0;cont<=MAXITEMS;cont++)
		{
			fila[cont] = 0;
			executada[cont]=0;

		}
}

Temos também a variável executada, que será utilizada na marcação dos itens executados.

Sessão Crítica

O controle da sessão crítica é feita nas funções IniciaSessaoCritica e TerminaSessaoCritica, conforme fonte abaixo:


int IniciaSessaoCritica()
{
	int  rc;
	int cont = 0;
	while ( (rc = pthread_mutex_lock(&mutex))!=0)
	{
		usleep(100); /*Aguarda um pouco*/
		cont++;
		printf("Sessao critica não conseguida\n");
		if (cont>3) break;
	}
	return rc;


}

int TerminaSessaoCritica()
{
	int  rc;
	int cont = 0;
	while ( (rc = pthread_mutex_unlock(&mutex))!=0)
	{
		usleep(100); /*Aguarda um pouco*/
		cont++;
		printf("Sessao critica não liberada\n");
		if (cont>3) break;
	}
	return rc;


}

Ambas as funções controlam a sessão criada mutex, declarada, conforme fonte abaixo:

pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;

Para cada sessão critica, deve-se criar uma variável de controle. Como usaremos apenas a fila, como variável de troca de dados, utilizaremos uma única sessão critica.

Criando a thread da recepção

Agora iremos dar inicio a criação da thread da recepção, na qual incluiremos o inicio da thread.

pthread_t  Start_Recepcao()
{
	pthread_t  pid	= 0;
	int ret;
	ret=pthread_create(&pid,NULL,&threadRecepcao,NULL);

	return pid;
}

Neste segmento do código, podemos acompanhar que criamos a thread com pthread_create, passando o ponteiro da função que será criada a thread threadRecepcao. Desta forma a função threadRecepcao, não mais seguirá na thread pai. O ultimo parâmetro é utilizado para passagens de argumentos, no nosso caso, não será usado.

Por fim a função da thread

/*thread function definition*/
void* threadRecepcao(void* args)
{
	for(int cont = 0;cont<=MAXITEMS;cont++)
	{

		printf("Criando pacote nro %d\n",cont);
		if(IniciaSessaoCritica()==0)
		{
			int Valor = (rand()% 100);
			fila[cont] = Valor; /*Grava Valor na fila*/
			printf("Registrou na fila[%d] = %d\n",cont,Valor);
			TerminaSessaoCritica();
			usleep(1000);
		} else {
				printf("Falha na Recepcao nro:\n",cont);
		}

	}
	printf("Recepcao terminou atendimento\n");

}

Podemos observar que a threadRecepção requisita a sessão crítica para movimentar a fila, apenas depois alocando valor para ela. Também podemos perceber que após seu uso, o mesmo é descartado.

Criando o Controlador

O controlador, é executado, em seguida, ordenando as informações.

void ordenacao()
{
int i, x;
bool flgordenado = false;
while((!flgordenado)&&(!flgTerminou))
{
	//flgordenado = true;
	for (i=0; i<=MAXITEMS-1; i++)
	{
		if ((fila[i]!=0)&&(fila[i+1]!=0))
		{
		  if(fila[i]>fila[i+1])
		  {
		    x = fila[i];
            fila[i] = fila[i+1];
		    fila[i+1] = x;
		    flgordenado = false;
		    //printf("Ordenando os pacote nro %d\n",i);
		  }
		}	else {
			//printf("Posicao vazia %d\n",i);
			flgordenado = false;
		}
    }


  }
}

/*thread function definition*/
void* threadControlador(void* args)
{
  int oldValue, newValue;
  int flgOrdenado = false;
  printf("Iniciou o controlador\n");
  while(!flgTerminou) /*Faz enquanto nao terminar e nao ordenao*/
  {
	if(IniciaSessaoCritica()==0)
	{
		ordenacao();

		TerminaSessaoCritica();
		//usleep(200);

	}
  }

  printf("Terminou ordenação de todos os itens\n");
}

Neste bloco temos duas funções:

A thread em si é a threadControlador, que chama a função de ordenação ordenacao.

A ordenação só para quando for atendida duas condições:

Tiver terminado as demais threads, indicado pelo flag flgTerminou e quando tiver sido totalmente ordenado flgordenado.

Executor

A thread do Executor, pode ser vista conforme apresentado a seguir:

/*thread function definition*/
void* threadExecutor(void* args)
{
  int oldValue, newValue;
  bool flgExecutado = false;
  printf("Iniciou o controlador\n");
  int posicao = 0;
  //while(!flgExecutado)
  while((!flgExecutado)&&(!flgTerminou))
  {
    //printf("Pesquisando Posicao %d\n",posicao);

	//printf("Entrou na sessao critica\n");
	if  (fila[posicao]==0) /*Fila nao foi preenchida*/
	{
		printf("posicao vazia %d\n",posicao);
		posicao = posicao;

	} else
	{
	   executada[posicao] = fila[posicao];
	   printf("Executou[%d] = %d\n",posicao,fila[posicao]);
	   if(posicao==MAXITEMS-1)
	   {
		   printf("Chegou ao fim\n ");
		   flgExecutado= true; /*Finaliza executor*/
	   } else
	   {
		   posicao ++;
	   }

	}
	//printf("terminou while\n");
  }

  flgTerminouExecucao = true;

  printf("Terminou ordenação de todos os itens\n");

}

Ela irá rodar até que duas condições sejam satisfeitas:

  • flgExecutado – Controla a execução de todas as tarefas da lista
  • flgTerminou – Controla o fim de todas as demais threads do sistema

Testando programa

Compilando programa

A compilação em um Raspberry PI ocorreu com sucesso.

Executando o programa

root@raspberrypi:/home/mmm/projetos/Threads-para-Raiz/c# ./threads

Bem vindo ao programa das threads
Este programa faz parte do artigo:
http://maurinsoft.com.br/index.php/2022/07/02/threads-para-raiz-parte-1/

Inicializando vetor

Iniciando Recepcao
Iniciando Controlador
Registrou na fila[0] = 80
Registrou na fila[1] = 11
Registrou na fila[2] = 76
Registrou na fila[3] = 71
Registrou na fila[4] = 27
Registrou na fila[5] = 23
Registrou na fila[6] = 33
Registrou na fila[7] = 68
Registrou na fila[8] = 32
Registrou na fila[9] = 92
Recepcao terminou atendimento
Iniciou o controlador
Iniciando Executor
Status:Iniciou o controlador
Executou[0] = 11
Executou[1] = 23
Executou[2] = 27
Executou[3] = 32
Executou[4] = 33
Executou[5] = 68
Executou[6] = 71
Executou[7] = 76
Executou[8] = 80
Executou[9] = 92
Chegou ao fim
 Terminou ordenação de todos os itens
Status:Terminou ordenação de todos os itens


Fila ordenada:11 23 27 32 33 68 71 76 80 92



Fila executada:11 23 27 32 33 68 71 76 80 92

Como a execução ficou um pouco longa, resolvi jogar como código.

Foto da execução

Conclusão

Podemos perceber que a execução de threads pode ser facilitada com uso de flags externos, que facilitam a comunicação entre os processos. Pudemos ver tambem, que a programação em threads é de fato, um estado de arte da programação C, pois envolve alem de um algoritmo bem desenvolvido, a elaboração de estratégias pensando em que uma thread não sabe exatamente quando a outra irá cumprir suas atividades.

Desta forma cada thread tem que ser pensada em aguardar e esperar as informações das threads que colaboraram com esta.

Desta forma o controle interno das informações é bem mais complicado.

Pudemos ver por ultimo o uso dos sinalizadores, que visão identificar o uso de uma sessão crítica do sistema. Que nada mais é que um recurso compartilhado.

Espero que tenham gostado do artigo.

Em caso de dúvidas ou sugestões, fico a disposição como sempre.

marcelomaurinmartins@gmail.com

Bibliografia

C/C++ Delphi Java Python
Threads para Raiz – Parte 1

Neste primeiro artigo, iremos estabelecer um projeto, que iremos desenvolver nos demais artigos.

Objetivo

A intenção deste projeto é apresentar solução em diversos linguagens de controle de threads com compartilhamento de informações entre elas.

Proposta de projeto

Imagine que temos 3 funcionários em um departamento público.

  • Recepção de Protocolo – Ele recebe os protocolos de serviço dos clientes.
  • Controlador de Serviço – Ele recebe os protocolos da recepção, colocando em ordem numérica em uma fila de execução. Por controlar e ordenar, sua atividade demora tempo mediano.
  • Executor de Serviço – Ele pega o serviço, por executar o serviço é o mais demorado de todos.
Fluxo de execução

Tempo de execução

Ao analisarmos o departamento, fizemos a seguinte constatação:

  • A recepção de protocolo, é o departamento mais rápido.
  • O Controlador de Serviço tem um tempo médio que é o dobro da recepção.
  • Executor de Serviço – Demora o dobro do tempo do controlador de serviço.

Agora que temos o projeto, podemos no próximo artigo começar sua implementação.

Espero voces no próximo artigo 😉

C/C++ Python
Cython – Integração entre Python e C/C++ – Segunda Parte

Neste segundo artigo, iremos criar um projeto em C, em seguida desenvolver um projeto Hello World em Python, que iremos chamar no C e compilar.

GITHUB

https://github.com/marcelomaurin/cython

Primeiramente vamos criar nosso projeto em C.

Primeiramente criamos um arquivo Makefile

CC= gcc
SAMPLE=sample.pyx
LIBS= `pkg-config --cflags --libs python3`
TARGET=hello
SOURCE= \
hello.c \
sample.c



all: clean compile install

clean:
	rm ./sample.c
	rm ./sample.h


compile:
	cython ./$(SAMPLE)
	$(CC) $(SOURCE) $(LIBS) -o ./$(TARGET)

install:
	cp ./$(TARGET) /usr/local/bin/

No exemplo acima, temos dois pontos chaves no nosso código.

A inclusão do sample.pyx que irá ser convertido em um sample.c e um sample.h, conforme script do compile.

Agora iremos mostrar o código do C, que chamará o python, nosso código: hello.c

#include <stdio.h>
#include "sample.h"

int main()
{
	call_hello();
}

Neste código vemos uma chamada para a lib sample.h, que será criada pelo cython a partir do script.

A função Call_hello é declarada já no python, e a seguir vemos como ela é apresentada.

Fonte: hello.pyx

from sam import sam

cdef public void call_hello():
	sam.hello()

Agora iremos escrever o sam.py, que será chamado:


def hello():
    print("Hello World")

Por fim, compilamos o script:

make compile

E rodamos o mesmo

./hello

Documentação de Apoio

https://riptutorial.com/Download/cython.pdf

Fóruns e Artigos coligados

Sem categoria
Instalar o Kaldi

Oque é o Kaldi é um conjunto de ferramentas de reconhecimento de voz para texto.

Kaldi suporta várias técnicas diferentes com recursos de transformação lineares e redes profundas.

Kaldi é uma poderosa ferramenta de manipulação de voz, e esta em pleno desenvolvimento.

Instalação do Kaldi

O processo de instalação de um aplicativo pode variar em função da distribuição e dos pacotes instalados em sua máquina.

Estou utilizando um Ubuntu, e realizei diversos testes, podendo alguns passos variarem ligeiramente conforme seu ambiente.

Pré requisitos

Existem uma série de pacotes que precisam ser instalados.

O primeiro passo é fazer a instalação dos seguintes pacotes:

apt install libfst-dev libfst-tools libfst8 libfst8-plugins-base

Baixar o Kaldi

Agora instalados os pré requisitos iniciais, iremos fazer a baixa dos pacotes.

git clone https://github.com/kaldi-asr/kaldi.git kaldi –origin upstream
cd kaldi

baixando o Kaldi

Agora iremos atualizar com o comando:

git pull

Compilação de ferramentas

Vá na pasta do kaldi, na pasta /kaldi/tools

Execute o make, conforme o exemplo abaixo:

make all

O software irá compilar uma série de pacotes, conforme apresentado a seguir.

compilando as ferramentas.

Configurando os scripts

Agora que fizemos a configuração, é hora de montar o ambiente, digite na pasta ./kaldi/src ,o seguinte comando:

./configure –shared

Este procedimento irá gerar o kaldi.mk, que conterá o makefile de compilação.

Pode ser necessário alterar o nivel de depuração:

o Padrão é -O1, porem pode ser modificado.

Veja no link abaixo, informações mais detalhadas:

https://kaldi-asr.org/doc/build_setup.html

maurinsoft.com.br