C++Guns – RoboBlog blogging the bot

13.01.2019

Linux: Zwei Monitore / Bildschirme anschliessen

Filed under: Allgemein — Tags: — Thomas @ 10:01

Ein paar nützliche Befehle:

# xrandr
Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 32767 x 32767
LVDS2 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 344mm x 193mm
1920x1080 60.00*+ 59.93 50.00
...
VGA-1-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 527mm x 296mm
1920x1080 60.00*+
...

Mein Laptop Bildschirm ist LBDS2, es ist der Hauptschirm. Und anhand den Abmessungen sieht man auch, dass es der kleinere ist.
Der externe Bildschirm ist über VGA anschlossen, kein DVI.

Der Befehlt xrandr stellt viele nützliche Befehle bereit. Z.B.:

# xrandr --listmonitors
0: +*LVDS2 1920/344x1080/193+0+0 LVDS2
1: +VGA-1-1 1920/527x1080/296+0+0 VGA-1-1

Um den externen Bildschirm auf die linke Seite zu verschieben, genügt einfach der Befehl
# xrandr --output VGA-1-1 --left-of LVDS2

Sehr angenehm das.

12.01.2019

Installation von FreeBSD

Filed under: Allgemein — Tags: — Thomas @ 21:01

Mir geht die Linux Gemeinschaft in letzter Zeit richtig auf die Nerven. Vor allem der Hype um systemd. Wenn ihr schon etwas besser machen wollt, dann baut es doch nicht noch schrottiger. Es wird wieder Zeit für ein unix! FreeBSD war damals vor >15 Jahren ganz toll. Also warum nicht.

Problem: Die Hardware will nicht. Der Computer ging aus, aber nicht mehr an. Und an was es liegt, da ist die Glaskugel gefragt :/ Auf gut Glück mal das Netzteil wechseln. War doch gar nicht alt. 2010 oder so gekauft.

Lustigerweise steht im Keller noch so ein komischer ALDI PC. Voll gepackt mit haste nicht gesehn. Neben 2 CD Laufwerken auch ein Multi Kartenleser, eine TV Karte, WLAN, VIELE USB Anschlüsse, seltsame Video Buchse, ein Infrarot Empfänger? Optische Leitungen, noch mehr Video/Audio Buchsen und ein SCART Anschluss!
Das Teile würde heute 4000Eur kosten!

Medion PC MT 6 Intel Pentium 4 3.0GHz ist die Bezeichnung.

Und das beste: Er geht an und zeigt ein Bild! Das BIOS ist zwar Passwort geschätzt, aber ein kurzer CMOS clear beseitigt auch das. Im BIOS stimmt sogar die System Uhr! Ich hab keine Ahnung wie die Batterie die Dezijahre überlebt hat.
Leider bootet das Teil nicht sofort vom USB Stick. Aber die Festplatte nimmt er sofort. Selbst wenn man sie im BIOS ausschaltet?!

Das FreeBSD Image ist auch schon runter geladen und auf die Festplatte kopiert

# dd if=FreeBSD-12.0-RELEASE-i386-memstick.img of=/dev/sdb bs=1M conv=sync

Noch eine zweite Festplatte für das System selbst bereit stellen, und schon geht es los. Mit dem kleinen Teufelchen.
Also die Dokumentation von FreeBSD muss ich wirklich mal loben. Die ist heute noch genauso gut und verständlich wie damals. Kein Brain gefummel.
Nur leider dauert das Backup nun schon 12 Stunden! Und erst die Hälfte ist kopiert. Ja es sind jede Menge kleine Dateien und er kopiert auch nur mit ein paar 100kB/s. Aber etwas schneller hätte ich schon erwartet. Vllt. geht auch diese Festplatte kaputt. Alt genug ist sie ja.

So, das Backup hat ganze 24 Stunden gedauert! Aber nun läuft die Installation von FreeBSD.
Nach der ersten Installation meldet grub unknown filesystem... Ja wieso grub? Klar kennt grub das BSD FS nicht. Hab ich wohl irgend etwas übersehen. Nochmal.

