Closed lsiebels closed 2 years ago
The current state of the seerep server does not give multiple warn_levels for health. There is just one. Do we need to extend Seerep or how will the log level be collected? @jarkenau @pbrozi @mklpiening
The different log levels are needed for the health status row as it has been designed so far. If we cannot get this data and it is not foreseen that it will be available from SEEREP at a later date, we will have to reconsider the pop-up and the presentation in the table.
@pbrozi Is there any other data that we cannot obtain as we would need it or is the rest covered by SEEREP apart from the calculation of the average?
The rest should be covered by SEEREP.
Hi, sry for not responding. We initially imagined something else when we thought about the health status, but i like your approach much better. I'll then implement the health status you described with n entries to allow extensions in the future. So make sure that the types you want to access exist.
I'll additionally keep the warn level and warn message to be used as notifications. These messages will then contain assembled sentences with recommendations for actions. I thunk it would also be useful to show these messages (if they exist) in the popup)
@mklpiening How did you imagine the health status? We have simply assumed that a plant can have multiple statuses because, theoretically, a plant needs to be watered and can have a nutrient deficit. 😄
This is our current state as we have imagined the table with the beds and the average health status. If you click on an entry, the table with the corresponding plants of the bed appears. The table is the same. As Gerrit has already mentioned, we need to explain the letters somewhere. The explanation of the status is done as a pop-up by hovering over the respective letter.
Yes, your idea makes sense. We initially (before the revisited mockups) thought of the deficiencies being analyzed by our Pipeline with just the combined result being put as a warn message into seerep. This would allow us to plan actions and send them to the gardeners (as one combined warn level). Our approach, however, would also create kind of a black box around the analysis part, which may be ok for unexpericned garneners, but unacceptable for experienced ones.
So lets go your way :)
@mklpiening @fmarahre @pbrozi Another question in general about the naming of health statuses nutrient deficiency
.
Can a deficiency be good? Actually, nutrients deficiency should be good and the loglevel danger
would be something like "deficiency detected".
{
"type":"Nutrient",
"loglevel": "1 || 2 || 3"
}
Alright, I now added the mock data to the seerep dummy in a way, that we dont need to change the proto files, since seerep will be used for way more project than just our plant mapping ;)
I thereby left some fields intentionally empty or just did not add them, to simulate a computation that has not been finished yet - so you just need to show N/A here ^^
I also added some warn messages with further information for you to test the notification widget.
In terms of loglevel: the status good (1) to bad (3) is always meant from the gardeners perspective. So, while i also called it "nutrients" now, a good "nutrient deficiency" would mean, that the plant has little to no deficiency. This applies to all types of health status ("diseases", "nutrients", "water"). Also keep in mind, that we might add new health measurement types after your project has finished :)
@mklpiening Thanks a lot! 😎
@fmarahre The way it is displayed now, it doesn't seem to me that it can be expanded very well if there are more than three messages. It is designed for exactly three messages, isn't it? Then we would have to look at how to keep the display basically the same, but the table doesn't look weird with more than three badges.
Maybe make it configurable by the user, which status to show, if it isn't too complicated by now (in difference table columns for example). The remaining health measurements could then be shown in the popup, as it was in the mockup ;)
A good idea, we'll take a closer look. 🤓
@pbrozi Do you need more information or can it be implemented like this? If you need/want to change something in the JSON structure we have proposed so far, please give us feedback.
I remade the api as described in the issue in 7f4e955eb8e11fb6f4ce23b181d21e7d8ba8411c.
Some things:
beds
endpoint with the current dummy data 600 gRPC requests (100 per bed) and ~20 sec.Managed to make it stream the response for beds
As far as I know, location should be the id of the bed the plant is in. The bed-id can be obtained from the database.
@Anafabula @lucaslootalot The location should probably only be included with the plants, so that their latitude
and longitude
is known to display them on the map. I created a python script to convert the local coordinates, it is currently on the feat/plant-location-to-ll
Branch. To use the script, the.ply
files of the plants have to be download.
https://github.com/naturerobots/HSOS-SEP-PlantMap-2022/blob/696f5e3a29b6ab3ed47af46fb6b33d1c0f0d6821/django/conversions/transform_coordinates.py#L28-L34
For the beds it doesn't really make sense to include a location, the use of a primary key makes even less sense.
@jarkenau If the coordinates are sent only with the plants, then we cannot display anything on the map until a bed is selected.
Also, if the location is the ID, I would leave that out as well.
Then you need some sort of array with all location from plants of a bed right? Could you give @Anafabula some hints of a useful structure for that?
The plants simply as an array with the coordinates for each bed.
However, the ID/location is needed to establish a relation between the markers on the map with the bed/plant entry in the table.
{
"beds":[
{
"id":1234,
"plant":"Beans",
"variety":"White Beans",
"plants":"http://localhost:3000/companies/{company_id}/gardens/{garden_id}/beds/1234/plants",
"soil_humidty":70,
"harvest":"1 week",
"yield":100,
"health":[
{
"type":"Watering",
"loglevel":1
},
{
"type":"Nutrient Deficiency",
"loglevel":3
},
{
"type":"Disease Detection",
"loglevel":2
}
],
"plant_coords":[
{
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
]
}
]
}
So actually like this? :grin:
"plant_coords":[
{
"id": 5
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"id": 7
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"id": 9
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
]
You can also add the bed ID to the plant coordinates. But then it must be the ID of the bed.
{
"beds":[
{
"id":1234,
"plant":"Beans",
"variety":"White Beans",
"plants":"http://localhost:3000/companies/{company_id}/gardens/{garden_id}/beds/1234/plants",
"soil_humidty":70,
"harvest":"1 week",
"yield":100,
"health":[
{
"type":"Watering",
"loglevel":1
},
{
"type":"Nutrient Deficiency",
"loglevel":3
},
{
"type":"Disease Detection",
"loglevel":2
}
],
"plant_coords":[
{
"id": 1234,
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"id": 1234,
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
{
"id": 1234,
"lat": "52.31703822683545",
"lng": "7.630155086517335"
},
]
}
]
}
The individual beds are streamed now, then it would look like this.
{
"id":1234,
"plant":"Beans",
"variety":"White Beans",
"plants":"http://localhost:3000/companies/{company_id}/gardens/{garden_id}/beds/1234/plants",
"soil_humidty":70,
"harvest":"1 week",
"yield":100,
"health":[
{
"type":"Watering",
"loglevel":1
},
{
"type":"Nutrient Deficiency",
"loglevel":3
},
{
"type":"Disease Detection",
"loglevel":2
}
],
"plant_coords":[
{
"id":1234,
"lat":"52.31703822683545",
"lng":"7.630155086517335"
},
{
"id":1234,
"lat":"52.31703822683545",
"lng":"7.630155086517335"
},
{
"id":1234,
"lat":"52.31703822683545",
"lng":"7.630155086517335"
}
]
}
Finally got this working for beds
at least.
Does the plants
endpoint need the coordinates as well? Since the pointcloud needed for the coordinates and the measurement for the rest are separate entries in the same list with different IDs idk how to find the pointcloud and measurement that belong to each other.
Is the id with the coordinates necessary? When you are iterating over the list, you probably also have the bed object the list belongs to, right? And it's the same for all entries.
{
"id": 1,
"plant": "mangold",
"variety": "Lucullus",
"plants": "http://localhost:8000/companies/1/gardens/1/beds/1/plants",
"soil_humidty": 0.65,
"harvest": "6 week",
"yield": 451.1587423100285,
"health": [
{
"type": "water",
"loglevel": 1
},
{
"type": "nutrients",
"loglevel": 1
},
{
"type": "diseases",
"loglevel": 1
}
],
"plant_coords": [
{
"id": 1,
"lat": 52.317118374885005,
"lon": 7.630641577424838
},
{
"id": 1,
"lat": 52.317126563936476,
"lon": 7.63064192673892
},
{
"id": 1,
"lat": 52.31712302636109,
"lon": 7.630644944039591
},
{
"id": 1,
"lat": 52.31711997964676,
"lon": 7.63064731009461
},
{
"id": 1,
"lat": 52.31712704329051,
"lon": 7.63063668011326
},
{
"id": 1,
"lat": 52.31712378354576,
"lon": 7.630640134315161
},
{
"id": 1,
"lat": 52.31712132599438,
"lon": 7.630639366710759
},
{
"id": 1,
"lat": 52.317120526347296,
"lon": 7.630643721642699
},
{
"id": 1,
"lat": 52.31712956545423,
"lon": 7.630638593156597
},
{
"id": 1,
"lat": 52.31712744848517,
"lon": 7.630632615014217
},
{
"id": 1,
"lat": 52.31712970346751,
"lon": 7.6306337274749865
},
{
"id": 1,
"lat": 52.31713088086202,
"lon": 7.630629429031545
},
{
"id": 1,
"lat": 52.31713306869006,
"lon": 7.6306323772616125
},
{
"id": 1,
"lat": 52.317132238143095,
"lon": 7.630635885026056
},
{
"id": 1,
"lat": 52.317135574785546,
"lon": 7.630632900208948
},
{
"id": 1,
"lat": 52.317133874274475,
"lon": 7.6306279124885075
},
{
"id": 1,
"lat": 52.317136018238564,
"lon": 7.630627624787251
},
{
"id": 1,
"lat": 52.31713649371331,
"lon": 7.630624918934556
},
{
"id": 1,
"lat": 52.31713860499551,
"lon": 7.630625582818097
},
{
"id": 1,
"lat": 52.31713836176265,
"lon": 7.630630193253661
},
{
"id": 1,
"lat": 52.31714137213531,
"lon": 7.630627615585415
},
{
"id": 1,
"lat": 52.317139281590286,
"lon": 7.630621477632502
},
{
"id": 1,
"lat": 52.31714197526744,
"lon": 7.630622819624421
},
{
"id": 1,
"lat": 52.317142630980015,
"lon": 7.630618189745578
},
{
"id": 1,
"lat": 52.31714439973367,
"lon": 7.630624162514495
},
{
"id": 1,
"lat": 52.31714502480713,
"lon": 7.630619321029704
},
{
"id": 1,
"lat": 52.317147296770386,
"lon": 7.630621315776511
},
{
"id": 1,
"lat": 52.31714564428777,
"lon": 7.630615467562744
},
{
"id": 1,
"lat": 52.31713485770003,
"lon": 7.630633316716556
},
{
"id": 1,
"lat": 52.317119309585074,
"lon": 7.630641707613764
},
{
"id": 1,
"lat": 52.31712554620787,
"lon": 7.630640460191728
},
{
"id": 1,
"lat": 52.317119309585074,
"lon": 7.630641707613764
},
{
"id": 1,
"lat": 52.317129860384526,
"lon": 7.630633846824412
}
]
}
Does the plants endpoint need the coordinates as well? Since the pointcloud needed for the coordinates and the measurement for the rest are separate entries in the same list with different IDs idk how to find the pointcloud and measurement that belong to each other.
Considering that it should also be possible to display the beds individually, I would say that the plants of Plants
Endpoint also hold the coordinates. I understand your question though, it feels a bit duplicated.
Is the id with the coordinates necessary? When you are iterating over the list, you probably also have the bed object the list belongs to, right? And it's the same for all entries.
The coordinates are not absolutely necessary. The markers can also be created with the ID of the bed. If you have a better idea, go for it.
Considering that it should also be possible to display the beds individually, I would say that the plants of
Plants
Endpoint also hold the coordinates. I understand your question though, it feels a bit duplicated.
It's not about it being duplicated. We get a list like
geometries: [
GeometryInfo {
name: "crop 29",
uuid: "e79b844a5f9e429ea84e1a9f5a700d40",
r#type: "pointcloud",
frame_id: "ground",
stamp: Some(
Timestamp {
seconds: 1626967568,
nanos: 0,
},
),
labels: [
"5cc606b4b4904f1aaae9516844d7ec38",
"b45b402cab6c47caba94176b5767c16b",
],
},
GeometryInfo {
name: "crop 29",
uuid: "4476adeaf36541408c042c71753b746b",
r#type: "measurement",
frame_id: "ground",
stamp: Some(
Timestamp {
seconds: 1626967568,
nanos: 0,
},
),
labels: [
"5cc606b4b4904f1aaae9516844d7ec38",
"b45b402cab6c47caba94176b5767c16b",
],
},
GeometryInfo {
name: "crop 30",
uuid: "f892521817554bf7a500e495b395e9ec",
r#type: "pointcloud",
frame_id: "ground",
stamp: Some(
Timestamp {
seconds: 1626967568,
nanos: 0,
},
),
labels: [
"_8dcb2a39d81c476db37b5a3077200245",
"b45b402cab6c47caba94176b5767c16b",
],
},
GeometryInfo {
name: "crop 30",
uuid: "fbeac53874034f3f8abe378ee495c875",
r#type: "measurement",
frame_id: "ground",
stamp: Some(
Timestamp {
seconds: 1626967568,
nanos: 0,
},
),
labels: [
"_8dcb2a39d81c476db37b5a3077200245",
"b45b402cab6c47caba94176b5767c16b",
],
},
GeometryInfo {
name: "crop 31",
uuid: "5162fef543f24b1b822533e5588bb8b9",
r#type: "pointcloud",
frame_id: "ground",
stamp: Some(
Timestamp {
seconds: 1626967568,
nanos: 0,
},
),
labels: [
"7c6ba0354bbe4cb6a1404002498c1c7d",
"8f460e87b27e4fb385e84f4a7dba677f",
],
}
]
With no ids indicating for sure which pointcloud and measurement belong to each other. Idk if "name" is definite.
You can customize the structure as you think is easiest for you to generate the JSON. Also you can drop the ID from the plant coordinates.
The bed ID at the Plants
endpoint is not needed, because we know the ID of the bed.
The end point for all beds in a garden as well as the end point for all plants in a bed must be adjusted.
We would define the health states as follows:
Health types
Log levels
Example for the beds end point:
Example for the end point of all plants in a bed: