• Non ci sono risultati.

Script di Matlab per la calibrazione del sensore

CAPITOLO 3: SVILUPPO E APPLICAZIONE DEL NUOVO “FAN-LIKE”

E. Script di Matlab per la calibrazione del sensore

F1. Sani convergenti F2. Sani divergenti F3. Post-ictus convergenti F4. Post-ictus divergenti F5. Cerebellari convergenti F6. Cerebellari divergenti

G. Script di Matlab per la valutazione dell’FDE G1. Sani convergenti G2. Sani divergenti G3. Post-ictus convergenti G4. Post-ictus divergenti G5. Cerebellari convergenti G6. Cerebellari divergenti

A. Scala di Ashworth Modificata

0 Nessuna spasticità

1 Moderata spasticità alla fine del movimento

1+ Moderata e continua spasticità durante meno della metà del movimento 2 Moderata spasticità durante tutto il movimento

3 Spasticità importante con limitazione severa del movimento 4 Spasticità irriducibile

114 B. Scala Fugl-Meyer per l’arto superiore

B1. Motricità

I Attività riflessa Flessori 0 1 2

Estensori 0 1 2

II

Movimenti nelle sinergie patologiche

Flessoria Scapola Retrazione 0 1 2 Elevazione 0 1 2 Spalla Abduzione 0 1 2 Rotazione esterna 0 1 2 Gomito Flessione 0 1 2 Avambraccio Supinazione 0 1 2 Estensoria Spalla Rotazione

interna

0 1 2

Adduzione 0 1 2 Gomito Estensione 0 1 2 Avambraccio Pronazione 0 1 2

III Iniziale indipendenza dalle sinergie patologiche

Mano alla regione sacrale 0 1 2

Flessione spalla 90° 0 1 2

Pronosupinazione a gomito flesso 90° 0 1 2

IV Relativa indipendenza dalle sinergie patologiche

Abduzione spalla a 90° 0 1 2 Flessione spalla a 180° 0 1 2 Pronosupinazione a gomito esteso 0 1 2

V Attività riflessa normale 0 1 2

Coordinazione-velocità Tremore 0 1 2 Velocità 0 1 2 Dismetria 0 1 2 Polso Stabilizzazione gomito a 90° 0 1 2 Stabilizzazione gomito esteso 0 1 2 Flesso-estensione gomito a 90° 0 1 2 Flesso-estensione gomito esteso 0 1 2

Circonduzione 0 1 2 Mano Flessione globale 0 1 2 Estensione globale 0 1 2 Presa a gancio 0 1 2 Presa laterale 0 1 2 Presa palmare 0 1 2 Presa cilindrica 0 1 2 Presa sferica 0 1 2 Totale /66

115 B2. Sensibilità Tattile Braccio 0 1 2 Palmo 0 1 2 Propriocettiva Spalla 0 1 2 Gomito 0 1 2 Polso 0 1 2 Pollice 0 1 2 Totale /12 B3. ROM-Dolore Spalla Flessione 0 1 2 0 1 2 Abduzione 0 1 2 0 1 2 Rotazione interna 0 1 2 0 1 2 Rotazione esterna 0 1 2 0 1 2 Gomito Flessione 0 1 2 0 1 2 Estensione 0 1 2 0 1 2 Supinazione 0 1 2 0 1 2 Pronazione 0 1 2 0 1 2

Polso e dita Flessione del polso 0 1 2 0 1 2

Estensione del polso 0 1 2 0 1 2

Flessione delle dita 0 1 2 0 1 2

Estensione delle dita 0 1 2 0 1 2

116 C. Mini Mental State Examination

AREE INDAGATE PUNTEGGIO

CONSEGUITO

PUNTEGGIO MASSIMO orientamento

data,giorno mese stagione anno 5

nazione, regione, città, luogo, reparto 5

memoria recente

nomi di tre soggetti 3

attenzione e calcolo

numerazione al contrario (100, 93,86) oppure sillabare al contrario (mondo=odnom)

5

richiamo alla memoria

ricordare i nomi di tre soggetti prima menzionati 3

linguaggio

identificazione della matita e dell’orologio 2

ripetere “sopra la panca la capra campa” 1

ordine: “prenda il foglio, lo pieghi a metà e lo metta sul pavimento”

3

esecuzione comando scritto “chiuda gli occhi” 1

scrittura di una frase di senso compiuto 1

