All posts by nouyang

corning glass studio / museum, waterfalls – pt 1

my partner went to take weekend glassblowing class at corning and i tagged along

(it was an encalmo workshop, for making a piece using two colors. semi-relatedly, i didn’t realize that colors affect the CTE, coefficient of thermal expansion, of the glass)

(that corning museum picture for explaining encalmo is a bit confusing, plates are made by spinning a cylinder of glass real fast and the glass centrifuges outward, so in that picture precision join is the center line between the inner and outer colors on the plate. err. maybe this a better picture maybe, where they kept it in cylinder form)

corning is about a 5 hr drive from boston, ma

we went to watkins glen state park ny first. (trying to go to cow cuddle but we would have had to set out at 7am, not 10am)

it has about a 1.5 hr loop to see a bunch of waterfalls, easy (mostly flat and paved). As it rained recently, the path was pretty full of puddles and there was spray from the waterfall. (we did have to walk past a misleading “DANGER do not enter” door — it’s actually open when ajar, if it were closed they would padlock it with chain). perhaps $10 for parking and we got a map which did come in handy.

Notes for next time: a former roommate also recommended Aunt Sarah’s Falls and Shequaga Falls Park which are a short drive (~5 mins) and visible from the parking lot. we were tired so we went to just aunt sarah’s, which, make sure to go to the “aunt sarah’s parking lot” on google maps not “aunt sarah’s falls”.

The next day we went to the Corning Glass Museum, which had both historical glass through the ages as well as an innovation section about the industrial change and technological advances in glass. The uses of glass are intense, not just windowshields and tupperware, but also fiber optics, telescopes, even missile heads.

Modern glassblowing for art does not look so different.

(click to embiggen)

Once i get my phone back i’ll post about what i learned second hand about glassblowing with some short videos.

ur5, hand tracking demo

i need to go clean up the code so the “documentation” post later —

but this was fun and quick !

I worked on this short coding challenge for many hours, got nowhere and gave up. Then in the same amount of time got this robot demo working …

Maybe 2 hours setting up a safety plane in ur5, 2 hrs on the actual hand coordinate to robot coordinate code, and 2 hrs taking videos and showing friends heh.

next steps thoughts

honestly with the word salad machine’s help (pointed out I could use servoL, aka giving it velocities, instead of position coordinates moveL) I finished this much faster than I thought and now I’m at a loss as to what to do next (then my brain was like “oh, it was so easy, the only thing it demoed was me not having enough experience to realize how simple it is” thanks brain that’s the whole point of why we’re doing this, to gain more experience)

i could make the code accept z as well (right now it’s limited to a xy plane for safety), add kd (right now if you swing your hand around too fast too many times the robot starts to wildly swing in bigger and bigger circles), try rewriting with moveJ and seeing what happens, make a gripper, switch to a wrist-mount camera, make the robot high-five and fist bump, switch back to small arms and collect sock data (probably the main issue is I should set the small arms up with my desktop instead of my laptop so I’m not having to plug in 6 cables each time to go between ur5 and the desktop arms), giving the robot expressions… putting aside thinking about what tasks are “how to job” since that will sap all the joy out of robots again

i think i was most excited about a robot that could fold my laundry and also do other tasks like put my tools back or sort screws. it’d be fun to have it make me a sandwich. then there’s another category of what other people would enjoy — people find interactive demos fun, and this hand-tracking fell under that.

Hmm, people also find food fun. So perhaps getting the UR5 to make sandwiches should be my next goal!!

hello world! waving hi with the ur5

(Using the moveJ command, just offsetting from the starting pose).

This is mostly notes to myself — assuming most people don’t have a UR5 arm to just play around with.

And also to maintain enthusiasm about robots (sometimes hard even for me in a vacuum) and what I’m doing (easy after each task I complete to go “oh, that wasn’t exciting at all”. I did that with my paper(s), thesis, and degrees, so I can definitely do it with any hacked project haha).

Create the hand

  1. Find a normal glove and a latex glove, put both on
  2. Blow up the latex glove and tie it off
  3. Put glove over end effector

Connecting via Python: ur-rtde library

Back in the day I used py urx — apparently now the standard is ur-rtde as a pip install python library. (whoo!)

The robot talks over TCP/IP. If you run a real time kernel, then the communication is safe from interference from e.g. web browsing. I chose to not install a RTK for my startup script as I heard it’s a major pain.

Per the UR5 manual about RTDE:
https://docs.universal-robots.com/tutorials/communication-protocol-tutorials/rtde-guide.html

“The Real-Time Data Exchange (RTDE) interface provides a way to synchronize external applications with the UR controller over a standard TCP/IP connection, without breaking any real-time properties of the UR controller. This functionality is useful for interacting with fieldbus drivers (e.g., Ethernet/IP), manipulating robot I/O, and plotting robot status (e.g., robot trajectories). The RTDE interface is by default available when the UR controller is running.”

https://sdurobotics.gitlab.io/ur_rtde/guides/guides.html re: RTKernel recommendations, which I promptly ignored (I did put my laptop on “performance” and not “balanced” mode though).

