Eine etwas andere Kettenlinie

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Übliche Demonstrationsprogramme für die Kettenlinie stellen meistens nur eine einfache, komplett durchhängende Linie dar. Interessanter finde ich eine Linie, die auf dem Boden aufliegt, weil sie zu lang ist, oder zwei zusammenhängende Linien. Ich hatte dies bereits einmal in C implementiert. Jetzt habe ich in anderem Zusammenhang erste Erfahrungen mit dem Scipy-Modul machen können. Deshalb habe ich das Problem jetzt einmal in Python mit Scipy umgesetzt. Eins vorweg: Es ist nicht langsamer als die C-Implementierung und die Entwicklung war wesentlich geradliniger. Gerade die Berechnung der Gleichungen für aufliegende Ketten erscheint mir ziemlich elegant. Im Prinzip ist es lediglich die Lösung eines nichtlinearen Gleichungssystems.
Die grafische Darstellung erfolgt mit Tkinter, weil sich das Canvas-Widget hierfür anbot. Die entsprechende Klasse enthält u.a. auch eine Methode draw_vecs, die für die Kettenlinie nicht benötigt wird. Ich verwende die Klasse aber auch für eine alternative Ausgabe der in einem anderen Thread behandelten Planetenbahnen: http://www.python-forum.de/topic-11982.html
Wenn man den mittleren Aufhängungspunkt verschiebt, fallen in Grenzbereichen abrupte Formänderungen der Kurve auf, die wahrscheinlich nicht korrekt sind. Nach Vermeidung negativer Werte für k, die z.T. von fsolve als Ergebnis geliefert wurden, in der Gleichung für die Kettenlinie und "Sicherheitsabstand" am oberen und den seitlichen Rändern für die Verschiebemarke ist dies wesentlich besser geworden, taucht aber gelegentlich weiterhin auf. Ich vermute, dass die Teilung der aufliegenden Kette (Zeile 138) das Problem darstellt. Ich habe die Grenze zwischen rechtem und linkem Teil einfach senkrecht durch das Minimum einer entsprechenden durchhängenden Kettenlinie gleicher Länge gelegt. Das scheint aber nicht korrekt zu sein: Wenn man z.B. den Verschiebepunkt nicht bei x=0, sondern bei x=50 hat (animate_drag(-100, 200, 100, 200, 500, graph, 50)), dann entsteht beim Übergang von der 2-Punkt- auf die 3-Punkt-Form plötzlich ein Knick. Ich weiß aber nicht, wie ich die Kette "physikalisch korrekt" in 2 Teile aufteile. Vielleicht hat ja jemand eine gute Idee oder kennt sich einfach besser in Physik aus.
Etwas komisch sehen die vielen Funktionen im Modul aus. Ich zumindest sehe hier aber keinen Sinn in der Verwendung einer Klasse. Auch hier würden mich Meinungen interessieren.
Bitte nicht über die z.T. kurzen Namen (a, b, k, l, l1 etc.) schimpfen. Sie sind halt kurz und trotzdem wohl verständlich.
Das Programm ist fast nicht kommentiert. Wenn es also Fragen gibt, nur zu.
Hier jetzt der Code: http://paste.pocoo.org/show/5299/
MfG
HWK
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hallo,

ich bin leider noch zu verschlafen um mir den Quellcode anzusehen, aber ich bekomm hier (Ubuntu Feisty) folgende Meldungen:
Traceback (most recent call last):
File "kette.py", line 182, in func
ret = [cosh(k * (x1 - b)) / k + a - y1]
OverflowError: math range error
Traceback (most recent call last):
File "kette.py", line 210, in func
ret = [cosh(k * (x2 - b)) / k + a - y2]
OverflowError: math range error
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ja, das stimmt. Sie erfolgen bei schlechten Schätzwerten für fsolve. Die Meldungen fange ich mit try...except ab und passe den Schätzwert dann an (Zeilen 160ff., 188ff. und 216ff.). Komischerweise werden die Fehlermeldungen in fsolve trotzdem irgendwo ausgegeben. Dem Programmablauf schadet es aber zumindest bei mir (Windows XP) nicht. Wen die Meldungen stören, der kann sie unter Windows aber unterdrücken, indem die Dateiendung auf pyw geändert wird. Läuft es denn bei Dir trotz der Meldungen ansonsten?
MfG
HWK
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

