From d89749c3a92abae859d253667f1d12b8a4ae3b6b Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Thu, 25 Jun 2020 20:14:51 +0900 Subject: [PATCH 01/44] switch to use jsk_maps multi_map_server --- .../jsk_fetch_startup/launch/fetch_bringup.launch | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch index 30e29fd74fd..4d280e75c2d 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch @@ -125,7 +125,7 @@ - + @@ -135,7 +135,9 @@ - + + + From 7e1ec927a5d45c554e6b6107875583101140224b Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Tue, 7 Jul 2020 18:10:41 +0900 Subject: [PATCH 02/44] use keepout for jsk_maps --- jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch index 4d280e75c2d..1f93cb6eb50 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch @@ -7,6 +7,7 @@ + @@ -126,6 +127,7 @@ + From 6d604efbaf30d7b24b3fadd6238bc1ff452176a4 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Thu, 9 Jul 2020 19:49:25 +0900 Subject: [PATCH 03/44] set use_keepout false in fetch_bringup.launch --- jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch index 1f93cb6eb50..456f5f41a84 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch @@ -137,7 +137,7 @@ - + From dfee9bdbb8c04c1120c9e7dce836b08a457c36cd Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Tue, 14 Jul 2020 20:09:33 +0900 Subject: [PATCH 04/44] [jsk_robot_startup] Add common safe teleop launch --- .../launch/safe_teleop.launch | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch new file mode 100644 index 00000000000..52df1fd2563 --- /dev/null +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6bc526eecdbeb23164420c7839e54ca8bf10460b Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Tue, 14 Jul 2020 20:10:02 +0900 Subject: [PATCH 05/44] Use common safe teleop for PR2 --- .../jsk_pr2_move_base/safe_teleop.xml | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml index 4a0b06075bf..9bb6c1341ef 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml @@ -19,39 +19,27 @@ - - - - - - - - - - - - - + + + + + - - - - - - - - - - + + + + + + + + + Date: Tue, 14 Jul 2020 20:10:10 +0900 Subject: [PATCH 06/44] Use common safe teleop for fetch --- .../launch/fetch_bringup.launch | 2 - .../jsk_fetch_startup/launch/fetch_teleop.xml | 96 +++++++++---------- .../jsk_fetch_startup/scripts/warning.py | 6 +- 3 files changed, 51 insertions(+), 53 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch index 30e29fd74fd..5ab3184574e 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_bringup.launch @@ -14,8 +14,6 @@ - - diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index dbe9a8382ec..0c2ee4fd11f 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -1,4 +1,5 @@ + @@ -11,13 +12,6 @@ - - - - - + + + + + + + + inflater: + inflation_radius: 1.0 # 0.7 + cost_scaling_factor: 3.0 # 25.0 default 10, increasing factor decrease the cost value + obstacles: + min_obstacle_height: 0.05 + # default 5 (http://wiki.ros.org/navigation/Tutorials/Navigation%20Tuning%20Guide) + update_frequency: 10.0 + footprint_padding: 0.05 + + + + + + + + + inflater: + inflation_radius: 1.0 # 0.7 + cost_scaling_factor: 3.0 # 25.0 default 10, increasing factor decrease the cost value + obstacles: + min_obstacle_height: 0.05 + # default 5 (http://wiki.ros.org/navigation/Tutorials/Navigation%20Tuning%20Guide) + update_frequency: 10.0 + footprint_padding: 0.05 + + + + + + + + + @@ -45,49 +84,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inflater: - inflation_radius: 1.0 # 0.7 - cost_scaling_factor: 3.0 # 25.0 default 10, increasing factor decrease the cost value - obstacles: - min_obstacle_height: 0.05 - # default 5 (http://wiki.ros.org/navigation/Tutorials/Navigation%20Tuning%20Guide) - update_frequency: 10.0 - footprint_padding: 0.05 - - diff --git a/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py b/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py index 196823dc37e..81e97c478e6 100755 --- a/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py +++ b/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py @@ -89,10 +89,12 @@ def __init__(self): self.base_breaker = rospy.ServiceProxy('base_breaker', BreakerCommand) # self.battery_sub = rospy.Subscriber("battery_state", BatteryState, self.battery_callback, queue_size = 1) - self.cmd_vel_sub = rospy.Subscriber("base_controller/command", Twist, self.cmd_vel_callback, queue_size = 1) + self.cmd_vel_sub = rospy.Subscriber("base_controller/command_unchecked", Twist, self.cmd_vel_callback, queue_size = 1) self.robot_state_sub = rospy.Subscriber("robot_state", RobotState, self.robot_state_callback, queue_size = 1) self.diagnostics_status_sub = rospy.Subscriber("diagnostics", DiagnosticArray, self.diagnostics_status_callback, queue_size = 1) self.undock_sub = rospy.Subscriber("/undock/status", GoalStatusArray, self.undock_status_callback) + # + self.cmd_vel_pub = rospy.Publisher("base_controller/command", Twist, queue_size=1) def undock_status_callback(self, msg): for status in msg.status_list: @@ -131,6 +133,8 @@ def cmd_vel_callback(self, msg): sound.play(4) # play builtin sound Boom! time.sleep(5) self.base_breaker(BreakerCommandRequest(enable=True)) + else: + self.cmd_vel_pub.publish(msg) ## self.twist_msgs = msg From d6a439f94e0d7b02c54ea96f9fd7921e45b37c2f Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Tue, 14 Jul 2020 21:01:24 +0900 Subject: [PATCH 07/44] Update README for safe teleop system --- jsk_fetch_robot/jsk_fetch_startup/README.md | 4 ++-- jsk_pr2_robot/README.md | 4 ++++ jsk_robot_common/jsk_robot_startup/README.md | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/README.md b/jsk_fetch_robot/jsk_fetch_startup/README.md index 5a673d6d877..21a7c40e2dc 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/README.md +++ b/jsk_fetch_robot/jsk_fetch_startup/README.md @@ -24,9 +24,9 @@ sudo mv rockmongo-1.1.7 /var/www/html/rockmongo ### Teleoperation -Below is a flow of commands from Joystick sent to base controller: +For the JSK safe teleop system, please see [data flow diagram of safe_teleop.launch](https://github.com/jsk-ros-pkg/jsk_robot/tree/master/jsk_robot_common/jsk_robot_startup#launchsafe_teleoplaunch) -![safe_teleop_system](https://user-images.githubusercontent.com/19769486/37566992-dab73142-2b03-11e8-94bc-4d1914c967b0.png) +The numbers assigned to the joystick are as follows. ![joystick_numbered](https://user-images.githubusercontent.com/19769486/28101905-889e9cc2-6706-11e7-9981-5704cc29f2b3.png) ![joystick_numbered2](https://user-images.githubusercontent.com/19769486/28101906-88b5f20a-6706-11e7-987c-d94e64ac2cc1.png) diff --git a/jsk_pr2_robot/README.md b/jsk_pr2_robot/README.md index 996b45d1da9..22bbf8ffa92 100644 --- a/jsk_pr2_robot/README.md +++ b/jsk_pr2_robot/README.md @@ -1,6 +1,10 @@ jsk_pr2_robot ============= +## Teleoperation + +For the JSK safe teleop system, please see [data flow diagram of safe_teleop.launch](https://github.com/jsk-ros-pkg/jsk_robot/tree/master/jsk_robot_common/jsk_robot_startup#launchsafe_teleoplaunch) + ![teleop_command](images/pr2_teleop_command.png) diff --git a/jsk_robot_common/jsk_robot_startup/README.md b/jsk_robot_common/jsk_robot_startup/README.md index 7affbb03c59..23aa3e89bb2 100644 --- a/jsk_robot_common/jsk_robot_startup/README.md +++ b/jsk_robot_common/jsk_robot_startup/README.md @@ -72,3 +72,10 @@ This script sets initial pose with relative pose from specified TF frame by publ ### Subscribing Topics * `/amcl_pose` (`geometry_msgs/PoseWithcovariancestamped`) + + +## 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). + +![jsk_safe_teleop](https://user-images.githubusercontent.com/19769486/87421378-d0ea9680-c611-11ea-90ae-17cfc729e039.png) From a7790850e7558635446a8ffeb0a2b20a6bd1a8e5 Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Wed, 15 Jul 2020 14:48:10 +0900 Subject: [PATCH 08/44] Use the name of the safe teleop input topics with args --- .../jsk_fetch_startup/launch/fetch_teleop.xml | 22 ++++++++------ .../jsk_pr2_move_base/safe_teleop.xml | 18 ++++++----- .../launch/safe_teleop.launch | 30 +++++++++++-------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index 0c2ee4fd11f..d1336a38197 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -1,5 +1,4 @@ - @@ -29,7 +28,19 @@ - + + + + + + + + + @@ -62,13 +73,6 @@ footprint_padding: 0.05 - - - diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml index 9bb6c1341ef..1df37440242 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml @@ -22,7 +22,18 @@ + + + + + + + @@ -33,13 +44,6 @@ - - - + + + + + + - + - - + + - + + args="/teleop/cmd_vel /teleop/cmd_vel/safe $(arg teleop_topic)"> + args="/joy 'm.buttons[9]==1' $(arg teleop_topic) /joy 'm.buttons[9]==0' /teleop/cmd_vel/safe"> - + - - + + - + + args="/joy 'm.buttons[10]==1' /teleop/cmd_vel $(arg navigation_topic) 'True' $(arg navigation_topic)"> + args="/base_controller/command_unchecked /input_vel/safe $(arg navigation_topic) /teleop/cmd_vel"> From 110805aa695a6de5598ae392f92f0ed6e3e6df0d Mon Sep 17 00:00:00 2001 From: iory Date: Fri, 4 Oct 2019 14:10:46 +0900 Subject: [PATCH 09/44] [jsk_robot_startup/util/mux_selector] Add wait option for topic --- .../jsk_robot_startup/util/mux_selector.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py index 6639f915427..d14e0857db5 100755 --- a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py +++ b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py @@ -46,13 +46,23 @@ def gen_callback(expr, select, index): return (lambda m: callback(m, expr, select, index)) -def add_trigger(topic, expr, select, index): +def add_trigger(topic, expr, select, index, wait=False): topic_type, _, _ = rostopic.get_topic_type(topic) topic_class, _, _ = rostopic.get_topic_class(topic) - if(topic_type is None): - rospy.loginfo('%s is not published yet', topic) - return None + if topic_type is None: + if wait is False: + rospy.loginfo('%s is not published yet', topic) + return None + elif wait is True: + rate = rospy.Rate(1) + while not rospy.is_shutdown() and topic_type is None: + topic_type, _, _ = rostopic.get_topic_type(topic) + topic_class, _, _ = rostopic.get_topic_class(topic) + rospy.loginfo('waiting topic %s' % topic) + rate.sleep() + else: + raise ValueError('wait should be bool') if(topic_class is None): rospy.loginfo('%s is not builded yet', topic_type) @@ -69,14 +79,15 @@ def add_trigger(topic, expr, select, index): return sub -def update_trigger(conditions): +def update_trigger(conditions, wait=False): # setting triggers global subs for index in range(len(conditions)): if subs[index] is not None: continue cond = conditions[index] - subs[index] = add_trigger(cond[0],cond[1],cond[2],index) + subs[index] = add_trigger(cond[0],cond[1],cond[2],index, + wait=wait) if __name__ == "__main__": @@ -101,6 +112,7 @@ def update_trigger(conditions): deadtime = rospy.get_param('~patient', 0.5) freq = rospy.get_param('~frequency', 20.0) default_select = rospy.get_param('~default_select', None) + wait = rospy.get_param('~wait', False) mux_name_ = rospy.resolve_name('mux') rospy.wait_for_service(mux_name_+'/select') @@ -113,7 +125,7 @@ def update_trigger(conditions): # loop try: before = default_select - update_trigger(conditions) + update_trigger(conditions, wait=wait) looprate = rospy.Rate(freq) while not rospy.is_shutdown(): lockobj.acquire() From bc2b94ca643d62c68bf5addd2ee73eb4006cbac7 Mon Sep 17 00:00:00 2001 From: iory Date: Mon, 27 Jan 2020 09:49:31 +0900 Subject: [PATCH 10/44] [jsk_robot_startup/README.md] Add mux_selector.py's docs' --- jsk_robot_common/jsk_robot_startup/README.md | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/jsk_robot_common/jsk_robot_startup/README.md b/jsk_robot_common/jsk_robot_startup/README.md index 23aa3e89bb2..65f4810d07b 100644 --- a/jsk_robot_common/jsk_robot_startup/README.md +++ b/jsk_robot_common/jsk_robot_startup/README.md @@ -74,6 +74,44 @@ This script sets initial pose with relative pose from specified TF frame by publ * `/amcl_pose` (`geometry_msgs/PoseWithcovariancestamped`) +## util/mux_selector.py + +This node check and select mux input topic on condition of the specified topic. +This node takes three arguments for one topic. +The first one is the topic to be monitored. +When a message from this topic is received, it is assigned as a variable `m`. +If a condition specified as the second argument, +this node calls a service to select the topic specified as the third argument. + +### Usage + +``` +rosrun jsk_robot_startup mux_selector.py /joy1 'm.buttons[9]==1' /cmd_vel1 /joy2 'm.buttons[9]==1' /cmd_vel2 +``` + +### Parameters + +* `~patient` (Double, default: 0.5) + + Indicates the allowable range of the difference between the received topic time and the current time. + +* `~frequency` (Double, default: 20.0) + + Frequency of processing loop. + +* `~default_select` (String, default: `None`) + + Default topic name. + +* `~wait` (Bool, default: `False`) + + If wait is `True`, this node waits for the topic to be received. + +### Subscribing Topics + +The topic specified in the argument is subscribed. + + ## 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). From d632e409942b6ac229abfaeb5c7cc9e3409b25b3 Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Wed, 15 Jul 2020 17:26:50 +0900 Subject: [PATCH 11/44] mux_selector wait for input topics --- jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index a5c328a1719..68c7947e096 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -27,6 +27,7 @@ args="/joy 'm.buttons[9]==1' $(arg teleop_topic) /joy 'm.buttons[9]==0' /teleop/cmd_vel/safe"> + @@ -43,6 +44,7 @@ args="/joy 'm.buttons[10]==1' /teleop/cmd_vel $(arg navigation_topic) 'True' $(arg navigation_topic)"> + Date: Fri, 24 Jul 2020 17:11:01 +0900 Subject: [PATCH 12/44] Do not use multiple safe_teleop_base to reduce CPU load --- .../jsk_fetch_startup/launch/fetch_teleop.xml | 23 +---- jsk_robot_common/jsk_robot_startup/README.md | 2 +- .../launch/safe_teleop.launch | 83 ++++++++++++------- 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index d1336a38197..3989ff33ba4 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -20,7 +20,7 @@ joystick_teleop need to publish /teleop/cmd_vel/unsafe , see https://github.com/jsk-ros-pkg/jsk_robot/blob/master/jsk_fetch_robot/jsk_fetch_startup/README.md --> - + @@ -30,9 +30,10 @@ - + - + + - - - - - - - inflater: - inflation_radius: 1.0 # 0.7 - cost_scaling_factor: 3.0 # 25.0 default 10, increasing factor decrease the cost value - obstacles: - min_obstacle_height: 0.05 - # default 5 (http://wiki.ros.org/navigation/Tutorials/Navigation%20Tuning%20Guide) - update_frequency: 10.0 - footprint_padding: 0.05 - - diff --git a/jsk_robot_common/jsk_robot_startup/README.md b/jsk_robot_common/jsk_robot_startup/README.md index 65f4810d07b..59c25e700cc 100644 --- a/jsk_robot_common/jsk_robot_startup/README.md +++ b/jsk_robot_common/jsk_robot_startup/README.md @@ -116,4 +116,4 @@ The topic specified in the argument is subscribed. 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). -![jsk_safe_teleop](https://user-images.githubusercontent.com/19769486/87421378-d0ea9680-c611-11ea-90ae-17cfc729e039.png) +![JSK teleop_base system](https://user-images.githubusercontent.com/19769486/88371623-608d0380-cdcf-11ea-859e-f3eccac120b3.png) diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index 68c7947e096..fa1094a6f64 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -3,54 +3,81 @@ - + - + + - + + + + + + + + + + + + - + - + + args="/teleop/cmd_vel /teleop/cmd_vel/safe /teleop/cmd_vel/unsafe"> + args="/joy 'm.buttons[9]==1' /teleop/cmd_vel/unsafe /joy 'm.buttons[9]==0' /teleop/cmd_vel/safe"> - - - - - - + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + From 23567c5028e99caee86e467a6862a8447b26064a Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Fri, 24 Jul 2020 21:36:08 +0900 Subject: [PATCH 13/44] [mux_selector.py] Add rosparam to set type of rostopic --- .../jsk_robot_startup/util/mux_selector.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py index d14e0857db5..cef4f7c7022 100755 --- a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py +++ b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py @@ -12,11 +12,16 @@ When a message from this topic is received, it is assigned as a variable `m`. If a condition specified as the second argument, this node calls a service to select the topic specified as the third argument. + +If the type of the monitored topic is unknown, you can set the type with `~topics` rosparam. +`~topics` should be the list like +[{'name': '/joy1', 'type': 'sensor_msgs/Joy'}, {'name': '/joy2', 'type': 'sensor_msgs/Joy'}, ...] """ import rospy import thread import sys +import roslib.message import rostopic from topic_tools.srv import MuxSelect import traceback @@ -47,8 +52,13 @@ def gen_callback(expr, select, index): def add_trigger(topic, expr, select, index, wait=False): - topic_type, _, _ = rostopic.get_topic_type(topic) - topic_class, _, _ = rostopic.get_topic_class(topic) + global topics + if topic in topics: + topic_type = topics[topic] + topic_class = roslib.message.get_message_class(topic_type) + else: + topic_type, _, _ = rostopic.get_topic_type(topic) + topic_class, _, _ = rostopic.get_topic_class(topic) if topic_type is None: if wait is False: @@ -91,11 +101,12 @@ def update_trigger(conditions, wait=False): if __name__ == "__main__": - global selects, subs + global selects, subs, topics global lockobj lockobj = thread.allocate_lock() selects = [] subs = [] + topics = {} # parse arguments conditions = [x for x in sys.argv[1:] if not ':=' in x] @@ -122,6 +133,10 @@ def update_trigger(conditions, wait=False): selects = [(None, rospy.Time(0))] * size subs = [None] * size + topic_list = rospy.get_param('~topics', []) + for topic in topic_list: + topics[topic['name']] = topic['type'] + # loop try: before = default_select From 925b5fcc33cc9f858e132b713c5bf3ddd8a04825 Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Fri, 24 Jul 2020 21:37:02 +0900 Subject: [PATCH 14/44] Allow unknown type topics as an input to safe_teleop.launch --- .../jsk_fetch_startup/launch/fetch_teleop.xml | 8 ++- .../launch/safe_teleop.launch | 53 +++++++------------ 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index 3989ff33ba4..2780433944e 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -33,7 +33,6 @@ - + + topics: + - name: /base_controller/cmd_vel + type: geometry_msgs/Twist + - name: /navigation/cmd_vel + type: geometry_msgs/Twist + diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index fa1094a6f64..68cfdda7142 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -6,7 +6,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + topics: + - name: /teleop/cmd_vel + type: geometry_msgs/Twist + + From 857cf00ee5bc838f76f8e5f4cc1ccdd4e6858132 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Fri, 24 Jul 2020 19:33:06 +0900 Subject: [PATCH 15/44] add base_controller_topic in jsk_robot_startup/launch/sate_teleop.launch --- .../jsk_robot_startup/launch/safe_teleop.launch | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index 68cfdda7142..ca2b700ca10 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -6,6 +6,7 @@ + - + + args="/base_controller/command_unchecked /teleop/cmd_vel $(arg navigation_topic) $(arg base_controller_topic)"> + args="/teleop/cmd_vel 'True' /teleop/cmd_vel $(arg navigation_topic) 'True' $(arg navigation_topic) $(arg base_controller_topic) 'True' $(arg base_controller_topic)"> From 78a56b15ca47d3eb64d6ddc40f62789e2b78d08e Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Fri, 24 Jul 2020 19:33:46 +0900 Subject: [PATCH 16/44] update jsk_pr2_move_base safe_teleop.xml for new jsk safe teleop system --- .../jsk_pr2_move_base/safe_teleop.xml | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml index 1df37440242..ba4c76e1e86 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml @@ -22,10 +22,11 @@ - - - - + + + + + + args="/teleop/joy_vel /joy_vel" /> - - - - - Date: Fri, 24 Jul 2020 19:48:48 +0900 Subject: [PATCH 17/44] update topic name for pr2_base_trajectory_action --- jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml index ba4c76e1e86..ab2fb7ab1e5 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml @@ -15,7 +15,7 @@ - + From cdbb80b01e06d697596828337dcdab7472f8f4e3 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Fri, 24 Jul 2020 22:05:17 +0900 Subject: [PATCH 18/44] move vel_type_selector rosparam into safe_teleop.launch --- jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml | 7 ------- .../jsk_robot_startup/launch/safe_teleop.launch | 6 +++++- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index 2780433944e..3b326c6662b 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -57,13 +57,6 @@ footprint_padding: 0.05 - - topics: - - name: /base_controller/cmd_vel - type: geometry_msgs/Twist - - name: /navigation/cmd_vel - type: geometry_msgs/Twist - diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index ca2b700ca10..937fd8c6d3e 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -59,10 +59,14 @@ - + topics: - name: /teleop/cmd_vel type: geometry_msgs/Twist + - name: $(arg navigation_topic) + type: geometry_msgs/Twist + - name: $(arg base_controller_topic) + type: geometry_msgs/Twist From c49f576037f7eb573220a03fd767b3ffdebcab1f Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Fri, 24 Jul 2020 23:16:40 +0900 Subject: [PATCH 19/44] fix topic name in jsk_pr2_startup/safe_teleop.xml --- jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml index ab2fb7ab1e5..67442a5aef4 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/safe_teleop.xml @@ -23,7 +23,7 @@ - + From d67c339e06f8300b5cb2fbaa363f8e69031a352e Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Sat, 17 Oct 2020 01:42:31 +0900 Subject: [PATCH 20/44] fix condition in mux_selector.py --- jsk_robot_common/jsk_robot_startup/util/mux_selector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py index cef4f7c7022..19320413903 100755 --- a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py +++ b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py @@ -152,7 +152,7 @@ def update_trigger(conditions, wait=False): else: next_topic = default_select try: - if before != next_topic and before is not None: + if not (before == next_topic or next_topic is None): mux_client(next_topic) except rospy.ServiceException, e: rospy.loginfo("Service did not process request: %s", str(e)) From 14b97f40fa6ec2af797b736640e6cbf3af03220b Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Sat, 17 Oct 2020 01:43:13 +0900 Subject: [PATCH 21/44] set vel_type_selector default None --- jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index 937fd8c6d3e..bebfd09689e 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -57,7 +57,8 @@ respawn="true" output="screen" machine="$(arg machine)" args="/teleop/cmd_vel 'True' /teleop/cmd_vel $(arg navigation_topic) 'True' $(arg navigation_topic) $(arg base_controller_topic) 'True' $(arg base_controller_topic)"> - + + topics: From 414a1ecbebf402ca6db89c6b82d956505c0c9ed6 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Sat, 17 Oct 2020 01:59:16 +0900 Subject: [PATCH 22/44] update safe teleop system image --- jsk_robot_common/jsk_robot_startup/README.md | 2 +- .../images/jsk_safe_teleop_system.png | Bin 0 -> 65303 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 jsk_robot_common/jsk_robot_startup/images/jsk_safe_teleop_system.png diff --git a/jsk_robot_common/jsk_robot_startup/README.md b/jsk_robot_common/jsk_robot_startup/README.md index 59c25e700cc..3666388ec3b 100644 --- a/jsk_robot_common/jsk_robot_startup/README.md +++ b/jsk_robot_common/jsk_robot_startup/README.md @@ -116,4 +116,4 @@ The topic specified in the argument is subscribed. 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). -![JSK teleop_base system](https://user-images.githubusercontent.com/19769486/88371623-608d0380-cdcf-11ea-859e-f3eccac120b3.png) +![JSK teleop_base system](images/jsk_safe_teleop_system.png) diff --git a/jsk_robot_common/jsk_robot_startup/images/jsk_safe_teleop_system.png b/jsk_robot_common/jsk_robot_startup/images/jsk_safe_teleop_system.png new file mode 100644 index 0000000000000000000000000000000000000000..870d1d45b4a4607370648c19344ec8c9bbc4bb3d GIT binary patch literal 65303 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 literal 0 HcmV?d00001 From d4514352b3a83413e4f7ad057e357ab2e2914eaf Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Fri, 27 Nov 2020 02:11:02 +0900 Subject: [PATCH 23/44] install jsk_demos from source for jsk_maps --- .travis.rosinstall | 6 +++++- .travis.rosinstall.kinetic | 4 ---- .travis.rosinstall.melodic | 4 ---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.travis.rosinstall b/.travis.rosinstall index 7aa482dc490..2c59362f0b8 100644 --- a/.travis.rosinstall +++ b/.travis.rosinstall @@ -1 +1,5 @@ -# see .travis.rosinstall.ROS_DISTRO +# see also .travis.rosinstall.ROS_DISTRO +- git: + local-name: jsk-ros-pkg/jsk_demos + uri: https://github.com/jsk-ros-pkg/jsk_demos.git + version: master diff --git a/.travis.rosinstall.kinetic b/.travis.rosinstall.kinetic index 33596fa568d..21b99e5f26e 100644 --- a/.travis.rosinstall.kinetic +++ b/.travis.rosinstall.kinetic @@ -21,10 +21,6 @@ - git: uri: https://github.com/ros-naoqi/nao_interaction.git local-name: ros-naoqi/nao_interaction -- git: - uri: https://github.com/tork-a/jsk_demos-release.git - local-name: jsk_maps - version: release/kinetic/jsk_maps # Need to wait for app_manager 1.1.1 for kinetic and later. For indigo, we could not expect newer releases..... # https://github.com/PR2/app_manager/issues/12 (Relerase request 1.1.1) - git: diff --git a/.travis.rosinstall.melodic b/.travis.rosinstall.melodic index d78566b5003..55bdd52bb18 100644 --- a/.travis.rosinstall.melodic +++ b/.travis.rosinstall.melodic @@ -19,10 +19,6 @@ uri: https://github.com/ros-planning/moveit_robots.git local-name: ros-planning/moveit_robots version: kinetic-devel -- git: # wait until releasing - uri: https://github.com/tork-a/jsk_demos-release.git - local-name: jsk_maps - version: release/kinetic/jsk_maps - git: # wait until releasing (https://github.com/PR2/app_manager/issues/12) uri: https://github.com/pr2/app_manager.git local-name: app_manager From 737c19ef3d33fdc4e8287e37c455e0fabd945fde Mon Sep 17 00:00:00 2001 From: Naoya Yamaguchi <708yamaguchi@gmail.com> Date: Tue, 1 Dec 2020 18:21:20 +0900 Subject: [PATCH 24/44] Add arg to select using safe teleop --- .../jsk_fetch_startup/launch/fetch_teleop.xml | 2 + .../launch/safe_teleop.launch | 48 +++++++++++-------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml index 3b326c6662b..505d8a27d30 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml +++ b/jsk_fetch_robot/jsk_fetch_startup/launch/fetch_teleop.xml @@ -1,5 +1,6 @@ + @@ -29,6 +30,7 @@ + diff --git a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch index bebfd09689e..73d9691b792 100644 --- a/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch +++ b/jsk_robot_common/jsk_robot_startup/launch/safe_teleop.launch @@ -2,6 +2,7 @@ + @@ -23,28 +24,33 @@
- - - - - - + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + Date: Thu, 10 Dec 2020 12:57:42 +0900 Subject: [PATCH 25/44] add comment in .travis.rosinstall --- .travis.rosinstall | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.rosinstall b/.travis.rosinstall index 2c59362f0b8..e9c39642de3 100644 --- a/.travis.rosinstall +++ b/.travis.rosinstall @@ -1,4 +1,7 @@ # see also .travis.rosinstall.ROS_DISTRO +# waiting for jsk_maps release +# add keepout map for entire eng2 building +# https://github.com/jsk-ros-pkg/jsk_demos/pull/1300 - git: local-name: jsk-ros-pkg/jsk_demos uri: https://github.com/jsk-ros-pkg/jsk_demos.git From 95f8a982ee94593e5693b6dc811c74a870c9b9b7 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Thu, 10 Dec 2020 12:57:51 +0900 Subject: [PATCH 26/44] add jsk_ik_server for jsk_demos build --- .travis.rosinstall.melodic | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.rosinstall.melodic b/.travis.rosinstall.melodic index 71169c4b522..baa90e440d2 100644 --- a/.travis.rosinstall.melodic +++ b/.travis.rosinstall.melodic @@ -36,3 +36,9 @@ local-name: fetchrobotics/fetch_ros uri: https://github.com/fetchrobotics/fetch_ros.git version: ba4bafdb802e474487d1e0d893aa25c9535dc55f +# for drc_task_common in jsk_demos +# jsk_control is not released in melodic +- tar: + local-name: jsk_control/jsk_ik_server + uri: https://github.com/tork-a/jsk_control-release/archive/release/kinetic/jsk_ik_server/0.1.14-0.tar.gz + version: jsk_control-release-release-kinetic-jsk_ik_server-0.1.14-0 From ffc10275694e046a1b01e1e3030da56dc47d6043 Mon Sep 17 00:00:00 2001 From: JSK PR2 Users Date: Wed, 6 Jan 2021 18:27:05 +0900 Subject: [PATCH 27/44] add virtual_force_publisher to pr2.launch --- jsk_pr2_robot/jsk_pr2_startup/pr2.launch | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jsk_pr2_robot/jsk_pr2_startup/pr2.launch b/jsk_pr2_robot/jsk_pr2_startup/pr2.launch index 014286586ef..9082d344625 100644 --- a/jsk_pr2_robot/jsk_pr2_startup/pr2.launch +++ b/jsk_pr2_robot/jsk_pr2_startup/pr2.launch @@ -11,6 +11,7 @@ + @@ -121,6 +122,11 @@ + + + + + From 700d9e9d7de407ac5a840d474090b590b24d2145 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 29 Jan 2021 11:18:37 +0900 Subject: [PATCH 28/44] update jsk_travis to 0.5.18, fix get-pip.py problem --- .travis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis b/.travis index cbcbaab8a9c..92c11b11bd1 160000 --- a/.travis +++ b/.travis @@ -1 +1 @@ -Subproject commit cbcbaab8a9ce7d1b369cdb3e08aa46fede046ec0 +Subproject commit 92c11b11bd185418f12af29c88c04793d1f761b9 From 17344b89e4f5624d1e5268b4368f90e80a880d45 Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Tue, 6 Apr 2021 00:05:06 +0900 Subject: [PATCH 29/44] update jsk_travis to 0.5.19 to fix get-pip problems --- .travis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis b/.travis index 92c11b11bd1..96cae291c71 160000 --- a/.travis +++ b/.travis @@ -1 +1 @@ -Subproject commit 92c11b11bd185418f12af29c88c04793d1f761b9 +Subproject commit 96cae291c7132a5220b69055d4fe77a0a6484a54 From e32659a0fd3ed5e98ad486341b7e764a6cff119a Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Wed, 28 Apr 2021 15:10:16 +0900 Subject: [PATCH 30/44] update .travis to 0.5.21 --- .travis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis b/.travis index 96cae291c71..0955a49eb55 160000 --- a/.travis +++ b/.travis @@ -1 +1 @@ -Subproject commit 96cae291c7132a5220b69055d4fe77a0a6484a54 +Subproject commit 0955a49eb558dbcc8f25c032668ad25774c41a8b From ed6f48c162c2c309808011cf5134267eb3da25bd Mon Sep 17 00:00:00 2001 From: Shingo Kitagawa Date: Sat, 15 May 2021 22:42:11 +0900 Subject: [PATCH 31/44] update .travis.yml --- .travis.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ad240ab694..807a17cc79e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,16 @@ -language: c++ +sudo: true +dist: bionic +language: python +services: + - docker cache: apt: true pip: true directories: - $HOME/.ccache + - $HOME/.cache/pip - $HOME/apt-cacher-ng -sudo: required -services: - - docker -dist: trusty + - $HOME/.ros/data notifications: email: on_success: always From 420d5bd9572c79bffeb78fd61a631b0e83f7e437 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Mon, 12 Jul 2021 18:42:40 +0900 Subject: [PATCH 32/44] add CHECK_PYTHON3_COMPILE --- .travis.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 807a17cc79e..7ce1180fbbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,10 @@ dist: bionic language: python services: - docker +addons: + apt: + packages: + - 2to3 cache: apt: true pip: true @@ -26,6 +30,7 @@ env: - CATKIN_PARALLEL_TEST_JOBS="-p1" - NOT_TEST_INSTALL=true matrix: + - CHECK_PYTHON3_COMPILE=true - ROS_DISTRO=hydro USE_DEB=true - ROS_DISTRO=hydro USE_DEB=false EXTRA_DEB="ros-hydro-convex-decomposition ros-hydro-ivcon" BUILD_PKGS="jsk_pr2_calibration jsk_robot_startup pr2_base_trajectory_action jsk_pr2_startup jsk_pr2_desktop" - ROS_DISTRO=indigo USE_DEB=true TEST_PKGS="jsk_robot_startup" # app_manager required to pass jsk_fetch test, so this job mainly test if we can build sources @@ -50,4 +55,6 @@ before_script: - if [ "$ROS_DISTRO" == "melodic" ]; then export BEFORE_SCRIPT="pwd; ls -al ; ls -al jsk_robot/; ls -al jsk_robot/.travis.rosinstall.melodic; wstool merge jsk_robot/.travis.rosinstall.melodic; wstool update"; fi # skip running postinst for ros-ROS_DISTRO-julius https://gist.github.com/jordansissel/748313#file-stripdeb-sh - export BEFORE_SCRIPT="apt-get download ros-$ROS_DISTRO-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-$ROS_DISTRO-julius*.deb; sudo dpkg --force-all -i ros-$ROS_DISTRO-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-$ROS_DISTRO-julius; $BEFORE_SCRIPT" -script: .travis/travis.sh +script: + - if [ "${CHECK_PYTHON3_COMPILE}" == "true" ]; then bash -c "ret=0; trap 'ret=1' ERR; python3 -m compileall .; 2to3 -w -f except -f execfile -f has_key -f import -f raw_input -f zip .; git diff --exit-code . :^.travis > /dev/null; echo Exitting with \$ret; exit \$ret"; exit $?; fi + - source .travis/travis.sh From 1d09f76be0e00319bab3a8b48532d273c35f40b4 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Mon, 12 Jul 2021 18:56:01 +0900 Subject: [PATCH 33/44] add .github/workflows/ --- .github/workflows/indigo.yml | 48 +++++++++++++++++++++++++++++++++++ .github/workflows/kinetic.yml | 45 ++++++++++++++++++++++++++++++++ .github/workflows/melodic.yml | 44 ++++++++++++++++++++++++++++++++ .github/workflows/noetic.yml | 45 ++++++++++++++++++++++++++++++++ .github/workflows/python3.yml | 24 ++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 .github/workflows/indigo.yml create mode 100644 .github/workflows/kinetic.yml create mode 100644 .github/workflows/melodic.yml create mode 100644 .github/workflows/noetic.yml create mode 100644 .github/workflows/python3.yml diff --git a/.github/workflows/indigo.yml b/.github/workflows/indigo.yml new file mode 100644 index 00000000000..6d2dfd8e481 --- /dev/null +++ b/.github/workflows/indigo.yml @@ -0,0 +1,48 @@ +# generated by `./generate_action_config.py indigo` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +env: + DISPLAY: ':0.0' + +jobs: + indigo: + runs-on: ubuntu-latest + name: indigo + + # use pip installed image due to https://github.com/jsk-ros-pkg/jsk_3rdparty/pull/237 : (Note that pip==21.0.1 is incompatible with python 2.x) + container: jskrobotics/ros-ubuntu:14.04 + + steps: + - name: Install latest git ( use sudo for ros-ubuntu ) + run: sudo apt-get update && sudo apt-get install -y software-properties-common && sudo apt-get update && sudo add-apt-repository -y ppa:git-core/ppa && sudo apt-get update && sudo apt-get install -y git + - name: Before Checkout # need for actoins/checkout with ros-ubuntu container + run: sudo chown -R user:jenkins $RUNNER_WORKSPACE $HOME + - name: Chcekout + uses: actions/checkout@v2 + - name: Start X server + run: | + sudo apt-get -y -qq install mesa-utils x11-xserver-utils xserver-xorg-video-dummy + export DISPLAY=:0 + wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_travis/master/dummy.xorg.conf -O /tmp/dummy.xorg.conf + sudo Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xorg.log -config /tmp/dummy.xorg.conf $DISPLAY & + sleep 3 # wait x server up + export QT_X11_NO_MITSHM=1 # http://wiki.ros.org/docker/Tutorials/GUI + xhost +local:root + - name: Run jsk_travis + uses: jsk-ros-pkg/jsk_travis@master + with: + ROS_PARALLEL_JOBS : "-j2" + CATKIN_PARALLEL_JOBS : "-p2" + ROS_PARALLEL_TEST_JOBS : "-j1" + CATKIN_PARALLEL_TEST_JOBS : "-p1" + NOT_TEST_INSTALL : true + ROS_DISTRO : indigo + USE_DEB : false + TEST_PKGS : "jsk_robot_startup" # app_manager required to pass jsk_fetch test, so this job mainly test if we can build sources + # to install pepper_meshes, nao_meshes, the licenses have to be accepted + BEFORE_SCRIPT : "echo 'ros-indigo-pepper-meshes ros-pepper-meshes/accepted-ros-pepper-meshes boolean true' | sudo debconf-set-selections; sudo apt-get install -y -qq ros-indigo-pepper-meshes; echo 'ros-indigo-nao-meshes ros-nao-meshes/accepted-ros-nao-meshes boolean true' | sudo debconf-set-selections; sudo apt-get install -y -qq ros-indigo-nao-meshes; apt-get download ros-indigo-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-indigo-julius*.deb; sudo dpkg --force-all -i ros-indigo-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-indigo-julius" \ No newline at end of file diff --git a/.github/workflows/kinetic.yml b/.github/workflows/kinetic.yml new file mode 100644 index 00000000000..92a4ec3dde0 --- /dev/null +++ b/.github/workflows/kinetic.yml @@ -0,0 +1,45 @@ +# generated by `./generate_action_config.py kinetic` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +env: + DISPLAY: ':0.0' + +jobs: + kinetic: + runs-on: ubuntu-latest + name: kinetic + + container: ubuntu:16.04 + + steps: + - name: Install latest git ( use sudo for ros-ubuntu ) + run: apt-get update && apt-get install -y software-properties-common && apt-get update && add-apt-repository -y ppa:git-core/ppa && apt-get update && apt-get install -y git + - name: Chcekout + uses: actions/checkout@v2 + - name: Start X server + run: | + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections # set non interactive tzdata https://stackoverflow.com/questions/8671308/non-interactive-method-for-dpkg-reconfigure-tzdata + apt-get -y -qq install mesa-utils x11-xserver-utils xserver-xorg-video-dummy wget + export DISPLAY=:0 + wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_travis/master/dummy.xorg.conf -O /tmp/dummy.xorg.conf + Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xorg.log -config /tmp/dummy.xorg.conf $DISPLAY & + sleep 3 # wait x server up + export QT_X11_NO_MITSHM=1 # http://wiki.ros.org/docker/Tutorials/GUI + xhost +local:root + - name: Run jsk_travis + uses: jsk-ros-pkg/jsk_travis@master + with: + ROS_PARALLEL_JOBS : "-j2" + CATKIN_PARALLEL_JOBS : "-p2" + ROS_PARALLEL_TEST_JOBS : "-j1" + CATKIN_PARALLEL_TEST_JOBS : "-p1" + NOT_TEST_INSTALL : true + ROS_DISTRO : kinetic + USE_DEB : false + BEFORE_SCRIPT : "wstool merge jsk_robot/jsk_fetch_robot/jsk_fetch.rosinstall.kinetic; wstool update; apt-get download ros-kinetic-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-kinetic-julius*.deb; sudo dpkg --force-all -i ros-kinetic-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-kinetic-julius" + EXTRA_DEB : "ros-kinetic-convex-decomposition ros-kinetic-ivcon" \ No newline at end of file diff --git a/.github/workflows/melodic.yml b/.github/workflows/melodic.yml new file mode 100644 index 00000000000..78641bb0150 --- /dev/null +++ b/.github/workflows/melodic.yml @@ -0,0 +1,44 @@ +# generated by `./generate_action_config.py melodic` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +env: + DISPLAY: ':0.0' + +jobs: + melodic: + runs-on: ubuntu-latest + name: melodic + + container: ubuntu:18.04 + + steps: + - name: Install latest git ( use sudo for ros-ubuntu ) + run: apt-get update && apt-get install -y software-properties-common && apt-get update && add-apt-repository -y ppa:git-core/ppa && apt-get update && apt-get install -y git + - name: Chcekout + uses: actions/checkout@v2 + - name: Start X server + run: | + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections # set non interactive tzdata https://stackoverflow.com/questions/8671308/non-interactive-method-for-dpkg-reconfigure-tzdata + apt-get -y -qq install mesa-utils x11-xserver-utils xserver-xorg-video-dummy wget + export DISPLAY=:0 + wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_travis/master/dummy.xorg.conf -O /tmp/dummy.xorg.conf + Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xorg.log -config /tmp/dummy.xorg.conf $DISPLAY & + sleep 3 # wait x server up + export QT_X11_NO_MITSHM=1 # http://wiki.ros.org/docker/Tutorials/GUI + xhost +local:root + - name: Run jsk_travis + uses: jsk-ros-pkg/jsk_travis@master + with: + ROS_PARALLEL_JOBS : "-j2" + CATKIN_PARALLEL_JOBS : "-p2" + ROS_PARALLEL_TEST_JOBS : "-j1" + CATKIN_PARALLEL_TEST_JOBS : "-p1" + NOT_TEST_INSTALL : true + ROS_DISTRO : melodic + USE_DEB : false + BEFORE_SCRIPT : "apt-get download ros-melodic-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-melodic-julius*.deb; sudo dpkg --force-all -i ros-melodic-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-melodic-julius" diff --git a/.github/workflows/noetic.yml b/.github/workflows/noetic.yml new file mode 100644 index 00000000000..62a46dc12f1 --- /dev/null +++ b/.github/workflows/noetic.yml @@ -0,0 +1,45 @@ +# generated by `./generate_action_config.py noetic` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +env: + DISPLAY: ':0.0' + +jobs: + noetic: + runs-on: ubuntu-latest + name: noetic + + container: ubuntu:20.04 + + steps: + - name: Install latest git ( use sudo for ros-ubuntu ) + run: apt-get update && apt-get install -y software-properties-common && apt-get update && add-apt-repository -y ppa:git-core/ppa && apt-get update && apt-get install -y git + - name: Chcekout + uses: actions/checkout@v2 + - name: Start X server + run: | + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections # set non interactive tzdata https://stackoverflow.com/questions/8671308/non-interactive-method-for-dpkg-reconfigure-tzdata + apt-get -y -qq install mesa-utils x11-xserver-utils xserver-xorg-video-dummy wget + export DISPLAY=:0 + wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_travis/master/dummy.xorg.conf -O /tmp/dummy.xorg.conf + Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xorg.log -config /tmp/dummy.xorg.conf $DISPLAY & + sleep 3 # wait x server up + export QT_X11_NO_MITSHM=1 # http://wiki.ros.org/docker/Tutorials/GUI + xhost +local:root + - name: Run jsk_travis + uses: jsk-ros-pkg/jsk_travis@master + with: + ROS_PARALLEL_JOBS : "-j2" + CATKIN_PARALLEL_JOBS : "-p2" + ROS_PARALLEL_TEST_JOBS : "-j1" + CATKIN_PARALLEL_TEST_JOBS : "-p1" + NOT_TEST_INSTALL : true + ROS_DISTRO : noetic + USE_DEB : false + TEST_PKGS : "jsk_robot_startup" # check only jsk_robot_startup + BEFORE_SCRIPT : "apt-get download ros-noetic-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-noetic-julius*.deb; sudo dpkg --force-all -i ros-noetic-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-noetic-julius" diff --git a/.github/workflows/python3.yml b/.github/workflows/python3.yml new file mode 100644 index 00000000000..14336105b0a --- /dev/null +++ b/.github/workflows/python3.yml @@ -0,0 +1,24 @@ +# generated by `./generate_action_config.py noetic` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + name: check_python3 + + container: ubuntu:20.04 + + steps: + - name: Install latest git to download .git directory in actions/checkout@v2 ( use sudo for ros-ubuntu ) + run: apt-get update && apt-get install -y software-properties-common && apt-get update && add-apt-repository -y ppa:git-core/ppa && apt-get update && apt-get install -y git + - name: Chcekout + uses: actions/checkout@v2 + - name: Check Python3 + run: | + apt update -q && apt install -y -q python3 git 2to3 + bash -c "ret=0; trap 'ret=1' ERR; python3 -m compileall .; 2to3 -w -f except -f execfile -f has_key -f import -f raw_input -f zip .; git diff --exit-code . :^.travis > /dev/null; echo Exitting with \$ret; exit \$ret" From e69bc31f5f3f7e78c9b83537155b03188b752449 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Wed, 14 Jul 2021 14:18:32 +0900 Subject: [PATCH 34/44] mv jsk_fetch.rosinstall.kinetic -> /jsk_fetch_user.rosinstall.kinetic, see https://github.com/jsk-ros-pkg/jsk_robot/pull/1008 --- .github/workflows/kinetic.yml | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/kinetic.yml b/.github/workflows/kinetic.yml index 92a4ec3dde0..5f94e92c803 100644 --- a/.github/workflows/kinetic.yml +++ b/.github/workflows/kinetic.yml @@ -41,5 +41,5 @@ jobs: NOT_TEST_INSTALL : true ROS_DISTRO : kinetic USE_DEB : false - BEFORE_SCRIPT : "wstool merge jsk_robot/jsk_fetch_robot/jsk_fetch.rosinstall.kinetic; wstool update; apt-get download ros-kinetic-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-kinetic-julius*.deb; sudo dpkg --force-all -i ros-kinetic-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-kinetic-julius" + BEFORE_SCRIPT : "wstool merge jsk_robot/jsk_fetch_robot/jsk_fetch_user.rosinstall.kinetic; wstool update; apt-get download ros-kinetic-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-kinetic-julius*.deb; sudo dpkg --force-all -i ros-kinetic-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-kinetic-julius" EXTRA_DEB : "ros-kinetic-convex-decomposition ros-kinetic-ivcon" \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 7ce1180fbbb..2a6101c46e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ before_script: # to install pepper_meshes, nao_meshes, the licenses have to be accepted - if [ "$ROS_DISTRO" == "indigo" ]; then export BEFORE_SCRIPT="echo \"ros-indigo-pepper-meshes ros-pepper-meshes/accepted-ros-pepper-meshes boolean true\" | sudo debconf-set-selections; sudo apt-get install -y -qq ros-$ROS_DISTRO-pepper-meshes"; fi - if [ "$ROS_DISTRO" == "indigo" ]; then export BEFORE_SCRIPT="echo \"ros-indigo-nao-meshes ros-nao-meshes/accepted-ros-nao-meshes boolean true\" | sudo debconf-set-selections; sudo apt-get install -y -qq ros-$ROS_DISTRO-nao-meshes"; fi - - if [ "$ROS_DISTRO" == "kinetic" ]; then export BEFORE_SCRIPT="wstool merge jsk_robot/jsk_fetch_robot/jsk_fetch.rosinstall.kinetic; wstool update"; fi + - if [ "$ROS_DISTRO" == "kinetic" ]; then export BEFORE_SCRIPT="wstool merge jsk_robot/jsk_fetch_robot/jsk_fetch_user.rosinstall.kinetic; wstool update"; fi - if [ "$ROS_DISTRO" == "melodic" ]; then export BEFORE_SCRIPT="pwd; ls -al ; ls -al jsk_robot/; ls -al jsk_robot/.travis.rosinstall.melodic; wstool merge jsk_robot/.travis.rosinstall.melodic; wstool update"; fi # skip running postinst for ros-ROS_DISTRO-julius https://gist.github.com/jordansissel/748313#file-stripdeb-sh - export BEFORE_SCRIPT="apt-get download ros-$ROS_DISTRO-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-$ROS_DISTRO-julius*.deb; sudo dpkg --force-all -i ros-$ROS_DISTRO-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-$ROS_DISTRO-julius; $BEFORE_SCRIPT" From 1e4f0ace7792a09f942fe73d5809b0e610914507 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Wed, 14 Jul 2021 18:53:44 +0900 Subject: [PATCH 35/44] add .travis.rosinstall.noetic --- .travis.rosinstall.noetic | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .travis.rosinstall.noetic diff --git a/.travis.rosinstall.noetic b/.travis.rosinstall.noetic new file mode 100644 index 00000000000..baa90e440d2 --- /dev/null +++ b/.travis.rosinstall.noetic @@ -0,0 +1,44 @@ +- git: + uri: http://github.com/RethinkRobotics/baxter_common.git + local-name: RethinkRobotics/baxter_common + version: kinetic-devel +- git: + # https://github.com/RethinkRobotics/baxter_simulator/pull/130 + uri: https://github.com/EmaroLab/baxter_simulator.git + local-name: RethinkRobotics/baxter_simulator + version: master +- git: + uri: https://github.com/RethinkRobotics/baxter_interface.git + local-name: baxter_interface + version: development +- git: + uri: https://github.com/RethinkRobotics/baxter_tools.git + local-name: baxter_tools + version: development +- git: + uri: https://github.com/ros-planning/moveit_robots.git + local-name: ros-planning/moveit_robots + version: kinetic-devel +- git: # wait for melodic release https://github.com/ros-naoqi/pepper_robot/issues/50 + uri: https://github.com/ros-naoqi/pepper_robot.git + local-name: pepper_robot +- git: # https://github.com/ros-naoqi/nao_robot/issues/40 + uri: https://github.com/ros-naoqi/nao_robot.git + local-name: nao_robot +- git: # use naoqi_pose, wait for melodic release https://github.com/ros-naoqi/naoqi_bridge/issues/94 + uri: https://github.com/ros-naoqi/naoqi_bridge-release.git + local-name: naoqi_pose + version: release/kinetic/naoqi_pose +# jsk_fetch_startup requires fetch_ros with following PRs. +# https://github.com/fetchrobotics/fetch_ros/pull/144 +# https://github.com/fetchrobotics/fetch_ros/pull/146 +- git: + local-name: fetchrobotics/fetch_ros + uri: https://github.com/fetchrobotics/fetch_ros.git + version: ba4bafdb802e474487d1e0d893aa25c9535dc55f +# for drc_task_common in jsk_demos +# jsk_control is not released in melodic +- tar: + local-name: jsk_control/jsk_ik_server + uri: https://github.com/tork-a/jsk_control-release/archive/release/kinetic/jsk_ik_server/0.1.14-0.tar.gz + version: jsk_control-release-release-kinetic-jsk_ik_server-0.1.14-0 From 9113a7bc2f08c159ef8fe6d9f1854155904773aa Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Thu, 15 Jul 2021 11:40:18 +0900 Subject: [PATCH 36/44] 2to3 -w -f except . --- .../jsk_pepper_startup/nodes/play_audio_stream.py | 4 ++-- .../jsk_pepper_startup/nodes/take_wakeup_pose.py | 2 +- jsk_naoqi_robot/naoeus/scripts/nao_laser.py | 6 +++--- .../jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py | 8 ++++---- .../jsk_pr2_startup/jsk_pr2_sensors/check_openni_node.py | 4 ++-- jsk_robot_common/jsk_robot_startup/util/mux_selector.py | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/jsk_naoqi_robot/jsk_pepper_startup/nodes/play_audio_stream.py b/jsk_naoqi_robot/jsk_pepper_startup/nodes/play_audio_stream.py index 86368e023fe..30c15bc8b41 100755 --- a/jsk_naoqi_robot/jsk_pepper_startup/nodes/play_audio_stream.py +++ b/jsk_naoqi_robot/jsk_pepper_startup/nodes/play_audio_stream.py @@ -15,7 +15,7 @@ def handle_start_srv(req): try: p=Popen(['roslaunch', 'jsk_pepper_startup', 'play_audio_stream.launch']) return EmptyResponse() - except RuntimeError, e: + except RuntimeError as e: rospy.logerr("Exception caught:\n%s", e) return res @@ -34,7 +34,7 @@ def handle_stop_srv(req): call(['rosnode', 'kill', nodelist[i]]) break return EmptyResponse() - except RuntimeError, e: + except RuntimeError as e: rospy.logerr("Exception caught:\n%s", e) return res diff --git a/jsk_naoqi_robot/jsk_pepper_startup/nodes/take_wakeup_pose.py b/jsk_naoqi_robot/jsk_pepper_startup/nodes/take_wakeup_pose.py index 96d76b0add8..7018b4f6d44 100755 --- a/jsk_naoqi_robot/jsk_pepper_startup/nodes/take_wakeup_pose.py +++ b/jsk_naoqi_robot/jsk_pepper_startup/nodes/take_wakeup_pose.py @@ -163,7 +163,7 @@ def take_initial_pose(self): msg.data = "\\vct=140\\よしっ\\vct=120\\\\rspd=100\\" self.pub.publish(msg) - except RuntimeError, e: + except RuntimeError as e: rospy.logerr("Exception caught:\n%s", e) if __name__=="__main__": diff --git a/jsk_naoqi_robot/naoeus/scripts/nao_laser.py b/jsk_naoqi_robot/naoeus/scripts/nao_laser.py index b84c24b68fd..ba0ba8a296e 100755 --- a/jsk_naoqi_robot/naoeus/scripts/nao_laser.py +++ b/jsk_naoqi_robot/naoeus/scripts/nao_laser.py @@ -39,14 +39,14 @@ def __init__(self): self.alurg.setOpeningAngle(-2.09439, 2.09439) self.alurg.setDetectingLength(20, 5600) self.alurg.laserON() - except Exception,e: + except Exception as e: print "Error when creating ALLaser proxy:" print str(e) exit(1) try: self.almem = self.getProxy("ALMemory") - except Exception,e: + except Exception as e: print "Error when creating ALMemory proxy:" print str(e) exit(1) @@ -104,7 +104,7 @@ def main_loop(self): try: naolaser = NaoLaser() naolaser.main_loop() - except RuntimeError, e: + except RuntimeError as e: rospy.logerr('Something went wrong: %s' % (e) ) rospy.loginfo('Laser stopped') diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py index 996b23be517..331513bf3c8 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py @@ -271,10 +271,10 @@ def dequeue(self): mongodb_store.util.store_message(self.collection, msg, meta) - except InvalidDocument, e: + except InvalidDocument as e: print("InvalidDocument " + current_process().name + "@" + topic +": \n") print e - except InvalidStringData, e: + except InvalidStringData as e: print("InvalidStringData " + current_process().name + "@" + topic +": \n") print e @@ -447,7 +447,7 @@ def subscribe_topics(self, topics): self.workers.append(w) self.collnames |= set([collname]) self.topics |= set([topic]) - except Exception, e: + except Exception as e: print('Failed to subsribe to %s due to %s' % (topic, e)) missing_topics.add(topic) @@ -457,7 +457,7 @@ def subscribe_topics(self, topics): def create_worker(self, idnum, topic, collname): try: msg_class, real_topic, msg_eval = rostopic.get_topic_class(topic, blocking=False) - except Exception, e: + except Exception as e: print('Topic %s not announced, cannot get type: %s' % (topic, e)) raise diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_sensors/check_openni_node.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_sensors/check_openni_node.py index 468162766cc..6d82d430571 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_sensors/check_openni_node.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_sensors/check_openni_node.py @@ -46,7 +46,7 @@ def image_callback(self, msg): try: cv_image = self.bridge.imgmsg_to_cv(msg, "bgr8") sum_of_pixels = max(cv.Sum(cv_image)) - except CvBridgeError, e: + except CvBridgeError as e: rospy.logerr("[%s] failed to convert image to cv", self.__class__.__name__) return @@ -84,7 +84,7 @@ def restart_openni_node(self): # 3 restarting self.speak("restarting processes") retcode = subprocess.call('roslaunch openni_launch openni.launch camera:=%s publish_tf:=false depth_registration:=true rgb_processing:=false ir_processing:=false depth_processing:=false depth_registered_processing:=false disparity_processing:=false disparity_registered_processing:=false hw_registered_processing:=true sw_registered_processing:=false rgb_frame_id:=/head_mount_kinect_rgb_optical_frame depth_frame_id:=/head_mount_kinect_ir_optical_frame' % self.camera, shell=True) - except Exception, e: + except Exception as e: rospy.logerr('[%s] Unable to kill kinect node, caught exception:\n%s', self.__class__.__name__, traceback.format_exc()) def run(self): diff --git a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py index 19320413903..fd0a9744e9f 100755 --- a/jsk_robot_common/jsk_robot_startup/util/mux_selector.py +++ b/jsk_robot_common/jsk_robot_startup/util/mux_selector.py @@ -82,7 +82,7 @@ def add_trigger(topic, expr, select, index, wait=False): cb_obj = gen_callback(expr, select, index) rospy.loginfo("start subscribe (topic=%s type=%s)", topic, topic_type); sub = rospy.Subscriber(topic,topic_class,cb_obj) - except Exception, e: + except Exception as e: rospy.loginfo(str(e)) return None @@ -154,10 +154,10 @@ def update_trigger(conditions, wait=False): try: if not (before == next_topic or next_topic is None): mux_client(next_topic) - except rospy.ServiceException, e: + except rospy.ServiceException as e: rospy.loginfo("Service did not process request: %s", str(e)) before = next_topic looprate.sleep() - except Exception, e: + except Exception as e: rospy.logerr('Error: '+str(e)) rospy.logerr(traceback.format_exc()) From 199cac9ca2cd54c0450da10851245e34c7f51076 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Thu, 15 Jul 2021 11:51:49 +0900 Subject: [PATCH 37/44] 2to3 -w -f print . --- jsk_naoqi_robot/naoeus/scripts/nao_laser.py | 8 ++++---- .../jsk_pr2_startup/jsk_pr2_joy/joy_controller.py | 2 +- .../jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py | 4 ++-- .../jsk_pr2_move_base/fullbody_action_node.py | 4 ++-- .../roseus_remote/scripts/roseus_command_sender.py | 2 +- jsk_robot_common/roseus_remote/scripts/test.py | 10 +++++----- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/jsk_naoqi_robot/naoeus/scripts/nao_laser.py b/jsk_naoqi_robot/naoeus/scripts/nao_laser.py index ba0ba8a296e..7be07591336 100755 --- a/jsk_naoqi_robot/naoeus/scripts/nao_laser.py +++ b/jsk_naoqi_robot/naoeus/scripts/nao_laser.py @@ -40,15 +40,15 @@ def __init__(self): self.alurg.setDetectingLength(20, 5600) self.alurg.laserON() except Exception as e: - print "Error when creating ALLaser proxy:" - print str(e) + print("Error when creating ALLaser proxy:") + print(str(e)) exit(1) try: self.almem = self.getProxy("ALMemory") except Exception as e: - print "Error when creating ALMemory proxy:" - print str(e) + print("Error when creating ALMemory proxy:") + print(str(e)) exit(1) self.pub_laser = rospy.Publisher('scan', LaserScan) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_joy/joy_controller.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_joy/joy_controller.py index 711bc1f7b76..6c7ea07a343 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_joy/joy_controller.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_joy/joy_controller.py @@ -22,7 +22,7 @@ def joy_callback(self, joy): def joy_execute(self): if self.check_pushed(0): - print "0 is pushed" + print("0 is pushed") pass def check_pushed(self, index): diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py index 331513bf3c8..4a9eb7e27d9 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_lifelog/mongodb_log.py @@ -273,10 +273,10 @@ def dequeue(self): except InvalidDocument as e: print("InvalidDocument " + current_process().name + "@" + topic +": \n") - print e + print(e) except InvalidStringData as e: print("InvalidStringData " + current_process().name + "@" + topic +": \n") - print e + print(e) else: #print("Quit W2: %s" % self.name) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/fullbody_action_node.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/fullbody_action_node.py index 5cebebcbdc3..7d4802fa3f0 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/fullbody_action_node.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_move_base/fullbody_action_node.py @@ -32,7 +32,7 @@ def __init__(self, name): for client in self._clients: client.wait_for_server() - print 'fullbody action initialized' + print('fullbody action initialized') # action methods def larm(self, traj): @@ -72,7 +72,7 @@ def joint(self, client, traj, joints): for pt in traj.points] client.send_goal(JointTrajectoryGoal(trajectory=jgoal)) except: - print 'error in joint client' + print('error in joint client') def execute_cb(self, goal): self.larm(goal.trajectory) diff --git a/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py b/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py index 75fb2f27780..c0133c53b69 100755 --- a/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py +++ b/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py @@ -9,7 +9,7 @@ def cmd_res_cb(msg): input_str = str(msg.data).rstrip(' \t\r\n\0') - print input_str + print(input_str) def on_shutdown(): rospy.logwarn("to exit immediately, press Enter") diff --git a/jsk_robot_common/roseus_remote/scripts/test.py b/jsk_robot_common/roseus_remote/scripts/test.py index 79a9d8f5e0a..614247fa724 100644 --- a/jsk_robot_common/roseus_remote/scripts/test.py +++ b/jsk_robot_common/roseus_remote/scripts/test.py @@ -23,9 +23,9 @@ def get_output(out, queue): if data: queue.put(data) else: - print "nodata" + print("nodata") else: - print "error" + print("error") cmd = ['roseus'] @@ -51,7 +51,7 @@ def get_output(out, queue): get_stderr_thread.start() while p.poll() is None: - print "alive?: ", p.poll() + print("alive?: ", p.poll()) cmd = raw_input('cmd$ ') p.stdin.write(cmd) p.stdin.flush() @@ -67,5 +67,5 @@ def get_output(out, queue): stderr += stderr_queue.get_nowait() except: pass - print "stdout: ", stdout - print "stderr: ", stderr + print("stdout: ", stdout) + print("stderr: ", stderr) From 7088c425ac63b2521248542a66bf74828b3faabd Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Thu, 15 Jul 2021 12:29:34 +0900 Subject: [PATCH 38/44] 2to3 -w -f has_key . --- jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py | 8 ++++---- .../jsk_fetch_startup/scripts/roslaunch_depends.py | 8 ++++---- jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py | 4 ++-- .../jsk_pepper_startup/script/roslaunch_depends.py | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py b/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py index f92143fd142..20fc73090bf 100644 --- a/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py +++ b/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if tag.attributes.has_key('value'): + if 'value' in tag.attributes: return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif tag.attributes.has_key('default'): + elif 'default' in tag.attributes: return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if tag.attributes.has_key('if'): + if 'if' in tag.attributes: val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif tag.attributes.has_key('unless'): + elif 'unless' in tag.attributes: val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False diff --git a/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py b/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py index 2dc7613e82b..3cf097a0f1e 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py +++ b/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if tag.attributes.has_key('value'): + if 'value' in tag.attributes: return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif tag.attributes.has_key('default'): + elif 'default' in tag.attributes: return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if tag.attributes.has_key('if'): + if 'if' in tag.attributes: val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif tag.attributes.has_key('unless'): + elif 'unless' in tag.attributes: val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False diff --git a/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py b/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py index 81e97c478e6..c748f112741 100755 --- a/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py +++ b/jsk_fetch_robot/jsk_fetch_startup/scripts/warning.py @@ -46,7 +46,7 @@ def run(self): global sound for status in self.error_status: # ignore error status if the error already occured in the latest 10 minites - if error_status_in_10_min.has_key(status.message): + if status.message in error_status_in_10_min: if rospy.Time.now().secs - error_status_in_10_min[status.message] < 600: continue else: @@ -144,7 +144,7 @@ def diagnostics_status_callback(self, msg): ## ## check if this comes from /robot_driver callerid = msg._connection_header['callerid'] - if not self.diagnostics_speak_thread.has_key(callerid): + if callerid not in self.diagnostics_speak_thread: self.diagnostics_speak_thread[callerid] = None error_status = filter(lambda n: n.level in self.diagnostics_list, msg.status) # when RunStopped, ignore message from *_mcb and *_breaker diff --git a/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py b/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py index 2dc7613e82b..3cf097a0f1e 100644 --- a/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py +++ b/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if tag.attributes.has_key('value'): + if 'value' in tag.attributes: return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif tag.attributes.has_key('default'): + elif 'default' in tag.attributes: return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if tag.attributes.has_key('if'): + if 'if' in tag.attributes: val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif tag.attributes.has_key('unless'): + elif 'unless' in tag.attributes: val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False From f2165383981cb2bfd3d2dbbfb13af002e4574dc3 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Thu, 15 Jul 2021 12:36:04 +0900 Subject: [PATCH 39/44] 2to3 -w -f zip . --- .../src/jsk_robot_startup/EKFGPFOdometry.py | 6 +++--- .../src/jsk_robot_startup/ParticleOdometry.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py index d563a8142b7..2180a78724d 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py @@ -75,13 +75,13 @@ def measure_odom_callback(self, msg): def sampling(self, current_pose_with_covariance): pose_mean = self.convert_pose_to_list(current_pose_with_covariance.pose) - pose_cov_matrix = zip(*[iter(current_pose_with_covariance.covariance)]*6) + pose_cov_matrix = list(zip(*[iter(current_pose_with_covariance.covariance)]*6)) return [self.convert_list_to_pose(x) for x in numpy.random.multivariate_normal(pose_mean, pose_cov_matrix, int(self.particle_num)).tolist()] def approximate_odometry(self, particles, weights): # use only important particels - combined_prt_weight = zip(self.particles, self.weights) - selected_prt_weight = zip(*sorted(combined_prt_weight, key = itemgetter(1), reverse = True)[:int(self.valid_particle_num)]) # [(p0, w0), (p1, w1), ..., (pN, wN)] -> [(sorted_p0, sorted_w0), (sorted_p1, sorted_w1), ..., (sorted_pN', sorted_wN')] -> [(sorted_p0, ..., sorted_pN'), (sorted_w0, ..., sorted_wN')] + combined_prt_weight = list(zip(self.particles, self.weights)) + selected_prt_weight = list(zip(*sorted(combined_prt_weight, key = itemgetter(1), reverse = True)[:int(self.valid_particle_num)])) # [(p0, w0), (p1, w1), ..., (pN, wN)] -> [(sorted_p0, sorted_w0), (sorted_p1, sorted_w1), ..., (sorted_pN', sorted_wN')] -> [(sorted_p0, ..., sorted_pN'), (sorted_w0, ..., sorted_wN')] # estimate gaussian distribution for Odometry msg mean, cov = self.guess_normal_distribution(selected_prt_weight[0], selected_prt_weight[1]) # overwrite pose pdf diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py index 36c454edecb..4c15b2b7be2 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py @@ -154,7 +154,7 @@ def resampling(self, particles, weights): def state_transition_probability_rvs(self, u, u_cov): # rvs = Random Varieties Sampling u_mean = [u.linear.x, u.linear.y, u.linear.z, u.angular.x, u.angular.y, u.angular.z] - u_cov_matrix = zip(*[iter(u_cov)]*6) + u_cov_matrix = list(zip(*[iter(u_cov)]*6)) return numpy.random.multivariate_normal(u_mean, u_cov_matrix, int(self.particle_num)).tolist() # input: x(pose), mean(array), cov_inv(matrix), output: pdf value for x @@ -207,8 +207,8 @@ def publish_odometry(self): self.odom.header.stamp = self.source_odom.header.stamp self.odom.twist = self.source_odom.twist # use only important particels - combined_prt_weight = zip(self.particles, self.weights) - selected_prt_weight = zip(*sorted(combined_prt_weight, key = itemgetter(1), reverse = True)[:int(self.valid_particle_num)]) # [(p0, w0), (p1, w1), ..., (pN, wN)] -> [(sorted_p0, sorted_w0), (sorted_p1, sorted_w1), ..., (sorted_pN', sorted_wN')] -> [(sorted_p0, ..., sorted_pN'), (sorted_w0, ..., sorted_wN')] + combined_prt_weight = list(zip(self.particles, self.weights)) + selected_prt_weight = list(zip(*sorted(combined_prt_weight, key = itemgetter(1), reverse = True)[:int(self.valid_particle_num)])) # [(p0, w0), (p1, w1), ..., (pN, wN)] -> [(sorted_p0, sorted_w0), (sorted_p1, sorted_w1), ..., (sorted_pN', sorted_wN')] -> [(sorted_p0, ..., sorted_pN'), (sorted_w0, ..., sorted_wN')] # estimate gaussian distribution for Odometry msg mean, cov = self.guess_normal_distribution(selected_prt_weight[0], selected_prt_weight[1]) self.odom.pose.pose = self.convert_list_to_pose(mean) @@ -318,7 +318,7 @@ def make_histogram_array(self, particles, stamp): histogram_array_msg.histograms.append(range_msg) # count particle_array = numpy.array([self.convert_pose_to_list(prt) for prt in particles]) - data = zip(*particle_array) # [(x_data), (y_data), ..., (yaw_data)] + data = list(zip(*particle_array)) # [(x_data), (y_data), ..., (yaw_data)] for i, d in enumerate(data): hist, bins = numpy.histogram(d, bins=50) for count, min_value, max_value in zip(hist, bins[:-1], bins[1:]): From 9f3648a0747b18765b6e9d121aac111b05788029 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Thu, 15 Jul 2021 12:38:10 +0900 Subject: [PATCH 40/44] use input/raw_input for pythoh2-3 compatibility --- .../roseus_remote/scripts/roseus_command_sender.py | 5 ++++- jsk_robot_common/roseus_remote/scripts/test.py | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py b/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py index c0133c53b69..6e976791a79 100755 --- a/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py +++ b/jsk_robot_common/roseus_remote/scripts/roseus_command_sender.py @@ -6,6 +6,9 @@ import rospy from roseus_remote.msg import RawCommand +# use raw_input for python2 c.f. https://stackoverflow.com/questions/5868506/backwards-compatible-input-calls-in-python +if hasattr(__builtins__, 'raw_input'): + input = raw_input def cmd_res_cb(msg): input_str = str(msg.data).rstrip(' \t\r\n\0') @@ -22,7 +25,7 @@ def main(): sub = rospy.Subscriber("input", RawCommand, cmd_res_cb) while not rospy.is_shutdown(): try: - cmd = raw_input("roseus$ ") + cmd = input("roseus$ ") if cmd: pub.publish(RawCommand(data=cmd)) rospy.sleep(0.01) diff --git a/jsk_robot_common/roseus_remote/scripts/test.py b/jsk_robot_common/roseus_remote/scripts/test.py index 614247fa724..9c40468b216 100644 --- a/jsk_robot_common/roseus_remote/scripts/test.py +++ b/jsk_robot_common/roseus_remote/scripts/test.py @@ -14,6 +14,10 @@ except ImportError: from queue import Queue, Empty +# use raw_input for python2 c.f. https://stackoverflow.com/questions/5868506/backwards-compatible-input-calls-in-python +if hasattr(__builtins__, 'raw_input'): + input = raw_input + ON_POSIX = 'posix' in sys.builtin_module_names BUFF_SIZE = 1 @@ -52,7 +56,7 @@ def get_output(out, queue): while p.poll() is None: print("alive?: ", p.poll()) - cmd = raw_input('cmd$ ') + cmd = input('cmd$ ') p.stdin.write(cmd) p.stdin.flush() stdout = "" From 10307e46775b07d93451a27b03df54d3ad8cf0ac Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 16 Jul 2021 09:30:04 +0900 Subject: [PATCH 41/44] 2to3 -w -f import, all fixed code locates under src/jsk_robot_startup/, so I think it is ok --- .../jsk_robot_startup/CalculateOdomInitToBaseLinkTransform.py | 2 +- .../jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py | 4 ++-- .../src/jsk_robot_startup/OdometryFeedbackWrapper.py | 2 +- .../jsk_robot_startup/src/jsk_robot_startup/OdometryOffset.py | 2 +- .../src/jsk_robot_startup/ParticleOdometry.py | 2 +- .../src/jsk_robot_startup/lifelog/action_logger.py | 2 +- .../src/jsk_robot_startup/lifelog/base_trajectory_logger.py | 4 ++-- .../src/jsk_robot_startup/lifelog/mongo_record.py | 2 +- .../src/jsk_robot_startup/lifelog/object_detection_logger.py | 4 ++-- .../src/jsk_robot_startup/lifelog/tf_logger.py | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/CalculateOdomInitToBaseLinkTransform.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/CalculateOdomInitToBaseLinkTransform.py index fd55ac15dc2..146df83bb14 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/CalculateOdomInitToBaseLinkTransform.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/CalculateOdomInitToBaseLinkTransform.py @@ -6,7 +6,7 @@ from geometry_msgs.msg import Quaternion, Vector3, TransformStamped import tf import threading -from odometry_utils import make_homogeneous_matrix +from .odometry_utils import make_homogeneous_matrix class CalculateOdomInitToBaseLinkTransform(object): def __init__(self): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py index 2180a78724d..fa0377a9ce3 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/EKFGPFOdometry.py @@ -12,8 +12,8 @@ from nav_msgs.msg import Odometry from geometry_msgs.msg import PoseWithCovariance, TwistWithCovariance, Twist, Pose, Point, Quaternion, Vector3, TransformStamped -from ParticleOdometry import ParticleOdometry -from odometry_utils import norm_pdf_multivariate, transform_quaternion_to_euler, transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform +from .ParticleOdometry import ParticleOdometry +from .odometry_utils import norm_pdf_multivariate, transform_quaternion_to_euler, transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform class EKFGPFOdometry(ParticleOdometry): def __init__(self): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryFeedbackWrapper.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryFeedbackWrapper.py index e05424f4837..75f9515a74e 100755 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryFeedbackWrapper.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryFeedbackWrapper.py @@ -16,7 +16,7 @@ from dynamic_reconfigure.server import Server from jsk_robot_startup.cfg import OdometryFeedbackWrapperReconfigureConfig -from odometry_utils import transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform, make_homogeneous_matrix +from .odometry_utils import transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform, make_homogeneous_matrix class OdometryFeedbackWrapper(object): def __init__(self): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryOffset.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryOffset.py index f5f165b6808..ce9ee4e5751 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryOffset.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/OdometryOffset.py @@ -11,7 +11,7 @@ import copy from dynamic_reconfigure.server import Server from jsk_robot_startup.cfg import OdometryOffsetReconfigureConfig -from odometry_utils import make_homogeneous_matrix, update_twist_covariance, update_pose, update_pose_covariance, broadcast_transform, transform_local_twist_to_global, transform_local_twist_covariance_to_global +from .odometry_utils import make_homogeneous_matrix, update_twist_covariance, update_pose, update_pose_covariance, broadcast_transform, transform_local_twist_to_global, transform_local_twist_covariance_to_global class OdometryOffset(object): def __init__(self): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py index 4c15b2b7be2..737180e7c11 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/ParticleOdometry.py @@ -16,7 +16,7 @@ from sensor_msgs.msg import Imu from geometry_msgs.msg import PoseWithCovariance, TwistWithCovariance, Twist, Pose, Point, Quaternion, Vector3, TransformStamped from jsk_recognition_msgs.msg import HistogramWithRangeArray, HistogramWithRange, HistogramWithRangeBin -from odometry_utils import norm_pdf_multivariate, transform_quaternion_to_euler, transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform +from .odometry_utils import norm_pdf_multivariate, transform_quaternion_to_euler, transform_local_twist_to_global, transform_local_twist_covariance_to_global, update_pose, update_pose_covariance, broadcast_transform from diagnostic_msgs.msg import * class ParticleOdometry(object): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/action_logger.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/action_logger.py index 96363315f1d..d42e5d89f48 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/action_logger.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/action_logger.py @@ -13,7 +13,7 @@ import actionlib_msgs.msg from actionlib_msgs.msg import GoalID, GoalStatus -from logger_base import LoggerBase +from .logger_base import LoggerBase class ActionLogger(LoggerBase): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/base_trajectory_logger.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/base_trajectory_logger.py index f3ec4455afd..664f8fac94d 100755 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/base_trajectory_logger.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/base_trajectory_logger.py @@ -5,9 +5,9 @@ import numpy as np import rospy import pymongo -from transformations import TransformListener +from .transformations import TransformListener from geometry_msgs.msg import PoseWithCovarianceStamped -from logger_base import LoggerBase +from .logger_base import LoggerBase def quaternion_distance(q1, q2): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/mongo_record.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/mongo_record.py index d0c91403057..71803288c15 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/mongo_record.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/mongo_record.py @@ -6,7 +6,7 @@ import re import rospy import rostopic -from logger_base import LoggerBase +from .logger_base import LoggerBase REGEX = re.compile(r"\$\{param\s*(\S+)\s*\}") diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/object_detection_logger.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/object_detection_logger.py index 58c524540ce..4b607dade1e 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/object_detection_logger.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/object_detection_logger.py @@ -10,8 +10,8 @@ import rosgraph from geometry_msgs.msg import PoseStamped from posedetection_msgs.msg import ObjectDetection -from logger_base import LoggerBase -from transformations import TransformListener +from .logger_base import LoggerBase +from .transformations import TransformListener class ObjectDetectionLogger(LoggerBase): diff --git a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/tf_logger.py b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/tf_logger.py index a0dfed8fa8d..38192b7737a 100644 --- a/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/tf_logger.py +++ b/jsk_robot_common/jsk_robot_startup/src/jsk_robot_startup/lifelog/tf_logger.py @@ -8,7 +8,7 @@ from tf2_msgs.srv import FrameGraph from tf2_msgs.msg import TFMessage from tf2_ros import ExtrapolationException -from logger_base import LoggerBase +from .logger_base import LoggerBase class TFLogger(LoggerBase): From 0d9df0ce558b9c3a1a3c6dd2a4e580f933bf4a70 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 16 Jul 2021 09:35:03 +0900 Subject: [PATCH 42/44] add python2 check --- .github/workflows/python2.yml | 24 ++++++++++++++++++++++++ .travis.yml | 2 ++ 2 files changed, 26 insertions(+) create mode 100644 .github/workflows/python2.yml diff --git a/.github/workflows/python2.yml b/.github/workflows/python2.yml new file mode 100644 index 00000000000..f974b88d5aa --- /dev/null +++ b/.github/workflows/python2.yml @@ -0,0 +1,24 @@ +# generated by `./generate_action_config.py noetic` +# jsk_travis +on: + push: + branches: + - master + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + name: check_python2 + + container: ubuntu:20.04 + + steps: + - name: Install latest git to download .git directory in actions/checkout@v2 ( use sudo for ros-ubuntu ) + run: apt-get update && apt-get install -y software-properties-common && apt-get update && add-apt-repository -y ppa:git-core/ppa && apt-get update && apt-get install -y git + - name: Chcekout + uses: actions/checkout@v2 + - name: Check Python2 + run: | + apt update -q && apt install -y -q python2 + python2 -m compileall . diff --git a/.travis.yml b/.travis.yml index 2a6101c46e2..ebe9561bce8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ env: - NOT_TEST_INSTALL=true matrix: - CHECK_PYTHON3_COMPILE=true + - CHECK_PYTHON2_COMPILE=true - ROS_DISTRO=hydro USE_DEB=true - ROS_DISTRO=hydro USE_DEB=false EXTRA_DEB="ros-hydro-convex-decomposition ros-hydro-ivcon" BUILD_PKGS="jsk_pr2_calibration jsk_robot_startup pr2_base_trajectory_action jsk_pr2_startup jsk_pr2_desktop" - ROS_DISTRO=indigo USE_DEB=true TEST_PKGS="jsk_robot_startup" # app_manager required to pass jsk_fetch test, so this job mainly test if we can build sources @@ -57,4 +58,5 @@ before_script: - export BEFORE_SCRIPT="apt-get download ros-$ROS_DISTRO-julius; wget -O stripdeb.sh https://gist.githubusercontent.com/jordansissel/748313/raw/8aebce360bc082e33af7bba3c90f755eb655783b/stripdeb.sh; bash stripdeb.sh ros-$ROS_DISTRO-julius*.deb; sudo dpkg --force-all -i ros-$ROS_DISTRO-julius*.deb; sudo apt-get -y -f install; sudo apt-mark hold ros-$ROS_DISTRO-julius; $BEFORE_SCRIPT" script: - if [ "${CHECK_PYTHON3_COMPILE}" == "true" ]; then bash -c "ret=0; trap 'ret=1' ERR; python3 -m compileall .; 2to3 -w -f except -f execfile -f has_key -f import -f raw_input -f zip .; git diff --exit-code . :^.travis > /dev/null; echo Exitting with \$ret; exit \$ret"; exit $?; fi + - if [ "${CHECK_PYTHON2_COMPILE}" == "true" ]; then python2 -m compileall .; exit $?; fi - source .travis/travis.sh From 847400234631656e2e0e2abe99e8322b875f4c63 Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 16 Jul 2021 09:38:14 +0900 Subject: [PATCH 43/44] 2to3 -w -f numliterals .; for 0777 -> 0o777 --- .../jsk_pr2_startup/jsk_pr2_warning/battery_logger.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_warning/battery_logger.py b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_warning/battery_logger.py index d80cb5038aa..d334cdbbdb0 100755 --- a/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_warning/battery_logger.py +++ b/jsk_pr2_robot/jsk_pr2_startup/jsk_pr2_warning/battery_logger.py @@ -41,7 +41,7 @@ def __init__(self, out_dir): "Output directory path already exitsts as file: %s" % self.out_dir) orig_umask = os.umask(0) try: - os.makedirs(self.out_dir, 0777) + os.makedirs(self.out_dir, 0o777) finally: os.umask(orig_umask) @@ -68,7 +68,7 @@ def write(self, date, info): if not is_file_writable(filename): orig_umask = os.umask(0) try: - os.chmod(os.path.abspath(filename), 0777) + os.chmod(os.path.abspath(filename), 0o777) finally: os.umask(orig_umask) From 6c5f2ad5af10d5c72742ea2e93ae3408dd0c2b5d Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 16 Jul 2021 10:38:45 +0900 Subject: [PATCH 44/44] fix 2to3 -f has_keys, changes, for kinetic --- jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py | 8 ++++---- .../jsk_fetch_startup/scripts/roslaunch_depends.py | 8 ++++---- .../jsk_pepper_startup/script/roslaunch_depends.py | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py b/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py index 20fc73090bf..35c13dee649 100644 --- a/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py +++ b/jsk_aero_robot/jsk_aero_startup/test/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if 'value' in tag.attributes: + if 'value' in tag.attributes.keys(): return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif 'default' in tag.attributes: + elif 'default' in tag.attributes.keys(): return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if 'if' in tag.attributes: + if 'if' in tag.attributes.keys(): val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif 'unless' in tag.attributes: + elif 'unless' in tag.attributes.keys(): val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False diff --git a/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py b/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py index 3cf097a0f1e..119c056bb51 100644 --- a/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py +++ b/jsk_fetch_robot/jsk_fetch_startup/scripts/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if 'value' in tag.attributes: + if 'value' in tag.attributes.keys(): return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif 'default' in tag.attributes: + elif 'default' in tag.attributes.keys(): return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if 'if' in tag.attributes: + if 'if' in tag.attributes.keys(): val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif 'unless' in tag.attributes: + elif 'unless' in tag.attributes.keys(): val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False diff --git a/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py b/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py index 3cf097a0f1e..119c056bb51 100644 --- a/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py +++ b/jsk_naoqi_robot/jsk_pepper_startup/script/roslaunch_depends.py @@ -86,21 +86,21 @@ def __str__(self): def _get_arg_value(tag, context): name = tag.attributes['name'].value - if 'value' in tag.attributes: + if 'value' in tag.attributes.keys(): return resolve_args(tag.attributes['value'].value, context) elif name in context['arg']: return context['arg'][name] - elif 'default' in tag.attributes: + elif 'default' in tag.attributes.keys(): return resolve_args(tag.attributes['default'].value, context) else: raise RoslaunchDepsException("No value for arg [%s]"%(name)) def _check_ifunless(tag, context): - if 'if' in tag.attributes: + if 'if' in tag.attributes.keys(): val = resolve_args(tag.attributes['if'].value, context) if not convert_value(val, 'bool'): return False - elif 'unless' in tag.attributes: + elif 'unless' in tag.attributes.keys(): val = resolve_args(tag.attributes['unless'].value, context) if convert_value(val, 'bool'): return False