Diesmal wählte ich "guides" Festplatten Partitionierung und habe mehr Optionen als vorher?! Nagut. Die Anleitung hilft.

Tataa. Login. Welcome. What now?

pkg install xorg xdm xfce vim firefox gcc
Was man so eben braucht.

Bei folgender Fehlermeldunf in den Ports:

size mismatch: expected 20137, actual 20118

Hilft folgendes Kommando

pkg update -f

Oder wenn es ganz schlimm ist

make makesum

11.01.2019

Druckerschrank Beleuchtung

Filed under: Allgemein — Thomas @ 19:01

Wir haben einen Druckerschrank mit allen drum und drin, was man so zum Drucken und Laminieren braucht.
Allerdings ist die Ecke ziemlich düster, wenn nicht sogar stockdunkel. Ein paar LED Streifen sollten helfen.
Kosten 25Eur Zeit 1 Tag

Sieht doch gut aus. Natürlich gehen die Lampen automatisch aus, wenn die Tür zu ist.

Update 23.06.2019
Als beim Toner austauschen irgendeine Feder durch die Gegend sprang, war klar, dass etwas nicht stimmt. Irgendein Plastik Schnübbelchen ist abgebrochen, welches besagte Feder an Ort und Stelle hielt. Und dieses brach, da beim Handtieren zu wenig Platz ist. Und dieser Mangel lässt sich darauf begründen, dass der Druckerdeckel nicht weit genug aufgeklappt werden kann, da die Schrankwand im Weg ist.
Also kurzerhand die Schrankwand passend ausgesägt und nun ist es besser :)
Bei dieser Gelegenheit habe ich auch die LED Streifen mit Heißkleber befestigt. Was anderes hält einfach nicht zuverlässig.

druckerschrank

07.01.2019

C++ Guns: PRNG

Filed under: Allgemein — Tags: , — Thomas @ 20:01

Parallel mit mehreren Zufallsgeneratoren zu arbeiten ist echt nicht einfach. Die Details verstecken sich im Verständnis.

Mit welchen Seed werden sie erstellt? Einfach die Zeit in Sekunden plus 1, 2 3, 4? Wir können das ja einfach mal ausprobieren.
Die ersten drei Zahlen von vier Generatoren:

int main() {
  for(int j=1; j < 5; ++j) {  
    cout << "\nseed " << j << "\n";
    std::minstd_rand gen(j);

    for(int i=0; i < 3; i++) {
      cout << gen() << "\n";
    }
  }
}

seed 1
48271
182605794
1291394886

seed 2
96542
365211588
435306125

seed 3
144813
547817382
1726701011

seed 4
193084
730423176
870612250

Setzt man die Zahlen ins Verhältnis zueinander und plottet sie, kommt der AHA Effekt:
PRNGparallelshit

Ach was. Zumindest die zuerst gezogenen Zahlen stehen ja in einem festen Verhältnis. Das Verhältnis der dritten gezogene Zufallszahl ist zwar nicht mehr gleich, aber immer noch bei allen eine kleine Zahl. Na, wenn diese vier Generatoren nicht "parallel" laufen ;)

Der C++ Standard antwortet uns mit std::seed_seq

std::seed_seq consumes a sequence of integer-valued data and produces a requested number of unsigned integer values i, 0 ? i < 232 , based on the consumed data. The produced values are distributed over the entire 32-bit range even if the consumed values are close.
...
The following algorithm is used (adapted from the initialization sequence of the Mersenne Twister generator by Makoto Matsumoto and Takuji Nishimura, incorporating the improvements made by Mutsuo Saito in 2007)

Weiterführende Quellen
Sehr interessant: Finding the Best 64-bit Simulation PRNG
Multiple independent random number streams
Dynamic Creation (DC) of Mersenne Twister generators.
Scalable Parallel Random Number Generators Library
Tina’s Random Number Generator Library

C++ Guns: Passing function objects around (Update Example random generators)

Filed under: Allgemein — Tags: — Thomas @ 19:01

