Get I/O's Via RTDE

Hi there,

We are trying to get I/O information from the robot via RTDE. But the library doesn’t give us possibility to write the script correctly ( Real-Time Data Exchange (RTDE) Guide - 22229 (universal-robots.com)).
Do you have any recommendation what we can do?

Regards,
Giorgi

The best way is using RTDE.
I had uploaded the sample for monitoring the IOs.

Please refer from the sample category.

Thanks for response.
In the sample category from the link mentioned above? Honestly I couldn’t find there a sample for getting I/O’s with rtde via python.
Also, I couldn’t find the function in library neither.

RTDE code in my sample is written by java.

Thanks for the sample.
I mainly look for possibilities for python3. Unfortunately I couldn’t find it anywhere. Libraries supplied by UR website doesn’t give a possibility to get such kind of information.

@giorgigedaminski

Below is how I modified the record.py script to read I/O’s

#!/usr/bin/env python

Copyright (c) 2020-2022, Universal Robots A/S,

All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright

notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright

notice, this list of conditions and the following disclaimer in the

documentation and/or other materials provided with the distribution.

* Neither the name of the Universal Robots A/S nor the names of its

contributors may be used to endorse or promote products derived

from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND

ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

DISCLAIMED. IN NO EVENT SHALL UNIVERSAL ROBOTS A/S BE LIABLE FOR ANY

DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

“”"
Python script record_v00_r01.py was modified from script
record.py on 4/6/23 by

  1. Write data to a text file
  2. Set a condition to print to the console when a
    simulated red tower light is turn on which means
    lost sheet on the UR5 Machine Tending of the Spartanics
    Auto-Punch machine.
    Python script record_v00_r02.py was modified from script
    record_v00_r01.py on 4/6/23 by
  3. Set the condition to print only once to the console
    when a simulated red tower light is lit.
  4. Set another condition to print only once to the
    console when the lost sheet issue is cleared.
  5. Write both condition to the text file.
    Python script record_v00_r03.py was modified from script
    record_v00_r02.py on 4/10/23 by
  6. Send alert with email.
    “”"
    import argparse
    import logging
    import sys
    from datetime import datetime
    now = datetime.now()

sys.path.append(“…”)
import rtde.rtde as rtde
import rtde.rtde_config as rtde_config
import rtde.csv_writer as csv_writer
import rtde.csv_binary_writer as csv_binary_writer

parameters

parser = argparse.ArgumentParser()
parser.add_argument(
“–host”, default=“172.16.5.38”, help=“name of host to connect to (localhost)”
)
parser.add_argument(“–port”, type=int, default=30004, help=“port number (30004)”)
parser.add_argument(
“–samples”, type=int, default=0, help=“number of samples to record”
)
parser.add_argument(
“–frequency”, type=int, default=10, help=“the sampling frequency in Herz”
)
parser.add_argument(
“–config”,
default=“record_configuration.xml”,
help=“data configuration file to use (record_configuration.xml)”,
)
parser.add_argument(
“–output”,
default=“robot_data.txt”,
help=“data output file to write to (robot_data.txt)”,
)
parser.add_argument(“–verbose”, help=“increase output verbosity”, action=“store_true”)
parser.add_argument(
“–buffered”,
help=“Use buffered receive which doesn’t skip data”,
action=“store_true”,
)
parser.add_argument(
“–binary”, help=“save the data in binary format”, action=“store_true”
)
args = parser.parse_args()

if args.verbose:
logging.basicConfig(level=logging.INFO)

conf = rtde_config.ConfigFile(args.config)
output_names, output_types = conf.get_recipe(“out”)

con = rtde.RTDE(args.host, args.port)
con.connect()

get controller version

con.get_controller_version()

setup recipes

if not con.send_output_setup(output_names, output_types, frequency=args.frequency):
logging.error(“Unable to configure output”)
sys.exit()

start data synchronization

if not con.send_start():
logging.error(“Unable to start synchronization”)
sys.exit()

writeModes = “wb” if args.binary else “w”
“”"
Open a text file and format it as a comma-separated values
(CVS) file but seperated by a tab (\t) with the following
fields:
Datetime
Robot Status
Robot Safety Status
Digital Output State

Save the file with the name ‘Assembly Robot Data (crrent
date time) csv.txt’
“”"
lostSheet = False
dt = now.strftime(“%Y-%m-%d %H.%M.%S”)

f1 = open(“Assembly Robot Data “+dt+” csv.txt”, “a+”)
f1.write(“Datetime\tRobot Status\tRobot Safety Status\tDigital Output States”)
with open(args.output, writeModes) as csvfile:
writer = None

if args.binary:
    writer = csv_binary_writer.CSVBinaryWriter(csvfile, output_names, output_types)
else:
    writer = csv_writer.CSVWriter(csvfile, output_names, output_types)

writer.writeheader()

i = 1
keep_running = True
while keep_running:

    #if i % args.frequency == 0:
        #if args.samples > 0:
            #sys.stdout.write("\r")
            #sys.stdout.write("{:.2%} done.".format(float(i) / float(args.samples)))
            #sys.stdout.flush()
        #else:
            #sys.stdout.write("\r")
            #sys.stdout.write("{:3d} samples.".format(i))
            #sys.stdout.flush()
    if args.samples > 0 and i >= args.samples:
        keep_running = False
    try:
        if args.buffered:
            state = con.receive_buffered(args.binary)
        else:
            state = con.receive(args.binary)
        if state is not None:
            #dt = str(datetime.datetime.now())
            dt1 = datetime.now()
            dt2 = dt1.strftime("%Y-%m-%d %H:%M:%S")
            #print dt
            #print '********************************************************'
            status = format(state.robot_status_bits, 'b')
            #print 'Robot status binary bits = ',status
            #print 'Lenght of robot status binary bits word = ',len(status)
            #print '---------------------------------------------------------'
            safety = format(state.safety_status_bits, 'b')
            #print 'Robot safety status binary bits = ',safety
            #print 'Lenght of robot safety status binary bits word = ',len(safety)
            #print '---------------------------------------------------------'
            IO = format(state.actual_digital_output_bits, 'b')
            #print 'Output IO binary bits = ',IO
            #print 'Lenght of robot output IO binary bits word = ',len(IO)
            #print dt2+'\t'+status+'\t'+safety+'\t'+IO
            f1.write('\n'+dt2+'\t'+status+'\t'+safety+'\t'+IO)
            """
            Print to the console when the red light is
            turned on which means a sheet was lost.
            """
            if len(IO) >= 5:
                if IO[len(IO)-3] == '1' and lostSheet == False:
                    print "Lost sheet "+dt2
                    f1.write("\nLost sheet "+dt2)
                    lostSheet = True
                if IO[len(IO)-3] == '0' and lostSheet == True:
                    print "Lost sheet issue cleared "+dt2
                    f1.write("\nLost sheet issue cleared "+dt2)
                    lostSheet = False
            #writer.writerow(state)
            i += 1

    except KeyboardInterrupt:
        keep_running = False
        #KeyboardInterrupt is CTRL + C or CTRL + Z 
        # while in the consule panel
    except rtde.RTDEException:
        con.disconnect()
        sys.exit()

sys.stdout.write(“\rComplete! \n”)
f1.close()

con.send_pause()
con.disconnect()

Also you’ll need to modify the record_configuration.xml as follows:

<?xml version="1.0"?>

<rtde_config>































</recipe>

</rtde_config>