How Do I get Keyence Laser Profiler data to populate variables in Polyscope?

I have a UR10e and a Keyence LJ-V7000 saeries laser profiler, both connected to a PLC. The UR10e adapter picks up the PLC scanner. I have a Keyence program made but I’m not sure how to pull the data from the Keyence controller and have the data populate variables in Polyscope. I am thinking a Python script but I’m not proficient in Python programming. Anyone done anything similar in the past?

I tend to like using the EthernetIP protocol, but you’d have to make sure the profiler supports EthernetIP. Then you just use a basic copy instruction on the PLC to take the data from the Profiler into one of the GP registers on the UR. From there you can just use the normal robot script to write the robot register to a variable.

Hi Eric! I know what bits to use for the Keyence.

For the UR10e, would I just use the TCP position bits?

This is something I pulled off one of the AI websites for the Python program since I have no experience with it.

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

ROBOT_IP = "192.168.1.17"  # Replace with your robot's IP address
ROBOT_PORT = 30004          # Default RTDE port

# Path to the RTDE configuration file
CONFIG_FILE = "control_configuration.xml"

# Load the RTDE configuration
config = rtde_config.ConfigParser(CONFIG_FILE)
output_names, output_types = config.get_recipe("output")

# Connect to the robot
con = rtde.RTDE(ROBOT_IP, ROBOT_PORT)
con.connect()

# Get the output recipe
con.send_output_setup(output_names, output_types)

# Start the RTDE data exchange
con.send_start()

try:
    # Read data from the robot
    data = con.receive()
    if data is not None:
        # Example: Read a specific register value (e.g., register 0)
        robot_register_value = data.actual_q[0]  # Replace 'actual_q' with the appropriate field
        print(f"Robot Register Value: {robot_register_value}")
except KeyboardInterrupt:
    print("Program interrupted by user.")
finally:
    # Stop the RTDE data exchange and disconnect
    con.send_pause()
    con.disconnect()

Would something like this work? Would I need to upload RTDE libraries to the robot?

Thanks for all the help!

Is your ultimate goal to control the robot with live data from the profiler? Keep in mind the robot does not run on Python. You have to call functions written there from XMLRPC, or else stream it via socket from an external source like a PC.

Personally, I never have had much success with the RTDE, it always seems overly complicated, and introduced a lot of failure points that I couldn’t debug or understand.

If you’re able to read the data from the Keyence profiler into the PLC, then you’re already almost done. At the bottom of the page I linked above, there is an EDS file for the UR robot. Import that as a new ethernet device, and just use a copy instruction to map the data from Keyence to Robot. Once you do that, the robot has access to the profiler data on whatever integer, float, etc register you chose to map it to. You’re free to do whatever you want with it right there in robot script.

It is!

I have the EDS for the robot and can copy the readouts from the Keyence to the TCP position bits in the ladder logic, but like I said the scripts is what I’m having the most trouble with. I’m hoping I can make a script to run at the same time as my regular benching prgram to adjust TCP on the fly.

The UR robot is an industrial robot. You have a PLC. Why not use good old school industrial automation like ProfiNet (Siemens) or EthernetIP (Allen Bradley)? UR supports both as slave (ProfiNet) / client/device (EthernetIP). The PLC will work as gateway between the LJ-V7000 and the robot. This is strait forward.

Thats exactly what I did!

It’s not straight-forward how to USE the values once you get them to the UR. This depends on the application. @jarred.burns has clarified he’s looking to do real-time pose manipulation.

I would additionally look at the script commands for servoJ and path_offset. See if either of these can suit your needs. We have used servoJ in the past with a keyence profiler for tracking a part driven by a positioner. It also wasn’t completely straightforward, as the servoJ’s lookahead time needed to be synced with the scan rate of the PLC and we had to buffer a certain number of datapoints first.

Path_offset lets you program say a single straight line and then impose offsets over top of that, which could be useful for tracking a seam for example.

Script manual is here: https://s3-eu-west-1.amazonaws.com/ur-support-site/234367/script_directory_PolyScope5.pdf

Ctrl+F is your friend there.

Otherwise yes you’re on the right track with thinking you need to use the RTDE. This is the interface I think most people use for the application you’re describing, I just have never gotten it to work.

OK, I just read the thread as if your problem was getting the data from Keyence to UR. It was clear how you wanted to use the data in the robot. So you’re good for now?

I’m still working on the script to take the information in the bits and copy them to a variable to use in a program.

So, in the Universal Robots EDS, it shows bits 205 and 209 are the TCP position bits.

In the script manual that Eric provided, 17.32 Read_Input_Float_Register should work right?

If I make a script,

float_val=read_input_float_register(205)
float_val=read_input_float_register(209)

But the script manual is saying registers 0:23 are reserved for fieldbus/PLC. What am I missing here?

Not trying to be pedantic here, the distinction is important. Those aren’t the BITS, those are the BYTES. You’ll notice they are all 4 apart, because the UR registers are 32-bits (4 bytes) large. The EDS file is breaking it into bytes (my Automation Direct PLC does the same thing).

The other important thing is to understand where the data is coming FROM and where it’s going TO. In my Automation Direct, I created a User Defined Type and called it UniversalRobot. I then gave it 2 arrays of bytes, and named them “From” and “To” so that when I use it, it looks like “UniversalRobot.From(205)”. This makes it clear that byte 205 is coming FROM the Universal robot, and in this case corresponds to the first BYTE of the X position of the TCP. In order to read the ACTUAL X value, you need to read bytes 205, 206, 207, and 208.

The read_input_float_register() script command takes as input a REGISTER NUMBER OF THE ROBOT, not the byte number of the EDS file.

For example, in the PLC, I would read the Keyence data, and copy the value to bytes 33, 34, 35, and 36. You may need to use some kind of “unpack word” instruction if the Keyence data is a 32-bit value so you can split it across the 4 bytes in the PLC. Then in the robot, the script manual command you would use is “read_input_integer_register(0)” because that is the register number that lines up with those bytes. Hopefully that makes sense.

Knowing your goal is realtime control of the robot, it’s worth pointing out that you cannot overwrite the TCP position from the PLC. You can only READ the tcp values via the PLC. To actually control it in real-time, the python implementation of the RTDE would be your best bet.

1 Like

Ok, I have an Industrial PC ordered. I found the RTDE Python Client Library package that has a lot of good examples in it. I think I got a good handle now on bits vs bytes in the Productivity Suite software. Thanks for all the help Eric!