Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
CREATE Lab
Agricultural robotics
Root Phenotyping
Commits
0434cf0c
Commit
0434cf0c
authored
Jun 23, 2022
by
Jonas Tobias Ulbrich
Browse files
Implement logger... needs feature test
parent
490eb311
Changes
17
Hide whitespace changes
Inline
Side-by-side
scripts/GUI/css/log.css
View file @
0434cf0c
root
{
html
{
top
:
0
;
bottom
:
0
;
left
:
0
;
right
:
0
;
height
:
100vh
;
width
:
100vw
;
}
body
{
background-color
:
#f0f0f0
;
display
:
flex
;
flex-direction
:
column
;
...
...
@@ -6,56 +15,63 @@ root {
font-size
:
calc
(
9pt
+
0.5vw
);
font-family
:
Arial
;
/*font-weight: bold;/**/
color
:
#
3a3a3a
;
color
:
#
787878
;
width
:
100vw
;
overflow-x
:
hidden
;
scrollbar-width
:
none
;
}
info
,
warn
,
error
{
body
>
*
{
display
:
flex
;
position
:
relative
;
width
:
calc
(
85vw
-
calc
(
1.5em
+
4px
));
min-height
:
3em
;
border-radius
:
1em
;
margin
:
0.5em
auto
0
auto
;
border-style
:
solid
;
border-width
:
2px
;
/*
border-style:solid;
border-width: 2px;
/**/
padding
:
0.5em
0.5em
0.5em
1em
;
text-shadow
:
2px
2px
2px
#00000080
;
background-color
:
#78787850
;
box-shadow
:
0.1vw
0.3vw
0.3vw
#888888
;
/*text-shadow: 2px 2px 2px #00000080;/**/
}
timestamp
{
.
timestamp
{
position
:
absolute
;
bottom
:
0.8em
;
right
:
0.8em
;
height
:
0.8em
;
font-size
:
calc
(
calc
(
9pt
+
0.5vw
)
*
0.7
);
color
:
#
cacaca
;
text-shadow
:
2px
2px
2px
#00000060
;
color
:
#
787878
;
/*
text-shadow: 2px 2px 2px #00000060;
/**/
}
message
{
.
message
{
margin-bottom
:
1.2em
;
min-height
:
1.2em
;
width
:
100%
;
text-align
:
left
;
}
info
{
background-color
:
lightskyblue
;
bo
rder-color
:
lightskyblue
;
color
:
#fafafa
;
.
info
{
background-color
:
#87cefa50
;
bo
x-shadow
:
0.1vw
0.3vw
0.3vw
#87defa
;
/*border-color: lightskyblue;/**/
}
warn
{
background-color
:
#ffb84d
;
bo
rder-color
:
#ffb8
4
d
;
color
:
#fafafa
;
.
warn
{
background-color
:
#ffb84d
50
;
bo
x-shadow
:
0.1vw
0.3vw
0.3vw
#ffb8
5
d
;
/*border-color: #ffb84d;/**/
}
error
{
background-color
:
lightcoral
;
bo
rder-color
:
lightcoral
;
color
:
#fafafa
;
.
error
{
background-color
:
#f0808050
;
bo
x-shadow
:
0.1vw
0.3vw
0.3vw
#f09090
;
/*border-color: lightcoral;/**/
}
scripts/GUI/css/styles.css
View file @
0434cf0c
...
...
@@ -42,7 +42,6 @@ section {
box-shadow
:
0.1vw
0.3vw
0.3vw
#888888
;
}
h2
{
margin
:
0
;
padding
:
0
;
...
...
@@ -73,13 +72,25 @@ h2 {
/* --- CONSOLE VIEW ---*/
.console
{
width
:
calc
(
49.5em
+
28px
);
height
:
22em
;
position
:
relative
;
margin-bottom
:
3em
;
}
.console
iframe
{
border
:
none
;
width
:
100%
;
height
:
100%
;
width
:
49.5em
;
height
:
22em
;
margin-top
:
0.5em
;
}
.console_gradient
{
display
:
block
;
position
:
absolute
;
bottom
:
1em
;
left
:
1em
;
right
:
1em
;
height
:
2em
;
background-image
:
linear-gradient
(
#00000000
,
var
(
--section-bg-color
));
}
/* --- ALERT BOX ---*/
...
...
@@ -148,7 +159,7 @@ input, button {
justify-content
:
center
;
flex-direction
:
column
;
background
:
#000000
b0
;
/*
display: none;/**/
display
:
none
;
/**/
}
#new_sample_form
form
{
...
...
scripts/GUI/index.html
View file @
0434cf0c
...
...
@@ -148,12 +148,16 @@
</div>
</section>
<section
class=
"inspection tab"
>
<iframe
src=
"sample.xml"
></iframe>
</section>
<!--
<section class="inspection tab">
<iframe src="sample
_data
.xml"></iframe>
</section>
-->
<section
class=
"console tab"
>
<iframe
src=
"../data/log.xml"
></iframe>
<h2>
Experiment Log
</h2>
<iframe
name=
"console_frame"
src=
"log.html"
></iframe>
<div
class=
"console_gradient"
>
</div>
</section>
<section
id=
"new_sample_form"
>
...
...
scripts/GUI/js/gui.js
View file @
0434cf0c
...
...
@@ -15,6 +15,12 @@ function require_GUI_update() {
});
}
eel
.
expose
(
require_GUI_update
);
function
log_update
()
{
//simply reload file
document
.
getElementsByName
(
"
console_frame
"
)[
0
].
src
=
document
.
getElementsByName
(
"
console_frame
"
)[
0
].
src
;
}
function
set_day_time_cb
()
{
var
hh
=
parseInt
(
document
.
getElementsByName
(
"
day_h
"
)[
0
].
value
);
var
mm
=
parseInt
(
document
.
getElementsByName
(
"
day_m
"
)[
0
].
value
);
...
...
scripts/GUI/log.html
0 → 100644
View file @
0434cf0c
<html
lang=
"en"
dir=
"ltr"
><head><meta
charset=
"utf-8"
/><link
rel=
"stylesheet"
href=
"css/log.css"
/></head><body><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:36.632130
</div><div
class=
"message"
>
tua mamma
</div></div><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:36.415099
</div><div
class=
"message"
>
tua mamma
</div></div><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:36.216926
</div><div
class=
"message"
>
tua mamma
</div></div><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:35.798924
</div><div
class=
"message"
>
tua mamma
</div></div><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:34.981212
</div><div
class=
"message"
>
tua mamma
</div></div><div
class=
"info"
><div
class=
"timestamp"
>
2022-06-23 17:48:30.426475
</div><div
class=
"message"
>
skuuuu
</div></div><div
class=
"error"
><div
class=
"timestamp"
>
2022-06-23 17:48:30.419492
</div><div
class=
"message"
>
oramai hai fatto la cacca
</div></div><div
class=
"warn"
><div
class=
"timestamp"
>
2022-06-23 17:48:30.408486
</div><div
class=
"message"
>
tua mamma
</div></div></body></html>
\ No newline at end of file
scripts/GUI/sample.xml
→
scripts/GUI/sample
_data
.xml
View file @
0434cf0c
File moved
scripts/app.py
View file @
0434cf0c
...
...
@@ -29,17 +29,21 @@ r_timeout = 1
#Rack
rows
=
2
slots
=
6
#Logger
path_to_log
=
"GUI/"
#Instantiate components
tracker
=
SampleTracker
(
rows
*
slots
)
logger
=
HTMLLogger
(
path_to_log
,
eel
)
tracker
=
SampleTracker
(
rows
*
slots
,
logger
)
controller
=
CentralCtrl
(
CameraCtrl
(
camera_idx
),
CartesianRobot
(
r_com_port
,
r_baud
,
r_timeout
),
Peripherals
(
g_com_port
,
g_baud
,
device_name
=
g_name
),
tracker
,
logger
,
eel
)
scheduler
=
Scheduler
(
controller
,
tracker
)
scheduler
=
Scheduler
(
controller
,
tracker
,
logger
)
def
delete_objects
(
scheduler
=
scheduler
,
controller
=
controller
,
tracker
=
tracker
):
scheduler
.
stopThread
()
...
...
@@ -90,27 +94,27 @@ def setRotationIntervall(hh,mm):
@
eel
.
expose
def
imageSample
(
sample_id
):
scheduler
.
addTask
(
Task
(
Task
.
RECORD_SAMPLE
,
sample_id
=
sample_id
,
priority
=
1
))
scheduler
.
addTask
(
Task
(
Task
.
RECORD_SAMPLE
,
sample_id
=
sample_id
,
priority
=
Task
.
NORMAL_PRIORITY
))
return
@
eel
.
expose
def
lightsOnCb
():
scheduler
.
addTask
(
Task
(
Task
.
LIGHTS_ON
,
priority
=
0
))
scheduler
.
addTask
(
Task
(
Task
.
LIGHTS_ON
,
priority
=
Task
.
HIGH_PRIORITY
))
return
@
eel
.
expose
def
lightsOffCb
():
scheduler
.
addTask
(
Task
(
Task
.
LIGHTS_OFF
,
priority
=
0
))
scheduler
.
addTask
(
Task
(
Task
.
LIGHTS_OFF
,
priority
=
Task
.
HIGH_PRIORITY
))
return
@
eel
.
expose
def
pickupSample
(
sample_id
):
scheduler
.
addTask
(
Task
(
Task
.
PICKUP_SAMPLE
,
sample_id
=
sample_id
,
priority
=
1
))
scheduler
.
addTask
(
Task
(
Task
.
PICKUP_SAMPLE
,
sample_id
=
sample_id
,
priority
=
Task
.
NORMAL_PRIORITY
))
return
@
eel
.
expose
def
putSample
(
target_slot
):
scheduler
.
addTask
(
Task
(
Task
.
PUT_SAMPLE
,
to_slot
=
target_slot
,
priority
=
1
))
scheduler
.
addTask
(
Task
(
Task
.
PUT_SAMPLE
,
to_slot
=
target_slot
,
priority
=
Task
.
NORMAL_PRIORITY
))
return
@
eel
.
expose
...
...
scripts/centralCtrl.py
View file @
0434cf0c
...
...
@@ -54,15 +54,15 @@ class CentralCtrl(object):
# Automatically launch the CV thread/process
AUTO_CV
=
False
def
__init__
(
self
,
camera
,
robot
,
peripherals
,
sample_tracker
,
gui
,
analyzer
=
None
):
def
__init__
(
self
,
camera
,
robot
,
peripherals
,
sample_tracker
,
logger
,
gui
):
super
(
CentralCtrl
,
self
).
__init__
()
#instantiate components
self
.
_camera
=
camera
self
.
_robot
=
robot
self
.
_peripherals
=
peripherals
self
.
_tracker
=
sample_tracker
self
.
_logger
=
logger
self
.
_gui
=
gui
self
.
_analyzer
=
analyzer
self
.
xy_speed
=
self
.
XY_SPEED
self
.
inDayCycle
=
False
...
...
@@ -70,7 +70,9 @@ class CentralCtrl(object):
try
:
self
.
_tracker
.
loadData
(
os
.
path
.
join
(
self
.
PATH_TO_DATA
,
"rack_data.pickle"
))
except
Exception
as
e
:
print
(
"could not load the rack data, samples must be added/loaded manually"
)
str
=
"could not load the rack data, samples must be added/loaded manually"
if
logger
is
not
None
:
logger
.
error
(
str
)
print
(
str
)
#setup lookup for slot coordinates
self
.
_slot_coords
=
[]
...
...
@@ -140,7 +142,9 @@ class CentralCtrl(object):
if
self
.
_checkXYCoordinates
(
x
,
y
):
self
.
_robot
.
moveXY
(
x
,
y
,
self
.
xy_speed
)
else
:
print
(
"something went wrong with the conversion indices to coordinates"
)
str
=
"something went wrong with the conversion indices to coordinates"
if
logger
is
not
None
:
logger
.
error
(
str
)
print
(
str
)
def
_pickupApproachSample
(
self
,
slot
):
x
,
y
=
self
.
_getCoordinates
(
slot
)
...
...
@@ -229,7 +233,9 @@ class CentralCtrl(object):
return
True
elif
self
.
_tracker
.
getSlotFromId
(
sample_id
)
is
not
None
:
#Only put down what it is holding if it can pickup something
print
(
f
"Putting back sample
{
sample
.
id
}
"
)
str
=
f
"Putting back sample
{
sample
.
id
}
"
if
logger
is
not
None
:
logger
.
info
(
str
)
print
(
str
)
ret
=
self
.
putSample
(
sample
.
home_slot
)
#If put sample fails pickup will not be attempted
ret
=
ret
and
self
.
pickupSample
(
sample_id
)
...
...
@@ -303,11 +309,6 @@ class CentralCtrl(object):
ret
=
ret
and
self
.
imageSample
(
auto_recording
=
True
)
#here one could queue the image processing and CV task
if
self
.
AUTO_CV
and
self
.
_analyzer
is
not
None
:
cv
=
threading
.
Thread
(
target
=
self
.
_analyzer
.
run
,
args
=
(
sample_id
))
cv
.
start
()
return
ret
and
self
.
putSample
(
self
.
_tracker
.
getSampleHome
(
sample_id
))
def
moveSample
(
self
,
sample_id
,
to
):
...
...
scripts/data/log.xml
deleted
100644 → 0
View file @
490eb311
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="../GUI/css/log.css"?>
<root>
<info>
<timestamp>
DD.MM.YYY, hh:mm:ss
</timestamp>
<message>
This is an info
</message>
</info>
<warn>
<timestamp>
DD.MM.YYY, hh:mm:ss
</timestamp>
<message>
This is a warning
</message>
</warn>
<error>
<timestamp>
DD.MM.YYY, hh:mm:ss
</timestamp>
<message>
This is an error
</message>
</error>
</root>
scripts/first_CV_test.py
View file @
0434cf0c
...
...
@@ -3,6 +3,7 @@ import numpy as np
import
glob
import
matplotlib.pyplot
as
plt
from
skimage
import
exposure
,
filters
,
morphology
,
measure
import
os
try
:
from
scripts.preprocessing
import
*
...
...
@@ -31,9 +32,27 @@ cv2.imshow('pre',out)
cv2
.
waitKey
(
0
)
cv2
.
destroyAllWindows
()
# %% Automatic preprocessing
#choose img
image_count
=
"0003"
sample_id
=
"brx1"
image_name
=
f
"raw_
{
image_count
}
.jpg"
# do stuff
data_path
=
os
.
path
.
join
(
"scripts/data/samples/"
,
sample_id
,
"RAW/"
,
image_name
)
image
=
roi
=
cv2
.
imread
(
data_path
)
p
=
Preprocrssor
()
out
,
roi
=
p
(
image
)
cv2
.
imshow
(
'img'
,
image
)
cv2
.
imshow
(
'ROI'
,
roi
)
cv2
.
imshow
(
'pre'
,
out
)
cv2
.
waitKey
(
0
)
cv2
.
destroyAllWindows
()
# %% Blob coloring
low
=
0.5
#0.45
high
=
0.
7
#0.7
low
=
0.
7
5
#0.45
high
=
0.
9
#0.7
pre
=
out
pre
=
exposure
.
adjust_gamma
(
pre
,
0.6
)
#pre = exposure.adjust_log(pre,0.1)
...
...
@@ -58,6 +77,21 @@ img_ov[idx,2]=0#img_ov[idx,1]/2
f
=
plt
.
figure
(
figsize
=
(
6
,
6
),
dpi
=
300
)
plt
.
imshow
(
img_ov
)
cv2
.
imshow
(
'overlay'
,
img_ov
)
cv2
.
imwrite
(
"img/pre
vious_roots
.png"
,
pre
)
cv2
.
imwrite
(
f
"img/pre
_
{
image_count
}
.png"
,
pre
)
cv2
.
waitKey
(
0
)
cv2
.
destroyAllWindows
()
# %% Overlay 3 preprocessing images
r
=
cv2
.
imread
(
"img/pre_0001.png"
)
g
=
cv2
.
imread
(
"img/pre_0002.png"
)
b
=
cv2
.
imread
(
"img/pre_0003.png"
)
overlay
=
r
.
copy
()
overlay
[:,:,
0
]
=
r
[:,:,
0
]
overlay
[:,:,
1
]
=
g
[:,:,
0
]
overlay
[:,:,
2
]
=
b
[:,:,
0
]
cv2
.
imshow
(
'overlay'
,
overlay
)
cv2
.
waitKey
(
0
)
cv2
.
destroyAllWindows
()
f
=
plt
.
figure
(
figsize
=
(
6
,
6
),
dpi
=
300
)
plt
.
imshow
(
overlay
)
scripts/logger.py
0 → 100644
View file @
0434cf0c
from
lxml
import
etree
as
ET
import
os
import
datetime
class
HTMLLogger
(
object
):
"""docstring for HTMLLogger."""
def
__init__
(
self
,
path_to_log
,
gui
,
log_name
=
'log.html'
):
super
(
HTMLLogger
,
self
).
__init__
()
self
.
path_to_log
=
path_to_log
self
.
log_name
=
log_name
self
.
_gui
=
gui
#check if log file is around
try
:
data
=
open
(
os
.
path
.
join
(
self
.
path_to_log
,
'log.html'
),
'r'
).
read
()
doc
=
ET
.
HTML
(
data
)
except
:
doc
=
None
if
doc
is
None
:
html
=
ET
.
Element
(
"html"
,
{
"lang"
:
"en"
,
"dir"
:
"ltr"
})
head
=
html
.
makeelement
(
"head"
)
head
.
append
(
head
.
makeelement
(
"meta"
,
{
"charset"
:
"utf-8"
}))
head
.
append
(
head
.
makeelement
(
"link"
,
{
"rel"
:
"stylesheet"
,
"href"
:
"css/log.css"
}))
html
.
append
(
head
)
body
=
html
.
makeelement
(
"body"
)
body
.
text
=
""
html
.
append
(
body
)
self
.
_writeHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
'log.html'
),
html
)
def
_openHtmlFile
(
self
,
path_to_file
):
try
:
data
=
open
(
path_to_file
,
'r'
).
read
()
doc
=
ET
.
HTML
(
data
)
except
:
doc
=
None
return
doc
def
_writeHtmlFile
(
self
,
path_to_file
,
html
):
with
open
(
path_to_file
,
"w"
)
as
html_file
:
html_file
.
write
(
ET
.
tostring
(
html
).
decode
(
"utf-8"
))
def
_addLogElement
(
self
,
root
,
str
,
log_priority
=
"info"
):
#create info element
elem
=
root
.
makeelement
(
"div"
,
{
"class"
:
log_priority
})
#create timestamp
timestamp
=
elem
.
makeelement
(
"div"
,
{
"class"
:
"timestamp"
})
timestamp
.
text
=
f
"
{
datetime
.
datetime
.
now
()
}
"
#create message
message
=
elem
.
makeelement
(
"div"
,
{
"class"
:
"message"
})
message
.
text
=
str
#add stuff
elem
.
append
(
timestamp
)
elem
.
append
(
message
)
root
.
insert
(
0
,
elem
)
def
_requireGUIupdate
(
self
):
self
.
_gui
.
log_update
()
def
info
(
self
,
str
):
#load HTML file
doc
=
self
.
_openHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
self
.
log_name
))
root
=
doc
[
1
]
#get body
#create info element
self
.
_addLogElement
(
root
,
str
)
#save file
self
.
_writeHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
'log.html'
),
doc
)
self
.
_requireGUIupdate
()
def
warn
(
self
,
str
):
#load HTML file
doc
=
self
.
_openHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
self
.
log_name
))
root
=
doc
[
1
]
#get body
#create warning element
self
.
_addLogElement
(
root
,
str
,
log_priority
=
"warn"
)
#save file
self
.
_writeHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
'log.html'
),
doc
)
self
.
_requireGUIupdate
()
def
error
(
self
,
str
):
#load HTML file
doc
=
self
.
_openHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
self
.
log_name
))
root
=
doc
[
1
]
#get body
#create info element
self
.
_addLogElement
(
root
,
str
,
log_priority
=
"error"
)
#save file
self
.
_writeHtmlFile
(
os
.
path
.
join
(
self
.
path_to_log
,
'log.html'
),
doc
)
self
.
_requireGUIupdate
()
scripts/preprocessing.py
View file @
0434cf0c
...
...
@@ -108,7 +108,7 @@ class Preprocrssor(object):
def
_loadConvolutionKernels
(
self
):
self
.
kernels
=
[]
# TODO: save kernel weights as pickle and load them properly
self
.
kernel_weights
=
[
1.0
,
0.8
,
0.5
,
0.
5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.8
,
1.0
,
0.8
,
0.5
,
0.
5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.8
]
self
.
kernel_weights
=
[
1.0
,
1.0
,
0.
8
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.8
,
1.0
,
1.0
,
1.0
,
0.
8
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.5
,
0.8
,
1.0
]
for
i
in
range
(
24
):
img
=
cv2
.
imread
(
f
"scripts/data/kernels/
{
i
}
.png"
)
...
...
@@ -189,11 +189,11 @@ class Preprocrssor(object):
def
extractROI
(
self
,
img
):
markers
=
self
.
getArUcoMarkers
(
img
)
#the true ROI starts 2mm below the top markers and ends
2
mm above the
#lower markers. The marker side is 11mm, thus the
2
/11. Here the vector
#the true ROI starts 2mm below the top markers and ends
3
mm above the
#lower markers. The marker side is 11mm, thus the
3
/11. Here the vector
#along the marker side is computed and then scaled to get to the true
#border
vector_scaling
=
(
1
+
2
/
11
)
vector_scaling
=
(
1
+
3
/
11
)
get_vector
=
lambda
f
,
t
:
t
-
f
scale_vector
=
lambda
v
:
vector_scaling
*
v
vector_addition
=
lambda
v
,
w
:
int
(
v
+
w
)
#int cast since those will be array indices
...
...
@@ -248,11 +248,11 @@ class Preprocrssor(object):
return
self
.
_minmax
(
out
)
def
__call__
(
self
,
img
):
out
=
self
.
extractROI
(
img
)
out
=
cv2
.
cvtColor
(
out
,
cv2
.
COLOR_BGR2GRAY
)
roi
=
self
.
extractROI
(
img
)
out
=
cv2
.
cvtColor
(
roi
,
cv2
.
COLOR_BGR2GRAY
)
#out = filters.gaussian(out,0)
out
=
self
.
enhanceFeatures
(
out
)
return
out
return
out
,
roi
################################################################################
### FUNC DEF ###################################################################
...
...
scripts/requirements.txt
View file @
0434cf0c
...
...
@@ -8,4 +8,6 @@ scipy==1.8.1
scripts==2.0
scikit-image
tifffile==2022.5.4
opencv-contrib-python
\ No newline at end of file
opencv-contrib-python
elementpath
lxml==4.9.0
scripts/rootExtraction.py
View file @
0434cf0c
...
...
@@ -538,7 +538,7 @@ class Root(Chain):
return
roots
,
data_img
# %% Example of code to test
img
=
cv2
.
imread
(
"img/
ideal_samples_refined.png"
)
#
previous_roots.png")#ideal_samples_refined.png")#root distance/dist_1.png")#
img
=
cv2
.
imread
(
"img/previous_roots.png"
)
#ideal_samples_refined.png")#root distance/dist_1.png")#
last_detection
=
None
;
#cv2.imread("img/root distance/dist_2.png")
bin_img
=
img
[:,:,
0
]
==
255
#convert to bool
...
...
scripts/sampleTracker.py
View file @
0434cf0c
...
...
@@ -51,12 +51,13 @@ class Sample(object):
class
SampleTracker
(
SampleTrackerBase
):
"""docstring for SampleTracker."""
def
__init__
(
self
,
number_of_slots
):
def
__init__
(
self
,
number_of_slots
,
logger
=
None
):
super
(
SampleTracker
,
self
).
__init__
()
self
.
_rack
=
[
None
]
*
number_of_slots
self
.
_gripper
=
None
self
.
_number_of_slots
=
number_of_slots
self
.
_logger
=
logger
def
_validTarget
(
self
,
target_slot
):
return
target_slot
is
not
None
and
0
<=
target_slot
<
self
.
_number_of_slots
...
...
@@ -64,7 +65,9 @@ class SampleTracker(SampleTrackerBase):
def
getSlotFromId
(
self
,
sample_id
):
slot
=
next
((
i
for
i
,
sample
in
enumerate
(
self
.
_rack
)
if
sample
is
not
None
and
sample
.
id
==
sample_id
),
None
)
if
slot
is
None
:
print
(
f
"No object with required id=
{
sample_id
}
found"
)
str
=
f
"No object with required id=
{
sample_id
}
found"
print
(
str
)
if
logger
is
not
None
:
logger
.
error
(
str
)
return
slot
...
...
@@ -121,7 +124,9 @@ class SampleTracker(SampleTrackerBase):
def
addSample
(
self
,
sample
,
target_slot
,
sample_overwrite
=
False
):
if
self
.
slotIsLoaded
(
target_slot
)
and
not
sample_overwrite
:
print
(
f
"Slot
{
target_slot
}
is already occupied"
)
str
=
f
"Slot
{
target_slot
}
is already occupied"
print
(
str
)
if
logger
is
not
None
:
logger
.
warn
(
str
)
return
False
sample
.
home_slot
=
target_slot
...
...
@@ -153,11 +158,17 @@ class SampleTracker(SampleTrackerBase):
if
self
.
slotIsLoaded
(
slot
)
and
not
holding
:
return
True
if
holding
and
warn
:
print
(
f
"Holding sample
{
self
.
_gripper
.
id
}
, can't pickup at target slot
{
slot
}
"
)
str
=
f
"Holding sample
{
self
.
_gripper
.
id
}
, can't pickup at target slot
{
slot
}
"
if
logger
is
not
None
:
logger
.
warn
(
str
)
print
(
str
)
elif
warn
:
print
(
f
"Target slot
{
slot
}
is empty, can't pick up anything"
)
str
=
f
"Target slot
{
slot
}
is empty, can't pick up anything"
if
logger
is
not
None
:
logger
.
warn
(
str
)
print
(
str
)
elif
warn
:
print
(
f
"target slot
{
slot
}
is invalid"
)
str
=
f
"target slot
{
slot
}
is invalid"
if
logger
is
not
None
:
logger
.
warn
(
str
)
print
(
str
)