Precisão crescente da solução da equação transcendental
Eu tenho uma cinemática específica como parte de uma máquina mais complexa e preciso calcular alguns parâmetros físicos que sãomuito difícil impossível de medir com a devidaprecisão com instrumentos que tenho à minha disposição
[cinemática]
À primeira vista, é uma simples1
braço de grau de liberdade (preto) que pode girar em tornox
eixo. Ele tem um peso para forçá-lo a subir sempre até atingir o ponto final mecânico (ânguloa0
) ou algum tubo (azul) com raior0
. O centro de rotação do braço está emy0
. O tubo pode ser movido para qualquery(t)
altura.
[uso]
Isso é usado para medir o raio de um tubo para processamento adicional. O raio pode ser calculado (por goniometria básica), o que leva à equação na parte inferior da imagem. As constantesa0,y0,z0
são muito difíceis de medir (é dentro de máquinas complexas), portanto a precisão da medição para distâncias é mínima0.1 mm
e ângulo0.1 deg
e até isso é questionável.
[calibração]
Por isso, decidi tentar calcular esses parâmetros a partir do conjunto de medições feitas pela própria máquina (calibração automática). Então eu tenho tubo de calibração com raio conhecidor0
. Todos os parâmetros verdes podem ser tratados como constantes. Agora eu posiciono o tubo juntoy
eixo para cobrir tantos ângulos de braço quanto eu poderia. Infelizmente, o alcance é apenas de cerca de20 degrees
(para configuração atual da máquina) lembrar as medidasa(t)
para predefiniçãoy(t)
... Comon
conjunto de dados de pontos. Isso me dá um sistema den
equações transcendentes. A partir disso, tento / acho que "todas" as possibilidades dea0,y0,z0
lembrando a melhor solução (mais próximar0
)
[aproximação de a0, y0, z0]
aproximação é baseada nesta minha classe:
//---------------------------------------------------------------------------
class approx
{
public:
double a,aa,a0,a1,da,*e,e0;
int i,n;
bool done,stop;
approx() { a=0.0; aa=0.0; a0=0.0; a1=1.0; da=0.1; e=NULL; e0=NULL; i=0; n=5; done=true; }
approx(approx& a) { *this=a; }
~approx() {}
approx* operator = (const approx *a) { *this=*a; return this; }
//approx* operator = (const approx &a) { ...copy... return this; }
void init(double _a0,double _a1,double _da,int _n,double *_e)
{
if (_a0<=_a1) { a0=_a0; a1=_a1; }
else { a0=_a1; a1=_a0; }
da=fabs(_da);
n =_n ;
e =_e ;
e0=-1.0;
i=0; a=a0; aa=a0;
done=false; stop=false;
}
void step()
{
if ((e0<0.0)||(e0>*e)) { e0=*e; aa=a; } // better solution
if (stop) // increase accuracy
{
i++; if (i>=n) { done=true; a=aa; return; } // final solution
a0=aa-fabs(da);
a1=aa+fabs(da);
a=a0; da*=0.1;
a0+=da; a1-=da;
stop=false;
}
else{
a+=da; if (a>a1) { a=a1; stop=true; } // next point
}
}
};
//---------------------------------------------------------------------------
Ele pesquisa toda a gama de variáveis únicas por algum passo inicial e depois encontra o ponto de desvio mínimo. Depois disso, altere o alcance e vá para fechar a área deste ponto e aumentar recursivamente a precisão.
A solução em si é assim:
// (global) input data
#define _irc_calib_n 100
#define _irc_approx_n 5
int irc_calib_ix; // number of measured points
double irc_calib_y[_irc_calib_n]; // y(t)
double irc_calib_a[_irc_calib_n]; // a(t)
double irc_calib_r; // calibration tube radius + arm radius
// approximation
int ix=0;
double e,a,deg=M_PI/180.0;
approx aa,ay,az;
// min max step recursions ErrorOfSolutionVariable
for (aa.init(-90.0*deg,+90.0*deg,10.0*deg,_irc_approx_n,&e);!aa.done;aa.step())
for (ay.init( 0.0 ,200.0 ,10.0 ,_irc_approx_n,&e);!ay.done;ay.step())
for (az.init( 50.0 ,400.0 ,10.0 ,_irc_approx_n,&e);!az.done;az.step())
{
for (e=0.0,ix=0;ix<_irc_calib_n;ix++) // test all measured points (e is cumulative error)
{
a=irc_calib_a[ix]+aa.a;
if (a> pi) a-=pi2;
if (a<-pi) a+=pi2;
if (fabs(a)>0.5*pi) { e=100.0; break; } // ignore too far angles
e+=fabs(+(cos(a)*(irc_calib_y[ix]-ay.a))
-(sin(a)*(az.a))
-(irc_calib_r));
}
}
// here aa.a,ay.a,az.a holds the result
Isso leva a uma solução próxima aos valores medidos, mas dentro da simulação o resultado ainda não é preciso o suficiente. É de 0,1 mm a 0,5 mm, dependendo do número de pontos e faixa de ângulo. Se eu medir adequadamentez0
e ignorar sua aproximação, a precisão é aumentada significativamente, deixandoy0
sem erro (em simulação) ea0
com erro em torno de 0,3 graus
Q1 como posso melhorar ainda mais a precisão da solução?
Não posso aumentar o alcance angular. O número de pontos é melhor em torno100
quanto mais, melhor a precisão, mas acima de 150 o resultado é instável (para alguns raios, é completamente desativado). Não tenho absolutamente nenhuma idéia do porquê. O número de recursões acima6
não tem muito efeito
Poderia ajudar a ponderar os desvios de acordo com a distância angular da0 degree
? Mas, infelizmentea(t)
intervalo não inclui necessariamente0 degrees
precisão desejada é0.01 mm
paray0,z0
e0.01 degree
paraa0
Q2 há algo que eu perdi?
Como aproximações incorretamente aninhadas ou alguma simplificação matemática ou abordagem diferente
[notas]
O ângulo deve estar na forma dea(t)+a0
porque é medido pelo IRC com reset do SW (16000 steps/round
) É redefinido quando ema0
posição Não conto vibrações e excentricidade do tubo de calibração de que eles já foram atendidos e meu primeiro objetivo é fazer com que isso funcione em simulação sem eles. Tuboy(t)
pode ser posicionado à vontade ea(t)
a medição pode ser feita à vontade.
No momento, os pontos de verificação do processo de calibraçãoy
eixo (movimento dea0
baixa). Computação com6
recursões levam em torno de35
segundos (seja paciente).5
recursões levam em torno de22
segundos
[edit1] aqui como a simulação é feita
approx aa; double e;
for (aa.init(-90.0*deg,+90.0*deg,10.0*deg,6,&e);!aa.done;aa.step())
e=fabs(+(cos(aa.a)*(y(t)-y0))
-(sin(aa.a)*(z0))
-(irc_calib_r));
if (aa.a<a0) aa.a=a0;
[edit2] alguns valores
Só percebi que eu tinha apenas4
recursões no código de simulação para corresponder à precisão do IRC de entrada, deve haver6
recursões. Depois de alterá-lo (também na edição anterior), aqui estão alguns resultados
| a0[deg]| y0[mm] | z0[mm] |
simulated | -7.4510|191.2590|225.9000|
z0 known | -7.4441|191.1433|225.9000|
z0 unknown | -7.6340|191.8074|225.4971|
Portanto, a precisão comz0
medido está quase na faixa desejada, mas comz0
desconhecido o erro ainda é~10
vezes maior que o necessário. Aumentar a precisão da simulação não tem efeito acima6
recursões e também não faz sentido, porque os dados reais de entrada também não serão mais precisos.
Aqui, os pontos simulados / medidos para teste com s simulados acima, configurações:
ix a [deg] y [mm]
0 -0.2475 +105.7231
1 -0.4500 +104.9231
2 -0.6525 +104.1231
3 -0.8550 +103.3231
4 -1.0575 +102.5231
5 -1.2600 +101.7231
6 -1.4625 +100.9231
7 -1.6650 +100.1231
8 -1.8675 +99.3231
9 -2.0700 +98.5231
10 -2.2725 +97.7231
11 -2.4750 +96.9231
12 -2.6775 +96.1231
13 -2.8575 +95.3077
14 -3.0600 +94.5154
15 -3.2625 +93.7231
16 -3.4650 +92.9308
17 -3.6675 +92.1385
18 -3.8700 +91.3462
19 -4.0725 +90.5538
20 -4.2750 +89.7615
21 -4.4877 +88.9692
22 -4.6575 +88.1769
23 -4.8825 +87.3615
24 -5.0850 +86.5154
25 -5.2650 +85.7000
26 -5.4675 +84.9077
27 -5.6700 +84.1154
28 -5.8725 +83.3231
29 -6.0750 +82.5308
30 -6.2775 +81.7000
31 -6.5025 +80.8462
32 -6.6825 +80.0462
33 -6.8850 +79.2538
34 -7.0875 +78.4615
35 -7.2900 +77.6538
36 -7.5159 +76.7692
37 -7.6725 +75.9769
38 -7.8750 +75.1846
39 -8.1049 +74.3692
40 -8.2800 +73.5000
41 -8.4825 +72.7077
42 -8.6850 +71.9154
43 -8.9100 +71.0308
44 -9.0900 +70.2231
45 -9.2925 +69.4308
46 -9.5175 +68.5462
47 -9.6975 +67.7462
48 -9.9000 +66.9462
49 -10.1025 +66.0615
50 -10.3148 +65.2692
51 -10.4850 +64.3769
52 -10.6875 +63.5846
53 -10.9125 +62.7462
54 -11.0925 +61.9077
55 -11.2950 +61.0846
56 -11.4975 +60.2231
57 -11.7000 +59.3923
58 -11.9025 +58.5308
59 -12.1288 +57.6692
60 -12.3075 +56.8385
61 -12.5100 +55.9462
62 -12.7125 +55.1538
63 -12.9150 +54.2615
64 -13.1175 +53.4000
65 -13.2975 +52.5769
66 -13.5000 +51.6846
67 -13.7025 +50.7923
68 -13.9050 +50.0000
69 -14.1075 +49.1077
70 -14.3100 +48.2154
71 -14.5350 +47.3615
72 -14.7150 +46.5308
73 -14.9175 +45.6385
74 -15.1200 +44.7462
75 -15.3225 +43.8538
76 -15.5250 +42.9615
77 -15.7490 +42.0692
78 -15.9075 +41.2769
79 -16.1100 +40.3846
80 -16.3125 +39.4923
81 -16.5150 +38.6000
82 -16.7175 +37.7077
83 -16.9200 +36.8154
84 -17.1225 +35.9231
85 -17.3250 +34.9308
86 -17.5275 +34.0385
87 -17.7300 +33.1462
88 -17.9325 +32.2538
89 -18.1350 +31.3615
90 -18.3405 +30.4692
91 -18.5175 +29.4769
92 -18.7200 +28.5846
93 -18.9225 +27.6923
94 -19.1250 +26.8000
95 -19.3275 +25.8077
96 -19.5300 +24.9154
97 -19.7325 +23.9231
98 -19.9350 +23.0308
99 -20.1375 +22.1385
atualização de progresso
alguns esclarecimentos para @Ben
como funciona
a equação colorida sob a primeira imagem fornece o raior0
é feito de 2 juntou90 degree
triângulos (trigonometria básica)
coisas vermelhas:
y(t)
é a posição do motor e é conhecidoa(t)
é o estado IRC também conhecidocoisas verdes:
a0,y0,z0
são dimensões mecânicas e são conhecidas, mas não precisas, então eu medo muitasa(t)
para diferentes posições dey(t)
com tubo de calibração conhecidor0
e calcular oa0,y0,z0
com maior precisãomelhoria da precisão adicional
Na verdade, consegui ser mais preciso medindoy1=y0+z0*cos(a0)
movimento de calibração especial com precisão0.03 mm
e melhor. É a altura da interseção entre o braço ema0
posição e tuboy
eixo de movimento. É medido e interpolado da situação em que o braço entra em contato pela primeira vez quando o tubo vem de cima para baixo, mas a posição real deve ser recalculada pelo raio usado ea0
... porque o ponto de contato não está neste eixo ... (a menos quer0=0.0
) Isso também elimina um loop de aproximação da calibração porquey1,a0,z0
são dependentes e podem ser calculados um do outro. Também remover o duplo aliasing da medição do IRC devido à maneira descontínua de medição ea(t),y(t)
posições ajudaram muito a aumentar a precisão e a estabilidade da computação (em máquinas reais). No momento, não posso avaliar com precisão a precisão porque, pela análise de muitos ciclos medidos, encontrei alguns problemas mecânicos na máquina, então espero até que ela seja reparada. De qualquer forma, a calibração vs. precisão da simulação parar0=80.03 mm
com contabilidade ambas as abordagens e_irc_calib_n=30
é agora:
; computed simulated |delta|
a0= -6.915840 ; -6.916710 +0.000870 deg
y0=+186.009765 ;+186.012822 +0.003057 mm
y1=+158.342452 ;+158.342187 +0.000264 mm
z0=+228.102470 ;+228.100000 +0.002470 mm
Quanto maior a calibraçãor0
menor precisão (devido a limitações dea(t)
alcance), isto é, computando tudoa0,y0,(y1),z1
nada é medido diretamente ou conhecido. Isso já é aceitável, mas como escrevi antes, é necessário verificar a máquina quando estiver pronta. Apenas para concluir aqui é como as medições simuladas se parecem agora:
[edit4] verComo a pesquisa por aproximação funciona