Universal Robots Forum

Write GeneralPurposeRegisters via RTDE

Hi!

I need to be able to WRITE general purpose registers via RTDE.

Unfortunately, up to now, i could not find a way to WRITE (and read) those general purpose registers since the only commands that are available deal with integer and float registers.

Has someone faced this problem?

Has someone already wrote on BIT registers via RTDE?

Could someone give me some hints about a possible solution? Do I have to implement a RTDE client to write these general purpose (bit) registers?

I am working on this issue from some time and i cannot find a way out

Thank you for your cooperation

Serena

Hi, I recommend that you use realtime client.

public class RealTimeClient {

    private String MESSAGE_HEADER = "Client -> port30003:";
    private String ipAddress;

    public RealTimeClient(String ipAddress) {
        this.ipAddress = ipAddress;
    }


    public void setBitToRegister(int addr, boolean bit) {
        String command = "write_output_boolean_register(" + String.valueOf(addr) + ","
                + String.valueOf(bit ? "True" : "False") + ")";
        sendCommand(command);
    }

    public void sendCommand(String command) {
        try {

            Socket socket = new Socket(ipAddress, 30003);
            socket.setSoTimeout(1000);

            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);

            if (socket.isConnected()) {

                System.out.println(MESSAGE_HEADER + "Send \"" + command + "\"");
                writer.println(command);
                writer.flush();

            }

            socket.close();
            reader.close();
            writer.close();

        } catch (Exception e) {
            System.out.println(MESSAGE_HEADER + e.getMessage());
        }
    }

}

HI!
Thanks for the reply!

I have a question: my goal is to WRITE_INPUT_BIT_REGISTER but you have used a command to write_output_bit_registers. how could i WRITE these input bit registers since no command is available on the ur scripts ?

my goal is to write the input bit register via RTDE.

thank you for your cooperation

My advice would be to control those registers via RTDE as the Realtime client is an older interface. Take a look at the two different guides which contain examples on how you can interact with the interface:
https://www.universal-robots.com/articles/ur/interface-communication/real-time-data-exchange-rtde-guide/

Overall remote operation guide (look to the sections on RTDE):
https://www.universal-robots.com/articles/ur/interface-communication/remote-operation-of-robots/

Hi!
I have taken a look at both guides that you have proposed.

Unfortunately in these guides, nobody speaks about the possibility of writing input bit registers since this is not an option up to now.

I had a look at the overall remote operation guide and especially at the RTDE section but i do not understand how could this help me:

  • should i define a new xml in which i put in the input section the WRITE input boolean registers, how can i then define the write command?

I am sorry to bother, but this looks like a topic with no solution

Just so I understand, you are trying to have your PC code write to the robot’s input bit registers? If so, then yes you can do this via RTDE. Your XML file would look something like this:

<recipe key="bitreg">
		<field name="input_bit_register_70" type="BOOL"/>
</recipe>

In my case I chose register 70, but you can choose any number from 64 to 127 (registers 0 to 63 are reserved for fieldbus/PLC’s and are therefore unavailable). From there you should be able to follow the examples in those guides for sending a new value; you can either use an integer 0/1 or a boolean True/False to change them.

On the other hand, if you are trying to have your PC code write to the robot’s OUTPUT bit registers (or any for that matter), that will not be possible.

Hi @fluffypancake39,

So you are working with python, trying to write into the boolean input registers over RTDE correct?

Have you had any success with RTDE communication at all yet? What errors are you seeing?

Expanding on @krmi’s example above, the below config and python sample pair is adapted from example_control_loop.py that’s included with the RTDE library download from the support site. It will both read and write input bit reg 70, and toggle the value between true and false each time you run it. Hopefully this gives a clear example of how to interact with this register through RTDE. It addresses the RTDE at localhost, so assumes you’re running this script on the robot or in the same environment as URSIM.

save as "example_boolreg_configuration.xml"

<?xml version="1.0"?>
<rtde_config>
	<recipe key="outputs">
		<field name="input_bit_register_70" type="BOOL"/>
	</recipe>
	<recipe key="inputs">
		<field name="input_bit_register_70" type="BOOL"/>
	</recipe>