copia del disegno (pentagoni intersecati) 1

117 D. Script del nuovo “fan-like”

#! /usr/bin/wish

# Copyright 2000-2004 Interactive Motion Technologies, Inc # trb 9/2000

# original comments:

# user moves cursor to touch blinking ball, # then blinking ball changes.

# alternating between center ball and edge balls.

# to make the game challenging, you may enter a threshold time # in milliseconds, and if you keep a floating average (over the last # 10 hits) below that number, the face stays green, or else it changes # to red.

# the number of spots on the perimeter may be specified (default 8). # the travel of the ball may be set to different increments, or

# to random.

# new comments, rtlinux port, 1/2004 # japanese i18n 3/2004

# more cleanup 7/2004

# This clock game is the basis of a battery of therapy and

# evaluation games. These games are all variations on the clock game, # with different settings specified in the games/ directory.

# this file contains a bunch of procs, and one call to main. # Tk GUI library

package require Tk package require counter global ob

if {[info exists env(CROB_HOME)]} { set ob(crobhome) $env(CROB_HOME) } else {

set ob(crobhome) /home/imt/crob }

#source $ob(crobhome)/shm.tcl

source $env(IMT_HOME)/crob/shm.tcl

# print a string, with a difference in ms since the last dtime set ob(dtimetime) [clock clicks -m]

118 global ob

set time [clock clicks -m]

set dtime [expr {$time - $ob(dtimetime)}] puts "dtime: $dtime - $str"

set ob(dtimetime) $time }

# print a stack trace

proc call_trace {{file stdout}} { puts $file "Tcl Call Trace"

for {set x [expr {[info level] -1}]} {$x > 0} {incr x -1} { puts $file "$x: [info level $x]"

} }

# print info on all current pending after events

proc after_info {} {foreach i [after info] {puts "$i [after info $i]"}} # counter aliases

interp alias {} ctadd {} ::counter::count interp alias {} ctget {} ::counter::get interp alias {} ctinit {} ::counter::init interp alias {} ctreset {} ::counter::reset # main

# this proc is called once (at the bottom of this file) # when the program is first run.

proc main {} { global ob argc argv

# game name and patient name

# they come in as command line args, usually from the # cons "game console" program

# in a HIPAA setting, the patient name will be a numeric ID. set ob(gamename) games/eval/test_log_frc

set ob(patname) dfltpat if {$argc >= 1} {

set ob(gamename) [lindex $argv 0] }

if {$argc >= 2} {

set ob(patname) [lindex $argv 1] }

# put the game and patient name in the title bar wm title . "$ob(gamename) $ob(patname)" # read in game support procs

119 source ../common/menu.tcl

source /home/ospedale/imt/i18n/i18n.tcl # is this planar or wrist?

localize_robot

set ob(programname) clock-$ob(gamename) font create default -family Times -size -18

# if you want to run with no arm and mouse cursor, # uncomment this following line:

# no_arm

# this initializes a bunch of variables, called once. onceg1

# this starts the game, may be called many times. # it is also bound to the n (new game) key. restartg1

}

# for init files

# the s command means "set." for instance, there is a variable called # "log" to turn on logging. if the game init file has the line:

# s log yes # then this proc will: # set ob(log) yes proc s {name val} { global ob

set ob($name) $val }

# turn beeping on and off, in response to a typed "b" proc toggle_nbeep {} {

global ob

if {$ob(dobeep)} { # was yes.

rename nbeep real_nbeep proc nbeep {args} {} set ob(dobeep) no } else {

# was no

rename nbeep {}

rename real_nbeep nbeep set ob(dobeep) yes }

120 # read the init file for the game specified.

# these flies consist of s (set) commands, and source commands, which # read other init files. this allows the differences between similar # games to be described in a simple way.

proc read_game_init {gamefilename} { set odir [pwd]

# normalize isn't available until tcl 8.4. not that important.

# set dir [file normalize [file join [pwd] [file dirname [info script] ... ]]] set dir [file join [pwd] [file dirname [info script]]\

[file dirname $gamefilename] ] set tail [file tail $gamefilename] if {[file isdirectory $dir]} {

cd $dir

# puts "cd $dir" } else {

error "read_game_init: can't source $dir $tail" }

if {[file exists $tail]} { source $tail

# puts "source $gamefilename" } else {

error "read_game_init: can't source $dir $tail" }

cd $odir }

