├── xml_rpc_on_robot ├── xml_request_list_methods.xml ├── xml_request_rg_calibration.xml ├── xml_request_get_rg_width.xml ├── xml_request_sys_method_help.xml ├── xml_request_vg10_get_vacuum.xml ├── twofg │ ├── xml_request_get_twofg_status.xml │ ├── xml_request_get_twofg_width.xml │ ├── xml_request_get_all_twofg_variables.xml │ ├── xml_request_twofg_grip.xml │ └── get_all_twofg_variables_response.xml ├── xml_request_get_all_rg_variables.xml ├── xml_request_add.xml ├── xml_request_grip.xml ├── xml_request_vg10_grip.xml ├── xml_request_vg10_release.xml ├── README.md ├── get_all_rg_variables_response.xml ├── to_do_list.txt ├── .vscode │ └── settings.json ├── test.py └── list_methods_response.xml ├── onRobot ├── onRobot │ ├── __init_.py │ └── gripper.py └── setup.py ├── .gitignore ├── LICENSE ├── README.md └── UOY-logo.svg /xml_rpc_on_robot/xml_request_list_methods.xml: -------------------------------------------------------------------------------- 1 | 2 | system.listMethods 3 | 4 | -------------------------------------------------------------------------------- /onRobot/onRobot/__init_.py: -------------------------------------------------------------------------------- 1 | """ 2 | onRobot 3 | 4 | An onRobot python library. 5 | """ 6 | 7 | __version__ = "0.1.0" 8 | __author__ = 'Ryan McKenna' 9 | __credits__ = 'The University of York' 10 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_rg_calibration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rg_calibration 4 | 5 | 6 | 1.1 7 | 8 | 9 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_get_rg_width.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rg_get_width 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_sys_method_help.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | system.methodSignature 4 | 5 | 6 | vg10_release 7 | 8 | 9 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_vg10_get_vacuum.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | vg10_get_vacuum 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/twofg/xml_request_get_twofg_status.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | twofg_get_status 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/twofg/xml_request_get_twofg_width.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | twofg_get_max_force 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_get_all_rg_variables.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rg_get_all_variables 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/twofg/xml_request_get_all_twofg_variables.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | twofg_get_all_variables 4 | 5 | 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | add 4 | 5 | 6 | 111 7 | 8 | 9 | 222 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | onRobot/dist/onRobot-0.1.0-py2.py3-none-any.whl 2 | onRobot/dist/onRobot-0.1.0.tar.gz 3 | onRobot/onRobot.egg-info/dependency_links.txt 4 | onRobot/onRobot.egg-info/PKG-INFO 5 | onRobot/onRobot.egg-info/SOURCES.txt 6 | onRobot/onRobot.egg-info/top_level.txt 7 | onRobot/build/lib/onRobot/gripper.py 8 | onRobot/build/lib/onRobot/__init_.py 9 | onRobot/dist/onRobot-0.1.0-py3-none-any.whl 10 | onRobot/onRobot/__pycache__/gripper.cpython-38.pyc 11 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_grip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rg_grip 4 | 5 | 6 | 0 7 | 8 | 9 | 30.0 10 | 11 | 12 | 0.6 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_vg10_grip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | vg10_grip 4 | 5 | 6 | 0 7 | 8 | 9 | 2 10 | 11 | 12 | 10.0 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/twofg/xml_request_twofg_grip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | twofg_grip_external 4 | 5 | 6 | 0 7 | 8 | 9 | 30.0 10 | 11 | 12 | 0.6 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/xml_request_vg10_release.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | vg10_release 4 | 5 | 6 | 0 7 | 8 | 9 | 1 10 | 11 | 12 | 1 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/README.md: -------------------------------------------------------------------------------- 1 | # All rg2 function names, implement each one in python or c++ 2 | 3 | rg_stop 4 | rg_grip 5 | rg_calibration 6 | rg_get_all_variables 7 | rg_get_all_double_variables 8 | rg_get_all_integer_variable> 9 | rg_get_all_boolean_variable> 10 | rg_get_speed 11 | rg_get_depth 12 | rg_get_relative_depth 13 | rg_get_angle 14 | rg_get_angle_speed 15 | rg_get_width 16 | rg_get_fingertip_offset 17 | rg_get_status 18 | rg_get_busy 19 | rg_get_grip_detected 20 | rg_get_s1_pushed 21 | rg_get_s1_triggered 22 | rg_get_s2_pushed 23 | rg_get_s2_triggered 24 | rg_get_safety_failed 25 | rg_set_fingertip_offset -------------------------------------------------------------------------------- /onRobot/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='onRobot', 5 | version='0.1.0', 6 | description='A simple gripper library for UR robot with onRobot gripper, no onrobot compute box needed!', 7 | url='https://github.com/RyanPaulMcKenna/onRobot', 8 | author='Ryan McKenna', 9 | author_email='ryan.mckenna@york.ac.uk', 10 | license='MIT', 11 | packages=['onRobot'], 12 | install_requires=[], 13 | classifiers=[ 14 | 'Development Status :: 1 - Planning', 15 | 'Intended Audience :: Science/Research', 16 | 'License :: OSI Approved :: BSD License', 17 | 'Operating System :: POSIX :: Linux', 18 | 'Programming Language :: Python :: 2.7', 19 | 'Programming Language :: Python :: 3', 20 | ], 21 | ) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 The University of York, Ryan McKenna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/get_all_rg_variables_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | angle 6 | 126.8000030517578 7 | angle_speed 8 | 2395.10009765625 9 | busy 10 | 0 11 | depth 12 | 38.5 13 | fingertip_offset 14 | 4.599999904632568 15 | relative_depth 16 | 2.5 17 | s1_pushed 18 | 0 19 | s1_triggered 20 | 0 21 | s2_pushed 22 | 0 23 | s2_triggered 24 | 0 25 | safety_failed 26 | 0 27 | speed 28 | 0 29 | status 30 | 0 31 | width 32 | 100.8000030517578 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/twofg/get_all_twofg_variables_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | busy 6 | 0 7 | error_linear_sensor 8 | 0 9 | error_not_calibrated 10 | 0 11 | external_width 12 | 70.3000030517578 13 | finger_height 14 | 45 15 | finger_length 16 | 8.5 17 | finger_orientation_outward 18 | 1 19 | fingertip_offset 20 | 3.5 21 | force 22 | 2 23 | grip_detected 24 | 0 25 | internal_width 26 | 84.3000030517578 27 | max_external_width 28 | 71 29 | max_force 30 | 140 31 | max_internal_width 32 | 85 33 | min_external_width 34 | 33 35 | min_internal_width 36 | 47 37 | status 38 | 0 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/to_do_list.txt: -------------------------------------------------------------------------------- 1 | # To do list 2 | 3 | Now I can control robot through ext ctrl and move with ros controllers. 4 | 5 | I can also move the onRobot gripper, however I want to without it interferring with ros 6 | or the ext control program in anyway. 7 | 8 | I need to put all this behaviour in a fully abstracted ros node. 9 | 10 | This method is purely using http requests to send xml files to the xmlrpc server. 11 | 12 | So I wil need to save most recent values of gripper set to keep them up to date 13 | for my whole ros program. 14 | 15 | 1. change robot description to the one that has the onRobot rg2 gripper. 16 | do this in the the standard launch command and in rviz, you can now also use move it 17 | if neccessary. 18 | 2. You will to write some classes and files that abstract this networking and interface with ros 19 | neatly as a package would. Keep track of gripper variables and use them to update rviz. 20 | rviz likely just subscribes to some topic that makes them available you just need to 21 | make a publisher and link it up. 22 | 23 | Here are the commands I used to work it out: 24 | curl -X POST -d @xml_request_add.xml 192.168.0.99:41414 25 | curl -X POST -d @xml_request_add.xml 192.168.0.99:31416 26 | 27 | If use extra sensors I can wire them into the power and analog inputs on the control box. 28 | 29 | Somehow need to read from these analog inputs passively in a way that doesn't interfere with 30 | ros or the http requests for the gripper. 31 | 32 | Maybe I can set up on robot fieldbus or modbus that or a just a socat device that can read from those 33 | analog inputs and set the values in registers that I can access by modbus client on my machine 34 | 35 | 36 | 37 | 38 | All the info about move it and rviz is here 39 | https://github.com/UniversalRobots/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/doc/usage_example.md 40 | 41 | 42 | Here is the urdf 43 | https://github.com/AndrejOrsula/ur5_rg2_ign -------------------------------------------------------------------------------- /xml_rpc_on_robot/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "ostream": "cpp", 4 | "cctype": "cpp", 5 | "clocale": "cpp", 6 | "cmath": "cpp", 7 | "cstdarg": "cpp", 8 | "cstddef": "cpp", 9 | "cstdio": "cpp", 10 | "cstdlib": "cpp", 11 | "cstring": "cpp", 12 | "ctime": "cpp", 13 | "cwchar": "cpp", 14 | "cwctype": "cpp", 15 | "array": "cpp", 16 | "atomic": "cpp", 17 | "hash_map": "cpp", 18 | "hash_set": "cpp", 19 | "strstream": "cpp", 20 | "*.tcc": "cpp", 21 | "bitset": "cpp", 22 | "chrono": "cpp", 23 | "codecvt": "cpp", 24 | "complex": "cpp", 25 | "condition_variable": "cpp", 26 | "cstdint": "cpp", 27 | "deque": "cpp", 28 | "list": "cpp", 29 | "unordered_map": "cpp", 30 | "unordered_set": "cpp", 31 | "vector": "cpp", 32 | "exception": "cpp", 33 | "algorithm": "cpp", 34 | "filesystem": "cpp", 35 | "functional": "cpp", 36 | "iterator": "cpp", 37 | "map": "cpp", 38 | "memory": "cpp", 39 | "memory_resource": "cpp", 40 | "numeric": "cpp", 41 | "optional": "cpp", 42 | "random": "cpp", 43 | "ratio": "cpp", 44 | "set": "cpp", 45 | "string": "cpp", 46 | "string_view": "cpp", 47 | "system_error": "cpp", 48 | "tuple": "cpp", 49 | "type_traits": "cpp", 50 | "utility": "cpp", 51 | "fstream": "cpp", 52 | "future": "cpp", 53 | "initializer_list": "cpp", 54 | "iomanip": "cpp", 55 | "iosfwd": "cpp", 56 | "iostream": "cpp", 57 | "istream": "cpp", 58 | "limits": "cpp", 59 | "mutex": "cpp", 60 | "new": "cpp", 61 | "sstream": "cpp", 62 | "stdexcept": "cpp", 63 | "streambuf": "cpp", 64 | "thread": "cpp", 65 | "cfenv": "cpp", 66 | "cinttypes": "cpp", 67 | "typeindex": "cpp", 68 | "typeinfo": "cpp", 69 | "variant": "cpp", 70 | "bit": "cpp" 71 | } 72 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # onRobot 2 | 3 | A simple gripper library to use a Universal Robot with an onRobot gripper, no onrobot compute box needed. 4 | Please note you must install the URcap file on the UR teach pendant. 5 | You must also have set all the correct IP addresses in the networking settings of the UR Teach Pendant and the computer you are connecting to the Robot via the ethernet. 6 | 7 | 8 | # Supported onRobot Grippers 9 | - [x] RG2 10 | - [x] VG10 11 | - [x] 2FG7 12 | - [ ] Gecko 13 | - [ ] SG 14 | - [ ] TFG 15 | - [ ] SDR 16 | - [ ] 2FG 17 | - [ ] MG 18 | - [ ] FGP 19 | 20 | **See further down for usage examples** 21 | 22 | - Simple and easy to use! 23 | - No onRobot compute box needed! 24 | - Communicates with XML-RPC interface so is compatible with ROS driver! 25 | - Contributions welcome! 26 | - onRobot URcap must be installed on Universal Robots Teach Pendant. 27 | 28 | # Install instructions 29 | 30 | ```bash 31 | 32 | pip install onrobot 33 | 34 | 35 | ``` 36 | # Example Usage 37 | 38 | ```python 39 | import onRobot.gripper as gripper 40 | 41 | rg_id = 0 42 | ip = "192.168.56.101" 43 | rg_gripper = gripper.RG2(ip,rg_id) 44 | 45 | rg_width = rg_gripper.get_rg_width() 46 | print("rg_width: ",rg_width) 47 | 48 | target_force = 40.00 49 | 50 | rg_gripper.rg_grip(100.0, target_force) 51 | 52 | 53 | 54 | ``` 55 | 56 | 57 | # Functions implemented for the RG2 58 | 59 | - [ ] rg_stop 60 | - [x] rg_grip 61 | - [ ] rg_calibration 62 | - [ ] rg_get_all_variables 63 | - [ ] rg_get_all_double_variables 64 | - [ ] rg_get_all_integer_variable> 65 | - [ ] rg_get_all_boolean_variable> 66 | - [ ] rg_get_speed 67 | - [ ] rg_get_depth 68 | - [ ] rg_get_relative_depth 69 | - [ ] rg_get_angle 70 | - [ ] rg_get_angle_speed 71 | - [x] rg_get_width 72 | - [ ] rg_get_fingertip_offset 73 | - [ ] rg_get_status 74 | - [ ] rg_get_busy 75 | - [ ] rg_get_grip_detected 76 | - [ ] rg_get_s1_pushed 77 | - [ ] rg_get_s1_triggered 78 | - [ ] rg_get_s2_pushed 79 | - [ ] rg_get_s2_triggered 80 | - [ ] rg_get_safety_failed 81 | - [ ] rg_set_fingertip_offset 82 | 83 | 84 | # Functions implemented for the VG10 85 | - [x] vg10_grip 86 | - [x] vg10_release 87 | - [] vg10_idle 88 | - [] vg10_get_vacuum 89 | - [] vg10_get_all_double_variables 90 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/test.py: -------------------------------------------------------------------------------- 1 | import pycurl 2 | import xmlrpc.client 3 | from io import BytesIO 4 | 5 | 6 | class OnRobotRG2Gripper: 7 | def __init__(self, rg_id: int = 0) -> None: 8 | self.rg_id = rg_id 9 | self.rg_width = None 10 | self.rg_force = None 11 | 12 | def clear_cache(self) -> None: 13 | self.rg_width = None 14 | self.rg_force = None 15 | 16 | def get_rg_force(self) -> float: 17 | return self.rg_force 18 | 19 | def get_rg_width(self) -> float: 20 | xml_request = f""" 21 | 22 | rg_get_width 23 | 24 | 25 | {self.rg_id} 26 | 27 | 28 | """ 29 | 30 | headers = ["Content-Type: application/x-www-form-urlencoded"] 31 | 32 | data = xml_request.replace('\r\n','').encode() 33 | 34 | # Create a new cURL object 35 | curl = pycurl.Curl() 36 | 37 | # Set the URL to fetch 38 | curl.setopt(curl.URL, 'http://192.168.56.101:41414') 39 | curl.setopt(curl.HTTPHEADER, headers) 40 | curl.setopt(curl.POSTFIELDS, data) 41 | # Create a BytesIO object to store the response 42 | buffer = BytesIO() 43 | curl.setopt(curl.WRITEDATA, buffer) 44 | 45 | # Perform the request 46 | curl.perform() 47 | 48 | # Get the response body 49 | response = buffer.getvalue() 50 | 51 | # Print the response 52 | print(response.decode('utf-8')) 53 | 54 | # Close the cURL object 55 | curl.close() 56 | 57 | xml_response = xmlrpc.client.loads(response.decode('utf-8')) 58 | rg_width = float(xml_response[0][0]) 59 | #print(rg_width) 60 | return rg_width 61 | 62 | 63 | def rg_grip(self, target_width: float = 100, target_force: float= 10) -> bool: 64 | #assert target_width <= 100 and target_width >= 0, 'Target Width must be within the range [0,100]' 65 | #assert target_force <= 40 or target_force >= 0, 'Target force must be within the range [0,40]' 66 | 67 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 68 | if (target_width > 100): 69 | target_width = 100 70 | if(target_width < 0): 71 | target_width = 0 72 | if(target_force > 40): 73 | target_force = 40 74 | if(target_force < 0): 75 | target_force = 0 76 | 77 | xml_request = f""" 78 | 79 | rg_grip 80 | 81 | 82 | {self.rg_id} 83 | 84 | 85 | {target_width} 86 | 87 | 88 | {target_force} 89 | 90 | 91 | """ 92 | 93 | headers = ["Content-Type: application/x-www-form-urlencoded"] 94 | 95 | # headers = ["User-Agent: Python-PycURL", "Accept: application/json"] 96 | data = xml_request.replace('\r\n','').encode() 97 | # Create a new cURL object 98 | curl = pycurl.Curl() 99 | 100 | # Set the URL to fetch 101 | curl.setopt(curl.URL, 'http://192.168.56.101:41414') 102 | curl.setopt(curl.HTTPHEADER, headers) 103 | curl.setopt(curl.POSTFIELDS, data) 104 | # Create a BytesIO object to store the response 105 | buffer = BytesIO() 106 | curl.setopt(curl.WRITEDATA, buffer) 107 | 108 | # Perform the request 109 | curl.perform() 110 | 111 | # Get the response body 112 | response = buffer.getvalue() 113 | 114 | # Print the response 115 | print(response.decode('utf-8')) 116 | 117 | # Close the cURL object 118 | curl.close() 119 | 120 | 121 | print("main") 122 | gripper = OnRobotRG2Gripper() 123 | gripper.rg_grip(0.0,15.0) 124 | -------------------------------------------------------------------------------- /xml_rpc_on_robot/list_methods_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | system.listMethods 6 | system.methodExist 7 | system.methodHelp 8 | system.methodSignature 9 | system.multicall 10 | system.shutdown 11 | system.capabilities 12 | system.getCapabilities 13 | set_toolconnector_mode 14 | set_toolconnector_simulator 15 | get_discovery 16 | cb_get_stop_devices_when_robot_is_stopped 17 | cb_enable_stop_devices_when_robot_is_stopped 18 | rg_stop 19 | rg_grip 20 | rg_calibration 21 | rg_get_all_variables 22 | rg_get_all_double_variables 23 | rg_get_all_integer_variables 24 | rg_get_all_boolean_variables 25 | rg_get_speed 26 | rg_get_depth 27 | rg_get_relative_depth 28 | rg_get_angle 29 | rg_get_angle_speed 30 | rg_get_width 31 | rg_get_fingertip_offset 32 | rg_get_status 33 | rg_get_busy 34 | rg_get_grip_detected 35 | rg_get_s1_pushed 36 | rg_get_s1_triggered 37 | rg_get_s2_pushed 38 | rg_get_s2_triggered 39 | rg_get_safety_failed 40 | rg_set_fingertip_offset 41 | vg10_grip 42 | vg10_release 43 | vg10_idle 44 | vg10_get_vacuum 45 | vg10_get_all_double_variables 46 | gecko_set_pad_position 47 | gecko_set_preload_spec 48 | gecko_reset_error_logs 49 | gecko_get_all_variables 50 | gecko_get_all_double_variables 51 | gecko_get_all_integer_variables 52 | gecko_get_all_boolean_variables 53 | gecko_get_preload_force 54 | gecko_get_ultrasonic 55 | gecko_get_part_detected 56 | gecko_get_pads_worn 57 | gecko_get_error 58 | gecko_get_pad_position 59 | gecko_get_busy 60 | sg_grip 61 | sg_initialize 62 | sg_stop 63 | sg_home 64 | sg_calibrate 65 | sg_get_all_variables 66 | sg_get_all_double_variables 67 | sg_get_all_integer_variables 68 | sg_get_all_boolean_variables 69 | sg_get_sg_tool_id 70 | sg_get_width 71 | sg_get_depth 72 | sg_get_depth_relative 73 | sg_get_depth_static_silicone 74 | sg_get_min_max 75 | sg_get_max_open 76 | sg_get_min_open 77 | sg_get_status 78 | sg_get_busy 79 | sg_get_initialized 80 | sg_get_grip_detected 81 | sg_get_calibrated 82 | sg_get_error 83 | tfg_move 84 | tfg_grip 85 | tfg_flexible_grip 86 | tfg_set_finger_position 87 | tfg_set_finger_length 88 | tfg_set_fingertip_offset 89 | tfg_set_power_limit 90 | tfg_stop 91 | tfg_get_all_variables 92 | tfg_get_all_double_variables 93 | tfg_get_all_integer_variables 94 | tfg_get_all_boolean_variables 95 | tfg_get_status 96 | tfg_get_busy 97 | tfg_get_grip_detected 98 | tfg_get_force_grip_detected 99 | tfg_get_calibration_valid 100 | tfg_get_safety_dc_error 101 | tfg_get_other_error 102 | tfg_get_diameter_raw 103 | tfg_get_diameter 104 | tfg_get_force 105 | tfg_get_finger_position 106 | tfg_get_finger_length 107 | tfg_get_fingertip_offset 108 | tfg_get_min_diameter 109 | tfg_get_max_diameter 110 | tfg_get_finger_setup 111 | sdr_stop 112 | sdr_start 113 | sdr_stop_gently 114 | sdr_set_button_led 115 | sdr_set_rpm_deviation_level 116 | sdr_set_vibration_limit_level_g 117 | sdr_get_all_variables 118 | sdr_get_all_double_variables 119 | sdr_get_all_integer_variables 120 | sdr_get_all_boolean_variables 121 | sdr_get_status 122 | sdr_get_warning 123 | sdr_get_current_rpm 124 | sdr_get_current_temp_c 125 | sdr_get_motor_voltage_v 126 | sdr_get_motor_power_w 127 | sdr_get_max_rpm_deviation_of_cycle 128 | sdr_get_vibration_g 129 | sdr_get_rpm_deviation_level 130 | sdr_get_vibration_limit_level_g 131 | sdr_get_accelerometer_x 132 | sdr_get_accelerometer_y 133 | sdr_get_accelerometer_z 134 | sdr_get_gyroscope_x 135 | sdr_get_gyroscope_y 136 | sdr_get_gyroscope_z 137 | sdr_get_ramp_up_speed 138 | sdr_get_ramp_down_speed 139 | sdr_get_pid_constant_p 140 | sdr_get_pid_constant_i 141 | sdr_get_pid_constant_d 142 | sdr_get_temp_limit_level_c 143 | sdr_get_disc_diameter 144 | sdr_get_orbit_size 145 | sdr_get_power_cycle_count 146 | sdr_get_over_temperature_count 147 | sdr_get_power_on_time_sec 148 | sdr_get_vibration_halt_count 149 | sdr_get_motor_on_time_sec 150 | sdr_get_rpm_deviation_count 151 | sdr_get_average_temperature 152 | sdr_get_average_vibration 153 | sdr_get_average_motor_speed 154 | sdr_get_average_motor_power 155 | sdr_get_motor_stopped 156 | sdr_get_motor_running 157 | sdr_get_motor_ramping_up 158 | sdr_get_motor_ramping_down 159 | sdr_get_button_pressed 160 | sdr_get_active_time_sec 161 | sdr_get_target_rpm 162 | sdr_get_error_flags 163 | sdr_clear_active_time_sec 164 | sdr_set_active_time_f3d_limit 165 | twofg_grip_external 166 | twofg_grip_internal 167 | twofg_stop 168 | twofg_set_finger_length 169 | twofg_set_finger_height 170 | twofg_set_finger_orientation 171 | twofg_set_fingertip_offset 172 | twofg_get_all_variables 173 | twofg_get_all_double_variables 174 | twofg_get_all_integer_variables 175 | twofg_get_all_boolean_variables 176 | twofg_get_status 177 | twofg_get_external_width 178 | twofg_get_internal_width 179 | twofg_get_min_external_width 180 | twofg_get_min_internal_width 181 | twofg_get_max_external_width 182 | twofg_get_max_internal_width 183 | twofg_get_force 184 | twofg_get_max_force 185 | twofg_get_finger_length 186 | twofg_get_finger_height 187 | twofg_get_finger_orientation_outward 188 | twofg_get_fingertip_offset 189 | twofg_get_busy 190 | twofg_get_grip_detected 191 | twofg_get_error_not_calibrated 192 | twofg_get_error_linear_sensor 193 | mg_grip 194 | mg_release 195 | mg_set_finger_settings 196 | mg_auto_calibrate 197 | mg_get_all_variables 198 | mg_get_all_double_variables 199 | mg_get_all_integer_variables 200 | mg_get_all_boolean_variables 201 | mg_get_status 202 | mg_get_magnet_strength_percent 203 | mg_get_error_code 204 | mg_get_finger_type 205 | mg_get_finger_height_mm 206 | mg_get_calibration_day 207 | mg_get_calibration_month 208 | mg_get_calibration_year 209 | mg_get_calibration_epoch 210 | mg_get_calibration_build 211 | mg_get_hall_calibration_day 212 | mg_get_hall_calibration_month 213 | mg_get_hall_calibration_year 214 | mg_get_hall_calibration_hour 215 | mg_get_hall_calibration_minute 216 | mg_get_hall_calibration_epoch 217 | mg_get_auto_calibrate_progress_percent 218 | mg_get_grip_detected 219 | mg_get_part_near 220 | mg_get_busy 221 | mg_get_magnet_strength_not_reached 222 | mg_get_smart_grip_available 223 | mg_get_smart_grip_failed 224 | mg_get_part_dropped 225 | fgp_vg_grip 226 | fgp_grip_external 227 | fgp_fg_stop 228 | fgp_vg_release 229 | fgp_set_fixed_finger_length 230 | fgp_set_fixed_finger_height 231 | fgp_set_fixed_fingertip_offset 232 | fgp_set_moving_finger_length 233 | fgp_set_moving_finger_height 234 | fgp_set_moving_fingertip_offset 235 | fgp_set_vacuum_cups_offset 236 | fgp_get_all_variables 237 | fgp_get_all_double_variables 238 | fgp_get_all_integer_variables 239 | fgp_get_all_boolean_variables 240 | fgp_get_status 241 | fgp_get_external_width 242 | fgp_get_min_external_width 243 | fgp_get_max_external_width 244 | fgp_get_force 245 | fgp_get_max_force 246 | fgp_get_fixed_finger_length 247 | fgp_get_fixed_finger_height 248 | fgp_get_fixed_fingertip_offset 249 | fgp_get_moving_finger_length 250 | fgp_get_moving_finger_height 251 | fgp_get_moving_fingertip_offset 252 | fgp_get_vg_vacuum_percent 253 | fgp_get_vg_grip_status 254 | fgp_get_vg_release_status 255 | fgp_get_busy 256 | fgp_get_fg_grip_detected 257 | fgp_get_error_motor_not_calibrated 258 | fgp_get_error_solenoid_not_calibrated 259 | fgp_get_error_encoders_not_calibrated 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /onRobot/onRobot/gripper.py: -------------------------------------------------------------------------------- 1 | import pycurl 2 | import xmlrpc.client 3 | from io import BytesIO 4 | 5 | # https://onrobot.com/sites/default/files/documents/VG10_Vacuun_Gripper_User_Manual_V1.1.1.pdf 6 | class VG10: 7 | def __init__(self, robot_ip, vg_id): 8 | self.vg_id = vg_id 9 | self.robot_ip = robot_ip 10 | 11 | def vg10_release(self, channelA: bool = True, channelB: bool = True): 12 | 13 | self.channelA = channelA # True/False 14 | self.channelB = channelB # True/False 15 | 16 | xml_request = f""" 17 | 18 | vg10_release 19 | 20 | 21 | {self.vg_id} 22 | 23 | 24 | {self.channelA} 25 | 26 | 27 | {self.channelB} 28 | 29 | 30 | """ 31 | 32 | headers = ["Content-Type: application/x-www-form-urlencoded"] 33 | 34 | # headers = ["User-Agent: Python-PycURL", "Accept: application/json"] 35 | data = xml_request.replace('\r\n','').encode() 36 | # Create a new cURL object 37 | curl = pycurl.Curl() 38 | 39 | # Set the URL to fetch 40 | curl.setopt(curl.URL, f'http://{self.robot_ip}:41414') 41 | curl.setopt(curl.HTTPHEADER, headers) 42 | curl.setopt(curl.POSTFIELDS, data) 43 | # Create a BytesIO object to store the response 44 | buffer = BytesIO() 45 | curl.setopt(curl.WRITEDATA, buffer) 46 | 47 | # Perform the request 48 | curl.perform() 49 | 50 | # Get the response body 51 | response = buffer.getvalue() 52 | 53 | # Print the response 54 | print(response.decode('utf-8')) 55 | 56 | # Close the cURL object 57 | curl.close() 58 | 59 | def vg10_grip(self, channel, vacuum_percent): 60 | 61 | self.channel = channel # 0,1,2 62 | self.vacuum_percent = vacuum_percent # softgrip => 30 = 30%, firm grip => 60 = 60% 63 | 64 | xml_request = f""" 65 | 66 | vg10_grip 67 | 68 | 69 | {self.vg_id} 70 | 71 | 72 | {self.channel} 73 | 74 | 75 | {self.vacuum_percent} 76 | 77 | 78 | 79 | """ 80 | 81 | headers = ["Content-Type: application/x-www-form-urlencoded"] 82 | 83 | # headers = ["User-Agent: Python-PycURL", "Accept: application/json"] 84 | data = xml_request.replace('\r\n','').encode() 85 | # Create a new cURL object 86 | curl = pycurl.Curl() 87 | 88 | # Set the URL to fetch 89 | curl.setopt(curl.URL, f'http://{self.robot_ip}:41414') 90 | curl.setopt(curl.HTTPHEADER, headers) 91 | curl.setopt(curl.POSTFIELDS, data) 92 | # Create a BytesIO object to store the response 93 | buffer = BytesIO() 94 | curl.setopt(curl.WRITEDATA, buffer) 95 | 96 | # Perform the request 97 | curl.perform() 98 | 99 | # Get the response body 100 | response = buffer.getvalue() 101 | 102 | # Print the response 103 | print(response.decode('utf-8')) 104 | 105 | # Close the cURL object 106 | curl.close() 107 | 108 | 109 | class RG2: 110 | def __init__(self, robot_ip, rg_id): 111 | self.rg_id = rg_id 112 | self.robot_ip = robot_ip 113 | 114 | def get_rg_width(self): 115 | xml_request = f""" 116 | 117 | rg_get_width 118 | 119 | 120 | {self.rg_id} 121 | 122 | 123 | """ 124 | 125 | headers = ["Content-Type: application/x-www-form-urlencoded"] 126 | 127 | data = xml_request.replace('\r\n','').encode() 128 | 129 | # Create a new cURL object 130 | curl = pycurl.Curl() 131 | 132 | # Set the URL to fetch 133 | curl.setopt(curl.URL, f'http://{self.robot_ip}:41414') 134 | curl.setopt(curl.HTTPHEADER, headers) 135 | curl.setopt(curl.POSTFIELDS, data) 136 | # Create a BytesIO object to store the response 137 | buffer = BytesIO() 138 | curl.setopt(curl.WRITEDATA, buffer) 139 | 140 | # Perform the request 141 | curl.perform() 142 | 143 | # Get the response body 144 | response = buffer.getvalue() 145 | 146 | # Print the response 147 | print(response.decode('utf-8')) 148 | 149 | # Close the cURL object 150 | curl.close() 151 | 152 | xml_response = xmlrpc.client.loads(response.decode('utf-8')) 153 | rg_width = float(xml_response[0][0]) 154 | #print(rg_width) 155 | return rg_width 156 | 157 | 158 | def rg_grip(self, target_width: float = 100, target_force: float= 10) -> bool: 159 | #assert target_width <= 100 and target_width >= 0, 'Target Width must be within the range [0,100]' 160 | #assert target_force <= 40 or target_force >= 0, 'Target force must be within the range [0,40]' 161 | 162 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 163 | # if (target_width > 100): 164 | # target_width = 100 165 | # if(target_width < 0): 166 | # target_width = 0 167 | # if(target_force > 40): 168 | # target_force = 40 169 | # if(target_force < 0): 170 | # target_force = 0 171 | 172 | xml_request = f""" 173 | 174 | rg_grip 175 | 176 | 177 | {self.rg_id} 178 | 179 | 180 | {target_width} 181 | 182 | 183 | {target_force} 184 | 185 | 186 | """ 187 | 188 | headers = ["Content-Type: application/x-www-form-urlencoded"] 189 | 190 | # headers = ["User-Agent: Python-PycURL", "Accept: application/json"] 191 | data = xml_request.replace('\r\n','').encode() 192 | # Create a new cURL object 193 | curl = pycurl.Curl() 194 | 195 | # Set the URL to fetch 196 | curl.setopt(curl.URL, f'http://{self.robot_ip}:41414') 197 | curl.setopt(curl.HTTPHEADER, headers) 198 | curl.setopt(curl.POSTFIELDS, data) 199 | # Create a BytesIO object to store the response 200 | buffer = BytesIO() 201 | curl.setopt(curl.WRITEDATA, buffer) 202 | 203 | # Perform the request 204 | curl.perform() 205 | 206 | # Get the response body 207 | response = buffer.getvalue() 208 | 209 | # Print the response 210 | print(response.decode('utf-8')) 211 | 212 | # Close the cURL object 213 | curl.close() 214 | 215 | 216 | class TwoFG7(): 217 | def __init__(self, robot_ip: str, id: int): 218 | self.robot_ip = robot_ip 219 | self.id = id 220 | 221 | self.max_force = self.twofg_get_max_force() 222 | self.max_ext_width = self.twofg_get_max_external_width() 223 | self.max_int_width = self.twofg_get_max_internal_width() 224 | self.min_ext_width = self.twofg_get_min_external_width() 225 | self.min_int_width = self.twofg_get_min_internal_width() 226 | 227 | self.gripper_width = [self.twofg_get_external_width(), self.twofg_get_internal_width()] 228 | 229 | 230 | def _send_xml_rpc_request(self, _req=None): 231 | 232 | headers = ["Content-Type: application/x-www-form-urlencoded"] 233 | 234 | data = _req.replace('\r\n','').encode() 235 | 236 | # Create a new cURL object 237 | curl = pycurl.Curl() 238 | 239 | # Set the URL to fetch 240 | curl.setopt(curl.URL, f'http://{self.robot_ip}:41414') 241 | curl.setopt(curl.HTTPHEADER, headers) 242 | curl.setopt(curl.POSTFIELDS, data) 243 | # Create a BytesIO object to store the response 244 | buffer = BytesIO() 245 | curl.setopt(curl.WRITEDATA, buffer) 246 | 247 | # Perform the request 248 | curl.perform() 249 | 250 | # Get the response body 251 | response = buffer.getvalue() 252 | 253 | # Print the response 254 | print(response.decode('utf-8')) 255 | 256 | # Close the cURL object 257 | curl.close() 258 | # Get response from xmlrpc server 259 | xml_response = xmlrpc.client.loads(response.decode('utf-8')) 260 | 261 | return xml_response[0][0] 262 | 263 | def twofg_get_external_width(self) -> float: 264 | xml_request = f""" 265 | 266 | twofg_get_external_width 267 | 268 | 269 | {self.id} 270 | 271 | 272 | """ 273 | 274 | return float(self._send_xml_rpc_request(xml_request)) 275 | 276 | def twofg_get_internal_width(self) -> float: 277 | xml_request = f""" 278 | 279 | twofg_get_internal_width 280 | 281 | 282 | {self.id} 283 | 284 | 285 | """ 286 | 287 | return float(self._send_xml_rpc_request(xml_request)) 288 | 289 | 290 | def twofg_grip_external(self, target_width: float = 40.00, target_force: int= 20, speed: int=1) -> int: 291 | """ 292 | speed is the range from 1 to 100. It represents the percentage of the maximum speed. 293 | """ 294 | assert target_width <= self.max_ext_width and target_width >= self.min_ext_width, f'Target Width must be within the range [{self.min_ext_width},{self.max_ext_width}]' 295 | assert target_force <= self.max_force or target_force >= 20, f'Target force must be within the range [20,{self.max_force}]' 296 | 297 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 298 | if (target_width > self.max_ext_width): 299 | target_width = self.max_ext_width 300 | if(target_width < self.min_ext_width): 301 | target_width = self.min_ext_width 302 | if(target_force > self.max_force): 303 | target_force = self.max_force 304 | if(target_force < 20): 305 | target_force = 20 306 | 307 | xml_request = f""" 308 | 309 | twofg_grip_external 310 | 311 | 312 | {self.id} 313 | 314 | 315 | {target_width} 316 | 317 | 318 | {target_force} 319 | 320 | 321 | {speed} 322 | 323 | 324 | """ 325 | 326 | # if status != 0, then command not succesful. Perhaps there is no space to move the gripper 327 | return int(self._send_xml_rpc_request(xml_request)) 328 | 329 | def twofg_ext_release(self, target_width: float = 40.00, speed: int=1) -> int: 330 | """ 331 | speed is the range from 1 to 100. It represents the percentage of the maximum speed. 332 | """ 333 | target_force: int= 80 334 | 335 | assert target_width <= self.max_ext_width and target_width >= self.min_ext_width, f'Target Width must be within the range [{self.min_ext_width},{self.max_ext_width}]' 336 | assert target_force <= self.max_force or target_force >= 20, f'Target force must be within the range [20,{self.max_force}]' 337 | 338 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 339 | if (target_width > self.max_ext_width): 340 | target_width = self.max_ext_width 341 | if(target_width < self.min_ext_width): 342 | target_width = self.min_ext_width 343 | if(target_force > self.max_force): 344 | target_force = self.max_force 345 | if(target_force < 20): 346 | target_force = 20 347 | 348 | xml_request = f""" 349 | 350 | twofg_grip_external 351 | 352 | 353 | {self.id} 354 | 355 | 356 | {target_width} 357 | 358 | 359 | {target_force} 360 | 361 | 362 | {speed} 363 | 364 | 365 | """ 366 | 367 | # if status != 0, then command not succesful. Perhaps there is no space to move the gripper 368 | return int(self._send_xml_rpc_request(xml_request)) 369 | 370 | def twofg_grip_internal(self, target_width: float = 40.00, target_force: int= 10, speed: int=1) -> int: 371 | """ 372 | speed is the range from 1 to 100. It represents the percentage of the maximum speed. 373 | """ 374 | assert target_width <= self.max_int_width and target_width >= self.min_int_width, f'Target Width must be within the range [{self.min_int_width},{self.max_int_width}]' 375 | assert target_force <= self.max_force or target_force >= 20, f'Target force must be within the range [20,{self.max_force}]' 376 | 377 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 378 | if (target_width > self.max_int_width): 379 | target_width = self.max_int_width 380 | if(target_width < self.min_int_width): 381 | target_width = self.min_int_width 382 | if(target_force > self.max_force): 383 | target_force = self.max_force 384 | if(target_force < 20): 385 | target_force = 20 386 | 387 | xml_request = f""" 388 | 389 | twofg_grip_internal 390 | 391 | 392 | {self.id} 393 | 394 | 395 | {target_width} 396 | 397 | 398 | {target_force} 399 | 400 | 401 | {speed} 402 | 403 | 404 | """ 405 | 406 | # if status != 0, then command not succesful. Perhaps there is no space to move the gripper 407 | return int(self._send_xml_rpc_request(xml_request)) 408 | 409 | def twofg_int_release(self, target_width: float = 40.00, speed: int=1) -> int: 410 | """ 411 | speed is the range from 1 to 100. It represents the percentage of the maximum speed. 412 | """ 413 | target_force: int= 80 414 | 415 | assert target_width <= self.max_int_width and target_width >= self.min_int_width, f'Target Width must be within the range [{self.min_int_width},{self.max_int_width}]' 416 | assert target_force <= self.max_force or target_force >= 20, f'Target force must be within the range [20,{self.max_force}]' 417 | 418 | # WARNING: params will be sent straight to electrical system with no error checking on robot! 419 | if (target_width > self.max_int_width): 420 | target_width = self.max_int_width 421 | if(target_width < self.min_int_width): 422 | target_width = self.min_int_width 423 | if(target_force > self.max_force): 424 | target_force = self.max_force 425 | if(target_force < 20): 426 | target_force = 20 427 | 428 | xml_request = f""" 429 | 430 | twofg_grip_internal 431 | 432 | 433 | {self.id} 434 | 435 | 436 | {target_width} 437 | 438 | 439 | {target_force} 440 | 441 | 442 | {speed} 443 | 444 | 445 | """ 446 | 447 | # if status != 0, then command not succesful. Perhaps there is no space to move the gripper 448 | return int(self._send_xml_rpc_request(xml_request)) 449 | 450 | def twofg_get_max_external_width(self) -> float: 451 | xml_request = f""" 452 | 453 | twofg_get_max_external_width 454 | 455 | 456 | {self.id} 457 | 458 | 459 | """ 460 | 461 | return float(self._send_xml_rpc_request(xml_request)) 462 | 463 | def twofg_get_max_internal_width(self) -> float: 464 | xml_request = f""" 465 | 466 | twofg_get_max_internal_width 467 | 468 | 469 | {self.id} 470 | 471 | 472 | """ 473 | 474 | return float(self._send_xml_rpc_request(xml_request)) 475 | 476 | def twofg_get_min_external_width(self) -> float: 477 | xml_request = f""" 478 | 479 | twofg_get_min_external_width 480 | 481 | 482 | {self.id} 483 | 484 | 485 | """ 486 | 487 | return float(self._send_xml_rpc_request(xml_request)) 488 | 489 | def twofg_get_min_internal_width(self) -> float: 490 | xml_request = f""" 491 | 492 | twofg_get_min_internal_width 493 | 494 | 495 | {self.id} 496 | 497 | 498 | """ 499 | 500 | return float(self._send_xml_rpc_request(xml_request)) 501 | 502 | def twofg_get_max_force(self) -> int: 503 | xml_request = f""" 504 | 505 | twofg_get_max_force 506 | 507 | 508 | {self.id} 509 | 510 | 511 | """ 512 | 513 | return int(self._send_xml_rpc_request(xml_request)) 514 | 515 | def twofg_get_status(self) -> int: 516 | # The status codes are not fully clear. 517 | # sofar: 518 | # 0: no grip 519 | # 2: has gripped an object 520 | 521 | xml_request = f""" 522 | 523 | twofg_get_status 524 | 525 | 526 | {self.id} 527 | 528 | 529 | """ 530 | 531 | return int(self._send_xml_rpc_request(xml_request)) 532 | 533 | def twofg_get_busy(self) -> bool: 534 | xml_request = f""" 535 | 536 | twofg_get_busy 537 | 538 | 539 | {self.id} 540 | 541 | 542 | """ 543 | 544 | return bool(self._send_xml_rpc_request(xml_request)) 545 | 546 | def twofg_get_grip_detected(self) -> bool: 547 | xml_request = f""" 548 | 549 | twofg_get_grip_detected 550 | 551 | 552 | {self.id} 553 | 554 | 555 | """ 556 | 557 | return bool(self._send_xml_rpc_request(xml_request)) 558 | 559 | def main(): 560 | 561 | # Default id is zero, if you have multiple grippers, 562 | # see logs in UR Teach Pendant to know which is which :) 563 | print("Main") 564 | rg_id = 0 565 | ip = "192.168.56.101" 566 | rg_gripper = RG2(ip,rg_id) 567 | 568 | rg_width = rg_gripper.get_rg_width() 569 | print("rg_width: ",rg_width) 570 | 571 | target_force = 40.00 572 | 573 | rg_gripper.rg_grip(100.0, target_force) 574 | 575 | 576 | 577 | if __name__ == "__main__": 578 | main() -------------------------------------------------------------------------------- /UOY-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------