Diferencia entre revisiones de «Butialo»

De Proyecto Butiá
Saltar a: navegación, buscar
(Ejemplo simple (también))
(agregar link a ejemplos)
 
(No se muestran 49 ediciones intermedias de 3 usuarios)
Línea 1: Línea 1:
 +
[[Archivo:Screenshot.png|thumb|right|300px|alt=Butialo, IDE de Lua para Butia|Butialo, Lua para Butia]]
 
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.
 
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.
 
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.
 
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.
 
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.
 
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.
 +
 +
 +
 +
== Instalación ==
 +
 +
La actividad puede descargarse desde [http://activities.sugarlabs.org/sugar/addon/4457 el repositorio de actividades de Sugar]
 +
  
  
Línea 7: Línea 15:
  
 
Avanzar mientras no haya un obstaculo.
 
Avanzar mientras no haya un obstaculo.
 +
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
Motores.setvel2mtr( 1, 500, 1, 500 )
 
Motores.setvel2mtr( 1, 500, 1, 500 )
 
while true do
 
while true do
   local dist = tonumber( Dist.getDistancia() )
+
   local dist = Dist.getDistancia()
   if dist and dist<700 then
+
   if dist<700 then
 
       Motores.setvel2mtr( 1, 0, 1, 0 )
 
       Motores.setvel2mtr( 1, 0, 1, 0 )
 
       repeat
 
       repeat
 
         wait(1)
 
         wait(1)
         dist = tonumber( Dist.getDistancia() )
+
         dist = Dist.getDistancia()
 
       until dist > 700
 
       until dist > 700
 
       Motores.setvel2mtr( 1, 500, 1, 500 )
 
       Motores.setvel2mtr( 1, 500, 1, 500 )
Línea 24: Línea 33:
  
  
== Ejemplo simple (también) ==
+
También se puede programar con eventos. Un programa equivalente al anterior puede ser el siguiente:
  
  
Butiá con estabilidad dinámica. Se toma un Butiá, se le retiran las ruedas locas y se colocan dos sensores de distancia IR apuntando al piso, uno adelante y otro atrás.
+
<syntaxhighlight lang="lua">
 +
local function adelante()
 +
  Motores.setvel2mtr( 1, 500, 1, 500 )
 +
end
 +
local function esperar()
 +
  Motores.setvel2mtr( 1, 0, 1, 0 )
 +
  wait( 1 )
 +
end
 +
 
 +
events.add( Dist.getDistancia, '<', 700, esperar )
 +
events.add( Dist.getDistancia, '>', 700, adelante )
 +
events.go()
 +
</syntaxhighlight>
 +
 
 +
 
 +
 
 +
== Ejemplo simple (otro) ==
 +
 
 +
 
 +
Butiá con estabilidad dinámica. Se toma un Butiá, se le retiran las ruedas locas y se coloca un sensor de distancia IR apuntando al piso. Con el botón se activa y desactiva el comportamiento.
  
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
local d1, d2 --lecturas de distancia
+
local d --lecturas de distancia
local dd --diferencia de distancias
+
local eq --posicion de equilibrio de d
local eq --posicion de equilibrio de dd
+
 
local v --velocidad calculada
 
local v --velocidad calculada
  
 
while true do
 
while true do
 
print ("Presione el botón para comenzar")
 
print ("Presione el botón para comenzar")
repeat
+
repeat until Boton.getBoton()==1
wait(0.1)
+
until tonumber(Boton.getBoton())==1
+
  
d1=tonumber( Dist.getDistancia() )
+
eq = Dist.getDistancia()  
d2=tonumber( Dist1.getDistancia() )
+
eq=d1-d2
+
 
 
 
print("Arrancando", eq)
 
print("Arrancando", eq)
wait(1)
+
util.wait(1)
  
 
repeat
 
repeat
d1=tonumber( Dist.getDistancia() )
+
d = Dist.getDistancia()
d2=tonumber( Dist1.getDistancia() )
+
v = 100+5*math.abs(d-eq)
dd=d1-d2
+
if v > 1024 then v = 1024 end
v=100+5*math.abs(dd-eq)
+
if d < eq then
if v>1024 then v=1024 end
+
if dd<eq then
+
 
Motores.setvel2mtr(1, v, 1, v)
 
Motores.setvel2mtr(1, v, 1, v)
 
else
 
else
 
Motores.setvel2mtr(0, v, 0, v)
 
Motores.setvel2mtr(0, v, 0, v)
 
end
 
end
until tonumber(Boton.getBoton())==1
+
until Boton.getBoton()==1
  
 
print("Fin")
 
print("Fin")
 
Motores.setvel2mtr(1, 0, 1, 0)
 
Motores.setvel2mtr(1, 0, 1, 0)
wait(1)
+
util.wait(1)
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
Línea 72: Línea 93:
  
  
[[Archivo:IMG_5747.JPG]]
+
 
 +
== Más ejemplos ==
 +
 
 +
 
 +
También hay disponible una [http://www.fing.edu.uy/inco/proyectos/butia/mediawiki/index.php/Ejemplos_de_Aplicaciones_en_Butialo colección de ejemplos] de aplicaciones básicas.
 +
 
 +
 +
 
 +
== Util ==
 +
 
 +
 
 +
Butialo provee varias funciones auxiliares.
 +
 
 +
 
 +
'''util.wait( t )'''
 +
 
 +
Pausa la ejecución del programa por t segundos.
 +
 
 +
 
 +
'''util.get_time()'''
 +
 
 +
Devuelve el tiempo del sistema, en segundos.
 +
 
 +
 
 +
'''util.new_array()'''
 +
 
 +
Lua provee una única estructura de datos, la tabla (array asociativo). Para facilitar la introducción a los conceptos de programación butialo provee el método util.new_array() que devuelve un array convencional. El array obtenido toma índices numéricos empezando en 1, y solo almacenará variables de un único tipo (determinado por la primer asignación que se haga). El array obtenido es dinámico y será expandido automáticamente cuando se agreguen elementos al final, y se contraerá cuando el último elemento se elimine. No se aceptan valores nil en el medio del array ("agujeros"). Las funciones estándar de Lua para tablas no funcionan con estos arrays. Los métodos disponible para manipular un array son
 +
 
 +
a.len() :  Devuelve el número de elementos contenidos en el array.
 +
 
 +
a.add( v ) : Agrega un elemento al final del array, aumentando su tamaño. Es lo mismo que escribir a[a.len()+1]=v
 +
 
 +
a.remove_last() : Retira y devuelve el último elemento del array, acortándo el array. Es lo mismo que escribir a[a.len()]=nil
 +
 
 +
a.containing() : Devuelve el tipo de elemento que está siendo almacenado en el array
 +
 
 +
Ejemplo de manipulación de arays:
 +
 
 +
<syntaxhighlight lang="lua">
 +
local a = new_array()
 +
for i=1, 5 do
 +
  a[i]="entrada" .. i
 +
end
 +
a.add("borrar esto")
 +
a.remove_last()
 +
a[2]="entrada cambiada"
 +
print("Array conteniendo", a.containing())
 +
for i=1, a.len() do
 +
print(i, ":", a[i])
 +
end
 +
</syntaxhighlight>
 +
 
 +
== Eventos ==
 +
 
 +
 
 +
Butialo puede ser programado usando eventos. Un evento permite asociar una función a una condición: si la condición se cumple, la función se ejecuta. Se pueden registrar varios eventos, y estos se pueden agregar y eliminar en cualquier momento. Los eventos se ejecutan de forma bloqueante: cuando un evento se dispara, la función asociada se ejecuta hasta terminar y no puede ser interrumpida por otro evento. Es más, mientras un evento se está ejecutando, no se evalúan las condiciones de los otros eventos. El evento se dispara cuando la condición empieza a cumplirse, pero no continuará haciéndolo hasta que la condición deje de cumplirse.
 +
 
 +
Para registrar un evento, se usa la función events.add
 +
 
 +
'''events.add( func, op, reference, callback [, hysteresis [, name]] )'''
 +
 
 +
Los párametros func, op y referencia especifican la condición que dispara el evento.
 +
 
 +
func: la función que al ser evaluada devuelve el valor que queremos vigilar.
 +
 
 +
op:  operador de comparación, puede ser '>', '<', '<=', '>=', '==' o '~='.
 +
 
 +
referencia: valor de refencia con el que se comparará func()
 +
 
 +
callback: la función que se va a invocar cuando se dispara el evento, o sea cuando se cumple que "func() op referencia". Cuando se invoca callback(), se le pasa como parámetro el valor de func() que disparó el evento. O sea, se invocará "callback( func() )"
 +
 
 +
hysteresis: un parámetro opcional, útil cuando se usan operadores de desigualdad.
 +
 
 +
name: parametro opcional, el nombre del evento. Útil para identificar el evento si en otro momento se lo quiere desactivar.
 +
 
 +
La función events.add devuelve el nombre asignado al evento (coincide con el parámetro name si fue provisto, sino se genera un nombre automáticamente). Esta función puede invocarse tanto desde el programa principal como desde una función callback.
 +
 
 +
Un evento puede desactivarse usando la función events.remove. Tal como events.add, se puede invocar en cualquier momento.
 +
 
 +
'''events.remove( name )'''
 +
 
 +
name: el nombre del evento que se quiere desactivar
 +
 
 +
Para empezar a procesar eventos se usa la llamada events.go
 +
 
 +
'''events.go()'''
 +
 
 +
Luego de invocada, el sistema queda bloqueado procesando eventos, invocando los callback según corresponda. Esto seguirá así hasta que se invoque la función events.stop
 +
 
 +
'''events.stop()'''
 +
 
 +
Esta función solo puede ser invocada en una función de callback para detener el procesamiento de eventos. Luego de invocada y terminada la función de callback responsable, el programa continuará ejecutándose en la línea siguiente al events.go.
 +
 
 +
Como ejemplo, el siguiente programa imprime "tick" cada 2 segundos, hasta que se presiona un botón y el programa finaliza.
 +
 
 +
 
 +
<syntaxhighlight lang="lua">
 +
local last = 0 --hora de la ultima vez que se imprimio tick
 +
 
 +
local function get_elapsed()
 +
  return util.get_time() - last
 +
end
 +
 
 +
local function tick_callback ( v )
 +
  last = util.get_time()
 +
  print("tick", v)
 +
end
 +
 
 +
local function stop_callback()
 +
  events.stop()
 +
end
 +
 
 +
events.add( get_elapsed, ">=", 2, tick_callback)
 +
events.add( Boton.get_boton, "==", 1, stop_callback )
 +
events.go()
 +
</syntaxhighlight>
 +
 
 +
== Temas avanzados ==
 +
 
 +
 
 +
Se provee una librería que implementa un [[controlador PID]].

Revisión actual del 13:19 16 oct 2012

Butialo, IDE de Lua para Butia
Butialo, Lua para Butia

Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua. Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido. Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.


Instalación

La actividad puede descargarse desde el repositorio de actividades de Sugar


Ejemplo simple

Avanzar mientras no haya un obstaculo.


Motores.setvel2mtr( 1, 500, 1, 500 )
while true do
   local dist = Dist.getDistancia()
   if dist<700 then
      Motores.setvel2mtr( 1, 0, 1, 0 )
      repeat
         wait(1)
         dist = Dist.getDistancia()
      until dist > 700
      Motores.setvel2mtr( 1, 500, 1, 500 )
   end
end


También se puede programar con eventos. Un programa equivalente al anterior puede ser el siguiente:


local function adelante()
  Motores.setvel2mtr( 1, 500, 1, 500 )
end
local function esperar()
  Motores.setvel2mtr( 1, 0, 1, 0 )
  wait( 1 )
end

events.add( Dist.getDistancia, '<', 700, esperar )
events.add( Dist.getDistancia, '>', 700, adelante )
events.go()


Ejemplo simple (otro)

Butiá con estabilidad dinámica. Se toma un Butiá, se le retiran las ruedas locas y se coloca un sensor de distancia IR apuntando al piso. Con el botón se activa y desactiva el comportamiento.


local d		--lecturas de distancia
local eq	--posicion de equilibrio de d
local v		--velocidad calculada

while true do
	print ("Presione el botón para comenzar")
	repeat until Boton.getBoton()==1

	eq = Dist.getDistancia() 
	
	print("Arrancando", eq)
	util.wait(1)

	repeat
		d = Dist.getDistancia()
		v = 100+5*math.abs(d-eq)
		if v > 1024 then v = 1024 end
		if d < eq then
			Motores.setvel2mtr(1, v, 1, v)
		else
			Motores.setvel2mtr(0, v, 0, v)
		end
	until Boton.getBoton()==1

	print("Fin")
	Motores.setvel2mtr(1, 0, 1, 0)
	util.wait(1)
end



Más ejemplos

También hay disponible una colección de ejemplos de aplicaciones básicas.


Util

Butialo provee varias funciones auxiliares.


util.wait( t )

Pausa la ejecución del programa por t segundos.


util.get_time()

Devuelve el tiempo del sistema, en segundos.


util.new_array()

Lua provee una única estructura de datos, la tabla (array asociativo). Para facilitar la introducción a los conceptos de programación butialo provee el método util.new_array() que devuelve un array convencional. El array obtenido toma índices numéricos empezando en 1, y solo almacenará variables de un único tipo (determinado por la primer asignación que se haga). El array obtenido es dinámico y será expandido automáticamente cuando se agreguen elementos al final, y se contraerá cuando el último elemento se elimine. No se aceptan valores nil en el medio del array ("agujeros"). Las funciones estándar de Lua para tablas no funcionan con estos arrays. Los métodos disponible para manipular un array son

a.len() : Devuelve el número de elementos contenidos en el array.

a.add( v ) : Agrega un elemento al final del array, aumentando su tamaño. Es lo mismo que escribir a[a.len()+1]=v

a.remove_last() : Retira y devuelve el último elemento del array, acortándo el array. Es lo mismo que escribir a[a.len()]=nil

a.containing() : Devuelve el tipo de elemento que está siendo almacenado en el array

Ejemplo de manipulación de arays:

local a = new_array()
for i=1, 5 do
  a[i]="entrada" .. i
end
a.add("borrar esto")
a.remove_last()
a[2]="entrada cambiada"
print("Array conteniendo", a.containing())
for i=1, a.len() do
	print(i, ":", a[i])
end

Eventos

Butialo puede ser programado usando eventos. Un evento permite asociar una función a una condición: si la condición se cumple, la función se ejecuta. Se pueden registrar varios eventos, y estos se pueden agregar y eliminar en cualquier momento. Los eventos se ejecutan de forma bloqueante: cuando un evento se dispara, la función asociada se ejecuta hasta terminar y no puede ser interrumpida por otro evento. Es más, mientras un evento se está ejecutando, no se evalúan las condiciones de los otros eventos. El evento se dispara cuando la condición empieza a cumplirse, pero no continuará haciéndolo hasta que la condición deje de cumplirse.

Para registrar un evento, se usa la función events.add

events.add( func, op, reference, callback [, hysteresis [, name]] )

Los párametros func, op y referencia especifican la condición que dispara el evento.

func: la función que al ser evaluada devuelve el valor que queremos vigilar.

op: operador de comparación, puede ser '>', '<', '<=', '>=', '==' o '~='.

referencia: valor de refencia con el que se comparará func()

callback: la función que se va a invocar cuando se dispara el evento, o sea cuando se cumple que "func() op referencia". Cuando se invoca callback(), se le pasa como parámetro el valor de func() que disparó el evento. O sea, se invocará "callback( func() )"

hysteresis: un parámetro opcional, útil cuando se usan operadores de desigualdad.

name: parametro opcional, el nombre del evento. Útil para identificar el evento si en otro momento se lo quiere desactivar.

La función events.add devuelve el nombre asignado al evento (coincide con el parámetro name si fue provisto, sino se genera un nombre automáticamente). Esta función puede invocarse tanto desde el programa principal como desde una función callback.

Un evento puede desactivarse usando la función events.remove. Tal como events.add, se puede invocar en cualquier momento.

events.remove( name )

name: el nombre del evento que se quiere desactivar

Para empezar a procesar eventos se usa la llamada events.go

events.go()

Luego de invocada, el sistema queda bloqueado procesando eventos, invocando los callback según corresponda. Esto seguirá así hasta que se invoque la función events.stop

events.stop()

Esta función solo puede ser invocada en una función de callback para detener el procesamiento de eventos. Luego de invocada y terminada la función de callback responsable, el programa continuará ejecutándose en la línea siguiente al events.go.

Como ejemplo, el siguiente programa imprime "tick" cada 2 segundos, hasta que se presiona un botón y el programa finaliza.


local last = 0 --hora de la ultima vez que se imprimio tick

local function get_elapsed()
  return util.get_time() - last
end

local function tick_callback ( v )
  last = util.get_time()
  print("tick", v)
end

local function stop_callback()
  events.stop()
end

events.add( get_elapsed, ">=", 2, tick_callback)
events.add( Boton.get_boton, "==", 1, stop_callback )
events.go()

Temas avanzados

Se provee una librería que implementa un controlador PID.