Update zu Passing random generators around (functor) In jenen Beispiel habe ich den RNG per std::function übergeben. Das muss nicht sein. Mit std::function verliert man die inline Performance. Und es geht auch ohne seltsames std::bind.

Aktualisierter Code:

#include <random>
#include <iostream>
#include <functional>
#include <omp.h>

// can be passed by value. it has no state
template<typename Function>
int function2(Function dice) {
  int sum = 0;
  for(int i=0; i < 1000; i++) {
    sum += dice();
  }
  return sum;
}

// pass by reference, it has state
int function(std::minstd_rand& generator) {
  // we need random numbers from 0 to 10
  std::uniform_int_distribution<int> distribution(0,10);
  // lambda instead of bind
  auto dice = [&](){ return distribution(generator); };

  return function2(dice);
}

int main() {
  omp_set_num_threads(2);

  // create  random generatores with random seed
  std::minstd_rand seedGen;
  std::minstd_rand generators[omp_get_num_threads()];
  for(int i=0; i < omp_get_num_threads(); i++) {
    generators[i].seed(seedGen());
  }

#pragma omp parallel for
  for(int i=0; i < 8; i++) {
    const int id = omp_get_thread_num();
    // pass one generator to our function
    int sum = function(generators[id]);

    std::cout << "Thread " << id << " sum " << sum << "\n";
  }

  std::cout << "Info sizeof std::function<int()> " << sizeof(std::function<int()>) << "\n";

  return 0;
}

C++ Guns: Pass function objects per Forwarding references!

Filed under: Allgemein — Tags: — Thomas @ 19:01

I say: Pass (template) function objects per Forwarding references! and not per value. The reason is simple: it works also with function objects with state.

https://en.cppreference.com/w/cpp/language/reference

A little example will show it:

#include <iostream>
#include <random>
using namespace std;

template<typename Function>
auto perValue(Function f) {
  return f();
}

template<typename Function>
auto perForwardReference(Function&& f) {
  return f();
}

int main() {
  std::minstd_rand gen(1156823295);
  
  cout << "Generate 5 random numbers:\n";
  cout << "calls to perValue:\n";
  for(int i=0; i < 5; i++) {
    cout << perValue(gen) << "\n";
  }
  
  cout << "calls to perForwardReference:\n";
  for(int i=0; i < 5; i++) {
    cout << perForwardReference(gen) << "\n";
  }  
}

Generate 5 random numbers:
calls to perValue:
4
4
4
4
4
calls to perForwardReference:
4
193084
730423176
870612250
1216431607

It doesn’t work because the random number generate object has a state. The call to function perValue() change this state on a copy of the generator. And not the one, we pass as argument. But there is no compile time error. Not a single warning. That's the worst case IMO.

The C++ standard and Scott Meyers book "Effective STL" recommend to pass by value. IMO for historical reasons.

C++11 §25.1/10:
[ Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely. Programmers for whom object identity is important should consider using a wrapper class that points to a noncopied implementation object such as reference_wrapper (20.8.3), or some equivalent solution. —end note ]

stackoverflow: why function objects should be pass-by-value

The standard should be updated and the book is horrible outdated. It was written 2008 and forward references come with C++2011. The old solution is to wrap the function into something which can be pass by value, but also change the state. We have now (2011) std::function for that task. And not this ugly thing in the book.

04.01.2019

C++ Guns: Rekursive Template Datentypen

Filed under: Allgemein — Tags: — Thomas @ 17:01

Schonmal probiert den ein und selben template Datentypen mit sich selbst zu nutzen? Mach nichts, ich auch nicht ;)

Als erstes Beispiel ein einfacher, nicht rekursiver Datentyp:

template<typename T>
struct Test {	
	T x;
};

auto func() {
   Test{0};
}

error: class template argument deduction failed:
    Test{0};
error: no matching function for call to 'Test(int)'
note: candidate: 'template<class T> Test(Test<T>)-> Test<T>'

Seit C++17 gibt es Class template argument deduction. Allerdings muss man für User-defined typen auch User-defined deduction guides angeben. Dieser hier ist sehr simpel.

template<typename T>
Test(T) -> Test<T>;

