Neuigkeiten aus der sogenannten Linux-Community

Wie http://www.pro-linux.de/news/1/24968/statusreport-des-debian-reproducible-builds-projekts.html berichtet gibt es Neuigkeiten aus dem Debian Projekt. Man sollte vielleicht erstmal erläutern, was Pro-linux.de überhaupt ist. Laut Selbstbeschreibung möchte man Linux fördern und berichtet regelmäßig zu Themen OpenSource und Linux. Tatsächlich gibt es jedoch nervige Pop-up Werbung zur „Microsoft Cloud“ und die Berichterstattung ist einseitig pro Debian und Anti Red Hat ausgelegt. Wer hinter dem Portal steckt ist nicht ganz offensichtlich, aber wenn Microsoft dort Werbung schaltet liegt der Verdacht nahe, dass Microsoft das Portal auch finanziert. Insofern sollte man skeptisch sein, ob die Informationen wirklich „pro linux“ sind.

Aber gehen wir mal auf den oben verlinkten Debian Status-Bericht etwas näher ein. Demzufolge geht es um reproduzierbare Debian Pakete. Genauer gesagt um die Buildinfo-Datei, welche sich in einem .deb Archiv befindet. Soweit ist das erstmal korrekt. Debian arbeitet tatsächlich an soetwas. Nur, was der Bericht auf Pro-Linux leider nicht erläutert ist, dass Debian mit seinem .deb Format ziemlich alleine dasteht, und es von keiner anderen Distribution genutzt wird. Und ganz besonders nicht von RHEL oder Fedora. Das heißt, auch das aktuelle Projekt zu verifizierbaren Builds wird Linux schwächen, die Gemeinschaft fragmentieren und ist ein aktiver Beitrag dafür, dass sich Linux niemals wird auf dem Desktop wird durchsetzen können. Mit dem Redhat Upstream sind die Arbeiten jedenfalls nicht abgestimmt. Und aller Voraussicht nach, wird auch nichts davon zu Redhat zurückfließen. Das heißt, außer den Debian Usern wird keiner davon profitieren.

Neue Version des Robot-Control-Systems

Wieder einmal ist es Zeit für eine Programmversion. Gegenüber dem letzten Mal hat sich viel verändert. Zum einen wird jetzt git als Version-Control-System eingesetzt, daher auch der obige Screenshot. Der Grund ist, dass sich damit der Sourcecode leichter memorieren lässt. Zum ersten Mal ist es möglich, den kompletten Sourcecode auswendig zu lernen. Git ist vergleichbar mit einem Vokabeltrainer.

Inhaltlich wurde auf die Box2D Physik-Engine verzichtet. Stattdessen wird eine Makrosimulation genutzt, wo also nur angedeutet wird, wie sich das Auto auf der Straße bewegt. Dadurch braucht man weniger Lines of Code und das Programm ist leichter für außenstehende verständlich. Trotzdem bleibt der Aufwand um die Behavior Trees zu erstellen unverändert hoch. Und hier ist nach wie vor der Flaschenhals. Aktuell hat das Programm nur 3-4 Tasks die implementiert wurden (followpoint, followwaygraph usw.). Die Leistungsfähigkeit der Künstlichen Intelligenz hängt davon ab, wieviele Actions / Behavior man implementiert. Leider ist jedoch das manuelle Coden dieser Behavior sehr zeitaufwendig.

# coding: utf8
'''
to do: rechteckiges auto
titel: selfdriving car
date: June 26, 2017

Anleitung: https://wiki.ubuntuusers.de/Git/
neues Projekt erzeugen: git init
Datei hinzufügen: git add 1.py
Änderung hinzufügen: git commit -am "AENDERUNGSBESCHREIBUNG"
Show: 
  git log
  git status
GUI: gitk --all

Branches:
  neuen Branch: git branch issue12
  Branch wechseln: git checkout issue12
  merge: git checkout master
         git merge --no-ff ssue12
  Branch löschen: git branch -d issue12

'''
import pygame, random, math, threading, sys

