Ir para o conteúdo
ou

Software livre Brasil

 Voltar a Projeto Soft...
Tela cheia Sugerir um artigo

AJ Alves: eFLL – Uma Biblioteca Fuzzy para Arduino e Sistemas Embarcados

28 de Setembro de 2012, 0:00 , por Software Livre Brasil - 0sem comentários ainda | Ninguém está seguindo este artigo ainda.
Visualizado 1643 vezes

Lógica Fuzzy é uma extensão da lógica booleana tradicional que através de variáveis linguísticas permite expressar valores lógicos intermediários entre o FALSO e VERDADEIRO, descrevendo com maior eficiência o princípio da incerteza do mundo real.

Sistemas Fuzzy são aplicações praticas que empregam a Lógica Fuzzy nas tomadas de decisões com base nos termos e variáveis linguísticas, tendo na robótica e na eletrônica um grande espaço e utilidade.

Desenvolvida pelo Robotic Research Group (RRG) na Universidade Estadual do Piauí (UESPI-Teresina) a biblioteca eFLL (Embedded Fuzzy Logic Library) é uma opção versátil, leve e eficiente de trabalhar com a Lógica Fuzzy em sistemas embarcados.


Por favor, reporte Bugs e sugestões via comentários ou na página oficial do projeto no GitHub.

Como instalar

1º Passo: Vá a página oficial do projeto no GitHub: eFLL

2º Passo: Faça um clone do projeto usando o Git ou faço o download em  Donwload pelo botão “Downloas as zip“.

3º Passo: Clone ou descompacte os arquivos para a pasta de bibliotecas do Arduino:

no Ubuntu (/usr/share/arduino/libraries/) caso instalado via apt-get;
no Windows, Mac ou Linux (Onde você baixou o IDE Arduino, a pasta de biblioteca está dentro)

Pronto, a biblioteca está pronta para ser usada.

Como importar

Caso a instalação da biblioteca tenha sido realizada com sucesso, para importar a biblioteca é fácil:

1º Passo: Abra o seu Arduino IDE, vá a aba no menu superior SKETCKS → BIBLIOTECA → Importar eFLL

Characteristics

Escrita em C++/C, usa apenas a biblioteca padrão da linguagem C “stdlib.h“, por isso a eFLL é uma biblioteca destinada não somente ao Arduino, mas qualquer Sistema Embarcado ou não que tenham seus comandos escritos em C.

Não possui limitações explicitas de quantidade de Conjuntos Fuzzy, Regras Fuzzy, Entradas ou Saídas, estas limitam-se a capacidade de processamento e armazenamento de cada microcontrolador

A biblioteca utilza o processo:
(MAX-MIN) e (Mínimo de Mamdani) para a inferência e composição e (Centro de Área) para a desfuzzyficação, no universo contínuo.

Testes realizados utilizando a biblioteca GTest para C, Google Inc

Exemplo simples:

Controle de velocidade de um robô, entrada: Distância obstáculo frontal.

#include <FuzzyRule.h>#include <FuzzyRule.h>#include <FuzzyComposition.h>#include <Fuzzy.h>#include <FuzzyRuleConsequent.h>#include <FuzzyOutput.h>#include <FuzzyInput.h>#include <FuzzyIO.h>#include <FuzzySet.h>#include <FuzzyRuleAntecedent.h>

// Passo 1 -  Instanciando um objeto da bibliotecaFuzzy* fuzzy = new Fuzzy();