Damit compiliert das oben gezeigte Beispiel (ab GCC7).
Und nun zu dem rekursiven Typen. Ob es geklappt hat, lässt sich mit einem static_assert mit std::is_same zeigen.

template<typename T>
auto func2(T) {	
    static_assert(std::is_same_v<T, Test<Test<int>> >);
}

auto func() {
  func2( Test{Test{0}} ); // Dies ruft den Copy-Konstruktor auf
}

In instantiation of 'auto func2(T) [with T = Test<int>]':
error: static assertion failed

Nein es hat nicht geklappt. Der Grund hierfür ist, dass wir ja eigentlich den Copy-Konstruktor aufgerufen haben.

Mit den deduction guides können wir aber dem Compiler bessere Anweisungen geben.

template<typename T>
Test(Test<T>) -> Test<Test<T>>;

Damit compiliert der Code nun.

Vielen Dank an Freundlich aus dem #c++ Chat für die Fragestellung ;)

03.01.2019

Punktewolke Paarweiser Abstand - Symmetrien entdecken

Filed under: Allgemein — Thomas @ 21:01

Ich habe mir letztens, aus gegebenen Anlass, die wunderbare Weihnachtsvorlesung von Dr. Edmund Weitz angesehen und bin gegen Ende im dritten Teil stecken geblieben.
Die Poincaré-Vermutung (Teil 3 von 3, Weihnachtsvorlesung 2018)
Es wurde die Frage gestellt, Wie sieht das Leben auf einem Torus aus?
Ich mach es kurz: Wenn das Universum ein Torus wäre (in höherer Dimension versteht sich), dann wäre es endlich, ohne Rand. Man könnte in eine Richtung schauen und würde irgendwann sich selbst von Hinten sehen. Und wenn man noch weiter schaut, sieht man sich selbst noch einmal, und noch einmal u.s.w. Natürlich ist die Sicht immer etwas verzerrt.
Damit ergibt auch folgender Satz Sinn: Das Universum ist kleiner als das was wir sehen können. Bzw.: Das beobachtbare Universum ist größer als das eigentliche.

Wie auch immer, zur Veranschaulichung wurde in 2D einige Punkte erstellt, nach rechts/links/oben/unten kopiert und von jedem Punkt zu jedem anderen den Abstand ermittelt und davon ein Histogramm erzeugt. Sieht etwa bei Minute 31:30.
Der Witz ist nun folgender: Gibt es keine sich wiederholende Muster, ist eine Poison Verteilung sichtbar. Gibt es solche Muster, hat die Verteilung Peaks.

Na, das lässt sich doch wunderbar auf ein Digitales Geländemodell (DGM) anwenden!

In der Regel sind die Punkte aus unstrukturierte Laserscans ziemlich dicht verteilt. Es gibt Bereiche an denen sich mehr Messpunkte befinden. Das Flugzeug fliegt die Landschaft ja hin und her ab, und da gibt es Überlappungen. Auch bei der ersten Nachbearbeitung der Daten passieren magische Dinge. Ich habe also keine Ahnung wie das Histogramm aussieht und bin sehr gespannt.

Als Datensatz fand ich von Open Geodata NRW viele DGMs. Die kleinste Datei dgm1l_05974056_Wickede_Ruhr_EPSG25832_XYZ.zip beinhaltete aber immer noch viele GB an Daten. Also nutze ich nur die Kachel 32420_5705 mit 1812468 (1.8M) Punkten.

So sieht die Höhenverteilung aus:
32420_5707_hoehen

Und hier die Punktverteilung. Nur an einigen weißen Stellen sind nicht so viele Punkte vorhanden.
32420_5707_punktwolke

Als nächstes schrieb ich ein Programm welches die Punkte einliest, in einer quadratischen Schleife alle Punkt Abstände berechnet und on-thy-fly ein Histogramm mit den ersten drei Momenten erzeugt. Dabei werden die Abstände zweier Punkte nur einmal berechnet. Also von Punkt A zu B. Aber nicht von B zu A. Der ist ja der selbe. Damit ergeben sich 1642 Milliarden Abstandsberechnungen. Um die alle zu speichern, bräuchte man 12233 GB an Speicherplatz. Den habe ich nicht. Daher habe ich ein Histogramm entwickelt, welches kontinuierlich mit Daten erstellt werden kann.