# after the game init variables are set in the GUI program, some of # the values need to be sent to the control loop in the Linux Kernel # Module (using wshm - write shared memory), and some other values # need to be calculated. proc apply_init_vars {} { global ob wshm offset_x $ob(centerx) wshm offset_y $ob(centery) #wshm safety_pos 1.0 wshm safety_pos 0.5 if {$ob(wrist)} { wshm wrist_diff_damp $ob(wrist_diff_damp) wshm wrist_ps_damp $ob(wrist_ps_damp) wshm wrist_diff_stiff $ob(wrist_diff_stiff) wshm wrist_ps_stiff $ob(wrist_ps_stiff) } wshm curl $ob(curl) wshm restart_stiff $ob(stiff) wshm restart_damp $ob(damp)

121 wshm restart_Hz $ob(Hz)

wshm restart_go 1

wshm logfnid $ob(logfnid) # wait before trip to edge (ms) # k here means thousands

set ob(kpre_wait) [expr {int($ob(pre_wait) * 1000)}] set ob(kvlim_wait) [expr {int($ob(vlim_wait) * 1000)}] # per slot implies log

if {$ob(logperslot)} {set ob(log) "yes"} }

# initialize the compass directions, happens when game is re/started # needs to be tweaked for random, to redo each circuit.

proc dodirlist {} { global ob

# the center is initally tagged as nextball, # this tag moves when a ball is touched. set ndirs [llength $ob(dirs)]

set nsets [expr {$ob(nslots) / $ndirs}] set nslots2 [expr {$ob(nslots) / 2 - 1}]

set idirlist {}

for {set i 0} {$i < $nsets} {incr i} { lappend idirlist $ob(dirs) }

set idirlist [join $idirlist]

# randomize the list in two halves if {$ob(random)} {

set id1 [lrange $idirlist 0 $nslots2] incr nslots2

set id2 [lrange $idirlist $nslots2 end] set idirlist {}

lappend idirlist [shuffle $id1] [shuffle $id2] set idirlist [join $idirlist]

} set ob(dirlist) {} foreach j $idirlist { lappend ob(dirlist) C $j } } # do once at init.