void setup(){ Serial.begin(9600);

 // Passo 2 - Criando o FuzzyInput distancia FuzzyInput* distance = new FuzzyInput(1);// Como parametro seu ID

 // Criando os FuzzySet que compoem o FuzzyInput distancia FuzzySet* small = new FuzzySet(0, 20, 20, 40); // Distancia pequena distance->addFuzzySet(small); // Adicionando o FuzzySet small em distance FuzzySet* safe = new FuzzySet(30, 50, 50, 70); // Distancia segura distance->addFuzzySet(safe); // Adicionando o FuzzySet safe em distance FuzzySet* big = new FuzzySet(60, 80, 80, 80); // Distancia grande distance->addFuzzySet(big); // Adicionando o FuzzySet big em distance

 fuzzy->addFuzzyInput(distance); // Adicionando o FuzzyInput no objeto Fuzzy

 // Passo 3 - Criando o FuzzyOutput velocidade FuzzyOutput* velocity = new FuzzyOutput(1);// Como parametro seu ID

 // Criando os FuzzySet que compoem o FuzzyOutput velocidade FuzzySet* slow = new FuzzySet(0, 10, 10, 20); // Velocidade lenta velocity->addFuzzySet(slow); // Adicionando o FuzzySet slow em velocity FuzzySet* average = new FuzzySet(10, 20, 30, 40); // Velocidade normal velocity->addFuzzySet(average); // Adicionando o FuzzySet average em velocity FuzzySet* fast = new FuzzySet(30, 40, 40, 50); // Velocidade alta velocity->addFuzzySet(fast); // Adicionando o FuzzySet fast em velocity

 fuzzy->addFuzzyOutput(velocity); // Adicionando o FuzzyOutput no objeto Fuzzy

 //Passo 4 - Montando as regras Fuzzy // FuzzyRule "SE distancia = pequena ENTAO velocidade = lenta" FuzzyRuleAntecedent* ifDistanceSmall = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso ifDistanceSmall->joinSingle(small); // Adicionando o FuzzySet correspondente ao objeto Antecedente FuzzyRuleConsequent* thenVelocitySlow = new FuzzyRuleConsequent(); // Instancinado um Consequente para a expressao thenVelocitySlow->addOutput(slow);// Adicionando o FuzzySet correspondente ao objeto Consequente // Instanciando um objeto FuzzyRule FuzzyRule* fuzzyRule01 = new FuzzyRule(1, ifDistanceSmall, thenVelocitySlow); // Passando o Antecedente e o Consequente da expressao

 fuzzy->addFuzzyRule(fuzzyRule01); // Adicionando o FuzzyRule ao objeto Fuzzy

 // FuzzyRule "SE distancia = segura ENTAO velocidade = normal" FuzzyRuleAntecedent* ifDistanceSafe = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso ifDistanceSafe->joinSingle(safe); // Adicionando o FuzzySet correspondente ao objeto Antecedente FuzzyRuleConsequent* thenVelocityAverage = new FuzzyRuleConsequent(); // Instancinado um Consequente para a expressao thenVelocityAverage->addOutput(average); // Adicionando o FuzzySet correspondente ao objeto Consequente // Instanciando um objeto FuzzyRule FuzzyRule* fuzzyRule02 = new FuzzyRule(2, ifDistanceSafe, thenVelocityAverage); // Passando o Antecedente e o Consequente da expressao

 fuzzy->addFuzzyRule(fuzzyRule02); // Adicionando o FuzzyRule ao objeto Fuzzy

 // FuzzyRule "SE distancia = grande ENTAO velocidade = alta" FuzzyRuleAntecedent* ifDistanceBig = new FuzzyRuleAntecedent(); // Instanciando um Antecedente para a expresso ifDistanceBig->joinSingle(big); // Adicionando o FuzzySet correspondente ao objeto Antecedente FuzzyRuleConsequent* thenVelocityFast = new FuzzyRuleConsequent(); // Instancinado um Consequente para a expressao thenVelocityFast->addOutput(fast);// Adicionando o FuzzySet correspondente ao objeto Consequente // Instanciando um objeto FuzzyRule FuzzyRule* fuzzyRule03 = new FuzzyRule(3, ifDistanceBig, thenVelocityFast); // Passando o Antecedente e o Consequente da expressao

 fuzzy->addFuzzyRule(fuzzyRule03); // Adicionando o FuzzyRule ao objeto Fuzzy}

void loop(){ float dist = getDistanceFromSonar();  // Passo 5 - Informar o valor das entradas, passando seu ID e valorfuzzy->setInput(1, dist);  // Passo 6 - Executar a fuzzyficação fuzzy->fuzzify();  // Passo 7 - Executar a desfuzzyficação para cada saída, passando seu ID float output = fuzzy->defuzzify(1);

 setRobotSpeed(output);

 delay(100);}

Breve documentação

Objeto Fuzzy – Este objeto engloba todo o Sistema Fuzzy, através dele, é possível manipular os Conjuntos Fuzzy, as Regras Linguísticas, entradas e saídas.

Objeto FuzzyInput  – Este objeto literalmente agrupa todos os Conjuntos Fuzzy de entradas que pertencem ao mesmo domínio

Objeto FuzzyOutput  – Este objeto é semelhante ao FuzzyInput, é usado para agrupa todos os Conjuntos Fuzzy de saída que pertencem ao mesmo domínio.

Objeto FuzzySet – Este é um dos principais objetos da Biblioteca Fuzzy, com é possível modelar cada conjunto do sistema em questão. Atualmente a biblioteca suporta as funções de pertinência triangular, trapezoidal e singleton, que são montadas com base nos pontos A, B, C e D que são passados por parametro no construtor FuzzySet(float a, float b, float c, float d), exemplos:

Função de pertinência triangular:

FuzzySet fs = FuzzySet(10, 20, 20, 30);

FuzzySet fs = FuzzySet(10, 33, 33, 33);
FuzzySet fs = FuzzySet(5, 5, 5, 30);

Função de pertinência trapezoidal:

FuzzySet fs = FuzzySet(10, 20, 30, 40);
FuzzySet fs = FuzzySet(0, 0, 10, 20);
Qualquer valor abaixo de 10 terá pertinência = 1
FuzzySet fs = FuzzySet(20, 30, 40, 40);
Qualquer valor acima de 30 terá pertinência = 1

Função de pertinência Singleton:

FuzzySet fs = FuzzySet(20, 20, 20, 20);

Objeto FuzzyRule – Este objeto é usado para montar a base de regras do objeto Fuzzy, que contem um ou mais deste. Instanciado com FuzzyRule fr = new FuzzyRule(ID, antecedent, consequente)

Objeto FuzzyRuleAntecedent – Este objeto é usado para compor o objeto FuzzyRule, responsavel por montar a expressão condicional do antecedente de um FuzzyRule, exemplos:

“SE distancia = pequena ENTAO velocidade = lenta”

FuzzyRuleAntecedent* ifDistanceSmall = new FuzzyRuleAntecedent(); ifDistanceSmall->joinSingle(small);

O método joinSingle(FuzzySet* fuzzySet); é usado para montar expressões simples de SE isto ENTÃO aquilo. Para compor expressões mais complexas existem outros métodos especiais.

“SE temperatura = quente E pressão = alta ENTAO risco = grande”

FuzzyRuleAntecedent* ifTemperatureHotAndPressureHight = new FuzzyRuleAntecedent();ifTemperatureHotAndPressureHight->joinWithAND(hot, hight); 

“SE temperatura = quente OU pressão = alta ENTAO risco = grande”

FuzzyRuleAntecedent* ifTemperatureHotAndPressureHight = new FuzzyRuleAntecedent();ifTemperatureHotAndPressureHight->joinWithOR(hot, hight);

Os métodos joinWithAND(FuzzySet* fuzzySet1, FuzzySet* fuzzySet2); e joinWithOR(FuzzySet* fuzzySet1, FuzzySet* fuzzySet2); podem fazer composições logicas entre os Conjuntos Fuzzy. Estes métodos possuem ainda variações mais avançadas que permitem aprimorar mais ainda a expressão, são eles:

bool joinWithAND(FuzzySet* fuzzySet, FuzzyRuleAntecedent* fuzzyRuleAntecedent);bool joinWithAND(FuzzyRuleAntecedent* fuzzyRuleAntecedent, FuzzySet* fuzzySet);bool joinWithOR(FuzzySet* fuzzySet, FuzzyRuleAntecedent* fuzzyRuleAntecedent);bool joinWithOR(FuzzyRuleAntecedent* fuzzyRuleAntecedent, FuzzySet* fuzzySet);bool joinWithAND(FuzzyRuleAntecedent* fuzzyRuleAntecedent1, FuzzyRuleAntecedent* fuzzyRuleAntecedent2);bool joinWithOR(FuzzyRuleAntecedent* fuzzyRuleAntecedent1, FuzzyRuleAntecedent* fuzzyRuleAntecedent2);

exemplos:

“SE (velocidade = alta E distância = pequena) OR combustível = pouco ENTAO velocidade = pequena E consumo = baixo”

FuzzyRuleAntecedent* speedHightAndDistanceSmall = new FuzzyRuleAntecedent();speedHightAndDistanceSmall->joinWithAND(hight, small); 

FuzzyRuleAntecedent* fuelLow = new FuzzyRuleAntecedent();fuelLow->joinSingle(low); 

// Este objeto FuzzyRuleAntecedente é que será usada para compor o objeto FuzzyRule FuzzyRuleAntecedent* ifSpeedHightAndDistanceSmallOrFuelLow = new FuzzyRuleAntecedent();ifSpeedHightAndDistanceSmallOrFuelLow->joinWithOR(speedHightAndDistanceSmall, fuelLow); 

Se fazendo valer destes métodos, qualquer expressão pode ser montada, pois um objeto FuzzyRuleAntecedent pode ser usado para compor outro objeto FuzzyRuleAntecedent, das mais diversas formas. OBS:. no exemplo anterior, o antecedente final foi composto pelos objetos speedHightAndDistanceSmall e
fuelLow mas este último poderia ser substituído sem perda pelo objeto FuzzySet low, já que o mesmo é uma expressão simples, sem nenhum operador condicional:

FuzzyRuleAntecedent* speedHightAndDistanceSmall = new FuzzyRuleAntecedent();speedHightAndDistanceSmall->joinWithAND(hight, small); 

// Este objeto FuzzyRuleAntecedente é que será usada para compor o objeto FuzzyRule FuzzyRuleAntecedent* ifSpeedHightAndDistanceSmallOrFuelLow = new FuzzyRuleAntecedent();ifSpeedHightAndDistanceSmallOrFuelLow->joinWithOR(speedHightAndDistanceSmall, low); 

Objeto FuzzyRuleConsequente – Este objeto é usado para compor o objeto FuzzyRule, responsavel por montar a expressão de saída de um FuzzyRule, exemplos:

“SE distancia = pequena ENTAO velocidade = lenta”

FuzzyRuleConsequent* thenSpeedSlow = new FuzzyRuleConsequent(); thenSpeedSlow->addOutput(slow);

O que resultaria em um objeto FuzzyRule:

FuzzyRule* fuzzyRule = new FuzzyRule(2, ifDistanceSmall, thenSpeedSlow);

“SE (velocidade = alta E distância = pequena) OR combustível = pouco ENTAO velocidade = pequena E consumo = baixo”

FuzzyRuleConsequent* thenSpeedSmallAndFeedTine = new FuzzyRuleConsequent(); thenSpeedSmallAndFeedSmall->addOutput(small);

thenSpeedSmallAndFeedSmall->addOutput(tine);  

Para o objeto FuzzyRuleConsequent toda a expressão é montada com o método addOutput(FuzzySet* fuzzySet);

O que resultaria em um objeto FuzzyRule:

FuzzyRule* fuzzyRule = new FuzzyRule(2, ifSpeedHightAndDistanceSmallOrFuelLow, thenSpeedSmallAndFeedTine);

Após montar um objeto FuzzyRule, use o método addFuzzyRule(FuzzyRule* fuzzyRule); do objeto Fuzzy para adicionar a regra na base de regras, repita o mesmo processo para todas as regras.

Dica

Estes são todos os objetos da biblioteca eFLL que são utilizados no processo. O passo seguinte, e geralmente interativo é manipulado por três métodos do objeto Fuzzy, o primeiro:

bool setInput(int ID, float valor);

É utilizado para repassar o valor de entrada crispe para o sistema, note que o primeiro parâmetro é o ID do objeto FuzzyInput ao qual o parâmetro valor é destinado.

bool fuzzify();

É utilizado para iniciar o processo de fuzzyficação, composição e inferência.

E por fim: float defuzzify(int ID);

É utilizado para finalizar o processo de fuzzyficação,  note que o ID que é passado por parametro é o ID do FuzzyOutput ao qual se deseja obter o valor desfuzzificado.

Dica: Algumas vezes é necessário conhecer a pertinência com a qual algum, ou cada Conjunto Fuzzy foi ativado. Para isso, utilize o método float getPertinence(); do objeto FuzzySet para objet esse valor, exemplo:

FuzzySet* hot = new FuzzySet(30, 50, 50, 70);...... // Após a fuzzyficação com ->fuzzyfy();...float pertinenceOfHot = hot->getPertinence();

Ou saber se determinada regra foi ativada, utilize o método bool isFired() do objeto FuzzyRule

FuzzyRule* fuzzyRule = new FuzzyRule(2, ifDistanceSmall, thenSpeedSlow);...... // Após a fuzzyficação com ->fuzzyfy();...bool wasTheRulleFired = fuzzyRule->isFired();

Exemplo avançado:

#include <FuzzyRule.h>#include <FuzzyRule.h>#include <FuzzyComposition.h>#include <Fuzzy.h>#include <FuzzyRuleConsequent.h>#include <FuzzyOutput.h>#include <FuzzyInput.h>#include <FuzzyIO.h>#include <FuzzySet.h>#include <FuzzyRuleAntecedent.h>

// Instanciando um objeto da bibliotecaFuzzy* fuzzy = new Fuzzy();

FuzzySet* close = new FuzzySet(0, 20, 20, 40);FuzzySet* safe = new FuzzySet(30, 50, 50, 70);FuzzySet* distante = new FuzzySet(60, 80, 100, 100);

FuzzySet* stoped = new FuzzySet(0, 0, 0, 0);FuzzySet* slow = new FuzzySet(1, 10, 10, 20);FuzzySet* normal = new FuzzySet(15, 30, 30, 50);FuzzySet* quick = new FuzzySet(45, 60, 70, 70);

FuzzySet* cold = new FuzzySet(-30, -30, -20, -10);FuzzySet* good = new FuzzySet(-15, 0, 0, 15);FuzzySet* hot = new FuzzySet(10, 20, 30, 30);

void setup(){  Serial.begin(9600);

  // FuzzyInput  FuzzyInput* distance = new FuzzyInput(1);  distance->addFuzzySet(close);  distance->addFuzzySet(safe);  distance->addFuzzySet(distante);

  fuzzy->addFuzzyInput(distance);

  // FuzzyInput  FuzzyInput* inputSpeed = new FuzzyInput(2);  inputSpeed->addFuzzySet(stoped);  inputSpeed->addFuzzySet(slow);  inputSpeed->addFuzzySet(normal);  inputSpeed->addFuzzySet(quick);

  fuzzy->addFuzzyInput(inputSpeed);

  // FuzzyInput  FuzzyInput* temperature = new FuzzyInput(3);  temperature->addFuzzySet(cold);  temperature->addFuzzySet(good);  temperature->addFuzzySet(hot);

  fuzzy->addFuzzyInput(temperature);

  // FuzzyOutput  FuzzyOutput* risk = new FuzzyOutput(1);

  FuzzySet* minimum = new FuzzySet(0, 20, 20, 40);  risk->addFuzzySet(minimum);  FuzzySet* average = new FuzzySet(30, 50, 50, 70);  risk->addFuzzySet(average);  FuzzySet* maximum = new FuzzySet(60, 80, 80, 100);  risk->addFuzzySet(maximum);

  fuzzy->addFuzzyOutput(risk);

  // FuzzyOutput  // adicionando speed como output também  FuzzyOutput* outputSpeed = new FuzzyOutput(2);

  FuzzySet* stopedOut = new FuzzySet(0, 0, 0, 0);  outputSpeed->addFuzzySet(stopedOut);  FuzzySet* slowOut = new FuzzySet(1, 10, 10, 20);  outputSpeed->addFuzzySet(slowOut);  FuzzySet* normalOut = new FuzzySet(15, 30, 30, 50);  outputSpeed->addFuzzySet(normalOut);  FuzzySet* quickOut = new FuzzySet(45, 60, 70, 70);  outputSpeed->addFuzzySet(quickOut);

  fuzzy->addFuzzyOutput(outputSpeed);

  // Building FuzzyRule  FuzzyRuleAntecedent* distanceCloseAndSpeedQuick = new FuzzyRuleAntecedent();  distanceCloseAndSpeedQuick->joinWithAND(close, quick);  FuzzyRuleAntecedent* temperatureCold = new FuzzyRuleAntecedent();  temperatureCold->joinSingle(cold);  FuzzyRuleAntecedent* ifDistanceCloseAndSpeedQuickOrTemperatureCold = new FuzzyRuleAntecedent();  ifDistanceCloseAndSpeedQuickOrTemperatureCold->joinWithOR(distanceCloseAndSpeedQuick, temperatureCold);

  FuzzyRuleConsequent* thenRisMaximumAndSpeedSlow = new FuzzyRuleConsequent();  thenRisMaximumAndSpeedSlow->addOutput(maximum);  thenRisMaximumAndSpeedSlow->addOutput(slowOut);

  FuzzyRule* fuzzyRule1 = new FuzzyRule(1, ifDistanceCloseAndSpeedQuickOrTemperatureCold, thenRisMaximumAndSpeedSlow);  fuzzy->addFuzzyRule(fuzzyRule1);

  // Building FuzzyRule  FuzzyRuleAntecedent* distanceSafeAndSpeedNormal = new FuzzyRuleAntecedent();  distanceSafeAndSpeedNormal->joinWithAND(safe, normal);  FuzzyRuleAntecedent* ifDistanceSafeAndSpeedNormalOrTemperatureGood = new FuzzyRuleAntecedent();  ifDistanceSafeAndSpeedNormalOrTemperatureGood->joinWithOR(distanceSafeAndSpeedNormal, good);

  FuzzyRuleConsequent* thenRiskAverageAndSpeedNormal = new FuzzyRuleConsequent();  thenRiskAverageAndSpeedNormal->addOutput(average);  thenRiskAverageAndSpeedNormal->addOutput(normalOut);

  FuzzyRule* fuzzyRule2 = new FuzzyRule(2, ifDistanceSafeAndSpeedNormalOrTemperatureGood, thenRiskAverageAndSpeedNormal);  fuzzy->addFuzzyRule(fuzzyRule2);

  // Building FuzzyRule  FuzzyRuleAntecedent* distanceDistanteAndSpeedSlow = new FuzzyRuleAntecedent();  distanceDistanteAndSpeedSlow->joinWithAND(distante, slow);  FuzzyRuleAntecedent* ifDistanceDistanteAndSpeedSlowOrTemperatureHot = new FuzzyRuleAntecedent();  ifDistanceDistanteAndSpeedSlowOrTemperatureHot->joinWithOR(distanceDistanteAndSpeedSlow, hot);

  FuzzyRuleConsequent* thenRiskMinimumSpeedQuick = new FuzzyRuleConsequent();  thenRiskMinimumSpeedQuick->addOutput(minimum);  thenRiskMinimumSpeedQuick->addOutput(quickOut);

  FuzzyRule* fuzzyRule3 = new FuzzyRule(3, ifDistanceDistanteAndSpeedSlowOrTemperatureHot, thenRiskMinimumSpeedQuick);  fuzzy->addFuzzyRule(fuzzyRule3);}

void loop(){  fuzzy->setInput(1, 10);  fuzzy->setInput(2, 30);  fuzzy->setInput(3, -15);

  fuzzy->fuzzify();

  Serial.print("Distancia: ");  Serial.print(close->getPertinence());  Serial.print(", ");  Serial.print(safe->getPertinence());  Serial.print(", ");  Serial.println(distante->getPertinence());

  Serial.print("Velocidade: ");  Serial.print(stoped->getPertinence());  Serial.print(", ");  Serial.print(slow->getPertinence());  Serial.print(", ");  Serial.print(normal->getPertinence());  Serial.print(", ");  Serial.println(quick->getPertinence());

  Serial.print("Temperatura: ");  Serial.print(cold->getPertinence());  Serial.print(", ");  Serial.print(good->getPertinence());  Serial.print(", ");  Serial.println(hot->getPertinence());

  float output1 = fuzzy->defuzzify(1);  float output2 = fuzzy->defuzzify(2);

  Serial.print("Saida risco: ");  Serial.print(output1);  Serial.print(", Saida velocidade: ");  Serial.println(output2);

  delay(100000);}

Licença Creative Commons

Baseado no trabalho em http://github.com/zerokol/eFLL.
Perssões além do escopo dessa licença podem estar disponível em http://zerokol.com.

Fonte: http://www.zerokol.com/2012/09/arduinofuzzy-uma-biblioteca-fuzzy-para.html

0sem comentários ainda

Enviar um comentário

Os campos são obrigatórios.

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.