Braccio robotico & matematica (trigonometria dei cerchi)

Buonasera a tutti,
È da un po' di tempo che lavoro per conto mio ad un braccio robotico. Sono riuscito a farlo funzionare correttamente utilizzando 4 servomotori e altrettanti interruttori a levetta a zero centrale. Una volta raggiunto questo traguardo ho pensato di alzare un po' l'asticella e di tentare qualcosa di più complicato. Ho pensato di creare una funzione che permetta al braccio robotico di andarsi a posizionare precisamente su delle coordinate che gli fornisco io. Al momento lui si muove su due assi: x e y che sarebbero lunghezza e altezza. Ha due bracci (come in figura)

Io tramite la trigonometria (considerando che so il valore dell'angolo dei due servomotori) vorrei riuscire a permettere ad Arduino di fare i calcoli e avere in uscita il valore degli angoli dei servi. Io partirei calcolando l'altezza da raggiungere e per fare ciò guarderei intanto come è messo il punto più alto (il valore y) da raggiungere. se è maggiore della lunghezza del primo braccio allora utilizzerà anche il secondo braccio, altrimenti si regola poi. La prima funzione matematica che vorrei utilizzare sarebbe il sin^(-1) sulla calcolatrice oppure l'arcsin (credo sia matematicamente parlando) ma non ho trovato la funzione già fatta quindi mi rivolgo a voi per sapere se esiste una libreria che permetta di svolgere questi calcoli in una sola funzione.
Spero di essere stato chiaro
Buon Weekend!

Includi math.h

E studia la sua documentazione

Comunque auguri e complimenti, è una bella sfida, avrai occasione di imparare tanto

1 Like

E aggiungiamo

Il tuo approccio non è l'ideale

Diremmo che devi passare le coordinate in polare
Il braccio ti serve per calcolare l'apertura dell'asse 2
L'asse 1 viene dall'angolo, dopo aver compensato l'apertura del 2

1 Like

Grazie mille per la libreria,
Per i calcoli pensavo di trovare matematicamente l'intersezione tra un cerchio di raggio asse 2 e centro nelle coordinate da me fornite e un cerchio di raggio asse 1 con centro alla base del braccio robotico (sarebbe 0; 0). Visivamente sarebbe cosi:

  • sapendo le coordinate della base del braccio e quelle del punto da raggiungere tracciamo i due cerchi di raggio R1 e R2 e ne vediamo l'interferenza. L'interferenza sarà il punto in cui si andrà a posizionare il giunto che unisce i due bracci

  • Successivamente possiamo calcolare due possibili posizioni del braccio (come in questo caso. altrimenti una nella quale i due cerchi sono tangenti) e possiamo visualizzare anche queste. Per semplicità io direi di utilizzare quella con il braccio avente l'angolo acuto verso il basso.

Per fare questi calcoli abbiamo bisogno di utilizzare formule che per la mia conoscenza
scolastica non ho ancora fatto, ma qualcosina so. So per esempio che se calcoliamo gli zeri di un polinomio P(x) otteniamo tutti i punti che intersecano gli assi su un piano cartesiano (se non erro). Credo che la stessa cosa sia possibile anche con i cerchi.

Io sono munito di un Arduino UNO e di un Arduino Mega2560. Spero di imparare tanto anche qui e buon finesettimana!

1 Like

Buona idea anche la tua

Conosci la matematica di queste formule? Io ho provato a cercare su internet e ho anche trovato qualche risultato interessante ma ci ho capito poco. Sapresti fornirmi le formule per risolvere questi calcoli?
Grazie

P.S. Non ho capito bene la tua.. potresti spiegarla più facilmente :sweat_smile:

Certo, ma non nel fine settimana
Porta pazienza

Oggi sostituisco io il fratello, che ha impegni...

prima cosa da dire è che mi sono interessato alla cosa anche per ragioni personali, ma sopratutto perchè lo OP è un ragazzetto di buona volontà e va quindi incoraggiato

quindi ho raccolto tutte le info che avevo e ne ho fatto un sunto teorico

vediamo un po' di stabilire di cosa parliamo:

manipolatore a due assi, con asse1 lungo diciamo R1 incernierato in 0,0 (in coordinate cartesiane) e asse2 lungo diciamo R2 incernierato al termine di asse1

noi vogliamo che il termine di asse2 arrivi a x,y

va da se che ci deve poter arrivare, poi vedremo la condizione da soddisfare

prima operazione da fare è calcolare la posizione di arrivo in coordinate polari

avremo un raggio, che chiameremo R e un angolo che chiameremo Alfa

la condizione da soddisfare è che R sia inferiore a R1+R2, e nel caso di assi di lunghezza differente una seconda condizione: che R sia superiore alla differenza di lunghezza dei bracci (o delle braccia?, ditemelo voi)

soddisfatta la condizione è possibile calcolare alcuni angoli

il manipolatore va disposto secondo un triangolo di lati R1, R2 ed R
applicando il teorema di Carnot è possibile calcolarne tutti e tre gli angoli

quello al giunto dell'asse2 lo chiameremo Beta e corrisponde all'apertura dell'asse2, che da adesso conosciamo

quello al giunto dell'asse1 lo chiamiamo Gamma, sommato (o sottratto, poi vedremo perchè) dall'angolo Alfa (posizione da raggiungere in coordinate polari) ci da l'apertura dell'asse1, e risolve il problema

quello al vertice di asse2, sottratto o sommato ad Alfa ci da l'assetto del manipolatore, ovvero da che parte guarda la sua estremità

la parte trigonometrica è solo l'applicazione di Carnot, alla fine non è difficile

perché sommare o sottrarre?
perché la stessa posizione può essere raggiunta con due differenti configurazioni del manipolatore, una col triangolo disegnato verso il basso e una disegnato verso l'alto

peraltro un trattamento più analitico del problema indica che per un due assi esistono ben 4 soluzioni, della quali due immaginarie ed all'infinito

ne rimangono due reali, che sono appunto le due ottenute sommando O sottraendo tra loro gli angoli

e per stasera mi fermo

sappimi dire se serve un disegno, che casomai domani faccio a mano e scannerizzo

1 Like

Buonasera,
scusa per il ritardo ma ero impegnato. Innanzitutto ti ringrazio molto per Ho provato a fra il disegno per conto mio e ho ottenuto questo disegno.

Spero sia giusto. Ho provato a sviluppare alcuni calcoli con il teorema di Carnot e ho portato tutto in sketch. Se non ho sbagliato nulla dovrebbero essere questi:

#include <math.h>
float alpha;
float beta;
float gamma;
byte x;
byte y;
byte R1;
byte R2;
byte R;

void setup() {
}

void loop() {
  alpha = atan(y/x)*57,296;
  R = sqrt((x*x)+(y*y));
  beta = acos(((R2*R2)+(R1*R1)-(R*R))/(2*R2*R1))*57,296;
  gamma = acos(((R*R)+(R1*R1)-(R2*R2))/(2*R*R1))*57,296;
}

Io direi che ora li posso aggiungere al mio sketch "finale".

Non riesco a far funzionare questo stekch:

#include <math.h>
float alpha;
float beta;
float gamma;
byte x = 65;
byte y = 32;
byte R1;
byte R2;
byte R;

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

void loop() {
  alpha = atan(y/x)*57,296;
  R = sqrt((x*x)+(y*y));
  beta = acos(((R2*R2)+(R1*R1)-(R*R))/(2*R2*R1))*57,296;
  gamma = acos(((R*R)+(R1*R1)-(R2*R2))/(2*R*R1))*57,296;
  Serial.print(alpha);
  Serial.print(";    ");
  Serial.print(gamma);
  Serial.print(";    ");
  Serial.println(beta);
}

In teoria dovrebbe scrivere i valori sul monitor seriale ma non lo fa, sta vuoto e non scrive nulla. Qual è il problema?

Domani nel pomeriggio lo provo

Cosa ti dice in compilazione?

Fa notare il fratello che la condizione di esistenza la devi verificare

Per R1 ed R2 pari a zero nessun movimento é possibile

Se fai una divisione per zero incatasti la CPU

Anche la virgola ci sta "poco bene"

1 Like

Hai ragione! grazie mille per l'info! Adesso riprovo. Comunque in compilazione non mi dice niente, e durante il funzionamento non fa nulla: non da ne messaggi di errore ne valori su seriale..

Ora ho inserito i valori delle lunghezze e in seriale ha iniziato a scrivere qualcosa. Il problema è cosa: 0.00; nan; nan. Lui mi scrive questo, dove ho sbagliato?

Nan significa not a number

Qualche calcolo impossibile, tipo arcoseno di un numero maggiore di 1

Ti conviene fare un poco di debug, stampando anche i valori intermedi dei calcoli

1 Like

57.296 da dove arriva?nera vergogna
In tanti anni non avevamo mai calcolato 180/PI, lo avevamo sempre lasciato fare al preprocessore....

Inoltre se tieni x ed y intere senza castarle per il calcolo dell'arcotangente avrai come rapporto 0 e come angolo parimenti 0
Serve che impari a "giocare" coi tipi dati di C

1 Like

Grazie mille, ci lavorerò su :wink:

il programma ho poi un errore minore, se guardi i valori ti rendi conto che forse devi guardare un lato differente per alfa, comunque dopo le opportuna correzione va, ma è "lento", se devi usarlo per movimenti in tempo reale
ci mette tra uno e due millisecondi a calcolo, sulla mia UNO orginale

serve accelerarlo un poco, non difficiel

ritiro, gli angoli mi sembrano OK e con le prove fatte assieme a Massimo non sembra possibile migliorare l'ottimizzazione dei calcoli

Grazie per gli aiuti,
ma non ho capito se a voi funzionano questi calcoli e se a voi scrive un valore sulla seriale..
A me con questo sketch (sotto) da come risultato 26.21; 72.45; nan; nan. I valori sarebbero rispettivamente alpha, R, beta e gamma. Ho provato anche su excel er vedere se fosse un problema di dati (float oppure int etc.) oppure un problema matematico e dai risultati sembrerebbe essere quest'ultimo..

#include <math.h>
float alpha;
float beta;
float gamma;
float x = 65.0;
float y = 32.0;
float R1 = 100.0;
float R2 = 50.0;
float R;

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

void loop() {
  if(R < (R1+R2) && R > abs(R1-R2)){
    alpha = atan(y/x)*(180.0/PI);
    Serial.print(alpha);
    Serial.print(";    ");
    R = sqrt((x*x)+(y*y));
    Serial.print(R);
    Serial.print(";    ");
    beta = acos(((R2*R2)+(R1*R1)-(R*R))/(2.0*R2*R1))*(180.0/PI);
    gamma = acos(((R*R)+(R1*R1)-(R2*R2))/(2.0*R*R1))*(180.0/PI);
    Serial.print(beta);
    Serial.print(";    ");
    Serial.println(gamma);
  }
}

Mi è venuto in mente un altro dubbio: voi con la differenza tra R1 e R2 intendete il valore assoluto della loro differenza oppure R1-R2 o viceversa?

A noi funziona, lo abbiamo segnalato ieri
Stampa il valore di

Scommetto che è maggiore di 1