122 proc onceg1 {} {

global ob mob

# blink rate for target ball set ob(blinkrate) 0.5

# set defaults, many of these will be overridden by the game_inits set ob(cur,x) 0.1 set ob(cur,y) 0.1 set ob(curcan,x) 0.1 set ob(curcan,y) 0.1 # control variables set ob(centerx) 0.0 set ob(centery) -0.72 set ob(damp) 5.0 # set ob(stiff) 200.0 set ob(Hz) 200 set ob(curl) 0.0

# which controller ID to use in movebox # planar set ob(controller) 0 if {$ob(wrist)} { set ob(controller) 7 } set ob(edge) 0 set ob(edgedir) t set ob(slotpairnum) 1 # default game type set ob(gametype) eval

# how close to the centers do balls need to be for a hit? in meters. # the on-screen balls are .025 cm in world space, so this is a bit # less than half-overlapped.

set ob(hitradius) 0.010 set ob(ball_size) .0125 if {$ob(wrist)} {

set ob(ball_size) [expr {$ob(ball_size) / $ob(wrist_scale)}] set ob(hitradius) [expr {$ob(hitradius) / $ob(wrist_scale)}] }

123 set ob(cur_ball_size) [expr {$ob(ball_size) / 2.}]

# is this a "static" game? (user holds handle in center) set ob(static) no

# is this a "static" game? (program holds handle in center) set ob(dynamic) no

# if noballhit is yes, then no events on ball hit set ob(noballhit) no

# do processing for adaptive games set ob(adaptive) no

# hide the score display set ob(hidescore) no

# see note above enter_target_do_adaptive set ob(just_ran_pm_display) no

# game description variables # are we logging?

set ob(log) no

# how many vars to log during each sample # time x y vx vy

# fx fy fz grasp set ob(logvars) 9

# base directory for log files

set ob(logdirbase) /home/ospedale/imt/experiment/ventaglio2/ventaglio_dx # default log function

set ob(logfnid) 0

# shall we log each slot in its own file? set ob(logperslot) no

# are we applying motor forces? set ob(motorforces) no

# how many target balls on the clock edge? # (not the center or the cursor)

set ob(nballs) 8

# how many slot paths before we finish? set ob(nslots) 16

# should the targets be chosen randomly (or sequentially) set ob(random) no

# show cursor?

set ob(showcursor) yes

# distance in meters from center ball to edge ball (center to center) set ob(slotlength) 0.21

# how long the movement should take, in seconds and ticks set ob(slottime) 1.4

# slotticks in samples, fed to movebox

set ob(slotticks) [expr {int($ob(slottime) * $ob(Hz))}] # how long to wait in seconds before "timing out" on a slot # time out sets to white-ball "paused" mode

124 set ob(slottimeout) 0.0

# should we pause when a slot times out? set ob(timeoutpause) no

# for circle eval games set ob(smallercircle) no # for shouler eval games set ob(shoulderarrow) no set ob(shoulderarrowdir) up

# center the arm with motor force, unless we ask not to. set ob(nocenterarm) no

set ob(pre_wait) 0.0 set ob(vlim_wait) 0.0 set ob(dobeep) yes toggle_nbeep

# file names built from current time. current time is taken once # here, so that all files for a run have the same time, which is # convenient for grouping them.

set curtime [clock seconds]

set ob(datestamp) [clock format $curtime -format "%Y%m%d_%a"] set ob(timestamp) [clock format $curtime -format "%H%M%S"] # set ob(dirname) [file join $ob(logdirbase) $ob(patname)

# $ob(gametype) $ob(datestamp) ] # blinking ball colors

set ob(ball,col,1) red set ob(ball,col,2) orange # compass directions

set ob(dirs) {E ENE NE NNE NNW NW WNW W} # this may be overrridden by read_game_init

# set ob(dirnums) {-3 -2 -1 0 1 2 3 4 } con questa istruzione si parte da sinistra set ob(dirnums) {4 3 2 1 0 -1 -2 -3 }

# which you hit the "Alt-m" key, you get a menu with various info # may be useful in a clinical setting, or not.

# off by default. toggles on and off. set m [menu_init .menu]

# build the menu.

# the menu building procs are: # menu_t label text

# menu_cb checkbox # menu_v variable entry

125 # menu_b button

menu_t $m hits Hits menu_t $m hittime Time menu_t $m avgtime Avg Time menu_t $m blank2 "" ""

# menu_cb $m random Random set mob(random) no

menu_t $m blank3 "" ""

menu_v $m increment Increment # menu_v $m nballs Spots menu_v $m thresh Threshold menu_t $m blank4 "" ""

menu_b $m restart "New Game (n)" restartg1 menu_t $m menu "Hide Menu (Alt-m)" "" menu_b $m quit "Quit (q)" {ventaglio_exit} # display scale

# 2000.0 means 1 meter on the table == 2000 pixels on the screen. # .14m == 280 pixels # for planar # set ob(scale) 1800.0 # for wrist, 1800 * 14 / 26 set ob(scale) 1800. if {$ob(wrist)} {

set ob(scale) [expr {1800. * $ob(wrist_scale)}] }

# array size for rolling average set ob(avn) 10

# not blinking yet. set ob(blinking) no

# bind . binds the big window # new window, quit

# bind . <n> restartg1 bind . <q> ventaglio_exit bind . <Escape> ventaglio_exit bind . <b> toggle_nbeep

# toggle start/stop. target blinks when started. # white when stopped.

bind . <space> ventaglio_space

# dump game variables to stdout, for debugging. bind . <o> dump_ob

# bind .menu binds the menu window # bind .menu <n> restartg1

bind .menu <q> ventaglio_exit bind .menu <Escape> ventaglio_exit # bind .menu <space> ventaglio_space

126 # useful for measurement/debugging.

# note that cur,x/y will not be updated when "no_arm" is called. # 1st two are ball cursor in world space,

# 2nd two are X cursor in screen space

# bind . <Motion> [list wm title . "cursor pos $ob(cur,x) $ob(cur,y) $ob(curcan,x) $ob(curcan,y) %x %y"]

# this is useful for debugging measurement and cursor placement start_lkm

start_shm

### read game control file here

### to override defaults, and apply some vars to shared memory read_game_init $ob(gamename)

apply_init_vars #wshm safety_pos 1.0 wshm safety_pos 0.5

set ob(dirname) [file join $ob(logdirbase) $ob(patname) \ $ob(gametype) $ob(datestamp) ]

# settable text variables, these are deprecated. set mob(increment) 1

set mob(random) $ob(random) set mob(nballs) 8