Auch die Laufzeit ist bei diesen Algorithmus ein Problem. Also berechne ich nur den quadratischen Abstand. Das spart eine Wurzel Berechnung. Und in der Summe ist das schon was. Zusätzlich gibt es noch ein Point2D mit SIMD/SSE Fähigkeiten. Dies spart noch ein paar Operationen pro Abstands Berechnung.

Auf einem 4GHz CPU dauerte die Berechnung drei Stunden. Für einen doppelt so großen Datensatz sind es schon 9 Stunden. Und für nicht unübliche 100M Punkte würde es ca. 12 Monate dauern. Immerhin noch realistisch.

Aber wie sieht nun das Histogramm aus? Nicht vergessen: Das sind quadratische Abstände. In Klammern die Wurzel aus den Werten.

Min: 0
Avg: 3.31e+05 (575.3) 
Max: 2e+06    (1414.2)
Var: 7.71e+10 (277668.9)
Std 2.78e+05  (527.3)

Der minimaler Abstand von 0 deutet auf doppelte Punkte hin. Das ist nicht ungewöhnlich.
Der maximale Abstand ist gerade die Länge der Diagonalen der Boundingbox von jeweils 1km Seitenlänge. Auch richtig.
Der mittlere Abstand ist auch okay. Stelle ich mich gedanklich in die Mitte der BB, habe ich nach allen Seiten mehr als 500m Platz.

hist200_1

Mit Logscale
hist200_2

Keine Peaks zu erkennen. Alles gut. Oder das Histogramm ist nicht fein genug ;)

Update:
Auch bei einem Histogramm mit 5000 Bins zeigen sich keine Peaks.

02.01.2019

Modellbahn: Gleis schottern

Filed under: Allgemein — Tags: , — Thomas @ 19:01

Ich möchte es auch mal probieren. Gleise schottern. Die alten Metall Gleise sind zwar nicht zum Schottern gedacht, aber irgendwie wird es schon.

Alle benötigten Materialien stehen bereit. Auch ein paar Schotterreste haben sich gefunden. Als Mischung habe ich 1:1 Leim und Wasser genommen. Das war aber vielleicht etwas zu dickflüssig. Oder es könnte etwas mehr Spüli rein.
schottertest1

Als erstes werden die Löcher verschlossen, damit der Schotter nicht durch fällt. Auch das Schraubenloch muss zu.
schottertest2

Danach auf der einen Seite den Schotter verteilen. Das ging leichter als gedacht. Auch wenn es etwas zuviel Schotter war.
schottertest3

Aus irgendeinem Grund schlägt mein Leimgemisch Blasen. Aber es geht noch.
schottertest4

Fertig ist die eine Seite. Und das war etwas zuviel Leim.
schottertest5

Auch die andere Seite und die Gleismitte ist fertig. Für die Mitte brauche ich aber unbedingt feineren Schotter. Und womöglich habe ich die Punktkontakte zugekleistert :D
schottertest6

Ich bin gespannt wie es getrocknet aussieht. Und ob das Gleis ohne weitere Befestigung hält.

So. Die Farbe blieb die selbe (diesmal mit Blitz fotografiert). In der Gleismitte brauche ich feineren Schotter. Das Gleis vorher braun anmalen wäre auch eine Möglichkeit. Das etwas steiler abfallende Schotterbett gefällt mir persönlich besser.
schottertest7

Weihnachten 2018: LEGO 40139 60181 & Lebkuchenhaus

Filed under: Allgemein — Thomas @ 18:01

Gretel etwas schüchtern.
Hänsel formt ein Schneeball.
Die böse Hexe wartet schon.
Doch die Gerechtigkeit naht.

LEGOlebkuchenhaus

Bonus 1UP
1UPpilz

« Newer PostsOlder Posts »

Powered by WordPress