Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event based infrastructure state update #68

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -34,44 +34,38 @@ def __init__(self, map_name):
super().__init__('building_systems_visualizer')
self.get_logger().info('Building systems visualizer started...')

qos = QoSProfile(
map_qos = QoSProfile(
history=History.KEEP_LAST,
depth=1,
reliability=Reliability.RELIABLE,
durability=Durability.TRANSIENT_LOCAL)

marker_qos = QoSProfile(
history=History.KEEP_LAST,
depth=5,
reliability=Reliability.RELIABLE,
durability=Durability.TRANSIENT_LOCAL)

self.marker_pub = self.create_publisher(
MarkerArray,
'building_systems_markers',
qos_profile=qos)
qos_profile=marker_qos)

self.create_subscription(
BuildingMap,
'map', self.map_cb,
qos_profile=qos)

self.create_subscription(
DoorState, 'door_states',
self.door_cb,
qos_profile=qos_profile_system_default)

self.create_subscription(
LiftState,
'lift_states',
self.lift_cb,
qos_profile=qos_profile_system_default)
qos_profile=map_qos)

self.create_subscription(
RvizParam,
'rmf_visualization/parameters',
self.param_cb,
qos_profile=qos_profile_system_default)

self.initialized = False

# data obtained from BuildingMap
self.building_doors = {}
self.building_lifts = {}
self.door_to_level_name = {}

# name of the current map to display
self.map_name = map_name
Expand All @@ -81,9 +75,36 @@ def __init__(self, map_name):
self.door_states = {}
self.door_states[self.map_name] = {}

# markers currently being displayed
# door markers currently being displayed
self.active_markers = {}

def publish_rviz_markers(self, map_name):
marker_array = MarkerArray()
if map_name != self.map_name:
# deleting previously active door markers
for marker in self.active_markers.values():
marker.action = Marker.DELETE
marker_array.markers.append(marker)
self.active_markers = {}
if map_name in self.building_doors:
self.map_name = map_name
else:
self.marker_pub.publish(marker_array)
return

for msg in self.door_states[self.map_name].values():
marker = self.create_door_marker(msg)
text_marker = self.create_door_text_marker(msg)
self.active_markers[msg.door_name] = marker
self.active_markers[f'{msg.door_name}_text'] = text_marker
marker_array.markers.append(marker)
marker_array.markers.append(text_marker)
self.marker_pub.publish(marker_array)
for msg in self.lift_states.values():
marker_array.markers.append(self.create_lift_marker(msg))
marker_array.markers.append(self.create_lift_text_marker(msg))
self.marker_pub.publish(marker_array)

def create_door_marker(self, msg):
door_marker = Marker()
door_marker.header.frame_id = 'map'
Expand Down Expand Up @@ -162,18 +183,15 @@ def create_door_text_marker(self, msg):

return marker

def create_lift_marker(self, lift_name):
if lift_name not in self.building_lifts or \
lift_name not in self.lift_states:
return
def create_lift_marker(self, msg):
marker = Marker()
marker.header.frame_id = 'map'
marker.ns = lift_name
marker.ns = msg.lift_name
marker.id = 1
marker.type = Marker.CUBE
marker.action = Marker.MODIFY

lift = self.building_lifts[lift_name]
lift = self.building_lifts[msg.lift_name]
marker.pose.position.x = lift.ref_x
marker.pose.position.y = lift.ref_y
marker.pose.position.z = -0.5 # below lane markers
Expand All @@ -183,7 +201,7 @@ def create_lift_marker(self, lift_name):
marker.scale.y = lift.depth
marker.scale.z = 0.1

if self.lift_states[lift_name].door_state == 2: # lift door open
if msg.door_state == 2: # lift door open
marker.color.r = 0.50
marker.color.g = 0.70
marker.color.b = 0.50
Expand All @@ -192,29 +210,26 @@ def create_lift_marker(self, lift_name):
marker.color.g = 0.50
marker.color.b = 0.65

if self.lift_states[lift_name].current_floor != self.map_name or \
self.lift_states[lift_name].motion_state == 1 or \
self.lift_states[lift_name].motion_state == 2:
if msg.current_floor != self.map_name or \
msg.motion_state == 1 or \
msg.motion_state == 2:
# lift moving or not on current floor
marker.color.a = 0.2
else:
marker.color.a = 0.8

return marker

def create_lift_text_marker(self, lift_name):
if lift_name not in self.building_lifts or \
lift_name not in self.lift_states:
return
def create_lift_text_marker(self, msg):
marker = Marker()
marker.header.frame_id = 'map'
marker.ns = lift_name + '_text'
marker.ns = msg.lift_name + '_text'
marker.id = 1
marker.type = Marker.TEXT_VIEW_FACING
marker.action = Marker.MODIFY
marker.scale.z = 0.3

lift = self.building_lifts[lift_name]
lift = self.building_lifts[msg.lift_name]

marker.pose.position.z = 0.0
marker.pose.position.x = lift.ref_x + 0.4
Expand All @@ -225,18 +240,17 @@ def create_lift_text_marker(self, lift_name):
marker.color.g = 1.0
marker.color.b = 1.0
marker.color.a = 1.0
lift_state = self.lift_states[lift_name]
marker.text = "Lift:" + lift_name
if self.lift_states[lift_name].motion_state != 0 and \
self.lift_states[lift_name].motion_state != 3: # lift is moving
marker.text += "\n MovingTo:" + lift_state.destination_floor
marker.text = "Lift:" + msg.lift_name
if msg.motion_state != 0 and \
msg.motion_state != 3: # lift is moving
marker.text += "\n MovingTo:" + msg.destination_floor
else:
marker.text += "\n CurrentFloor:" + lift_state.current_floor
if lift_state.door_state == 0:
marker.text += "\n CurrentFloor:" + msg.current_floor
if msg.door_state == 0:
marker.text += "\n DoorState:Closed"
elif lift_state.door_state == 1:
elif msg.door_state == 1:
marker.text += "\n DoorState:Moving"
elif lift_state.door_state == 2:
elif msg.door_state == 2:
marker.text += "\n DoorState:Open"