# this is the green/red threshold in ms. 0 is off. set mob(thresh) 0 # counters set mob(hits) 0 set ob(slotnum) 1 set mob(hittime) 0 set mob(avgtime) 0 if {$ob(adaptive)} { init_adap }

# unpause the robot control loop LKM start_loop

after 100 }

# restart the game

# reset vars, calculate some positions proc restartg1 {} {

127 global ob mob

# not first time through. if {[winfo exists .fl]} {

destroy .fl }

# if there are any slots running, stop them stop_movebox 0

set ob(random) $mob(random) set ob(increment) $mob(increment) set mob(hits) 0

set ob(slotnum) 1 set mob(hittime) 0 set mob(avgtime) 0 set ob(t0) [clockms] set ob(avi) 0

set ob(avgtime) 0

for {set i 0} {$i < $ob(avn)} {incr i} { set ob(avg,$i) 0

}

# found empirically on 1024x768 screen under gnome # the size of the window on screen

# wm geom . 1009x738+0+0

# the size of the canvas in the window set ob(can,x) 1000

set ob(can,y) 650

# center of window in pixels

set ob(half,x) [expr {$ob(can,x) / 2.}] set ob(half,y) [expr {$ob(can,y) / 2.}]

# inner radius world space (with the balls centered on it). set ob(irad) $ob(slotlength)

# outer radius (the enclosing circle)

set ob(orad) [expr {16./14. * $ob(slotlength)}] # set up direction list

dodirlist

# .fl - originally the left frame, when the menu was the right frame. # has the status line .fl.status on the bottom,

# and setupg1 sets up the big clock canvas in .fl too. frame .fl

128 label .fl.status -textvariable ob(status) -font default\

-background gray20 -foreground gray50 pack .fl.status -fill x -expand true -side bottom status_mes [imes "Press Space Bar to Start"] set w [setupg1 .fl.c]

# grid $w pack $w

set ob(bigcan) $w # experiment...

if {[winfo exists .disp]} { destroy .disp

}

set ob(score) "$mob(hits)/$ob(nslots)"

label .disp -textvariable ob(score) -font $ob(scorefont) -bg gray25 -fg yellow place .disp -in . -relx 1.0 -rely 0.0 -anchor ne

# puts "window size $ob(can,x) $ob(can,y)"

# do final initialization of game vars gameinit $w

# event loop to handle things that move and blink xyinit $w

}

# status message on the bottom line proc status_mes {mes} {

global ob

set ob(status) $mes }

# do the actual canvas munging proc setupg1 {w} {

global ob

# create a canvas, $w this will be ob(bigcan)

set w [canvas $w -width $ob(can,x) -height $ob(can,y) -bg gray25] $w config -highlightthickness 0

# the window outside the canvas . configure -background gray25

# the edge highlight of the canvas should be 0 width

# this is important for the math that converts robot x/y to screen x/y $w configure -highlightthickness 0

# make the center be 0,0 - translate by "scrolling"

129 $ob(half,y)]

# draw big filled circle (questa riga in clock era attiva solo che io ora nn devo disegnare il cerchio

#$w create oval [centxy 0 0 $ob(orad)] -fill gray25 -width 3 -tag bigcircle # draw eight (or whatever) nballs, in a loop.

# nballs should now be fixed to 8. set col1 navyblue

set col2 blue

#set pi [expr {acos(0.) * 2.}] istruzione vecchia

# nel clock il valore di pi corrisponde alla costante pi greco; in questo caso e' un valore # calcolato in maniera empirica per posizionare i target in modo appropriato.

set pi [expr {acos(0.35) * 2.88}]

# if there are 8 slices, each slice is 180/9 degrees. set extdeg [expr {185 /9}]

for {set i 0} {$i < $ob(nballs)} {incr i} { set k [lindex $ob(dirnums) $i]

set ideg [expr {$k * 177 / 8}]

set i2 [expr {($ideg - $extdeg / 2)-280}] # outer circle

eval $w create arc [centxy 0 -0.07 $ob(orad)] -start $i2 -extent $extdeg\ -style pieslice -fill $col1 -width 3 -tag outer

# inner circle

eval $w create arc [centxy 0 -0.07 $ob(irad)] -start $i2 -extent $extdeg\ -style pieslice -fill $col2 -width 3 -tag inner

}

# draw a ball in the center, then balls on edge. # call it C for center.

set ob(ball,C,dir) W

