diff --git a/config.yml b/config.yml index 4d98384..3a9f9ec 100644 --- a/config.yml +++ b/config.yml @@ -6,7 +6,7 @@ core: loopspeed: 60 # fps mqtt: - enabled: True + enabled: False server: 172.31.108.4 arm: @@ -28,8 +28,8 @@ cables: cameras: banner: - ip: 192.168.1.125 - port: 32200 + ip: 192.168.1.199 + port: 80 animation_time: 60 @@ -268,7 +268,7 @@ led: size: 24 diameter: 63.5 angle: 180 - pos: [197.973, 38.1] + pos: [201.973, 34.1] - type: circle start: 624 size: 24 @@ -474,7 +474,7 @@ position_map: - index: 7 pos: [-38.1, 197.973] - index: 8 - pos: [38.1, 197.973] + pos: [34.1, 201.973] - index: 9 pos: [114.3, 197.973] - index: 10 @@ -564,4 +564,4 @@ position_map: - index: 52 pos: [76.2, -263.965] - index: 53 - pos: [152.4, -263.965] \ No newline at end of file + pos: [152.4, -263.965] diff --git a/map.png b/map.png index f0f08f2..6fa53ff 100644 Binary files a/map.png and b/map.png differ diff --git a/pick_count.txt b/pick_count.txt index 7c6ba0f..2ebc651 100644 --- a/pick_count.txt +++ b/pick_count.txt @@ -1 +1 @@ -55 \ No newline at end of file +56 \ No newline at end of file diff --git a/process_video.py b/process_video.py index 303ab59..13143d6 100755 --- a/process_video.py +++ b/process_video.py @@ -43,7 +43,7 @@ class qr_reader(): response = requests.get(self.url, timeout=tries * 15) response.raise_for_status() # Raise an error for bad status codes print(response.text) # Or handle the response as needed - if len(response.text < 8): + if len(response.text) < 8: return False return response.text except requests.Timeout: @@ -69,4 +69,4 @@ if __name__ == "__main__": import time while True: fprint(test.read_qr(300)) - time.sleep(1) \ No newline at end of file + time.sleep(1) diff --git a/requirements.txt b/requirements.txt index e5aefa5..5aa5e39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Runtime camelot-py[base]==0.9.0 -opencv-python +#opencv-python pypdf2==2.12.1 alive-progress requests diff --git a/run.py b/run.py index 2311388..99887b9 100755 --- a/run.py +++ b/run.py @@ -11,6 +11,7 @@ import multiprocessing from time import sleep from util import fprint from util import run_cmd +from util import win32 import sys import ur5_control from ur5_control import Rob @@ -33,9 +34,10 @@ import fileserver import paho.mqtt.client as mqtt import pickle import time +import subprocess # set to false to run without real hardware for development -real = False +real = True skip_scanning = True mbconn = None @@ -82,8 +84,10 @@ unacked_publish = set() mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) counter_file = 'pick_count.txt' cycle_start_time = time.time() - - +arm_distance = 0 +arm_distance_old = 0 +arm_distance_total = 0 +kill_ssh = False mqttc.user_data_set(unacked_publish) def arm_start_callback(res): @@ -375,7 +379,8 @@ def check_server(): mainloop_get.put(("pickup", data["position"])) elif "tray" in data: fprint("Adding tray return to dispense queue") - mainloop_get.put(("return", data["tray"])) + mainloop_get.put(("returnCheck", 0)) + #mainloop_get.put(("return", data["tray"])) else: fprint("Invalid data.") elif call == 'request': @@ -549,7 +554,7 @@ def get_sensors(): """ if real: - sens = [352, 288, 304, 368] + sens = [320, 336, 352, 368] for idx in range(len(sens)): reg = sens[idx] val = mbconn.read_holding_registers(reg) @@ -636,10 +641,13 @@ def mainloop_server(pool, manager): global timecount global secondsclock global cycle_start_time - + global arm_distance + global arm_distance_old + global arm_distance_total if mode != oldmode: print(" ***** Running mode:", mode, "***** ") + send_data("mode", "send", "{\"mode\": \"" + mode + "\" }") oldmode = mode mqtt_send(mode, "mode") if mode == "Startup": # very first loop @@ -661,6 +669,12 @@ def mainloop_server(pool, manager): if isinstance(val, tuple): arm_position = val + if arm_distance_old == 0: + arm_distance_old = val[0] + val[1] + val[2] + arm_distance = 0 + else: + arm_distance += val[0] + val[1] + val[2] - arm_distance_old + arm_distance_old = val[0] + val[1] + val[2] else: print("Arm queue message " + str(val)) checkpoint = val @@ -706,7 +720,13 @@ def mainloop_server(pool, manager): # every 1 second if secondsclock >= config["core"]["loopspeed"]: secondsclock = 1 - + arm_distance_total += arm_distance + if abs(arm_distance) < 0.001: + arm_distance = 0.0 + + mqtt_send("{\"value\": " + str(abs(arm_distance)) + " }", "arm_speed") + mqtt_send("{\"value\": " + str(abs(arm_distance_total)) + " }", "arm_distance") + arm_distance_old = 0 # reset counter @@ -767,7 +787,7 @@ def mainloop_server(pool, manager): global scan_value if scan_value is False: cable_list.append(scan_value) - elif scan_value.upper.find("BLDN.APP/") > -1: + elif scan_value.upper().find("BLDN.APP/") > -1: scan_value = scan_value[scan_value.find("bldn.app/")+9:] else: cable_list.append(scan_value) @@ -880,14 +900,7 @@ def mainloop_server(pool, manager): else: global mainloop_get - #print("Checking sensors..") - if real: - newtube = get_sensors() - else: - newtube = -1 - if newtube >= 0: - # need to return a cable - mainloop_get.put(("return", newtube)) + if not mainloop_get.empty(): action, get_cable = mainloop_get.get() @@ -902,8 +915,19 @@ def mainloop_server(pool, manager): pool.apply_async(ur5_control.move_to_packup, (arm,), callback=arm_start_callback, error_callback=handle_error) sleep(30) killme.set(1) + elif action == "returnCheck": + print("Checking sensors..") + if real: + newtube = get_sensors() + else: + newtube = -1 + if newtube >= 0: + # need to return a cable + mainloop_get.put(("return", newtube)) + mainloop_get.put(("returnCheck", 0)) else: fprint("Movement requested. Keep clear of the machine!") + arm_distance_total = 0 #mqtt_send("{\"value\": " + str(time.time() * 1000) + " }", "cycle_start") cycle_start_time = int(time.time() * 1000) increment_counter() @@ -995,8 +1019,8 @@ def mainloop_server(pool, manager): timecount = 0 pool.apply_async(camera.read_qr, (10,), callback=camera_start_callback, error_callback=handle_error) - elif scan_value.find("bldn.app/") > -1: - scan_value = scan_value[scan_value.find("bldn.app/")+9:] + elif scan_value.upper().find("BLDN.APP/") > -1: + scan_value = scan_value[scan_value.upper().find("BLDN.APP/")+9:] fprint("Got cable: " + str(scan_value)) if scan_value[0:2] == "BL" or scan_value[0:2] == "AW": @@ -1054,7 +1078,23 @@ def mainloop_server(pool, manager): +def ping(host): + #Returns True if host (str) responds to a ping request. + # Option for the number of packets as a function of + if win32: + param1 = '-n' + param2 = '-w' + param3 = '250' + else: + param1 = '-c' + param2 = '-W' + param3 = '0.25' + + # Building the command. Ex: "ping -c 1 google.com" + command = ['ping', param1, '1', param2, param3, host] + + return subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) == 0 def run_loading_app(): @@ -1071,25 +1111,44 @@ def setup_client(pool): global serverproc if config["core"]["server"] == "Hyper-V": run_cmd("Start-VM -Name Jukebox*") # any and all VMs starting with "Jukebox" + + fprint("Waiting for VM to start...") + while not ping("192.168.1.25"): + sleep(0.25) + + fprint("VM online.") # Windows client setup + from subprocess import PIPE + fprint("Running full jukebox control system...") + jb = subprocess.Popen("ssh root@192.168.1.25 -- /root/jukebox-software/run.sh".split(' '), stdout=PIPE, stderr=PIPE) + for line in jb.stdout: + print(line, end='') + if line.find("Running mode: Idle") > 0: + # Jukebox started + break # continue with program + fprint("Opening browser...") firefox = webdriver.Firefox() firefox.fullscreen_window() - - # Open loading wepage - p = Process(target=run_loading_app) - p.start() - firefox.get('http://localhost:7000') - - # start Linux server VM + # firefox.get('http://localhost:7000') - sleep(35) - p.terminate() firefox.get('http://192.168.1.25:3000') + global kill_ssh + while kill_ssh is False: + sleep(0.1) + + firefox.close() + jb.terminate() + run_cmd("Stop-VM -Name Jukebox*") + killall() + + #firefox.execute_script('document.body.style.MozTransform = "scale(0.80)";') + #firefox.execute_script('document.body.style.MozTransformOrigin = "0 0";') + #firefox.execute_script("document.body.style.zoom='80%'") # import time # while True: # time.sleep(2) # Wait for a given interval @@ -1101,12 +1160,12 @@ def setup_client(pool): # # else: # # break # Exit the loop or continue depending on your logic - return True + #return True def mainloop_client(pool): sleep(0.1) - + killall() # listen for & act on commands from VM, if needed # mainly just shut down, possibly connect to wifi or something @@ -1139,7 +1198,11 @@ def killall_signal(a, b): global config if config["core"]["server"] == "Hyper-V": run_cmd("Stop-VM -Name Jukebox*") # any and all VMs starting with "Jukebox" - killall() + if config["core"]["mode"] == "winclient": + global kill_ssh + kill_ssh = True + else: + killall() def error(msg, *args): return multiprocessing.get_logger().error(msg, *args) diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..90cd12d --- /dev/null +++ b/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +pkill -9 python # kill any old processes +cd /root/jukebox-software +python run.py \ No newline at end of file diff --git a/ur5_control.py b/ur5_control.py index 21c3c97..0269453 100755 --- a/ur5_control.py +++ b/ur5_control.py @@ -581,7 +581,7 @@ def tray_routine(robot, slot=0, pick_up=True): # Positions for each slot slot_distance = .052 - slot_height = -.015-.0095 + slot_height = -.015-.0095+0.007 # add 7mm for shim first_slot = -0.3084+0.01 slot_position = [ [first_slot, -0.3426, slot_height, 1.5899, 1.5526, -0.9411], @@ -745,27 +745,28 @@ def close_gripper(): def get_position_thread(robot, pos_updates): - robot = connect(robot) - rob = robot.robot - oldvals = rob.getl() - deltavals = [0,0,0] - import uptime - t = 0.01 - count = 0 - while True: - start = uptime.uptime() - if pos_updates.qsize() < 2: - vals = rob.getl() - if vals != oldvals: - if pos_updates is not None: - pos_updates.put(tuple(oldvals)) + try: + robot = connect(robot) + rob = robot.robot + oldvals = rob.getl() + deltavals = [0,0,0] + import uptime + t = 0.01 + count = 0 + while True: + start = uptime.uptime() + if pos_updates.qsize() < 2: + vals = rob.getl() + if vals != oldvals: + if pos_updates is not None: + pos_updates.put(tuple(oldvals)) #time.sleep(0.01) # deltavals = list() # deltavals.append(vals[0]-oldvals[0]) # deltavals.append(vals[1]-oldvals[1]) # deltavals.append(vals[2]-oldvals[2]) # count = 0 - oldvals = vals + oldvals = vals # else: # count += 0.2 @@ -775,9 +776,10 @@ def get_position_thread(robot, pos_updates): # tmpvals[1] = oldvals[1] + deltavals[1]*count # tmpvals[2] = oldvals[2] + deltavals[2]*count # pos_updates.put(tuple(tmpvals)) - while start + t > uptime.uptime(): - time.sleep(0.0001) - + while start + t > uptime.uptime(): + time.sleep(0.0001) + except: + pass if __name__ == "__main__": @@ -795,9 +797,9 @@ if __name__ == "__main__": rob = robot.robot # rob is robot.robot is the urx robot class, what we've been using previously - move_to_packup(robot) - - # pick_up_holder(robot, 2) + #move_to_packup(robot) + move_to_home(robot) + pick_up_holder(robot, None, 8) #drop_off_tray(robot, 0) # drop_off_tray(robot, 1) # drop_off_tray(robot, 2)