</rtde_config>

#!/usr/bin/env python

import sys
sys.path.append('..')
import logging
import time

import rtde.rtde as rtde
import rtde.rtde_config as rtde_config


logging.basicConfig(level=logging.INFO)

ROBOT_HOST = 'localhost'
ROBOT_PORT = 30004
config_filename = 'example_boolreg_configuration.xml'
keep_running = True

logging.getLogger().setLevel(logging.INFO)

conf = rtde_config.ConfigFile(config_filename)
output_names, output_types = conf.get_recipe('outputs')
input_names, input_types = conf.get_recipe('inputs')


con = rtde.RTDE(ROBOT_HOST, ROBOT_PORT)
con.connect()


# get controller version
con.get_controller_version()

# setup recipes
con.send_output_setup(output_names, output_types)
inputs = con.send_input_setup(input_names, input_types)


#start data synchronization
if not con.send_start():
    sys.exit()

#inputs.standard_digital_output_mask = 1

print("running now")

# control loop
while keep_running:
    # receive the current state
    outputs = con.receive()
    
    if outputs is None:
        break;

    reg_value = outputs.input_bit_register_70
    print("reg70: "+str(reg_value))
    inputs.input_bit_register_70 = not reg_value
    con.send(inputs)
    break

con.send_pause()
con.disconnect()

Hi!
thank you for your huge help!ù
Yes, my goal is to write the input bit registers via rtde

i have tried and implemented a similar code in order to solve the given problem.

do you know if it is possible to set dynamically the number of the register?

I’ll try to explain myself better:

  • i want to have a main program in which i request the user which number of input register he wants to use

  • as a consequence, i want to write on that given register

i have tried to set a general parameter like intRegNumber and then pass it as outputs.input_bit_register_intRegisterNumber but this did not work.

Have you already tried something like this?

If you use the python built in setattr() function, you can use a string to address the attribute you want to set as shown below. Does that help?

    x = 70
    reg = 'input_bit_register_'+str(x)
    setattr(inputs,reg,True)

Note for this to work you will need to list all registers that you might possibly want to write to in your XML config file.

Hi!

Thank you for your help.