return marker
Expand All @@ -254,79 +268,65 @@ def map_cb(self, msg):
self.door_states[level.name] = {}
for door in level.doors:
self.building_doors[level.name][door.name] = door
self.initialized = True
self.door_to_level_name[door.name] = level.name
self.init_subscriptions()

def init_subscriptions(self):
state_qos = QoSProfile(
history=History.KEEP_LAST,
depth=100,
reliability=Reliability.RELIABLE,
durability=Durability.VOLATILE)

self.create_subscription(
DoorState, 'door_states',
self.door_cb,
qos_profile=state_qos)

self.create_subscription(
LiftState,
'lift_states',
self.lift_cb,
qos_profile=state_qos)

def door_cb(self, msg):
if not self.initialized or \
msg.door_name not in self.building_doors[self.map_name]:
if msg.door_name not in self.door_to_level_name:
return

map_name = self.door_to_level_name[msg.door_name]

publish_marker = False
door_state = self.door_states[self.map_name]
door_state = self.door_states[map_name]
if msg.door_name not in door_state:
door_state[msg.door_name] = msg
publish_marker = True
publish_marker = self.map_name == map_name
else:
if msg.current_mode.value != \
door_state[msg.door_name].current_mode.value:
door_state[msg.door_name] = msg
publish_marker = True
publish_marker = self.map_name == map_name

if publish_marker:
marker_array = MarkerArray()
marker = self.create_door_marker(msg)
text_marker = self.create_door_text_marker(msg)
if marker is not None:
marker_array.markers.append(marker)
self.active_markers[msg.door_name] = marker
if text_marker is not None:
marker_array.markers.append(text_marker)
self.active_markers[f'{msg.door_name}_text'] = text_marker
self.marker_pub.publish(marker_array)
self.publish_rviz_markers(self.map_name)

def lift_cb(self, msg):
if not self.initialized:
if msg.lift_name not in self.building_lifts:
return
publish_marker = False

if msg.lift_name not in self.lift_states:
self.lift_states[msg.lift_name] = msg
publish_marker = True
self.publish_rviz_markers(self.map_name)
else:
stored_state = self.lift_states[msg.lift_name]
if msg.current_floor != stored_state.current_floor or \
msg.motion_state != stored_state.motion_state or \
msg.door_state != stored_state.door_state:
self.lift_states[msg.lift_name] = msg
publish_marker = True
self.publish_rviz_markers(self.map_name)

if publish_marker:
marker_array = MarkerArray()
marker = self.create_lift_marker(msg.lift_name)
text_marker = self.create_lift_text_marker(msg.lift_name)
if marker is not None:
marker_array.markers.append(marker)
if text_marker is not None:
marker_array.markers.append(text_marker)
self.marker_pub.publish(marker_array)

def param_cb(self, msg):
if not self.initialized or \
msg.map_name not in self.building_doors:
return

self.map_name = msg.map_name
marker_array = MarkerArray()
# deleting previously avtive door markers
for name, marker in self.active_markers.items():
if marker is not None:
marker.action = Marker.DELETE
marker_array.markers.append(marker)
self.active_markers = {}
self.marker_pub.publish(marker_array)

# clearing door states and lift states so that markers can be updated
self.door_states[self.map_name] = {}
self.lift_states = {}
self.publish_rviz_markers(msg.map_name)


def main(argv=sys.argv):
Expand Down
4 changes: 3 additions & 1 deletion rmf_visualization_rviz2_plugins/src/DoorPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ DoorPanel::DoorPanel(QWidget* parent)
: rviz_common::Panel(parent),
_requester_id(DoorPanelRequesterId)
{
const auto default_qos =
rclcpp::SystemDefaultsQoS().durability_volatile().keep_last(100).reliable();
_node = std::make_shared<rclcpp::Node>(_requester_id + "_node");
_door_state_sub = _node->create_subscription<DoorState>(
DoorStateTopicName, 10, [&](DoorState::UniquePtr msg)
DoorStateTopicName, default_qos, [&](DoorState::UniquePtr msg)
{
door_state_callback(std::move(msg));
});
Expand Down
10 changes: 7 additions & 3 deletions rmf_visualization_rviz2_plugins/src/LiftPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ LiftPanel::LiftPanel(QWidget* parent)
: rviz_common::Panel(parent),
_session_id(LiftPanelSessionId)
{
const auto default_qos =
rclcpp::SystemDefaultsQoS().durability_volatile().keep_last(100).reliable();
const auto transient_qos =
rclcpp::SystemDefaultsQoS().transient_local().keep_last(100).reliable();
_node = std::make_shared<rclcpp::Node>(_session_id + "_node");
_lift_state_sub = _node->create_subscription<LiftState>(
LiftStateTopicName, 10, [&](LiftState::UniquePtr msg)
LiftStateTopicName, default_qos, [&](LiftState::UniquePtr msg)
{
lift_state_callback(std::move(msg));
});
_lift_request_pub = _node->create_publisher<LiftRequest>(
LiftRequestTopicName, rclcpp::QoS(10));
LiftRequestTopicName, transient_qos);
_adapter_lift_request_pub = _node->create_publisher<LiftRequest>(
AdapterLiftRequestTopicName, rclcpp::QoS(10));
AdapterLiftRequestTopicName, transient_qos);

create_layout();
create_connections();
Expand Down
Loading