Pull to refresh

Играемся с гироскопом ноутбука thinkpad в linux

Reading time 2 min
Views 4K
В линукс показания с этого датчика можно считать из файла /sys/devices/platform/hdaps/position
Можно создать виртуальный джойстик и, например, катать им шарики в neverball, крутить google earth и т.п. :)
Всё это описано тут
Я тоже решил развлечься и написал небольшую программу, которая заставляет cairo-clock сползать по экрану в зависимости от наклона ноутбука.

Для поиска и управления окном я использовал wnck и pygtk. Чтобы сгладить движение я взял физический движок pyode(биндинг к Open Dynamics Engine).

#!/usr/bin/python
# coding: utf-8
import gobject
from os import system
import gtk,wnck
import ode

STALE = (501,487) #значения в hdaps/position в нормальном положении

def hdaps():
    pos = list(eval(open('/sys/devices/platform/hdaps/position').read()))
    pos[0]+=STALE[0]
    pos[1]+=STALE[1]
    if abs(pos[0])<4: pos[0]=0
    if abs(pos[1])<4: pos[1]=0
    if not any(pos): return 0
    return pos

def find_clock(scr,body,world):
    """ пытаемся найти окно cairo-clock, если не находим-запускаем его
    и пытаемся найти снова """
    clk = None
    for w in scr.get_windows():
        if w.get_application().get_name()=='cairo-clock':
            print clk
            clk = w
            break
    if not clk:
        system('cairo-clock &')
        gobject.timeout_add(500,find_clock,scr,body,world)
    else:
        print clk
        clk=gtk.gdk.window_foreign_new(clk.get_xid())
        gscr=clk.get_screen()
        body.setPosition((list(clk.get_root_origin())+[1]))
        # мы нашли окно и запускаем таймер который будет им управлять
        gobject.timeout_add(20,play,clk,body,world,gscr.get_width(),gscr.get_height())

def play(clk,body,world,sw,sh):
    gval = hdaps()
    if gval:
        body.addForce( (gval+[0]))
    world.step(0.04)

    fx,fy,fz = body.getLinearVel()
    body.addForce( (-fx/2,-fy/2,0)) #потихоньку притормаживаем движение

    # при выходе за края экрана-выскакиваем с противоположного края
    bx,by,bz = body.getPosition()
    x,y = clk.get_position()
    w,h = clk.get_size()
    if x<-(w/2): bx=sw-(w/2)
    elif x>sw-(w/2): bx=-(w/2)
    if y<-(h/2): by=sh-(h/2)
    elif y>sh-(h/2): by=-(h/2)
    body.setPosition((bx,by,bz))
    clk.move(int(bx),int(by))
    return True

def main():
    try: 
        scr=wnck.screen_get_default()
        scr.get_windows()
        world = ode.World()
        world.setGravity( (0,0,0) )
        body = ode.Body(world)
        M = ode.Mass()
        M.setSphere(2500.0, 0.05)
        M.setBox(1000,250,250,1)
        M.mass = 0.5
        body.setMass(M)
        gobject.timeout_add(200,find_clock,scr,body,world)
        gtk.main()
    except Exception,e: 
        print(e) 
         
if __name__ == "__main__": 
    main()


Вот как это выглядит:
www.youtube.com/v/l_Ts2BESraI&hl=en — снято фотиком для наглядности
www.youtube.com/v/5oBpODqookY&hl=en_US&rel=0 — видео с экрана

Ещё небольшой скриптик, который поворачивает экран если его сильно наклонить.(тот что есть на сайте ibm — не рабочий)
#!/usr/bin/env python
# coding: utf-8
import os,sys
from time import sleep

ROTATE_ON = 100
STALE_VALUE = 500 # первое значение в hdaps/position в нормальном положении

def rotate(where):
    return os.system('xrandr --output LVDS --rotate %s' % where)

def readx():
    return int(open('/sys/devices/platform/hdaps/position').read().split(',')[0].lstrip('(')) + STALE_VALUE

if __name__ == '__main__':
    while True:
        sleep(0.1)
        x = readx()
        if x<-ROTATE_ON: rotate('right')
        elif x>ROTATE_ON: rotate('left')
        else: rotate('normal')
Tags:
Hubs:
+53
Comments 21
Comments Comments 21

Articles