Connect & Run Code

Install the libraries. Probably some of the below is redundant, but hey it worked.

uv venv --python=3.9
apt install cmake build-essential pyhton3-dev libboost-all-dev
uv pip install wheel
uv pip install ur-rtde
Connect to robot

Connect to robot:

I plugged in ethernet to my laptop via a USB-C adapter. For whatever reason at first nothing would show up. I did mess around with the subnet settings on my linux laptop network ethernet settings. Not sure if that’s what fixed it, or rebooting, etc. But in the end I didn’t need to connect my robot to my router, just direct to my laptop.

Sanity check: Is network connection working?

( Have to admit, the word salad machines do decently at this basic ur5 stuff. Though they probably gave me a lot of misconceptions … )

Credit to https://gist.github.com/lauzadis

#!/usr/bin/env python3
import rtde_control
import rtde_receive
import time

ROBOT_IP = "192.168.1.150"

def test_ur_rtde():
    try:
        print(f"Connecting to UR5 at {ROBOT_IP}...")

        # Connect to receive interface (read robot state)
        rtde_r = rtde_receive.RTDEReceiveInterface(ROBOT_IP)

        # Read some basic robot data
        actual_q = rtde_r.getActualQ()  # Joint positions
        actual_tcp = rtde_r.getActualTCPPose()  # TCP position

        print("\n--- Robot State ---")
        print(f"Joint positions: {[f'{q:.3f}' for q in actual_q]}")

        # Connect to control interface
        rtde_c = rtde_control.RTDEControlInterface(ROBOT_IP)
        print("\n Successfully connected to RTDE control interface")

        # Cleanup
        rtde_c.stopScript()
        rtde_r.disconnect()
        rtde_c.disconnect()
        return True

    except Exception as e:
        print(f"\nError: {e}")
        print("\nTroubleshooting:")
        print("- Make sure the robot is powered on")
        print("- Check that RTDE is enabled on the robot")
        print("- Verify IP address is correct")
        return False

if __name__ == "__main__":
    # Make sure ur-rtde is installed
    try:
        import rtde_control
        import rtde_receive
    except ImportError:
        print("ur-rtde not installed.")
        print("Run: pip3 install ur-rtde or similar")
        exit(1)

    test_ur_rtde()

Write to the robot, waving the arm

We’ll use the moveJ command which takes a list of 6 floats in radians as well as the velocity and acceleration (in rad/s) and whether the command should be asynchronous or not — if set to False, the robot will wait for the first command to complete.

Move the robot using freedrive mode on the back of the pendant to a good starting position.


#!/usr/bin/env python3
import rtde_control
import rtde_receive
import time

ROBOT_IP = "192.168.1.150"

def test_ur_rtde():
    try:
        print(f"Connecting to UR5 at {ROBOT_IP}...")

        rtde_r = rtde_receive.RTDEReceiveInterface(ROBOT_IP)
        print("Successfully connected to RTDE *receive* interface")

        # Read some basic robot data
        home_q = rtde_r.getActualQ()  # Joint positions
        robot_mode = rtde_r.getRobotMode()  # Robot mode

        print("\n--- Robot State ---")
        print(f"Joint positions: {[f'{q:.3f}' for q in actual_q]}")

        # Connect to control interface
        rtde_c = rtde_control.RTDEControlInterface(ROBOT_IP)
        print("\nSuccessfully connected to RTDE *control* interface")

        target_q = home_q.copy()
        target_q[5] += 0.3  # 
        target_q[4] += 0.1  # 
        target_q[3] += 0.3  # 
        target_q[2] += 0.2  # 0.2 radians ~= 11.5 degrees # elbow

        # Movement parameters
        velocity = 2.2      # Rad/s (0.1 Very slow)
        acceleration = 1.8  # Rad/s^2
        asynchronous = False # Set to True if you don't want the script to wait

        print(f"Moving elbow joint to {target_q[2]}...")

        # Execute the move. Repeat five times to wave.
        for i in range(5):
            rtde_c.moveJ(target_q, velocity, acceleration, asynchronous)
            rtde_c.moveJ(home_q, velocity, acceleration, asynchronous)

        print("Movement completed")

        rtde_c.stopScript()

        rtde_r.disconnect()
        rtde_c.disconnect()

        return True

    except Exception as e:
        print(f"\nError: {e}")


if __name__ == "__main__":
    # Make sure ur-rtde is installed
    try:
        import rtde_control
        import rtde_receive
    except ImportError:
        print("ur-rtde not installed.")
        exit(1)

    test_ur_rtde()

Video

yay

that was a nice afternoon’s work
(didn’t rescue my terrible surprise zero preparation interview, but hey, i have an arm now?)

Fin.

Side note: Why q?

Why do we have joint angles labeled as q?

Per reddit it may just be that generalized coordinates q are an adjacent concept to momentum p — and per reddit that is named potentially due to the calling momentum “impetus” and not confusing it with mass in p=mv.

Anyway, tl;dr I’ve as usual forgotten all the things I learned the better part of a decade ago (rip).