rhöhung der Genauigkeit der Lösung der transzendentalen Gleichu

Ich habe eine bestimmte Kinematik als Teil einer komplexeren Maschine und muss einige physikalische Parameter berechnen, diesehr schwe (eher unmöglich) zu messen mit richtigenRichtigkei mit Instrumenten, die ich zur Verfügung habe

[Kinematik

Auf den ersten Blick ist es ein einfaches1 Freiheitsgrad Arm (schwarz), der sich drehen kannx Achse. Es hat ein Gewicht, das es zwingt, immer nach oben zu fahren, bis es den mechanischen Endpunkt erreicht (Winkela0) oder eine Röhre (blau) mit Radiusr0. Das Rotationszentrum des Arms liegt beiy0. Die Röhre kann zu jedem @ verschoben werdy(t) height.

[Verwendung

Dies wird verwendet, um den Radius eines Rohrs für die weitere Verarbeitung zu messen. Der Radius kann (durch grundlegende Goniometrie) berechnet werden, was zu einer Gleichung im unteren Teil des Bildes führt. Die Konstantena0,y0,z0 sind sehr schwer zu messen (es befindet sich in komplexen Maschinen), daher ist die Messgenauigkeit für Entfernungen min0.1 mm und Winkel0.1 deg und auch das ist fraglich.

[Kalibrierung

So habe ich mich entschlossen, diese Parameter aus einer Reihe von Messungen zu berechnen, die von der Maschine selbst durchgeführt wurden (automatische Kalibrierung). Ich habe also ein Kalibrierrohr mit bekanntem Radiusr0. Alle grünen Parameter können als Konstanten behandelt werden. Jetzt positioniere ich die Röhre entlangy Achse, um so viele Winkel des Arms abzudecken, wie ich konnte. Leider geht es in der Reichweite nur um20 degrees (für das aktuelle Maschinen-Setup) Speichern des gemessenena(t) für Presety(t) ... wien point-Datensatz. Das gibt mir System vonn transzendente Gleichungen. Daraus versuche ich "alle" Möglichkeiten vona0,y0,z0 Erinnerung an die beste Lösung (am nächsten anr0)

[Approximation von a0, y0, z0]

approximation basiert auf meiner Klasse:

//---------------------------------------------------------------------------
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
            }
        }
    };
//---------------------------------------------------------------------------

Es durchsucht den gesamten Bereich einer einzelnen Variablen nach einem Anfangsschritt und ermittelt dann den minimalen Abweichungspunkt. Ändern Sie danach den Bereich und den Schritt, um den Bereich dieses Punkts zu schließen und die Genauigkeit rekursiv zu erhöhen.

Die Lösung selbst sieht folgendermaßen aus:

// (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

Dies führt zu einer Lösung in der Nähe der gemessenen Werte, aber in der Simulation ist das Ergebnis immer noch nicht genau genug. Sie liegt je nach Punktzahl und Winkelbereich zwischen 0,1 mm und 0,5 mm. Wenn ich richtig messez0 und ignorieren Sie seine Annäherung, dann wird die Präzision deutlich erhöht und @ verlassy0 ohne Fehler (in der Simulation) unda0 mit einem Fehler um 0,3 Grad

F1 Wie kann ich die Genauigkeit der Lösung weiter verbessern?

Ich kann den Winkelbereich nicht vergrößern. Die Anzahl der Punkte ist am besten um100 je mehr desto besser die Genauigkeit, aber über 150 ist das Ergebnis instabil (für einige Radien ist es völlig aus). Habe absolut keine Ahnung warum. Die Rekursionsnummer über6 hat nicht viel Wirkung

Könnte helfen, die Abweichungen nach Winkelabstand von @ zu gewicht0 degree? Aber traurigerweisea(t) range beinhaltet nicht unbedingt0 degrees

Gewünschte Genauigkeit ist0.01 mm zumy0,z0 und0.01 degree zuma0

Q2 habe ich etwas verpasst?

Wie falsch verschachtelte Näherungen oder eine mathematische Vereinfachung oder einen anderen Ansatz

