GitHub PullRequestReviewCommentEvent at 2014-01-28 23:22:26
Repository: baxter_sandbox
Actor: rethink-rlinsalata
Payload: {"comment":{"url":"https://api.github.com/repos/RethinkRobotics/baxter_sandbox/pulls/comments/9250404","id":9250404,"diff_hunk":"@@ -0,0 +1,402 @@\n+#!/usr/bin/env python\n+\n+# Copyright (c) 2013, Rethink Robotics\n+# All rights reserved.\n+#\n+# Redistribution and use in source and binary forms, with or without\n+# modification, are permitted provided that the following conditions are met:\n+#\n+# 1. Redistributions of source code must retain the above copyright notice,\n+#    this list of conditions and the following disclaimer.\n+# 2. Redistributions in binary form must reproduce the above copyright\n+#    notice, this list of conditions and the following disclaimer in the\n+#    documentation and/or other materials provided with the distribution.\n+# 3. Neither the name of the Rethink Robotics nor the names of its\n+#    contributors may be used to endorse or promote products derived from\n+#    this software without specific prior written permission.\n+#\n+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n+# POSSIBILITY OF SUCH DAMAGE.\n+\n+import cv\n+import cv_bridge\n+import rospy\n+import rospkg\n+import os\n+from PIL import Image, ImageDraw, ImageFont, ImageOps\n+from signal import SIGINT\n+import time\n+import copy\n+import json\n+\n+from baxter_interface import Navigator, RobotEnable, CameraController, Gripper\n+from brr_ui import (\n+    mk_process,\n+    rostopic_handler,\n+    ros_process,\n+    gen_msg,\n+    rgb_to_bgr,\n+    PIL_to_cv,\n+    cv_to_msg,\n+    msg_to_cv,\n+    overlay,\n+    BrrButton,\n+    BrrWindow,\n+    exit_with_return_code,\n+    kill_python_procs,\n+    python_proc_ids,\n+)\n+from sensor_msgs.msg import Image as ImageMsg\n+from baxter_core_msgs.srv import ListCameras\n+\n+class BrrUi():\n+    def __init__(self, windows, btn_context):\n+        self.topic = rostopic_handler('/robot/xdisplay', latch=True)\n+        self.status = RobotEnable()\n+        self._rp = rospkg.RosPack()\n+        self.font = ImageFont.truetype(self._rp.get_path('brr_ui') + '/share/FreeSerif.ttf', 25)\n+        self.windows = windows\n+        self.btn_context = btn_context\n+\n+        self.textHeight = self.font.getsize('W')[1]\n+        self.img = Image.new('RGB', (1024, 600), 'white')\n+        \n+        self.frames = {}\n+\n+        self.selected_btn_index = 0\n+        self.active_window = 'demo_1'\n+        self.active_example = False\n+        self.current_frame=None\n+        \n+\n+        self.navigators = {'left': Navigator('left'), 'right': Navigator('right')}\n+\n+        self.navigators['left'].button0_changed.connect(self.left_ok_pressed)\n+        self.navigators['right'].button0_changed.connect(self.right_ok_pressed)\n+\n+        self.navigators['left'].wheel_changed.connect(self.left_wheel_moved)\n+        self.navigators['right'].wheel_changed.connect(self.right_wheel_moved)\n+\n+        self.navigators['left'].button2_changed.connect(self.enable)\n+        self.navigators['right'].button2_changed.connect(self.enable)\n+\n+        self.navigators['left'].button1_changed.connect(self.back)\n+        self.navigators['right'].button1_changed.connect(self.back)\n+\n+\n+        self.recent_wheel = False\n+        self.wheel_time = 0\n+        self.wheel_states = {'left': self.navigators['left'].wheel, \n+                             'right': self.navigators['right'].wheel}\n+        \n+        self.cameras = {'left_hand': CameraController('left_hand_camera'), \n+                        'right_hand': CameraController('right_hand_camera'),\n+                        'head': CameraController('head_camera')}\n+        self.cam_sub = ''\n+\n+        self.l_grip = {'interface': Gripper('left'), 'type': 'custom'}\n+        self.r_grip = {'interface': Gripper('right'), 'type': 'custom'}\n+        rospy.Timer(rospy.Duration(.5), self.update_grippers)\n+    \n+        self.enable()\n+        mk_process('rosrun baxter_tools tuck_arms.py -u')\n+\n+    def enable_cuff(self):\n+        if len(python_proc_ids('gripper_cuff_control')) == 0:\n+            ros_process('rosrun baxter_examples gripper_cuff_control.py')\n+\n+    def update_grippers(self, event):\n+        new_l = self.l_grip['interface'].type()\n+        new_r = self.r_grip['interface'].type()\n+        if new_l != self.l_grip['type']:\n+            self.l_grip['type'] = new_l\n+            if new_l == 'electric':\n+                self.l_grip['interface'].calibrate()\n+        if new_r != self.r_grip['type']:\n+            self.r_grip['type'] = new_r\n+            if new_r == 'electric':\n+                self.r_grip['interface'].calibrate()\n+        self.enable_cuff()\n+\n+    def selected(self):\n+        return self.windows[self.active_window].selected_btn()\n+\n+    '''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+    # Main Draw function.\n+    # Converts the appropriate frame to a ros message and sends \n+    #     it to the screen.\n+    # Also sets the current_frame parameter, in expectation of \n+    #     future hooks to merge images into the current view\n+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'''\n+\n+    def draw(self):\n+        img = Image.new('RGB', (1024, 600), 'white')\n+        d = ImageDraw.Draw(img)\n+        print self.active_window\n+        img = gen_msg(self.draw_window(img, d, self.active_window))\n+        self.img = img\n+        msg = cv_to_msg(img)\n+        self.topic.pub(msg)\n+        rospy.sleep(.1)\n+\n+    def draw_window(self, img, draw, window, selected=True):\n+        if self.windows[window].parent:\n+            print '--@draw_window: drawing parent: %s' % self.windows[window].parent\n+            img = self.draw_window(img, draw, window=self.windows[window].parent, selected=False)\n+        return self.windows[window].draw(img, draw, selected)\n+\n+    '''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+    # Functions linking wheel turns with scrolling in the UI\n+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'''\n+\n+    def left_wheel_moved(self, v):\n+        self.wheel_moved(v, 'left')\n+\n+    def right_wheel_moved(self, v):\n+        self.wheel_moved(v, 'right')\n+\n+    def wheel_moved(self, v, side):\n+        print '--@wheel_moved():  v=%s    side=%s   last=%s ok=%s' % (v, side, self.wheel_states[side], self.wheel_ok())\n+        print 'active?: %s' % self.active_example\n+        if not self.active_example and self.wheel_ok():\n+            print \"?\"\n+            wheel = self.wheel_states[side]\n+            if v > wheel and v-wheel < 100:\n+                self.scroll(1)\n+            else:\n+                self.scroll(-1)\n+            self.wheel_states[side] = v \n+            self.recent_wheel = True\n+            self.wheel_time = time.time()\n+\n+    def wheel_ok(self):\n+        return (self.recent_wheel==False or time.time()-self.wheel_time > .01)\n+\n+    def scroll(self, direction):\n+        print '--@scroll():  direction=%s' % direction\n+        if not self.windows[self.active_window].no_scroll:\n+            self.inc_scroll(direction)\n+            i=0\n+            while True:\n+                i+=1\n+                if self.selected().selectable == False:\n+                    self.inc_scroll(direction)\n+                else:\n+                    break\n+                if i > len(self.windows[self.active_window].buttons):\n+                    break\n+            self.draw()\n+\n+    def inc_scroll(self, inc):\n+        win_name = self.active_window\n+        win = self.windows[self.active_window]\n+        btn_index = win.selected_btn_index\n+        print \"--@inc_scroll: btn_index = %s\" % btn_index\n+        if inc==1:\n+            if btn_index < len(win.buttons)-1:\n+                self.windows[win_name].selected_btn_index += 1\n+        else:\n+            if btn_index > 0:\n+                self.windows[win_name].selected_btn_index -= 1\n+\n+    '''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+    # Functions linking pressing the OK button on either arm with \n+    #     the currently selected example\n+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'''\n+\n+    def left_ok_pressed(self, v):\n+        self.ok_pressed(v, 'left')\n+\n+    def right_ok_pressed(self, v):\n+        self.ok_pressed(v, 'right')\n+    \n+    def ok_pressed(self, v, side):\n+        if v == True:\n+            context = self.btn_context[self.windows[self.active_window].selected_btn().name]\n+            func = self.btn_context[self.selected().name]['function']\n+            if func==\"Back\":\n+                self.kill_examples()\n+            self.active_window = context['nextWindow']\n+            self.draw()\n+            if func and func != \"Back\":\n+                globals()[func](side)\n+\n+    def back(self, v):\n+        if v == True:\n+            if self.windows[self.active_window].parent:\n+                self.kill_examples()\n+                self.active_window = self.windows[self.active_window].parent\n+                self.draw()\n+\n+    '''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+    # Commands to enable the robot (if it is disabled when the demo\n+    #     starts) and to kill all currently running examples.\n+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'''\n+\n+    def kill_examples(self, v=1):\n+        print '--@kill_examples'\n+        self.active_example = False\n+        self.selected().status = 'selected'\n+        commands = ['joint_torque', 'wobbler', 'puppet', 'joint', 'baxter_interface', 'baxter_examples']\n+        for cmd in commands:\n+            kill_python_procs(cmd)\n+        for camera in self.cameras:\n+            self.cameras[camera].close()\n+        if self.cam_sub != '':\n+            self.cam_sub.unregister()\n+        self.draw()\n+        self.enable()\n+    \n+\n+    def enable(self, v=1):\n+        if v==1:\n+            try:\n+                self.status.enable()\n+            except:\n+                self.error_screen('stopped')\n+                return false\n+            if not self.status.state().enabled:\n+                self.error_screen('no_enable')\n+        self.enable_cuff()\n+\n+    def error_screen(self, error):\n+        self.windows[error].parent = self.active_window\n+        self.active_window = error\n+        self.draw()\n+\n+def cam_right(side):\n+    camera_disp('right_hand')\n+def cam_left(side):\n+    camera_disp('left_hand')\n+def cam_head(side):\n+    camera_disp('head')\n+def camera_disp(side):\n+    def _display(camera, name):\n+        camera.close()","path":"brr_ui/scripts/launch_ui.py","position":284,"original_position":284,"commit_id":"b4ce963b0fa290a295c3b4a9579835ed6b02b8ba","original_commit_id":"b4ce963b0fa290a295c3b4a9579835ed6b02b8ba","user":{"login":"rethink-rlinsalata","id":3229231,"avatar_url":"https://gravatar.com/avatar/c0f214d6bf2a97da93b081b60750aaf3?d=https%3A%2F%2Fidenticons.github.com%2F95b78ba1c61620f7e67234880c930bbe.png&r=x","gravatar_id":"c0f214d6bf2a97da93b081b60750aaf3","url":"https://api.github.com/users/rethink-rlinsalata","html_url":"https://github.com/rethink-rlinsalata","followers_url":"https://api.github.com/users/rethink-rlinsalata/followers","following_url":"https://api.github.com/users/rethink-rlinsalata/following{/other_user}","gists_url":"https://api.github.com/users/rethink-rlinsalata/gists{/gist_id}","starred_url":"https://api.github.com/users/rethink-rlinsalata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rethink-rlinsalata/subscriptions","organizations_url":"https://api.github.com/users/rethink-rlinsalata/orgs","repos_url":"https://api.github.com/users/rethink-rlinsalata/repos","events_url":"https://api.github.com/users/rethink-rlinsalata/events{/privacy}","received_events_url":"https://api.github.com/users/rethink-rlinsalata/received_events","type":"User","site_admin":false},"body":"don't need the close() call, I believe","created_at":"2014-01-28T23:22:26Z","updated_at":"2014-01-28T23:22:26Z","html_url":"https://github.com/RethinkRobotics/baxter_sandbox/pull/2#discussion_r9250404","pull_request_url":"https://api.github.com/repos/RethinkRobotics/baxter_sandbox/pulls/2","_links":{"self":{"href":"https://api.github.com/repos/RethinkRobotics/baxter_sandbox/pulls/comments/9250404"},"html":{"href":"https://github.com/RethinkRobotics/baxter_sandbox/pull/2#discussion_r9250404"},"pull_request":{"href":"https://api.github.com/repos/RethinkRobotics/baxter_sandbox/pulls/2"}}}}