# world position of center of the ball for movebox, x,y set ob(ball,C,center) {0.0 -0.07}

# canvas object id, returned by canvas create

set ob(ball,C,id) [$w create oval [centxy 0.0 -0.07 $ob(ball_size)] \ -fill black -tag [list ball W]]

# ball dir from id, N, NE, etc, and C for center. set ob(ball,$ob(ball,C,id),dir) $ob(ball,C,dir) # draw balls at circumference, all tagged as balls. # starting at top, going clockwise

130 # irad is radius of inner circle

set rad $ob(irad)

for {set i 0} {$i < $ob(nballs)} {incr i} { set k [lindex $ob(dirnums) $i] # use trig to calculate positions

set sx [expr {sin(($k * $pi / 9)-0.2)}] set sy [expr {cos(($k * $pi / 9)-0.2)}] set cx [expr {($rad * $sx)}]

set cy [expr {($rad * $sy)-0.07}] # see comments for center ball above set dir [lindex $ob(dirs) $i]

set ob(ball,$dir,center) [list $cx $cy]

set ob(ball,$dir,id) [$w create oval [centxy $cx $cy $ob(ball_size)] \ -fill black -tag [list ball $dir]]

set ob(ball,$ob(ball,$dir,id),dir) $dir

}

# create cursor off center

# will soon be at actual cursor position after pointer motion

set ob(cursor,id) [$w create oval [centxy .1 .1 $ob(cur_ball_size)] -tag cursor\ -fill yellow]

# to hide mouse pointer:

# $w itemconfig cursor -state hidden # scale the canvas, and flip y

$w scale all 0 0 $ob(scale) -$ob(scale) # return the widget ID of the canvas return $w

}

# show indictator arrows for circle games proc circlearrow {w} {

global ob mob

set smallrad [expr {$ob(orad) / 2.0}] switch -- $ob(circlestart) {

9cw {

set x1 [expr {0.0 - $smallrad}] set y1 0.0

131 set y2 .04

} 9ccw {

set x1 [expr {0.0 - $smallrad}] set y1 0.0

set x2 [expr {0.0 - $smallrad + .01}] set y2 -.04

} 3cw {

set x1 [expr {$smallrad}] set y1 0.0

set x2 [expr {$smallrad - .01}] set y2 -.04

} 3ccw {

set x1 [expr {$smallrad}] set y1 0.0

set x2 [expr {$smallrad - .01}] set y2 .04

}

default return }

$w create line $x1 $y1 $x2 $y2 \

-arrow last -arrowshape {15 20 10} \ -width 10 -fill orange -tag dirarrow $w scale dirarrow 0 0 $ob(scale) -$ob(scale) $w raise cursor

}

# show indicator arrows for shoulder games proc shoulderarrow {w} {

global ob

set smallrad [expr {0 - $ob(orad) / 2.0}] set x1 $smallrad

set y1 0.0 set x2 $smallrad

if {[string equal $ob(shoulderarrowdir) "up"]} { set y2 0.04

} else {

set y2 -0.04 }

$w create line $x1 $y1 $x2 $y2 \

-arrow last -arrowshape {15 20 10} \ -width 10 -fill orange -tag dirarrow

132 $w scale dirarrow 0 0 $ob(scale) -$ob(scale)

$w raise cursor }

# final init before starting game proc gameinit {w} {

global ob mob

if {$ob(smallercircle)} {

set smallrad [expr {$ob(orad) / 2.0}] $w coords bigcircle [centxy 0 0 $smallrad] $w scale bigcircle 0 0 $ob(scale) -$ob(scale) circlearrow $w } if {$ob(shoulderarrow)} { shoulderarrow $w } # blink counter set ob(blinki) 0

# if a blink loop already exists, cancel it. after cancel blinkloop $w

if {!$ob(nocenterarm)} {

# move the arm from its current position to world origin center_arm 0.0 -0.07

}

# if you want to hide the score display if {$ob(hidescore)} { lower .disp } set mob(hits) 0 set ob(slotnum) 1 init_target }

# cancel blink loop and stop blinking # cancel slot timeout too

proc blinkstop {w} { global ob

after cancel blinkloop $w if {!$ob(dynamic)} {

133 # after_info

if {[info exists ob(mb2_after_id)]} { after cancel $ob(mb2_after_id) unset ob(mb2_after_id)

} }

set ob(blinking) no }

