From a79fe71e7a3b6db552e4e6f27db6355e49ec7d9f Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Thu, 5 May 2022 18:06:31 +0200 Subject: [PATCH] new functions - display latest svg image - updated demo commands - updated conversion topics --- cgv_connector.proto | 63 +++++--- cgv_connector_pb2.py | 275 +++++++++++++++++++++++++++------ main.py | 355 ++++++++++++++++++++++++++----------------- utils.py | 18 ++- 4 files changed, 500 insertions(+), 211 deletions(-) diff --git a/cgv_connector.proto b/cgv_connector.proto index ca2f8c4..0a7e924 100644 --- a/cgv_connector.proto +++ b/cgv_connector.proto @@ -1,5 +1,5 @@ -// cgv_connector.proto -// this file contains the messages that are exchanged between the cgv framework and the st ROS interface +// connector.proto +// this file contains the messages that are exchanged between the ROS connector and other systems syntax = "proto3"; @@ -10,22 +10,22 @@ message Object { // Position is object-center related message Position { - float x = 1; // in m - float y = 2; // in m - float z = 3; // height in m + double x = 1; // in m + double y = 2; // in m + double z = 3; // height in m } // 3D description of the object message Size { - float length = 1; // in m - float width = 2; // in m - float height = 3; // in m + double length = 1; // in m + double width = 2; // in m + double height = 3; // in m } message Orientation { - float x = 1; // normalized quaternion - float y = 2; - float z = 3; - float w = 4; + double x = 1; // normalized quaternion + double y = 2; + double z = 3; + double w = 4; } message Color { float r = 1; // 0..1 @@ -38,6 +38,9 @@ message Object { BIN = 2; ARM = 3; DROP_OFF_LOCATION = 4; + HUMAN = 5; + ROBOT = 6; + COLLABORATION_ZONE = 7; } string id = 1; @@ -46,26 +49,46 @@ message Object { Size size = 4; Orientation orientation = 5; Color color = 6; + bool active = 7; } -// the scene is stored within the ROS side and sent to the CGV framework +// the scene is stored within the ROS side and sent to clients message Scene { repeated Object objects = 1; } // the selection is done by the CGV framework and sent to ROS +// FIXME can be removed message Selection { string id = 1; // the id corresponds to an id of an Object in a Scene } -// vvv from rs vvv. -// Merged message to contain both pick and place in one -message MergedSelection { - string idRobot = 1; // the id corresponds to and id of the robot Object that should execute this operation - string idPick = 2; // the id corresponds to an id of the Object in a Scene to be picked - string idPlace = 3; // the id corresponds to an id of the Object in a Scene where the picked object shall be placed +message Command { + oneof msg { + PickAndPlace pickAndPlace = 1; + ConfigChange configChange = 2; + Evacuate evacuate = 3; + } +} + +message PickAndPlace { + string idRobot = 1; // id of the robot that should execute this operation + string idPick = 2; // id of the object in the scene to be picked + string idPlace = 3; // id of the location the picked object shall be placed. +} + +message ConfigChange { + string idCollaborationZone = 1; // id of collaboration zone to change + string idRobotNewOwner = 2; // id of robot that will become new owner } + +message Evacuate { + string idRobot = 1; // id of robot that need to move out of its currently defined collision objects + string idCollaborationZone = 2; // id of collaboration zone to evacuate +} + // Reachability of objects, as reported by MoveIt +// FIXME can be removed message Reachability { message ObjectReachability { string idObject = 1; // the id of the object to reach @@ -73,4 +96,4 @@ message Reachability { } string idRobot = 1; // the id of the robot arm repeated ObjectReachability objects = 2; // all objects reachable -} \ No newline at end of file +} diff --git a/cgv_connector_pb2.py b/cgv_connector_pb2.py index 2ae9aa9..9434e42 100644 --- a/cgv_connector_pb2.py +++ b/cgv_connector_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: cgv_connector.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -19,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( syntax='proto3', serialized_options=b'\n\030de.tudresden.inf.st.cetiP\001', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x13\x63gv_connector.proto\"\xc3\x03\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1a\n\x04type\x18\x02 \x01(\x0e\x32\x0c.Object.Type\x12\x1d\n\x03pos\x18\x03 \x01(\x0b\x32\x10.Object.Position\x12\x1a\n\x04size\x18\x04 \x01(\x0b\x32\x0c.Object.Size\x12(\n\x0borientation\x18\x05 \x01(\x0b\x32\x13.Object.Orientation\x12\x1c\n\x05\x63olor\x18\x06 \x01(\x0b\x32\r.Object.Color\x1a+\n\x08Position\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\x1a\x35\n\x04Size\x12\x0e\n\x06length\x18\x01 \x01(\x02\x12\r\n\x05width\x18\x02 \x01(\x02\x12\x0e\n\x06height\x18\x03 \x01(\x02\x1a\x39\n\x0bOrientation\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\x12\t\n\x01w\x18\x04 \x01(\x02\x1a(\n\x05\x43olor\x12\t\n\x01r\x18\x01 \x01(\x02\x12\t\n\x01g\x18\x02 \x01(\x02\x12\t\n\x01\x62\x18\x03 \x01(\x02\"E\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x42OX\x10\x01\x12\x07\n\x03\x42IN\x10\x02\x12\x07\n\x03\x41RM\x10\x03\x12\x15\n\x11\x44ROP_OFF_LOCATION\x10\x04\"!\n\x05Scene\x12\x18\n\x07objects\x18\x01 \x03(\x0b\x32\x07.Object\"\x17\n\tSelection\x12\n\n\x02id\x18\x01 \x01(\t\"C\n\x0fMergedSelection\x12\x0f\n\x07idRobot\x18\x01 \x01(\t\x12\x0e\n\x06idPick\x18\x02 \x01(\t\x12\x0f\n\x07idPlace\x18\x03 \x01(\t\"\x8d\x01\n\x0cReachability\x12\x0f\n\x07idRobot\x18\x01 \x01(\t\x12\x31\n\x07objects\x18\x02 \x03(\x0b\x32 .Reachability.ObjectReachability\x1a\x39\n\x12ObjectReachability\x12\x10\n\x08idObject\x18\x01 \x01(\t\x12\x11\n\treachable\x18\x02 \x01(\x08\x42\x1c\n\x18\x64\x65.tudresden.inf.st.cetiP\x01\x62\x06proto3' + serialized_pb=b'\n\x13\x63gv_connector.proto\"\x81\x04\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1a\n\x04type\x18\x02 \x01(\x0e\x32\x0c.Object.Type\x12\x1d\n\x03pos\x18\x03 \x01(\x0b\x32\x10.Object.Position\x12\x1a\n\x04size\x18\x04 \x01(\x0b\x32\x0c.Object.Size\x12(\n\x0borientation\x18\x05 \x01(\x0b\x32\x13.Object.Orientation\x12\x1c\n\x05\x63olor\x18\x06 \x01(\x0b\x32\r.Object.Color\x12\x0e\n\x06\x61\x63tive\x18\x07 \x01(\x08\x1a+\n\x08Position\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\x1a\x35\n\x04Size\x12\x0e\n\x06length\x18\x01 \x01(\x01\x12\r\n\x05width\x18\x02 \x01(\x01\x12\x0e\n\x06height\x18\x03 \x01(\x01\x1a\x39\n\x0bOrientation\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\x12\t\n\x01w\x18\x04 \x01(\x01\x1a(\n\x05\x43olor\x12\t\n\x01r\x18\x01 \x01(\x02\x12\t\n\x01g\x18\x02 \x01(\x02\x12\t\n\x01\x62\x18\x03 \x01(\x02\"s\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x42OX\x10\x01\x12\x07\n\x03\x42IN\x10\x02\x12\x07\n\x03\x41RM\x10\x03\x12\x15\n\x11\x44ROP_OFF_LOCATION\x10\x04\x12\t\n\x05HUMAN\x10\x05\x12\t\n\x05ROBOT\x10\x06\x12\x16\n\x12\x43OLLABORATION_ZONE\x10\x07\"!\n\x05Scene\x12\x18\n\x07objects\x18\x01 \x03(\x0b\x32\x07.Object\"\x17\n\tSelection\x12\n\n\x02id\x18\x01 \x01(\t\"}\n\x07\x43ommand\x12%\n\x0cpickAndPlace\x18\x01 \x01(\x0b\x32\r.PickAndPlaceH\x00\x12%\n\x0c\x63onfigChange\x18\x02 \x01(\x0b\x32\r.ConfigChangeH\x00\x12\x1d\n\x08\x65vacuate\x18\x03 \x01(\x0b\x32\t.EvacuateH\x00\x42\x05\n\x03msg\"@\n\x0cPickAndPlace\x12\x0f\n\x07idRobot\x18\x01 \x01(\t\x12\x0e\n\x06idPick\x18\x02 \x01(\t\x12\x0f\n\x07idPlace\x18\x03 \x01(\t\"D\n\x0c\x43onfigChange\x12\x1b\n\x13idCollaborationZone\x18\x01 \x01(\t\x12\x17\n\x0fidRobotNewOwner\x18\x02 \x01(\t\"8\n\x08\x45vacuate\x12\x0f\n\x07idRobot\x18\x01 \x01(\t\x12\x1b\n\x13idCollaborationZone\x18\x02 \x01(\t\"\x8d\x01\n\x0cReachability\x12\x0f\n\x07idRobot\x18\x01 \x01(\t\x12\x31\n\x07objects\x18\x02 \x03(\x0b\x32 .Reachability.ObjectReachability\x1a\x39\n\x12ObjectReachability\x12\x10\n\x08idObject\x18\x01 \x01(\t\x12\x11\n\treachable\x18\x02 \x01(\x08\x42\x1c\n\x18\x64\x65.tudresden.inf.st.cetiP\x01\x62\x06proto3' ) @@ -56,11 +56,26 @@ _OBJECT_TYPE = _descriptor.EnumDescriptor( serialized_options=None, type=None, create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='HUMAN', index=5, number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ROBOT', index=6, number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='COLLABORATION_ZONE', index=7, number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), ], containing_type=None, serialized_options=None, - serialized_start=406, - serialized_end=475, + serialized_start=422, + serialized_end=537, ) _sym_db.RegisterEnumDescriptor(_OBJECT_TYPE) @@ -75,21 +90,21 @@ _OBJECT_POSITION = _descriptor.Descriptor( fields=[ _descriptor.FieldDescriptor( name='x', full_name='Object.Position.x', index=0, - number=1, type=2, cpp_type=6, label=1, + number=1, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='y', full_name='Object.Position.y', index=1, - number=2, type=2, cpp_type=6, label=1, + number=2, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='z', full_name='Object.Position.z', index=2, - number=3, type=2, cpp_type=6, label=1, + number=3, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -106,8 +121,8 @@ _OBJECT_POSITION = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=205, - serialized_end=248, + serialized_start=221, + serialized_end=264, ) _OBJECT_SIZE = _descriptor.Descriptor( @@ -120,21 +135,21 @@ _OBJECT_SIZE = _descriptor.Descriptor( fields=[ _descriptor.FieldDescriptor( name='length', full_name='Object.Size.length', index=0, - number=1, type=2, cpp_type=6, label=1, + number=1, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='width', full_name='Object.Size.width', index=1, - number=2, type=2, cpp_type=6, label=1, + number=2, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='height', full_name='Object.Size.height', index=2, - number=3, type=2, cpp_type=6, label=1, + number=3, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -151,8 +166,8 @@ _OBJECT_SIZE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=250, - serialized_end=303, + serialized_start=266, + serialized_end=319, ) _OBJECT_ORIENTATION = _descriptor.Descriptor( @@ -165,28 +180,28 @@ _OBJECT_ORIENTATION = _descriptor.Descriptor( fields=[ _descriptor.FieldDescriptor( name='x', full_name='Object.Orientation.x', index=0, - number=1, type=2, cpp_type=6, label=1, + number=1, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='y', full_name='Object.Orientation.y', index=1, - number=2, type=2, cpp_type=6, label=1, + number=2, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='z', full_name='Object.Orientation.z', index=2, - number=3, type=2, cpp_type=6, label=1, + number=3, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='w', full_name='Object.Orientation.w', index=3, - number=4, type=2, cpp_type=6, label=1, + number=4, type=1, cpp_type=5, label=1, has_default_value=False, default_value=float(0), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -203,8 +218,8 @@ _OBJECT_ORIENTATION = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=305, - serialized_end=362, + serialized_start=321, + serialized_end=378, ) _OBJECT_COLOR = _descriptor.Descriptor( @@ -248,8 +263,8 @@ _OBJECT_COLOR = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=364, - serialized_end=404, + serialized_start=380, + serialized_end=420, ) _OBJECT = _descriptor.Descriptor( @@ -302,6 +317,13 @@ _OBJECT = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='active', full_name='Object.active', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -316,7 +338,7 @@ _OBJECT = _descriptor.Descriptor( oneofs=[ ], serialized_start=24, - serialized_end=475, + serialized_end=537, ) @@ -347,8 +369,8 @@ _SCENE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=477, - serialized_end=510, + serialized_start=539, + serialized_end=572, ) @@ -379,35 +401,86 @@ _SELECTION = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=512, - serialized_end=535, + serialized_start=574, + serialized_end=597, +) + + +_COMMAND = _descriptor.Descriptor( + name='Command', + full_name='Command', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='pickAndPlace', full_name='Command.pickAndPlace', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='configChange', full_name='Command.configChange', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='evacuate', full_name='Command.evacuate', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='msg', full_name='Command.msg', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=599, + serialized_end=724, ) -_MERGEDSELECTION = _descriptor.Descriptor( - name='MergedSelection', - full_name='MergedSelection', +_PICKANDPLACE = _descriptor.Descriptor( + name='PickAndPlace', + full_name='PickAndPlace', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='idRobot', full_name='MergedSelection.idRobot', index=0, + name='idRobot', full_name='PickAndPlace.idRobot', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='idPick', full_name='MergedSelection.idPick', index=1, + name='idPick', full_name='PickAndPlace.idPick', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='idPlace', full_name='MergedSelection.idPlace', index=2, + name='idPlace', full_name='PickAndPlace.idPlace', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, @@ -425,8 +498,86 @@ _MERGEDSELECTION = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=537, - serialized_end=604, + serialized_start=726, + serialized_end=790, +) + + +_CONFIGCHANGE = _descriptor.Descriptor( + name='ConfigChange', + full_name='ConfigChange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='idCollaborationZone', full_name='ConfigChange.idCollaborationZone', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='idRobotNewOwner', full_name='ConfigChange.idRobotNewOwner', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=792, + serialized_end=860, +) + + +_EVACUATE = _descriptor.Descriptor( + name='Evacuate', + full_name='Evacuate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='idRobot', full_name='Evacuate.idRobot', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='idCollaborationZone', full_name='Evacuate.idCollaborationZone', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=862, + serialized_end=918, ) @@ -464,8 +615,8 @@ _REACHABILITY_OBJECTREACHABILITY = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=691, - serialized_end=748, + serialized_start=1005, + serialized_end=1062, ) _REACHABILITY = _descriptor.Descriptor( @@ -502,8 +653,8 @@ _REACHABILITY = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=607, - serialized_end=748, + serialized_start=921, + serialized_end=1062, ) _OBJECT_POSITION.containing_type = _OBJECT @@ -517,12 +668,27 @@ _OBJECT.fields_by_name['orientation'].message_type = _OBJECT_ORIENTATION _OBJECT.fields_by_name['color'].message_type = _OBJECT_COLOR _OBJECT_TYPE.containing_type = _OBJECT _SCENE.fields_by_name['objects'].message_type = _OBJECT +_COMMAND.fields_by_name['pickAndPlace'].message_type = _PICKANDPLACE +_COMMAND.fields_by_name['configChange'].message_type = _CONFIGCHANGE +_COMMAND.fields_by_name['evacuate'].message_type = _EVACUATE +_COMMAND.oneofs_by_name['msg'].fields.append( + _COMMAND.fields_by_name['pickAndPlace']) +_COMMAND.fields_by_name['pickAndPlace'].containing_oneof = _COMMAND.oneofs_by_name['msg'] +_COMMAND.oneofs_by_name['msg'].fields.append( + _COMMAND.fields_by_name['configChange']) +_COMMAND.fields_by_name['configChange'].containing_oneof = _COMMAND.oneofs_by_name['msg'] +_COMMAND.oneofs_by_name['msg'].fields.append( + _COMMAND.fields_by_name['evacuate']) +_COMMAND.fields_by_name['evacuate'].containing_oneof = _COMMAND.oneofs_by_name['msg'] _REACHABILITY_OBJECTREACHABILITY.containing_type = _REACHABILITY _REACHABILITY.fields_by_name['objects'].message_type = _REACHABILITY_OBJECTREACHABILITY DESCRIPTOR.message_types_by_name['Object'] = _OBJECT DESCRIPTOR.message_types_by_name['Scene'] = _SCENE DESCRIPTOR.message_types_by_name['Selection'] = _SELECTION -DESCRIPTOR.message_types_by_name['MergedSelection'] = _MERGEDSELECTION +DESCRIPTOR.message_types_by_name['Command'] = _COMMAND +DESCRIPTOR.message_types_by_name['PickAndPlace'] = _PICKANDPLACE +DESCRIPTOR.message_types_by_name['ConfigChange'] = _CONFIGCHANGE +DESCRIPTOR.message_types_by_name['Evacuate'] = _EVACUATE DESCRIPTOR.message_types_by_name['Reachability'] = _REACHABILITY _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -579,12 +745,33 @@ Selection = _reflection.GeneratedProtocolMessageType('Selection', (_message.Mess }) _sym_db.RegisterMessage(Selection) -MergedSelection = _reflection.GeneratedProtocolMessageType('MergedSelection', (_message.Message,), { - 'DESCRIPTOR' : _MERGEDSELECTION, +Command = _reflection.GeneratedProtocolMessageType('Command', (_message.Message,), { + 'DESCRIPTOR' : _COMMAND, + '__module__' : 'cgv_connector_pb2' + # @@protoc_insertion_point(class_scope:Command) + }) +_sym_db.RegisterMessage(Command) + +PickAndPlace = _reflection.GeneratedProtocolMessageType('PickAndPlace', (_message.Message,), { + 'DESCRIPTOR' : _PICKANDPLACE, + '__module__' : 'cgv_connector_pb2' + # @@protoc_insertion_point(class_scope:PickAndPlace) + }) +_sym_db.RegisterMessage(PickAndPlace) + +ConfigChange = _reflection.GeneratedProtocolMessageType('ConfigChange', (_message.Message,), { + 'DESCRIPTOR' : _CONFIGCHANGE, + '__module__' : 'cgv_connector_pb2' + # @@protoc_insertion_point(class_scope:ConfigChange) + }) +_sym_db.RegisterMessage(ConfigChange) + +Evacuate = _reflection.GeneratedProtocolMessageType('Evacuate', (_message.Message,), { + 'DESCRIPTOR' : _EVACUATE, '__module__' : 'cgv_connector_pb2' - # @@protoc_insertion_point(class_scope:MergedSelection) + # @@protoc_insertion_point(class_scope:Evacuate) }) -_sym_db.RegisterMessage(MergedSelection) +_sym_db.RegisterMessage(Evacuate) Reachability = _reflection.GeneratedProtocolMessageType('Reachability', (_message.Message,), { diff --git a/main.py b/main.py index ccb658b..92152b6 100644 --- a/main.py +++ b/main.py @@ -3,6 +3,8 @@ import datetime import queue import threading import time +import base64 +import flask import dash from dash import dcc @@ -16,8 +18,14 @@ import cgv_connector_pb2 import utils external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] - -MQTT_SERVER = 'localhost' +fixed_svg_filename = "ros3rag/ros3rag.placeB/images/2022-05-04T10-19-30-9155.svg" +fixed_svg_filename = "2022-05-04T10-19-30-9155.svg" +# fixed_svg_filename = "" +image_directory = '/data/git/jastadd/ros3rag/ros3rag.placeB/images/' +static_image_route = '/static/' + +MQTT_SERVER = '192.168.0.122' +# MQTT_SERVER = 'localhost' mqttc = mqtt.Client() # mqtt client connected? @@ -41,22 +49,30 @@ commands = { 'send-place-b-rewind': ('place-b/rewind', '1'), 'send-place-b-start': ('coordinating/rag-b/command', 'start'), 'send-place-b-exit': ('place-b/exit', '1'), - 'send-place-a-demo-objRed-blue': ('place-a/demo/move/objectRed1/blue', '1'), - 'send-place-a-demo-objRed-red': ('place-a/demo/move/objectRed1/red', '1'), - 'send-place-b-demo-objRed-red': ('place-b/demo/move/objectRed1/red', '1'), + # 'send-place-a-demo-objRed-blue': ('place-a/demo/move/objectRed1/blue', '1'), + # 'send-place-a-demo-objRed-red': ('place-a/demo/move/objectRed1/red', '1'), + # 'send-place-b-demo-objRed-red': ('place-b/demo/move/objectRed1/red', '1'), + + 'send-place-b-demo-initial_scene': ('demo/initial_scene', '1'), + 'send-place-b-demo-arm1-active': ('demo/arm1/active', '1'), + 'send-place-b-demo-arm1-inactive': ('demo/arm1/inactive', '1'), + 'send-place-b-demo-arm2-active': ('demo/arm2/active', '1'), + 'send-place-b-demo-arm2-inactive': ('demo/arm2/inactive', '1'), + 'send-place-b-demo-big-blue-cz': ('demo/big-blue/cz', '1'), + 'send-place-b-demo-big-blue-g1': ('demo/big-blue/g1', '1'), 'send-coordinator-model': ('coordinator/model', '1'), 'send-coordinator-model-details': ('coordinator/model', 'details'), 'send-coordinator-exit': ('coordinator/exit', '1'), - 'send-place-a-robot-ctrl-up': ('ros-place-a/status', 'up'), - 'send-place-b-robot-ctrl-up': ('ros-place-b/status', 'up'), + # 'send-place-a-robot-ctrl-up': ('ros-place-a/status', 'up'), + # 'send-place-b-robot-ctrl-up': ('ros-place-b/status', 'up'), 'send-place-a-rag-up': ('rag-a/status', 'up'), 'send-place-b-rag-up': ('rag-b/status', 'up'), 'send-dummy-up': ('random/status', 'up'), - 'send-place-a-robot-ctrl-ready': ('ros-place-a/status', 'ready'), - 'send-place-b-robot-ctrl-ready': ('ros-place-b/status', 'ready'), + # 'send-place-a-robot-ctrl-ready': ('ros-place-a/status', 'ready'), + # 'send-place-b-robot-ctrl-ready': ('ros-place-b/status', 'ready'), 'send-place-a-rag-ready': ('rag-a/status', 'ready'), 'send-place-b-rag-ready': ('rag-b/status', 'ready'), 'send-dummy-ready': ('random/status', 'ready'), @@ -75,9 +91,13 @@ complex_commands = { } conversion_topics = { + '/ceti_cell_placeworld/scene/update': (cgv_connector_pb2.Scene(), utils.format_scene), + '/ceti_cell_2_placeworld/scene/update': (cgv_connector_pb2.Scene(), utils.format_scene), + '/moveit_sorting_controller/scene/update': (cgv_connector_pb2.Scene(), utils.format_scene), 'place-a/scene/update': (cgv_connector_pb2.Scene(), utils.format_scene), 'place-b/scene/update': (cgv_connector_pb2.Scene(), utils.format_scene), - 'place-b/command': (cgv_connector_pb2.MergedSelection(), utils.format_command), + 'place-b/command': (cgv_connector_pb2.Command(), utils.format_command), + '/ceti_cell_placeworld/command': (cgv_connector_pb2.Command(), utils.format_command), 'place-b/reachability/arm1': (cgv_connector_pb2.Reachability(), utils.format_reachability), 'place-b/reachability/arm2': (cgv_connector_pb2.Reachability(), utils.format_reachability), 'place-b/reachability/arm3': (cgv_connector_pb2.Reachability(), utils.format_reachability), @@ -85,6 +105,7 @@ conversion_topics = { bytes_topics = [ ] +svg_image_topic = 'place-b/model/svg/path' button_style_normal = {"marginRight": "15px"} button_style_exit = {**button_style_normal, "backgroundColor": "red", "color": "white"} @@ -92,146 +113,167 @@ textarea_style_normal = {'width': '100%', 'height': '200px', 'resize': 'vertical app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div([ - html.Div([ # First Row - html.Div([ # Column for place a - dcc.Textarea( - id='place-a-input-json', - placeholder='place-a-input-json', - value='{}', - style=textarea_style_normal - ), - html.Button('Send to place-a/scene/update', id='send-place-a-update'), - html.Div(id='hidden-div-scene-a', style={'display': 'none'}) - ], className="six columns"), - html.Div([ # Column for place b - dcc.Textarea( - id='place-b-input-json', - placeholder='place-b-input-json', - value='{}', - style=textarea_style_normal - ), - html.Button('Send to place-b/scene/update', id='send-place-b-update'), - html.Div(id='hidden-div-scene-b', style={'display': 'none'}), - html.Div([ # Row for reachability - html.Div([ # Column for reachability arm 1 + dcc.Tabs([ + dcc.Tab(label="Buttons and Log", children=[ + html.Div([ # First Row + html.Div([ # Column for place a dcc.Textarea( - id='place-b-reachability-1-json', - placeholder='place-b-reachability-1-json', + id='place-a-input-json', + placeholder='place-a-input-json', value='{}', style=textarea_style_normal ), - html.Button('Send to place-b/reachability/arm1', id='send-place-b-reachability-1-update'), + html.Button('Send to place-a/scene/update', id='send-place-a-update'), + html.Div(id='hidden-div-scene-a', style={'display': 'none'}) ], className="six columns"), - html.Div([ # Column for reachability arm 2 + html.Div([ # Column for place b dcc.Textarea( - id='place-b-reachability-2-json', - placeholder='place-b-reachability-2-json', + id='place-b-input-json', + placeholder='place-b-input-json', value='{}', style=textarea_style_normal ), - html.Button('Send to place-b/reachability/arm2', id='send-place-b-reachability-2-update'), + html.Button('Send to place-b/scene/update', id='send-place-b-update'), + html.Div(id='hidden-div-scene-b', style={'display': 'none'}), + html.Div([ # Row for reachability + html.Div([ # Column for reachability arm 1 + dcc.Textarea( + id='place-b-reachability-1-json', + placeholder='place-b-reachability-1-json', + value='{}', + style=textarea_style_normal + ), + html.Button('Send to place-b/reachability/arm1', id='send-place-b-reachability-1-update'), + ], className="six columns"), + html.Div([ # Column for reachability arm 2 + dcc.Textarea( + id='place-b-reachability-2-json', + placeholder='place-b-reachability-2-json', + value='{}', + style=textarea_style_normal + ), + html.Button('Send to place-b/reachability/arm2', id='send-place-b-reachability-2-update'), + ], className="six columns"), + ], className='row', style={'marginTop': '15px'}), ], className="six columns"), - ], className='row', style={'marginTop': '15px'}), - ], className="six columns"), - ], className='row', style={'display': 'none'}), - # dcc.Markdown("---"), - html.Div([ # Row for commands - html.Div([ # Column for commands of place b - html.H3("Coordinator"), - # html.Div([ # Row for commands coordinator - html.Button('Model', id='send-coordinator-model', style=button_style_normal), - html.Button('Model (Details)', id='send-coordinator-model-details', style=button_style_normal), - html.Button('Exit', id='send-coordinator-exit', style=button_style_exit), - # ], className='row'), - # html.Div([ # Row for commands up - html.Button('Robot Control A Up', id='send-place-a-robot-ctrl-up', style=button_style_normal), - html.Button('Robot Control B Up', id='send-place-b-robot-ctrl-up', style=button_style_normal), - html.Button('RAG A Up', id='send-place-a-rag-up', style=button_style_normal), - html.Button('RAG B Up', id='send-place-b-rag-up', style=button_style_normal), - html.Button('Dummy Up', id='send-dummy-up', style=button_style_normal), - # ], className='row'), - # html.Div([ # Row for commands ready - html.Button('Robot Control A Ready', id='send-place-a-robot-ctrl-ready', style=button_style_normal), - html.Button('Robot Control B Ready', id='send-place-b-robot-ctrl-ready', style=button_style_normal), - html.Button('RAG A Ready', id='send-place-a-rag-ready', style=button_style_normal), - html.Button('RAG B Ready', id='send-place-b-rag-ready', style=button_style_normal), - html.Button('Dummy Ready', id='send-dummy-ready', style=button_style_normal), - # ], className='row'), - ], className="four columns"), - html.Div([ # Column for commands of place a - html.H3("Commands Place A"), - html.Button('Model', id='send-place-a-model', style=button_style_normal), - html.Button('Model (Details)', id='send-place-a-model-details', style=button_style_normal), - html.Button('Rewind', id='send-place-a-rewind', style=button_style_normal), - html.Button('Start', id='send-place-a-start', style=button_style_normal), - html.Button('Exit', id='send-place-a-exit', style=button_style_exit), - html.Button('obj-Red -> Red', id='send-place-a-demo-objRed-red', style=button_style_normal), - html.Button('obj-Red -> Blue', id='send-place-a-demo-objRed-blue', style=button_style_normal), - ], className="four columns"), - html.Div([ # Column for commands of place b - html.H3("Commands Place B"), - html.Button('Model', id='send-place-b-model', style=button_style_normal), - html.Button('Model (Details)', id='send-place-b-model-details', style=button_style_normal), - html.Button('Rewind', id='send-place-b-rewind', style=button_style_normal), - html.Button('Start', id='send-place-b-start', style=button_style_normal), - html.Button('Exit', id='send-place-b-exit', style=button_style_exit), - html.Button('obj-Red -> Red', id='send-place-b-demo-objRed-red', style=button_style_normal), - ], className="four columns"), - ], className='row'), - # dcc.Markdown("---"), - html.H2("Filtered MQTT Log"), - dcc.Textarea( - id='filtered-mqtt-log', - value="", - readOnly=True, - style={**textarea_style_normal, 'height': '400px', 'fontFamily': 'Consolas, monospace'} - ), - dcc.Checklist( - id='topics-to-filter', - options=[{'label': topic, 'value': topic} for topic in conversion_topics], - value=[topic for topic in conversion_topics], - labelStyle={'display': 'inline-block'} - ), - html.H2("MQTT Log"), - dcc.Textarea( - id='mqtt-log', - value="", - readOnly=True, - style={**textarea_style_normal, 'height': '400px', 'fontFamily': 'Consolas, monospace'} - ), - dcc.Checklist( - id="should-scroll-mqtt-log", - options=[{"label": "Auto-Scroll", "value": "Auto-Scroll"}], - value=["Auto-Scroll"], - labelStyle={"display": "inline-block"}, - ), - dcc.Checklist( - id="mqtt-connected", - options=[{"label": "MQTT connected?", "value": "yes", "disabled": True}], - value=[], - labelStyle={"display": "inline-block"}, - ), - html.Button('Clear log', id='clear-mqtt-log', style=button_style_normal), - dcc.Markdown("---"), - html.Div([ - html.P("Topic"), - dcc.Input(id='manual-mqtt-topic'), - html.P("Message"), - dcc.Input(id='manual-mqtt-message'), - # dcc.Textarea(id='manual-mqtt-message', style={'width': '50%', 'font-family': 'Consolas, monospace'}), - html.Button('Send', id='manual-mqtt-send') - ], className='row', style=dict(display='flex')), - - # -- Invisible elements -- - dcc.Location(id='url', refresh=False), - dcc.Interval( - id='every-1-second', - interval=1000, # in milliseconds - n_intervals=0 - ), - visdcc.Run_js(id='javascriptLog', run=""), - html.Div(id='hidden-div', style={'display': 'none'}) -]) + ], className='row', style={'display': 'none'}), + # dcc.Markdown("---"), + html.Div([ # Row for commands + html.Div([ # Column for commands of place b + html.H3("Coordinator"), + # html.Div([ # Row for commands coordinator + html.Button('Model', id='send-coordinator-model', style=button_style_normal), + html.Button('Model (Details)', id='send-coordinator-model-details', style=button_style_normal), + html.Button('Exit', id='send-coordinator-exit', style=button_style_exit), + # ], className='row'), + # html.Div([ # Row for commands up + # html.Button('Robot Control A Up', id='send-place-a-robot-ctrl-up', style=button_style_normal), + # html.Button('Robot Control B Up', id='send-place-b-robot-ctrl-up', style=button_style_normal), + html.Button('RAG A Up', id='send-place-a-rag-up', style=button_style_normal), + html.Button('RAG B Up', id='send-place-b-rag-up', style=button_style_normal), + html.Button('Dummy Up', id='send-dummy-up', style=button_style_normal), + # ], className='row'), + # html.Div([ # Row for commands ready + # html.Button('Robot Control A Ready', id='send-place-a-robot-ctrl-ready', style=button_style_normal), + # html.Button('Robot Control B Ready', id='send-place-b-robot-ctrl-ready', style=button_style_normal), + html.Button('RAG A Ready', id='send-place-a-rag-ready', style=button_style_normal), + html.Button('RAG B Ready', id='send-place-b-rag-ready', style=button_style_normal), + html.Button('Dummy Ready', id='send-dummy-ready', style=button_style_normal), + # ], className='row'), + ], className="four columns"), + html.Div([ # Column for commands of place a + html.H3("Commands Place A"), + html.Button('Model', id='send-place-a-model', style=button_style_normal), + html.Button('Model (Details)', id='send-place-a-model-details', style=button_style_normal), + html.Button('Rewind', id='send-place-a-rewind', style=button_style_normal), + html.Button('Start', id='send-place-a-start', style=button_style_normal), + html.Button('Exit', id='send-place-a-exit', style=button_style_exit), + # html.Button('obj-Red -> Red', id='send-place-a-demo-objRed-red', style=button_style_normal), + # html.Button('obj-Red -> Blue', id='send-place-a-demo-objRed-blue', style=button_style_normal), + ], className="four columns"), + html.Div([ # Column for commands of place b + html.H3("Commands Place B"), + html.Button('Model', id='send-place-b-model', style=button_style_normal), + html.Button('Model (Details)', id='send-place-b-model-details', style=button_style_normal), + html.Button('Rewind', id='send-place-b-rewind', style=button_style_normal), + html.Button('Start', id='send-place-b-start', style=button_style_normal), + html.Button('Exit', id='send-place-b-exit', style=button_style_exit), + # html.Button('obj-Red -> Red', id='send-place-b-demo-objRed-red', style=button_style_normal), + html.Button('initial_scene', id='send-place-b-demo-initial_scene', style=button_style_normal), + html.Button('arm1-active', id='send-place-b-demo-arm1-active', style=button_style_normal), + html.Button('arm1-inactive', id='send-place-b-demo-arm1-inactive', style=button_style_normal), + html.Button('arm2-active', id='send-place-b-demo-arm2-active', style=button_style_normal), + html.Button('arm2-inactive', id='send-place-b-demo-arm2-inactive', style=button_style_normal), + html.Button('big-blue-cz', id='send-place-b-demo-big-blue-cz', style=button_style_normal), + html.Button('big-blue-g1', id='send-place-b-demo-big-blue-g1', style=button_style_normal), + ], className="four columns"), + ], className='row'), + # dcc.Markdown("---"), + html.H2("Filtered MQTT Log"), + dcc.Textarea( + id='filtered-mqtt-log', + value="", + readOnly=True, + style={**textarea_style_normal, 'height': '400px', 'fontFamily': 'Consolas, monospace'} + ), + dcc.Checklist( + id='topics-to-filter', + options=[{'label': topic, 'value': topic} for topic in conversion_topics], + value=[topic for topic in conversion_topics], + labelStyle={'display': 'inline-block'} + ), + html.H2("MQTT Log"), + dcc.Textarea( + id='mqtt-log', + value="", + readOnly=True, + style={**textarea_style_normal, 'height': '400px', 'fontFamily': 'Consolas, monospace'} + ), + dcc.Checklist( + id="should-scroll-mqtt-log", + options=[{"label": "Auto-Scroll", "value": "Auto-Scroll"}], + value=["Auto-Scroll"], + labelStyle={"display": "inline-block"}, + ), + dcc.Checklist( + id="mqtt-connected", + options=[{"label": "MQTT connected?", "value": "yes", "disabled": True}], + value=[], + labelStyle={"display": "inline-block"}, + ), + html.Button('Clear log', id='clear-mqtt-log', style=button_style_normal), + dcc.Markdown("---"), + html.Div([ + html.P("Topic"), + dcc.Input(id='manual-mqtt-topic', style={"margin-left": "5px"}), + html.P("Message", style={"margin-left": "15px"}), + dcc.Input(id='manual-mqtt-message', style={"margin-left": "5px"}), + # dcc.Textarea(id='manual-mqtt-message', style={'width': '50%', 'font-family': 'Consolas, monospace'}), + html.Button('Send', id='manual-mqtt-send', style={"margin-left": "15px"}) + ], className='row', style=dict(display='flex')), + + # -- Invisible elements -- + dcc.Location(id='url', refresh=False), + dcc.Interval( + id='every-1-second', + interval=1000, # in milliseconds + n_intervals=0 + ), + visdcc.Run_js(id='javascriptLog', run=""), + html.Div(id='hidden-div', style={'display': 'none'}) + ]), # Tab "Buttons and Log" + dcc.Tab(label="SVG Model B", children=[ + html.Div([ + html.P("Name:"), + html.P(id='model-b-svg-name', style={"margin-left": "15px"}), + ], className='row', style=dict(display='flex')), + html.Div([ + html.Img(id='model-b-svg-img', src="/static/{}".format(fixed_svg_filename)) + ], style=dict(position='fixed', overflow='scroll', width='100%')), + # html.Img(src="data:image/svg;base64,{}".format(base64.b64encode(open(fixed_svg_filename, 'rb').read()).decode())) + ]) # Tab "SVG Model B" + ]) # Tabs +]) # Div @app.callback( @@ -339,15 +381,17 @@ def check_connection(_n_intervals): Output('mqtt-log', 'value'), Output('javascriptLog', 'run'), Output('topics-to-filter', 'options'), + Output('model-b-svg-img', 'src'), Input('every-1-second', 'n_intervals'), Input('clear-mqtt-log', 'n_clicks'), Input('topics-to-filter', 'options'), Input('topics-to-filter', 'value'), + Input('model-b-svg-img', 'src'), State('filtered-mqtt-log', 'value'), State('mqtt-log', 'value'), State('should-scroll-mqtt-log', 'value') ) -def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_filter, +def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_filter, previous_svg_img_src, filtered_value, value, should_scroll): """ Periodically update mqtt log @@ -355,18 +399,20 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_f :param (Input) clear_n_clicks: clear.n_clicks :param (Input) filter_options: displayed topics to show in filtered log :param (Input) topics_to_filter: topics to show in filtered log + :param (Input) previous_svg_img_src: previous 'src' of the svg showing latest model of site B :param (State) value: current content of mqtt log :param (State) filtered_value: current content of filtered mqtt log :param (State) should_scroll: checkbox value whether to scroll to the end after update :return: new content of mqtt log """ + new_svg_img_src = previous_svg_img_src ctx = dash.callback_context if not ctx.triggered: return dash.no_update trigger_id = ctx.triggered[0]['prop_id'].split('.')[0] if trigger_id == 'clear-mqtt-log': - return "", "", "", filter_options + return "", "", "", filter_options, new_svg_img_src if trigger_id == 'topics-to-filter': filtered_value = "" @@ -392,6 +438,9 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_f filtered_value = "" for msg in local_messages: topic_match, topic = utils.topic_match(topics_to_filter, msg) + if topic == svg_image_topic: + new_svg_img_src = '/static/' + utils.parse_log_msg(msg)[2] + print('found new svg: ' + new_svg_img_src) if topic_match: filtered_value += msg + "\n" if topic not in (option['label'] for option in filter_options): @@ -404,7 +453,7 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_f var textarea = document.getElementById('mqtt-log'); textarea.scrollTop = textarea.scrollHeight; ''' if should_scroll else "" - return filtered_value, value, log_cmd, filter_options + return filtered_value, value, log_cmd, filter_options, new_svg_img_src @app.callback( @@ -448,6 +497,26 @@ def send_manual(n_clicks, topic, message): return dash.no_update +@app.callback( + Output('model-b-svg-name', 'children'), + Input('model-b-svg-img', 'src'), +) +def update_svg_name(name): + return name + + +# Add a static image route that serves images from desktop +# Be *very* careful here - you don't want to serve arbitrary files +# from your computer or server +@app.server.route('{}<image_path>.svg'.format(static_image_route)) +def serve_image(image_path): + image_name = '{}.svg'.format(image_path) + print('{}/{}'.format(image_directory, image_name)) + # if image_name not in list_of_images: + # raise Exception('"{}" is excluded from the allowed static files'.format(image_path)) + return flask.send_from_directory(image_directory, image_name) + + def on_mqtt_connect(_client, _userdata, _flags, _rc, _properties=None): # Callback for mqtt client when connected print('\nConnected at ' + datetime.datetime.now().isoformat()) diff --git a/utils.py b/utils.py index b3751da..271200a 100644 --- a/utils.py +++ b/utils.py @@ -49,14 +49,24 @@ def topic_match(topics_to_filter, msg, last_match=True): def format_scene(scene: cgv_connector_pb2.Scene): result = "" for obj in scene.objects: - if obj.type == cgv_connector_pb2.Object.Type.BOX: + if obj.type != cgv_connector_pb2.Object.Type.DROP_OFF_LOCATION and obj.type != cgv_connector_pb2.Object.Type.UNKNOWN: pos = obj.pos - result += f"\n<obj {obj.id:15} at ({pos.x:6.2} {pos.y:6.2} {pos.z:6.2})>" + result += f"\n<{cgv_connector_pb2.Object.Type.Name(obj.type):20} {obj.id:15} at ({pos.x:6.2} {pos.y:6.2} {pos.z:6.2}) {obj.active}>" + # result += str(obj) + # result = scene return result -def format_command(command: cgv_connector_pb2.MergedSelection): - return f"<cmd by {command.idRobot} of {command.idPick} to {command.idPlace}>" +def format_command(command: cgv_connector_pb2.Command): + if command.HasField("pickAndPlace"): + pickAndPlace = command.pickAndPlace + return f"<PickAndPlace by {pickAndPlace.idRobot} of {pickAndPlace.idPick} to {pickAndPlace.idPlace}>" + if command.HasField("configChange"): + configChange = command.configChange + return f"<ConfigChange by {configChange.idRobotNewOwner} for {configChange.idCollaborationZone}>" + if command.HasField("evacuate"): + return f"<Evacuate by {command.evacuate.idRobot}>" + return "<unknown command>" def _get_reach_objects(r): -- GitLab