class Settings(object):
  def __init__(self):
    self.screen = (600, 338)
    self.fps = 20  # 30 fps
    self.white = (220, 220, 220)
    self.black = (0, 0, 0)
    self.grey = (150, 150, 150)
    self.red = (230, 0, 0)
    self.blue = (0, 0, 230)
  def calcdistance(self, p1, p2):
    """ Euclidean ordinary distance """
    return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
  def angle_between_two_points(self, p1, p2):
    angle = math.degrees(math.atan2(p2[1] - p1[1], p2[0] - p1[0]))
    angle += 90
    if angle < 0: angle += 360
    return angle
  def floattoint(self, p):
    return (int(p[0]), int(p[1]))
  def polarpoint(self, p1, angle, radius):
    """ polar coordinates for a point on circle """
    angle = (angle - 90) * math.pi / 180
    x = p1[0] + radius * math.cos(angle)
    y = p1[1] + radius * math.sin(angle) 
    x,y=self.floattoint((x,y))
    return (x, y)
  def incircle(self,p1,radius,p2):
    """ checks if p2 is in circle """
    square_dist = (p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2
    return square_dist <= radius ** 2    

class Physics(Settings):
  def __init__(self):
    super(Physics, self).__init__()
    self.pos = (40,150)
    self.radius=20

class Dictionary(Physics):
  def __init__(self):
    super(Dictionary, self).__init__()
    self.primitive =[] # group, name, taskname 
    self.primitive.append(("move","path","taskfollowpath()")) 
    self.primitive.append(("move","waypoint","taskfollowwaypoints()")) 
    self.primitive.append(("move","mouse","taskmove()")) 
    self.primitive.append(("radius","smaller","task2()")) 
    self.primitive.append(("pos","right","taskright()")) 
    self.primitive.append(("pos","left","taskleft()")) 
    self.primitive.append(("-","-","misc()")) 
    self.primitive.append(("-","-","misc()")) 
    self.linestart=0
    self.linemax=5
  def taskmenu(self):
    self.status="Running"
    temp = self.menuselect1
    taskname="self."+ self.primitive[temp][2]
    eval(taskname)
    self.status="Ready"
  def pause(self,frames):
    for i in range(frames):
      self.updateGUI()
  def movetoangle(self,angle):
    radius=3
    self.pos=self.polarpoint(self.pos, angle, radius)
  def movetopos(self,goal):
    for i in range(1000):
      dist=self.calcdistance(goal,self.pos)
      angle=self.angle_between_two_points(self.pos,goal)
      print angle
      self.movetoangle(angle)
      self.pause(1)
      if dist<10: break
  def taskmove(self):
    self.movetopos(self.mouse)
  def task2(self):
    for i in range(10):
      self.radius-=1
      self.pause(1)
  def taskright(self):
    p=(self.pos[0]+50,self.pos[1])
    self.movetopos(p)
  def taskleft(self):
    p=(self.pos[0]-50,self.pos[1])
    self.movetopos(p)

class Waypoints(Dictionary):
  def __init__(self):
    super(Waypoints, self).__init__()
    # graph
    self.node=[] # x,y
    self.node.append((54,290))
    self.node.append((300,290))
    self.node.append((530,180))
    self.node.append((150,150))
    self.path=[] # waypoint
    self.path.append(0)
    self.path.append(2)
    self.path.append(0)
    self.path.append(1)
  def taskfollowwaypoints(self):
    for i in range(len(self.node)):
      self.movetopos(self.node[i])
  def taskfollowpath(self):
    for i in range(len(self.path)):
      self.movetopos(self.node[self.path[i]])


class GUI(Waypoints):
  def __init__(self):
    super(GUI, self).__init__()
    random.seed()
    pygame.init()
    self.window = pygame.display.set_mode(self.screen)
    self.mouse = (0, 0)
    self.menuselect1 = 0   
    self.control = 1 # mode 
    self.status="Ready"    
  def updateGUI(self):
    pygame.time.wait(1000/self.fps)
    self.window.fill(self.white)
    self.painttext()
    self.paintmenu()
    self.paintobjects()
    pygame.display.update()   
    self.inputhandling()
  def painttext(self):
    # mouse
    myfont = pygame.font.SysFont("freesans", 16)
    text = str(self.control)+" " + str(self.mouse)+" "+str(self.step)
    label = myfont.render(text, True, self.black)
    self.window.blit(label, (220,30))
  def paintmenu(self):
    myfont = pygame.font.SysFont("freesans", 16)
    count=0
    xstart, ystart=400,15
    height=18
    for i in range(self.linestart,self.linestart+self.linemax):
      # select
      color=self.black
      if self.menuselect1==i:
        color=self.blue
        if self.status=="Running": color=self.red # running color
        label = myfont.render(">", True, color)
        self.window.blit(label, (xstart-10,ystart+count*height)) 
      # scrolling
      self.linestart=self.menuselect1-(self.linemax/2)
      if self.linestart<0: self.linestart=0
      elif self.linestart>len(self.primitive)-self.linemax:
        self.linestart=len(self.primitive)-self.linemax
      # textout
      if self.primitive[i][0]==self.primitive[i-1][0]: text = str(i)
      else: text = str(i)+" "+self.primitive[i][0]
      label = myfont.render(text, True, color)
      self.window.blit(label, (xstart,ystart+count*height))
      label = myfont.render(self.primitive[i][1], True, color)
      self.window.blit(label, (xstart+90,ystart+count*height))
      count+=1      
  def paintobjects(self):
    # robot
    pygame.draw.circle(self.window, self.blue, self.pos, self.radius, 0)    
    # waypoint
    myfont = pygame.font.SysFont("freesans", 14)
    for i in range(len(self.node)):
      pygame.draw.circle(self.window, self.black, self.node[i], 3, 0)           
      label = myfont.render(str(i), True, self.black)
      self.window.blit(label, self.node[i])
    # path
    for i in range(len(self.path)-1):
      p1 = self.node[self.path[i]]
      p2 = self.node[self.path[i+1]]
      pygame.draw.line(self.window, self.blue, p1, p2, 1)
  def inputhandling(self):
    for event in pygame.event.get(): 
      if event.type == pygame.QUIT: sys.exit(0) 
      if event.type == pygame.MOUSEMOTION: 
        self.mouse = event.pos
      if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_1: pass
        if event.key == pygame.K_2: pass
        if event.key == pygame.K_UP: 
          temp=self.menuselect1-1
          if temp==-1: temp=len(self.primitive)-1
          self.menuselect1=temp
        if event.key == pygame.K_DOWN:
          temp=self.menuselect1+1
          if temp==len(self.primitive): temp=0
          self.menuselect1=temp
        if event.key == pygame.K_RIGHT: self.taskmenu()       

class Game: 
  def __init__(self):
    self.myGUI = GUI()    
    for self.myGUI.step in range(10000000):
      self.myGUI.updateGUI()
 
if __name__ == "__main__":
  myGame = Game()

Wann ist ein Text fertig?

[1] In der obigen Abbildung ist die Rohversion eines Papers zu sehen, an dem ich gerade schreibe. Bisher besteht es aus 25 Seiten, allerdings ist unklar wann der richtige Zeitpunkt ist, es tatsächlich abzugeben bzw. ins Netz zu stellen. Klar, ich könnte nach der Methode verfahren „publish or perish“ und möglichst sofort auf den Upload Knopf drücken. Leider hat die Vergangenheit gezeigt, dass nachdem das Paper erstmal online war, noch weitere Kapitel hinzugekommen sind, die sich dann nicht mehr einfügen lassen. Eine bessere Strategie besteht darin, den Umfang des Papers zu beobachten. Man muss jeden Tag notieren, wieviele Wörter das Paper hat, und wenn der Zuwachs nur noch minimal ausfällt oder gar zum Stillstand kommt ist es Zeit für den Upload.

* 19. Juli 2017, 26145 Wörter
* 20. Juli 2017, 27154 Wörter
* 21. Juli 2017, 28036 Wörter
* 22. Juli 2017, 28200 Wörter
* 23. Juli 2017, 28198 Wörter

Das hört sich jetzt ein wenig merkwürdig an, aber Paper haben die Angewohnheit ein Eigenleben zu führen. Damit ist gemeint, selbst wenn man sich vornimmt es auf einem Stand x einzufrieren wird daraus meist nichts. Plötzlich hat man doch noch eine Idee und muss diese noch unbedingt hineinbringen. Besser ist es, wenn man den Fortgang der Textproduktion möglichst neutral beobachtet und die Abgabe an einem gleichbleibenden Word-Count festmacht. Motto: wenn der Umfang längere Zeit konstant bleibt ist es wahrscheinlich, dass es auch in Zukunft so bleiben wird.

Zumindest eine Entscheidung ist ausgesprochen simpel: ob man das Paper nochmal Korrektur lesen sollte oder ob man Absätze wieder streichen sollte. Die Antwort ist nein. Rechtschreibkontrolle bringt nichts und Absätze löschen geht gar nicht. Die Idee ist es vielmehr ein unfertiges und umständliches Paper online zu stellen. Um es dann in einem größeren Abstand von 1 Jahr nochmal komplett neu schreiben zu können. Das heißt, das was in dem Paper drinsteht ist ohnehin nicht der Weisheit letzter Schuss, selbst wenn man da noch 2-3 Rechtschreibfehler ausmerzt. Und das sich daran die Leser stören, ist auch nicht zu erwarten, weil die Leser ohnehin das Gesamtwerk beurteilen, also wieviel Mühe man sich gegegeben hat.

Git Probleme mit Branches

Vom Ansatz her ist git eine super-Sache. Man führt regelmäßig commit Befehle aus und git läuft so im Hintergrund nebenher. Der Vorteil besteht darin, dass man sich den Sourcecode leichter memorieren kann, aber auch dass man eine Statistik erhält, wann man am Code gearbeitet hat. Unklar ist mir aktuell noch wie das mit dem Branching geht. Die Anleitungen dazu sind vielfältig, und wenn ich das Prinzip richtig verstanden habe soll man einen Release Branche erstellen, in dem man den kompletten Code rüberkopiert. Aber was dann? Einmal kann man den Branch löschen, dann ist er aber weg, was ja dem Ansatz widerspricht, oder man mergt ihn, aber das macht auch keinen Sinn, weil ja der Release Code ein anderer sein soll, also beides getrennt wird. Vermutlich ist die Antwort darauf simpel, nur mir erschließt sich das Prinzip aktuell nicht. Komplett auf git zu verzichten kommt nicht in Frage, also bleibe ich vorerst bei dem bewährten Scheme genau einen Master Branch zu nutzen und sonst gar nichts. Das hält die Anzahl der möglichen Aktionen übersichtlich. Im Grunde gibt es dann nur den einen Commit-Befehl den man lediglich mit unterschiedlichen Kommentaren versieht. Und wenn man eine Kopie des kompletten Repositories braucht, nutzt man einfach „cp -R source/ destination/“ und kopiert den Arbeitsordner inkl. „.git“ Verzeichnis. Das ist zwar nicht das was, wie man es eigentlich machen sollte, aber was solls. Git ist ohnehin zu komplex, da heißt es sich auf grundlegende Dinge zu konzentrieren. Und das dürfte primär der Sourcecode des eigenen Projektes sein.

Ich will nicht behaupten, dass Branches generell eine schlechte Idee sind. Weil das allen Anleitungen wiedersprechen würde. Sondern ich will nur sagen, dass sie für mich und auf meinem Wissensstand ein Overkill darstellen würden.

https://stackoverflow.com/questions/24019609/is-it-okay-to-use-git-without-branches

Neuer Vorlesungspodcast vom KIT online

Unter der Adresse https://www.youtube.com/watch?v=ryqsTcbO9nc hat das Karlsruher Institut für Technologie (KIT) eine Reihe an Vorlesungsmitschnitten online gestellt, die sich mit Künstlicher Intelligenz beschäftigen. Genauer gesagt geht es um Sprach- und Bilderkennung. Die ersten Episoden, welche von Alexander Waibel vorgetragen werden, beginnen noch mit relativ einfachen Methoden wie neuronale Netze und stochastischer Mustererkennung, spätestens ab Episode 12 wird es jedoch spannend weil dann rule-based Systems, PDDL und Strips vorgestellt werden. Insgesamt gebe ich dem Podast die bestmögliche Note sehr gut, weil das Niveau der Vorlesung hoch genug ist und vor allem als Unterrichtssprache Deutsch gewählt wurde. Der Podcast ist konkurrenzfähig zu den Online-Lectures von Harvard und Stanford.

Das interessante an dem KIT Podcast ist, dass es kein Vorlesungsmitschnitt ist. Das heißt, die Veranstaltungsreihe wurde nicht an einer traditionellen Universität im Hörsaal aufgenommen sondern wurde als dezidierter Online-Content am KIT produziert. Es gibt noch weiteren hochqualitativen Content der wiederum in Konkurrenz steht zum etablierten Hochschulsystem. Für die Hörer ist das ein Gewinn, weil sie darüber Einblick erhalten in die Themen, welche an den Universitäten nicht unterrichtet werden.

Ubuntu hat es plötzlich eilig, Sicherheitslücken zu stopfen

Wie Heise.de berichtet ist Ubuntu diesmal besonders schnell gewesen eine Sicherheitslücke im Evince Dokokumentenanzeiger zu patchen, https://www.heise.de/security/meldung/Peng-Comic-HACKT-Linux-3771980.html Zwar wurde auch Red Hat schon über die Lücke informiert, aber der Patch wurde bisher noch nicht freigegeben. Auf den ersten Blick spricht das für die Distributution von Marc Shuttleworth. Doch nicht so schnell, wer Ubuntu kennt wird wissen, dass allein das WordPress Package seit mehr als 1 Jahr ungepatcht geblieben ist und die Anzahl an CVE-Exploits die in Ubuntu ungefixt sind deutlich oberhalb von 20 liegt. Warum also jetzt auf einmal die Eile, wenn nochnichtmal Red Hat ihren zahlenden Kunden ein Patch bereitstellt? Fakt ist jedenfalls, dass der Patch bei Debian/Ubuntu von Leuten freigegeben wird, die ehrenamtlich tätig sind, weil man Ubuntu ja nicht kaufen kann, sondern es sich um ein freiwilligen Projekt handelt. Das sollte man wissen, um die Qualität des Security-Patches einschätzen zu können. Anders gesagt, ich bin froh kein Ubuntu mehr einzusetzen, ich traue Canonical nicht.

CentOS: Videoschnitt läuft

Nach einigem Herumprobieren gibt es wiedereinmal eine Erfolgsmeldung. Inzwischen läuft auch Kdenlive unter CentOS. Man muss um die Buttons anzeigen zu lassen, das Paket breeze-icon-theme manuell nachinstallieren. Den Tipp habe ich aus einem Ubuntu Forum wo es offenbar ähnliche Probleme gab. In der obigen Abbildung sind mal all jene Programme aufgeführt die auf dem Desktop zur Verfügung stehen: LMMS, Kdenlive, Geany, git, Lyx, Google Chrome, Mehr braucht es nicht für eine High-End Workstation. Ob Steam und Skype ebenfalls laufen weiß ich nicht, ausprobiert habe ich es nicht, wäre aber denkbar dass es mit manuellen Anpassungen geht. Lange Rede kurzer Sinn: CentOS ist perfekt als Desktop-Umgebung geieignet. Das einzige was fehlt, ist die Dokumentation, also ein Forum, ein Wiki usw. nach dem Vorbild debianforum.de Sowas hat CentOS tatsächlich nicht anzubieten, und selbst mit dem Premium Red Hat Tarif gibt es sowas aktuell nicht. Die Community welche CentOS als Anwender nutzt ist offenbar sehr klein. Zu Fedora habe ich zumindest ein Forum gefunden https://www.fedoraforum.de/

Jetzt mag man sich vielleicht fragen warum es unbedingt Centos sein muss, wenn die Debian/Ubuntu Community doch soviel mehr User hat, die noch dazu besser vernetzt sind. Nun ich glaube, die Anwender haben auf das falsche Pferd gesetzt, Debian ist am Sinken, die Community mag stable & healthy erscheinen doch unter der Oberfläche sind Risse zu erkennen. Wenn man Debian nur einmal von der Seite anpustet, dann sind die Developer dort so verschreckt, dass sie den Linux Kernel aus ihrem Projekt entfernen und stattdessen auf den bewährten GNU Hurd Kernel setzen, der um so viel besser getestet ist und von der Philosophie weitaus besser mit dem GNU Projekt harmoniert. Anders gesagt, Linux ist im Debian Projekt keineswegs abgemacht, sondern steht unter Vorbehalt. Eigentlich würde man lieber auf einen Kernel setzen, der aus den 1980’er stammt, eine klare Distanz zu Red Hat aufweist und wo der Maintainer (gemeint ist Linus Torvalds) sehr viel verträglicher ist.