In this week i have tried working with this and i have encountered the following issue:

  • As proposed by @ajp , i have set my input/output registers with a “free” number that can be selected each time in a different way
  • My goal is to associate to the values of those registers some actions (like to get the TCP value after that a push button has been pressed)
  • in order to perform this association, i have tried adding to my .xml file these ne inputs/outputs. For example, in the output section, i have added a new line of the following form
    field name=“regOutBit1” type=“BOOL”/>
    where
    x = 70
    regOutBit1= ‘input_bit_register_’+str(x)
    setattr(inputs,reg,True)
  • This mechanism seems not to work since i get the following error:
    File “/home/ur/Desktop/boolFinale_v5/rtde/serialize.py”, line 193, in unpack_recipe
    raise ValueError('Unknown data type: ’ + i)
    ValueError: Unknown data type: NOT_FOUND
  • I have tried having a look at the serialize.py and at the other .py files but i could not figure out how to proceed.

Have you already faced this problem?

Thank you for your cooperation

Sorry if that was not clear, you can’t do that in the XML file. You need to hard code the registers in there. So you’d need to include every register that the user could possibly choose to use:

<?xml version="1.0"?>
<rtde_config>
	<recipe key="outputs">
		<field name="input_bit_register_70" type="BOOL"/>
		<field name="input_bit_register_71" type="BOOL"/>
		<field name="input_bit_register_72" type="BOOL"/>
		<field name="input_bit_register_73" type="BOOL"/>
		<field name="input_bit_register_74" type="BOOL"/>
		<field name="input_bit_register_75" type="BOOL"/>
		<field name="input_bit_register_76" type="BOOL"/>
		<field name="input_bit_register_77" type="BOOL"/>
		<field name="input_bit_register_78" type="BOOL"/>
		<field name="input_bit_register_79" type="BOOL"/>
	</recipe>
	<recipe key="inputs">
		<field name="input_bit_register_70" type="BOOL"/>
		<field name="input_bit_register_71" type="BOOL"/>
		<field name="input_bit_register_72" type="BOOL"/>
		<field name="input_bit_register_73" type="BOOL"/>
		<field name="input_bit_register_74" type="BOOL"/>
		<field name="input_bit_register_75" type="BOOL"/>
		<field name="input_bit_register_76" type="BOOL"/>
		<field name="input_bit_register_77" type="BOOL"/>
		<field name="input_bit_register_78" type="BOOL"/>
		<field name="input_bit_register_79" type="BOOL"/>
	</recipe>
</rtde_config>

Hi!
I got what you sad, maybe i was not clear about my doubt.

I have hard coded every needed register inside the .xml and this is fine to me.

  • my goal is to let the user be able to choose at startup which register he wants to use: for example, when i run python my code
    python3.8 test.py 101 102 103

  • since it is possible to do it thanks to your previous answer, i am able to set these registers via
    x = 70
    regOutBit1= ‘input_bit_register_’+str(x)
    setattr(inputs,reg,True)

  • i have set these bindings in my program and then, i have followed the following idea:

  1. since i have set regOutBit in the previous way, then i am able to assess the state of this register by outputs.regOutbit (due to the fact that RegOutBit in the reality is input_bit_register_x)

  2. Unfortunately, while i try to assess these registers, for example with the following syntax
    if output.regOutBit == 1:
    do something
    i get the following error
    File “/home/ur/Desktop/boolFinale_v5/rtde/serialize.py”, line 193, in unpack_recipe
    raise ValueError('Unknown data type: ’ + i)
    ValueError: Unknown data type: NOT_FOUND
    i cannot figure this error out since i am using RegOutBit = output_bit_register_x and in the .xml i have hard coded all the needed registers.

have i been a bit more clear about my issue?
I am sorry if my English is not clear enough

You’ll need to use getattr to read in the same way you’re using setattr to write:

x = 70
reg = 'input_bit_register_'+str(x)
getattr(outputs,reg)

Back to the topic of setting up your XML config, I thought you would be receiving the registers the user wants to use via RTDE not via command line.

As you’re getting this from the arguments, you could actually build your XML config file in python and write it to file before using it to set up your RTDE connection. (this may be overcomplicating things, feel free to skip over this).

#!/usr/bin/env python

import sys
sys.path.append('..')
import logging
import time

import rtde.rtde as rtde
import rtde.rtde_config as rtde_config

#BUILD XML CONFIG BASED ON COMMAND LINE ARGS
arg = str(sys.argv[1])

xml1 = """<?xml version="1.0"?>
<rtde_config>
	<recipe key="outputs">
		<field name="input_bit_register_"""

xml2 = """" type="BOOL"/>
	</recipe>
	<recipe key="inputs">
		<field name="input_bit_register_""" 

xml3 = """" type="BOOL"/>
	</recipe>
</rtde_config>
"""

xml = xml1+arg+xml2+arg+xml3
config_filename = 'example_boolreg_configuration.xml'
file1 = open(config_filename, "w") 
file1.write(xml)
file1.close()



logging.basicConfig(level=logging.INFO)

ROBOT_HOST = 'localhost'
ROBOT_PORT = 30004

keep_running = True
logging.getLogger().setLevel(logging.INFO)

conf = rtde_config.ConfigFile(config_filename)
output_names, output_types = conf.get_recipe('outputs')
input_names, input_types = conf.get_recipe('inputs')


con = rtde.RTDE(ROBOT_HOST, ROBOT_PORT)
con.connect()


# get controller version
con.get_controller_version()

# setup recipes
con.send_output_setup(output_names, output_types)
inputs = con.send_input_setup(input_names, input_types)


#start data synchronization
if not con.send_start():
    sys.exit()

#inputs.standard_digital_output_mask = 1

print("running now")

# control loop
while keep_running:
    # receive the current state
    outputs = con.receive()
    
    if outputs is None:
        break;

    reg = 'input_bit_register_'+arg
    reg_value = getattr(outputs,reg)
    setattr(inputs,reg,not reg_value)
    print(reg+": "+str(reg_value))

    con.send(inputs)
    break

con.send_pause()
con.disconnect()