[Anmerkungen

Der Winkel muss in Form von @ sea(t)+a0 weil es von IRC mit SW-Reset gemessen wird 16000 steps/round). Es wird zurückgesetzt, wenn ina0 position Ich zähle nicht die Vibrationen und die Exzentrizität des Kalibrierrohrs, für die sie bereits gesorgt haben, und mein erstes Ziel ist es, diese Arbeit in der Simulation ohne sie zu machen. Tubey(t) kann frei positioniert werden und dasa(t) Messung kann nach Belieben durchgeführt werden.

Rechts jetzt scannt der Kalibrierungsprozess die Punkte entlangy Achse (Bewegung vona0 Nieder). Berechnung mit6 Rekursionen nehmen um35 Sekunden (also etwas Geduld).5 Rekursionen nehmen um22 Sekunden

[edit1] hier wie die simulation gemacht wird

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] einige Werte

Nur realisiert, dass ich nur @ hat4 Rekursionen im Simulationscode, die mit der IRC-Genauigkeit der Eingabe übereinstimmen, dann muss es @ geb6 Rekursionen. Nach der Änderung (auch in der vorherigen Bearbeitung) sind hier einige Ergebnisse

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

So die Genauigkeit mitz0 gemessen ist fast im gewünschten Bereich, aber mitz0 unbekannt der Fehler ist immer noch~10 mal größer als nötig. Die Erhöhung der Simulationsgenauigkeit hat keine Auswirkungen über6 Rekursionen und auch keinen Sinn, weil echte Eingabedaten auch nicht genauer sein werden.

Hier sind die simulierten / gemessenen Punkte zum Testen mit den oben simulierten Einstellungen:

 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 

[edit3] Fortschrittsaktualisierung

einige Klarstellungen für @ Ben

wie es funktionier

die farbige Gleichung unter dem ersten Bild gibt Ihnen den Radiusr0 es besteht aus 2 verbundenen90 degree Dreiecke (grundlegende Trigonometrie)

red stuff:

y(t) ist Motorposition und es ist bekannt,a(t) ist der IRC-Status auch bekannt

Grünzeug

a0,y0,z0 sind mechanische Maße und sind bekannt, aber nicht genau, deshalb messe ich vielea(t) für verschiedene Positionen vony(t) mit bekanntem Kalibrierröhrchenr0 und berechne dasa0,y0,z0 mit höherer Präzision daraus

weitere Genauigkeitsverbesserung

Ich habe es tatsächlich geschafft, es durch Messen genauer zu macheny1=y0+z0*cos(a0) von speziellen Kalibrierungsbewegung mit Präzision um0.03 mm und besser. Es ist die Schnitthöhe zwischen Arm ina0 Position und Tubey Bewegungsachse. Es wird gemessen und aus der Situation interpoliert, in der der Arm das erste Mal berührt wird, wenn das Rohr von oben nach unten kommt. Die tatsächliche Position muss jedoch mit dem verwendeten Radius und @ neu berechnet werdea0 ... weil der Kontaktpunkt nicht auf dieser Achse liegt ... (außerr0=0.0). Dies eliminiert auch eine Approximationsschleife aus der Kalibrierung, day1,a0,z0 sind abhängig und können voneinander berechnet werden. Entfernen von Double Aliasing bei der Messung von IRC aufgrund von diskontinuierlichen Messmethoden unda(t),y(t) -Positionen haben wesentlich zur Erhöhung der Präzision und der Rechenstabilität (auf realen Maschinen) beigetragen. Ich kann die Genauigkeit momentan nicht zuverlässig beurteilen, da ich bei der Analyse vieler gemessener Zyklen einige mechanische Probleme an der Maschine festgestellt habe und warte, bis sie repariert ist. Wie auch immer, die Kalibrierung vs. Simulationsgenauigkeit fürr0=80.03 mm mit Buchhaltung beide Ansätze und_irc_calib_n=30 ist jetzt

    ;      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

Je größer die Kalibrierungr0 die geringere Genauigkeit (aufgrund begrenztera(t) range) Dies erfolgt durch Berechnung von alla0,y0,(y1),z1 nichts wird direkt gemessen oder ist bekannt. Dies ist bereits akzeptabel, aber wie ich bereits geschrieben habe, muss die Maschine überprüft werden, wenn sie bereit ist. Um hier vollständig zu sein, sehen simulierte Messungen jetzt so aus:

[edit4] sieheWie die Annäherungssuche funktioniert

Antworten auf die Frage(2)

Ihre Antwort auf die Frage