28 marca 2016

vpython, gify i mechanika klasyczna

Od dawna planuje zabrać się za naukę mechaniki klasycznej. To kolejne podejście, tym razem jednak, zacząłem od poszukiwania narzędzi, które pomogą mi w nauce. Zaczęło się od bardzo fajnego artykułu na temat biblioteki vpython, linki poniżej i inne przydatne:
Za cel eksperymentu postawiłem sobie, wygenerowanie gif-a, z animacją ruchu. Liczyłem, że wystarczy do tego ImageMagic, jednak tworzenie gif-ów jest na tyle zagmatwane, że trzeba było skorzystać również z pakietu FFmpeg. Efekt nie jest do końca satysfakcjonujący. Od pewnego czasu, za bardzo skupiam się nad idealną wersją prototypu. Co więcej staram się znaleźć odpowiedzi na wszystkie pytania jakie się pojawią podczas jego wytwarzania, szczególnie te poboczne. Nie taka był idea tego bloga, czas więc na refleksję.

W każdym razie, oto przerobiony przykład "bouncing ball" z niewielkimi modyfikacjami. Po pierwsze, skorzystałem z biblioteki PIL (Python Image Library), aby tworzyć zrzuty ekranu kolejnych klatek animacji. Biblioteka działa jedynie pod systemem Windows, a jej zamiennik pyscreenshot nie zdał rezultatu. Jakoś się z tym pogodziłem. Druga sprawa, to warunek przerwania animacji, czyli moment gdy piłka znów znajdzie się w tej samej pozycji.
from visual import *
import ImageGrab    # from PIL


starting_height = 4
floor = box (pos=(0, 0, 0), length=4, height=0.5, width=4, color=color.blue)
ball = sphere (pos=(0, starting_height, 0), radius=1, color=color.red)
ball.velocity = vector(0, -1, 0)
dt = 0.01

frame = 0
while 1:
    rate (100)
    ball.pos = ball.pos + ball.velocity*dt
    if ball.y < ball.radius:
        ball.velocity.y = abs(ball.velocity.y)
    else:
        ball.velocity.y = ball.velocity.y - 9.8*dt

    file_name = 'img-' + '{fr:03d}'.format(fr=frame)  + '.png'
    frame += 1

    im = ImageGrab.grab((0, 0, 500, 500))  # screen box from (0,0)-(500,500)
    im.save(file_name)                     # save image to disk

    if ball.pos.y > starting_height:
        exit()
Skrypt wygenerował około 140 zrzutów ekranu, które trzeba było poddać obróbce, nieoceniony okazał się tutaj ImageMagic. Kluczowym problem jest wysterowanie czasu pomiędzy kolejnymi klatkami.
Wszystkie obrazki zawierały ramki Windows-owego okienka, które trzeba było usunąć:
Przycinanie zdjęcia za pomocą mogrify (z ImageMagic). Pozycje i rozmiar dobrałem eksperymentalnie.
mogrify -crop 413x411+9+30 +repage $(ls -v *.png)
Chociaż ImageMagic potrafi generować gif-y, jednak za żadne skarby nie mogłem skonfigurować właściwego opóźnienia, pomiędzy kolejnymi klatkami. Szperając po internecie udało się ten problem ominąć, wymaga to jednak kroków pośrednich, w postaci utworzenia filmiku z animacją, a następnie przepuszczenia go jeszcze raz przez ffmpeg i convert (ImageMagic). Magiczny zestaw komend:
# Filmik ze zdjęć
ffmpeg -r 100 -f image2 -i img-%3d.png video.avi

# Wyciąganie klatek z filmiku i zlepianie w gif-a
ffmpeg -i video.avi -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -loop 0 - gif:- | convert -layers Optimize - output.gif

# Alternatywna wersja, też działa
ffmpeg -i video.avi -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -loop 0 - output2.gif
W animacji jest jakiś uszczerbek jakości, tak jakby brakowało wszystkich potrzebnych klatek. Być może uda mi się kiedyś rozwiązać tą zagadką i odpowiednio dobrać parametry, wtedy też o nich napiszę. Próbowałem także innych rozwiązań, bezskutecznie próbując wysterować opóźnienie pomiędzy kolejnymi klatkami.
# Gif generowany tylko przez convert (ImageMagic)
convert -dispose none -delay 1.5 $(ls -v *.png) -coalesce output3.gif

# Gif generowany tylko przez ffmpeg
ffmpeg -f image2 -framerate 100 -i img-%3d.png output4.gif

16 marca 2016

Klient OpenVPN - pierwsze kroki

Postawienie dobrze zabezpieczonego połączenia VPN, jest jak się okazuje czynnością dość pracochłonną. Szczególnie warty uwagi jest pierwszy link, który opowiada o dobrym zabezpieczeniu całej usługi:
Moje pierwsze kroki, sprowadziły się do rozwiązania kilku problemów, związanych z systemem operacyjnym (Ubuntu) jak i usługodawcą VPN. Pierwsza próba odpalenia zakończyła się błędem:
Wed Mar 16 10:10:10 2016 ERROR: Cannot ioctl TUNSETIFF tap: Operation not permitted (errno=1)
Wed Mar 16 10:10:10 2016 Exiting due to fatal error
A więc klient, musi w jakiś sposób uzyskać prawa super użytkownika, aby działać na urządzeniu tun/tab, na co jest kilka rozwiązań:
Najprościej jest oczywiście, gdy posiadamy prawa root-a. Możemy wtedy wykonać komendę (gdzie w pliku secret.txt, w kolejnych linijkach zapisany jest login i hasło):
openvpn --config vpn_provider/conf.ovpn --ca vpn_provider/ca.crt \
        --auth-nocache --auth-user-pass secret.txt
Kolejny problem, z którym się spotkałem to niedziałające DNS-y. Czasami usługodawca VPN nie oferuje takiej usługi ze swojej strony, a ISP nie zgadza się na łączenie ze swoimi serwerami DNS, dla osób spoza sieci. DNS-owe zapytania, można przerzucić na router (192.168.1.1), co może nie być najlepszym pomysłem ze względów bezpieczeństwa, można też skorzystać z publicznych serwerów DNS (np. google). Nie wiem jak dokładnie wybierane są serwery DNS-owe z pliku /etc/resolve.conf, przez aplikacje, ale to co zaobserwowałem (przynajmniej w stosunku do komendy ping), warto wpisy o nowych serwerach podać jako pierwsze.
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
namseerver 8.8.4.4