buzz-lang / Buzz

A programming language designed for robot swarms.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

problems with files

alacalcasis opened this issue · comments

I have a file: fpd = io.fopen("fpd.csv","a+") # have also tried with "w" and "a"
and use it: fpd.fwrite(string.tostring(s),",",id,",",string.tostring(pd)), where s has an integer and pd a float.

Since there are no examples on how to use files, I couldn't deduce why i get this error on every bot:

[ROBOT 7] afluir.bo: execution terminated abnormally: /home/alan/Documentos/pruebas/khepera-iv/afluir.bzz:166:1: type mismatch: expected closure, got nil

============================================================
state: error error: 6
code size: 2444 oldpc: 2003 pc: 2004
stacks: 2 cur: 1
cur instr: callc
next instr: pop
6 [string] 157:'209,972672'
5 [string] 64:','
4 [int] 7
3 [string] 64:','
2 [string] 156:'0'
1 [nil]
0 [table] 2 elements
[string] 152:'handle' -> [TODO] type = 6
[string] 153:'name' -> [string] 21:'fpd.csv'

Hours later I realized that there could be a conflict since every bot will be trying to use the same file, so i changed it to:
nmb_arch = string.concat("fpd",string.tostring(id),".csv")
fpd = io.fopen(nmb_arch,"a+")
......
fpd.fwrite(string.tostring(s),",",id,",",string.tostring(pd))
So now every bot creates and uses its own file, indeed the files are created, but I still got the same error.
Thank you in advance for any help!

Can you please post your afluir.bzz file? It's hard to say what is going on without the rest of the code. Something that should be a closure is nil at line 166, but I don't know what is at line 166. Also, what is id?

Hello, thanks for answering, here is the complete code, but line 166 is precisely fpd.fwrite(string.tostring(s),",",id,",",string.tostring(pd)) so I guess fpd is nil but don't understand why. And, so far I've used id as the id of robots and it has worked.

The general idea is to make kheperas flock using some heuristics similar to what birds use.

CONSTANTES BÁSICAS:

pi = math.PI		# == 3.1415926535
rxg = 0.0174533		# radianes por grado

Constantes para un giro de 360 grados en 36 segundos o 360 tics:

vri_iz = 1.0 # velocidad de rueda izq para giro hacia la izquierda
vrd_iz = 2.8395756 # velocidad de rueda der para giro hacia la izquierda
vri_de = 2.8395756 # velocidad de rueda izq para giro hacia la derecha
vrd_de = 1.0 # velocidad de rueda der para giro hacia la derecha
fg = 6.0 # factor para aumentar la velocidad de un giro de 360 en 360 / fg tics, o sea: fg grados por tic
cg = 1 # OJO: el contador de giros debe iniciarse en 1 para cumplir el giro en la cantidad esperada de tics (10 t / s)
# dado fg grados por tic, el giro total sería de cg * fg grados

PARAMETROS DE AFLUIR:

ang_vision = 180		# en grados 
rng_vision = 50			# en centímetros, cada cuadro en la grilla es de un metro cuadrado
dst_minima = 25			# distancia mínima en centímetros entre los kiv
v_gir_aln = 6.0			# velocidad de giro para alinearse en grados por tic
v_gir_coh = 6.0			# velocidad de giro para cohesionarse en grados por tic
v_gir_sep = 6.0			# velocidad de giro para separarse en grados por tic
v = 10.0				# velocidad base: a 10cms / s, 1cm / décima
cnt_bots = 30			# cantidad total de bots en el enjambre

Executed at init time

function init() {
nmb_arch = string.concat("fpd",string.tostring(id),".csv")
#fpd = io.fopen(nmb_arch,"a+") # /home/alan/Documentos/pruebas/khepera-iv/
s = 0

# variables para moverse y girar
vri = v
vrd = v
cg = 0				

# cantidad de vecinos en el radio y rango de visión
set_wheels(vri,vrd)

# variables globales:
yaw_p = 0.0
t_yaws = {}

# listeners:
neighbors.listen("y",
	function(msj, yaw_r, oid) {	#recibe el mensaje "yaw" de cada vecino oid en yaw_r
		#log(id," recibo de ", oid," yaw = ", yaw_r)
		yaw_p = yaw_p + yaw_r
		t_yaws[oid] = yaw_r
	})

}

function reset() {

}

function obt_prom_dist(){
pd = 0.0
neighbors.foreach(
function(vid, data){
pd = pd + data.distance
}
)
return pd / neighbors.count()
}

REQ: 0 <= ang_vision <= 360, es decir, en grados.

REQ: 0 < rng_vision, y en centímetros.

RET: tabla con los vecinos en el ángulo y rango de visión.

function obt_vecinos(){
return neighbors.filter(
function(vid,data){
return ((math.abs(data.azimuth) <= (ang_vision * rxg)/2.0) and (data.distance < rng_vision))
}
)
}

REQ: vcns sea una tabla de vecinos.

RET: una tabla {.rid = x, .dst = y}, donde rid es el id del bot más cercano y dst la distancia.

function vecino_mas_cercano(vcns){
p_vmc = { .rid = -1, .dst = -1 }
dst_m = rng_vision
vcns.foreach(
function(rid, data){
if (data.distance <= dst_m)
p_vmc["rid"] = rid
p_vmc["dst"] = data.distance
}
)
return p_vmc
}

RET: si el promedio de los giros hacia los vecinos es mayor a cero, lo retorna;

RET: si no, retorna la propia orientación