HWK hat geschrieben:Wen die Meldungen stören, der kann sie unter Windows aber unterdrücken, indem ...
*lach* ich mag deine Art, mit Fehlermeldungen umzugehen :D

Aber du hast recht, das Programm läuft trotzdem.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Im Ernst: Siehst Du eine Möglichkeit, die Meldungen zu unterdrücken? Normalerweise dürften Sie ja gar nicht angezeigt werden, da ich Sie abfange. Vielleicht kennt sich ja jemand besser mit Scipy aus. Kann man da evtl. irgendwie das Verhalten bei Fehlern einstellen?
MfG
HWK

Edit: Wohl nicht. Wenn man sich den Code von fsolve in minpack.py anschaut, passiert da ja eher wenig. Das Problem scheint in _minpack._hybrd, also dem Fortran-Anteil, zu liegen. Von hier wird func aufgerufen.

Edit2: Und ein Programmlauf ohne try...except bestätigt das:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Programme\Python24\Scripts\Mixed\Kopie von Chain.py", line 181, in func
    ret = [cosh(k * (x1 - b)) / k + a - y1]
OverflowError: math range error # Bis hierhin wird es immer angezeigt
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Programme\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
    return self.func(*args)
  File "C:\Programme\Python24\lib\lib-tk\Tkinter.py", line 456, in callit
    func(*args)
  File "C:\Programme\Python24\Scripts\Mixed\Kopie von Chain.py", line 332, in update_func
    ret = two_points(x1, y1, x2, y2, ll)
  File "C:\Programme\Python24\Scripts\Mixed\Kopie von Chain.py", line 138, in two_points
    ret1 = chain_line(x1, y1, b, l1)
  File "C:\Programme\Python24\Scripts\Mixed\Kopie von Chain.py", line 189, in chain_line
    ret = fsolve(func, (0, bb, 1), full_output=True)
  File "C:\Programme\Python24\Lib\site-packages\scipy\optimize\minpack.py", line 121, in fsolve
    retval = _minpack._hybrd(func,x0,args,full_output,xtol,maxfev,ml,mu,epsfcn,factor,diag)
error: Error occured while calling the Python function named func
Es werden also scheinbar zwei Meldungen ausgegeben und try...except verhindert nur die zweite in der Exception.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Als Bemerkung zum Python-math-Modul steht folgendes:

Code: Alles auswählen

Note: The math module consists mostly of thin wrappers around the platform C math library functions.
Behavior in exceptional cases is loosely specified by the C standards,
and Python inherits much of its math-function error-reporting behavior from the platform C implementation.
Die Ursache des Problems liegt also in der C-Library math. Dort steht für z.B. cosh:

Code: Alles auswählen

The cosh function returns the hyperbolic cosine value. When the argument is outside the permissible range,
the matherr function is called. Unless the default matherr function is replaced,
it will set the global variable errno to ERANGE,
and print a "RANGE error" diagnostic message using the stderr stream.
Da ich nicht weiß, wie man matherr von Python aus ändern kann, muss man wohl die Fehlermeldungen akzeptieren.
MfG
HWK

Edit: Ich habe die Pythonfunktionen func für fsolve mal in identische C-Funktionen geändert und in eine pyd ausgelagert. Hier tauchen keine Meldungen mehr auf. Wahrscheinlich weil die math-Lib von mingw, mit dem ich kompiliert habe, Fehler anders handhabt als die von MSVC, der ja für Python verwendet wird.
Übrigens: An der subjektiven Geschwindigkeit des Programms ändert sich hierdurch nichts.
Antworten