# the real action happens in xyloop on ball cursor hits. # blink target ball every half second, or ob(blinkrate) proc blinkloop {w} {

global ob

if {$ob(in_ventaglio_exit)} {return} # blink alternate colors

if {$ob(blinki) % 2} { set color $ob(ball,col,1) } else {

set color $ob(ball,col,2) }

# the current target ball

$w itemconfigure $ob(ball,next,id) -fill $color set blinkrate [expr {int(1000.0 * $ob(blinkrate))}] after $blinkrate blinkloop $w

incr ob(blinki) }

# start the cursor motion loop proc xyinit {w} {

# give the lkm time to unpause, or rshm will return 0's after 100 xyloop $w

}

# the cursor motion loop, runs 20x/sec proc xyloop {w} {

global ob mob

if {$ob(in_ventaglio_exit)} {return} # 20x / sec

after 50 xyloop $w # get world space coords,

# for planar, meters, for wrist, radians set x [getptr x]

134 if {$ob(wrist)} {

foreach {x y} [wrist_ptr_scale $x $y] break }

set ob(cur,x) $x set ob(cur,y) $y

# move the yellow cursor ball, scale, and flip its y $w coords cursor [centxy $x $y $ob(cur_ball_size)] set ob(curcan,x) [expr {$x * $ob(scale) + $ob(half,x)}] set ob(curcan,y) [expr {-$y * $ob(scale) + $ob(half,y)}] $w scale cursor 0 0 $ob(scale) [expr {-$ob(scale)}]

# status_mes "x $x y $y cx $ob(curcan,x) y $ob(curcan,y)" # no check for ball hit if target not blinking.

# or static or no edge balls. if {!$ob(blinking)} { return } if {$ob(static)} { return } if {$ob(nballs) == 0} { return } if {$ob(noballhit)} { return }

# if adaptive, check the velocity magnitude.

# if the patient's hand has moved enough, start the slot now. if {$ob(adaptive)} {

# if there is a movebox event pending... if {[info exists ob(mb2_after_id)]} {

if {$ob(slottime) <= 0.0} { set slot_time 1.0 } # .20 controls the sensitivity of the velocity limit. # lower is more sensitive

set ob(vellim) [expr {.20 * 1.875 * $ob(slotlength) / $ob(slottime)}] set ob(velmag) [rshm velmag]

set ob(adap_patient_moved) "no" if {$ob(velmag) > $ob(vellim)} {

set ob(adap_patient_moved) "yes" # the patient moved the handle ctadd initiate

# puts "velmag $ob(velmag) > vellim $ob(vellim) cancel and start movebox" # execute the command immediately.

# mb_command will cancel the after.

set mb_command [lindex [after info $ob(mb2_after_id)] 0] nbeep 1

eval $mb_command }

} }

# did the cursor enter the next target ball? # see if the cursor is close enough to ball,next set curx $x

set cury $y

set dir $ob(ball,next,dir)

135 set nexty [lindex $ob(ball,$dir,center) 1]

set dist [edist $curx $cury $nextx $nexty] # did the cursor hit the target ball?

if {$dist < $ob(hitradius)} {

# puts "$curx $cury $nextx $nexty edist: $dist" enter_target_ball hit

if {$ob(blinking)} {

set ballid $ob(ball,$dir,id)

leave_target_ball $ballid $ob(bigcan) hit }

}

wm title . "$ob(gamename) $ob(patname) Average Time: $mob(avgtime) Hits: $mob(hits)" }

# this handles the menu clock and the red/green center of the clock # only called when you hit a target ball.

proc bumpclock {} { global ob mob # rolling average set avi $ob(avi) set t1 [clockms]

set dt [expr {$t1 - $ob(t0)}]

set ob(avgtime) [expr {$ob(avgtime) + $dt - $ob(avg,$avi)}] # change blue/red/green if we want.

if {$mob(thresh) > 0 && $ob(avgtime) > [expr {$mob(thresh) * 10}]} { set acol firebrick

} else {

#set acol darkgreen set acol blue

}

set mob(avgtime) [format %.3f [expr {($ob(avgtime)/($ob(avn)*1000.0))}]] $ob(bigcan) itemconfigure inner -fill $acol

set ob(avg,$avi) $dt

set ob(avi) [expr {($avi + 1) % $ob(avn)}] set mob(hittime) [expr {$dt/1000.0}] set ob(t0) $t1

}

# some simple games have no edge balls

Documenti correlati