function prm_giros_hacia_vcns(){
giros_p = 0.0 # variable para calcular el promedio de los giros hacia los vecinos
neighbors.foreach(
function(rid, data) {
giros_p = giros_p + data.azimuth
})
if (neighbors.count() > 0)
return giros_p / neighbors.count()
else return pose.orientation.yaw
}

EFE: cambia m_rumbo para el bot con base en n_rumbo en g grados porque cg == 1.

function girar_hacia(n_rumbo, m_rumbo, g){
if (m_rumbo > n_rumbo) { # giro ha la derecha
cg = 1
set_wheels(vri_de * g, vrd_de * g)
} else { # giro a la izquierda
cg = 1
set_wheels(vri_iz * g, vrd_iz * g)
}
}

EFE: el bot se aleja del grupo porque está muy cerca.

function separarse(vmc){
yaw_vcn_mas_cerca = t_yaws[vmc.rid]
#log(id, " vmc = ", vmc, " yaw_vmc = ", t_yaws[vmc.rid], " c_vcns = ", size(t_yaws))

if (pose.position.yaw > yaw_vcn_mas_cerca) { # giro ha la izquierda
	cg = 1
	set_wheels(vri_iz * v_gir_sep, vrd_iz * v_gir_sep)
} else { # giro a la derecha
	cg = 1
	set_wheels(vri_de * v_gir_sep, vrd_de * v_gir_sep)	
}

}

EFE: el rumbo del bot se re-alinea con el del grupo yaw_p.

function alinearse(yaw_p){
# se basa en yaw_p - pose.position.yaw
girar_hacia(yaw_p, pose.position.yaw, v_gir_aln)
}

#EFE: el bot se acerca al grupo porque está muy lejos.
function agruparse(){
pg_vcns = prm_giros_hacia_vcns()
girar_hacia(pg_vcns, pose.orientation.yaw, v_gir_coh)
}

Executed every time step

function step() {
# calcula promedio de distancia a todos los vecinos:
pd = obt_prom_dist()
log(string.tostring(s),",",id,",",string.tostring(pd))
#fpd.fwrite(string.tostring(s),",",id,",",string.tostring(pd))

# enviar el yaw a TODOS los vecinos:
neighbors.broadcast("y", pose.orientation.yaw)

# calcula el promedio del yaw de TODOS los vecinos. El yaw es el rumbo.
if (neighbors.count() > 0)
	yaw_p = yaw_p / neighbors.count()
else yaw_p = pose.orientation.yaw	

# determina comportamiento para este paso:
if (cg == 0){
	# cuando termina de girar, retoma la marcha en recta
	set_wheels(vri,vrd)
	
	# y determina si debe girar de nuevo:
	vcns = obt_vecinos()
	#log(id," mi pd: ", pd)
	if (vcns.count() != 0) {
		vmc = vecino_mas_cercano(vcns)
		if (vmc.dst < dst_minima)
			separarse(vmc)
		else {
			alinearse(yaw_p)
			agruparse()
		}
	}
} else cg = cg - 1				

# se reinician variables, OJO: DEBE SER AL FINAL, DE LO CONTRARIO NO CALCULA CORRECTAMENTE!!!
yaw_p = 0.0
s = s + 1

}

Execute at exit

function destroy() {
fpd.fclose()
}

Maybe I should simplify the post to the relevant chunk of the code:

function init() {
nmb_arch = string.concat("fpd",string.tostring(id),".csv")
fpd = io.fopen(nmb_arch,"a+") # here i create the file
s = 0

vri = v
vrd = v
cg = 0

set_wheels(vri,vrd)

yaw_p = 0.0
t_yaws = {}

neighbors.listen("y",
function(msj, yaw_r, oid) { #recibe el mensaje "yaw" de cada vecino oid en yaw_r
#log(id," recibo de ", oid," yaw = ", yaw_r)
yaw_p = yaw_p + yaw_r
t_yaws[oid] = yaw_r
})

}

function step() {

pd = obt_prom_dist()
fpd.fwrite(string.tostring(s),",",id,",",string.tostring(pd)) # and here i use the file

neighbors.broadcast("y", pose.orientation.yaw)

if (neighbors.count() > 0)
yaw_p = yaw_p / neighbors.count()
else yaw_p = pose.orientation.yaw

if (cg == 0){
set_wheels(vri,vrd)

vcns = obt_vecinos()
if (vcns.count() != 0) {
	vmc = vecino_mas_cercano(vcns)
	if (vmc.dst < dst_minima)
		separarse(vmc)
	else {
		alinearse(yaw_p)
		agruparse()
	}
}

} else cg = cg - 1

yaw_p = 0.0
s = s + 1

}

I think you use a local variable in init (fpd) and the garbage collector kills it before the call in step. Try with a global.

OK, sorry, answering on the phone is not ideal. The variables you define in init should not be destroyed by the gc. The solution is actually quite simple, the function is not a member of fpd, but of io, and it should read:
io.fwrite(fpd, ....)

Thank you very much, it worked now!!!

Maybe I could help adding some examples on the use of files, if you agree.

Sure, that would be helpful! The only examples we have are what's in testing

OK, how do I proceed? Do I need an account? Didn't see how to make an account on the wiki page.

The wiki si managed by @ilpincy, I think that perhaps we should migrate it to GitHub to keep things simple. @ilpincy: how do you want to manage some additions to the wiki?

We can allow more people in the wiki. If we want to migrate, I would suggest we move away from the MISTLab organization and make a dedicated Buzz organization, so we can make a dedicated example repository (as I did with ARGoS).