Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion jsk_robot_common/jsk_robot_startup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,16 +302,28 @@ flowchart TB

Tweet message with description and image

* `/google_chat_ros/send/goal` (`google_chat_ros/SendMessageActionGoal`)

Send google chat message with description and image.

### Parameters

* `~sender_address` (String)

Sender address

* `~receiver_address` (String)

Receiver address

* `~google_chat_space` (String)

Receiver Google Chat space name

* `~google_chat_tmp_image_dir` (String)

Directory where images are temporarily stored for google_chat_ros

## launch/safe_teleop.launch

This launch file provides a set of nodes for safe teleoperation common to mobile robots. Robot-specific nodes such as `/joy`, `/teleop` or `/cable_warning` must be included in the teleop launch file for each robot, such as [safe_teleop.xml for PR2](https://github.com/jsk-ros-pkg/jsk_robot/blob/master/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml) or [safe_teleop.xml for fetch](https://github.com/jsk-ros-pkg/jsk_robot/blob/master/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml).
Expand Down
27 changes: 27 additions & 0 deletions jsk_robot_common/jsk_robot_startup/launch/smach_to_mail.launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<launch>
<arg name="use_mail" default="true" />
<arg name="use_twitter" default="true" />
<arg name="use_google_chat" default="true" />
<arg name="email_sender_address" default="" />
<arg name="email_receiver_address" default="" />
<arg name="google_chat_space" default="" />
<arg name="namespace" default="smach_to_mail" />

<group if="$(arg use_mail)" ns="$(arg namespace)">
<param name="sender_address" value="$(arg email_sender_address)" />
<param name="receiver_address" value="$(arg email_reveiver_address)" />
</group>
<group if="$(arg use_google_chat)" ns="$(arg namespace)">
<param name="google_chat_space" value="$(arg google_chat_space)" />
</group>

<node name="$(arg namespace)" pkg="jsk_robot_startup" type="smach_to_mail.py" output="screen">
<rosparam subst_value="true">
use_mail: $(arg use_mail)
use_twitter: $(arg use_twitter)
use_google_chat: $(arg use_google_chat)
</rosparam>
</node>

</launch>
1 change: 1 addition & 0 deletions jsk_robot_common/jsk_robot_startup/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<run_depend>dynamic_reconfigure</run_depend>
<run_depend>geometry_msgs</run_depend>
<run_depend>gmapping</run_depend>
<run_depend>google_chat_ros</run_depend>
<run_depend>jsk_recognition_msgs</run_depend>
<run_depend version_gte="2.2.7">jsk_topic_tools</run_depend>
<run_depend>message_runtime</run_depend>
Expand Down
54 changes: 51 additions & 3 deletions jsk_robot_common/jsk_robot_startup/scripts/smach_to_mail.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python

import actionlib
import base64
import cv2
import datetime
Expand All @@ -8,6 +9,11 @@
import sys

from cv_bridge import CvBridge
from google_chat_ros.msg import Card
from google_chat_ros.msg import Section
from google_chat_ros.msg import SendMessageAction
from google_chat_ros.msg import SendMessageActionGoal
from google_chat_ros.msg import WidgetMarkup
from jsk_robot_startup.msg import Email
from jsk_robot_startup.msg import EmailBody
from sensor_msgs.msg import CompressedImage
Expand All @@ -21,6 +27,9 @@ def __init__(self):
rospy.init_node('server_name')
# it should be 'smach_to_mail', but 'server_name'
# is the default name of smach_ros
self.use_mail = rospy.get_param("~use_mail", True)
self.use_twitter = rospy.get_param("~use_twitter", True)
self.use_google_chat = rospy.get_param("~use_google_chat", True)
self.pub_email = rospy.Publisher("email", Email, queue_size=10)
self.pub_twitter = rospy.Publisher("tweet", String, queue_size=10)
rospy.Subscriber(
Expand All @@ -38,7 +47,11 @@ def __init__(self):
else:
rospy.logerr("Please set rosparam {}/receiver_address".format(
rospy.get_name()))

if self.use_google_chat:
self.gchat_ac = actionlib.SimpleActionClient("/google_chat_ros/send", SendMessageAction)
self.chat_space = rospy.get_param("~google_chat_space")
self.gchat_image_dir = rospy.get_param("~google_chat_tmp_image_dir", "/tmp")
self._gchat_thread = None

def _status_cb(self, msg):
'''
Expand Down Expand Up @@ -125,8 +138,12 @@ def _status_cb(self, msg):
for x in self.smach_state_list[caller_id]:
rospy.loginfo(" - At {}, Active state is {}{}".format(x['TIME'], x['STATE'],
"({})".format(x['INFO']) if x['INFO'] else ''))
self._send_mail(self.smach_state_subject[caller_id], self.smach_state_list[caller_id])
self._send_twitter(self.smach_state_subject[caller_id], self.smach_state_list[caller_id])
if self.use_mail:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do not want to publish /email /twitter and /google_chat all time, how about write code to check if there are topic subscrribers, instead of asking users to manually set use_email manually.

if rospy.get_num_connections() > 0:
   rospy.publish("email")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the node for handling email, twitter, chatting should be launched all time, and if we want to suppress the notification, the demo code or this smach notification system should do it.

Copy link
Member

@tkmtnt7000 tkmtnt7000 Oct 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the node for handling email, twitter, chatting should be launched all time, and if we want to suppress the notification, the demo code or this smach notification system should do it.

I am for this idea. We set default notification interfaces when robot starts, but robots should switch to better interfaces dependent on demo or behavior.
For example, we can use info data for switching notification interface or embed the message which interface should be used in user_data, though I still don't know what is the better way so much..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I think this implementation is almost OK and the function of switching to better interfaces may be our near future work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about using dynamic reconfigure to change parameters dynamically?
rosparam only loaded at the beginning, so other node cannot change it.

or user_data can contain the info, too.
also I think we dont need to suppress the notification from the beginning.
When someone says it is annoying, we can think about it probably 🤣

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking into ways to set the importance of smach information

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about using dynamic reconfigure to change parameters dynamically?
rosparam only loaded at the beginning, so other node cannot change it.

or user_data can contain the info, too.
also I think we dont need to suppress the notification from the beginning.
When someone says it is annoying, we can think about it probably rofl

Sorry I overlooked this comment... and I've just created suppressing node by setting notification level dyn param. Please check #1648

self._send_mail(self.smach_state_subject[caller_id], self.smach_state_list[caller_id])
if self.use_twitter:
self._send_twitter(self.smach_state_subject[caller_id], self.smach_state_list[caller_id])
if self.use_google_chat:
self._send_google_chat(self.smach_state_subject[caller_id], self.smach_state_list[caller_id])
self.smach_state_list[caller_id] = None

def _send_mail(self, subject, state_list):
Expand Down Expand Up @@ -205,6 +222,37 @@ def _send_twitter(self, subject, state_list):
if len(text) > 1:
self.pub_twitter.publish(String(text))

def _send_google_chat(self, subject, state_list):
self.gchat_ac.wait_for_server()
goal = SendMessageActionGoal()
if subject:
goal.goal.text = subject
card = Card()
for i, x in enumerate(state_list):
section = Section()
widget = WidgetMarkup()
if 'DESCRIPTION' in x:
text = x['DESCRIPTION']
section.header = text
if 'IMAGE' in x and x['IMAGE']:
path = os.path.join(self.gchat_image_dir, 'smach_gchat_{}.png'.format(i))
with open(path, "wb") as f:
f.write(base64.b64decode(x['IMAGE']))
widget.image.localpath = path
if section.header and widget.image.localpath:
section.widgets.append(widget)
card.sections.append(section)
goal.goal.cards.append(card)
goal.goal.space = self.chat_space
if self._gchat_thread:
goal.goal.thread_name = self._gchat_thread
self.gchat_ac.send_goal(goal.goal)
self.gchat_ac.wait_for_result()
result = self.gchat_ac.get_result()
if not self._gchat_thread:
self._gchat_thread = result.message_result.thread_name
rospy.loginfo("Sending google chat messsage: {} to {} chat space".format(text, self.chat_space))
rospy.logdebug("Google Chat result: {}".format(self.gchat_ac.get_result()))

if __name__ == '__main__':
stm = SmachToMail()
Expand Down