├── README.md ├── example ├── points.ini └── run.rbt └── robot.py /README.md: -------------------------------------------------------------------------------- 1 | # RXB1 Software 2 | 3 | [![N|Roboteurs](https://cdn.shopify.com/s/files/1/0742/2899/files/logosmall.png?575371702457707276 4 | )](https://www.roboteurs.com) 5 | 6 | The RXB1 is a 6 axis remix of the famous Thor robot. This robot can be driven by a number of different method. Using the SlushEngine this robot can be driven with a purley Python implementation. This makes it simple to understand how the robot is working and makes it easy for engineers and students to make changes to. 7 | *It should be noted that at the moment this software is still under a lot of development. It is working but the software will undergo a lot of changes. 8 | # Installation 9 | To install this software all you need to do is clone the directory somewhere. This software does require the Slush library and Inputs 10 | ```sh 11 | $ sudo pip3 install Inputs 12 | ``` 13 | # Usage 14 | To use this code to drive your robot just go into the working directory and run robot.py. Make sure you have a joystick connected or you can do nothing 15 | ```sh 16 | $ cd rbx1-software 17 | $ python3 robot.py 18 | ``` 19 | Now you are up and running. If you move the connected joystick you will see movment in the robot. For more info on using the software check out the wiki. 20 | # How does it work? 21 | Good question. Its actually pretty straight forward really. The Python program reads the commands comming from the joystick and translates them into motions in the robot. If you want to save a point then robot.py saves your point to the points file located in examples. If you want to run a program the robot will execute the instructions that it finds in the run.rbt file. 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/points.ini: -------------------------------------------------------------------------------- 1 | HOME:0:0:0:0:0:0:7 2 | 1PREPICK:777:-1010:-23288:-85:6:-862:7 3 | 1PICK:815:-1766:-23252:-60:-8:-1394:8 4 | 1PICKLIFT:815:-1568:-23635:-75:-4:-1399:16 5 | 1PICKHIGH:815:-425:-24062:-62:-4:-1399:17 6 | MIDDLEHIGH:-3709:-805:-17031:-8:-44:1585:17 7 | 1DROPHIGH:-4839:-1891:-21261:44:-201:1088:17 8 | 1DROP:-4839:-2346:-20521:21:-201:1088:17 9 | 2PREPICK:-138:-1155:-23114:24:6:-862:7 10 | 2PICK:-39:-1841:-23666:-12:50:-1638:17 11 | 2PICKLIFT:-39:-1586:-24031:-16:50:-1638:17 12 | 2PICKHIGH:-39:-922:-22756:-13:7:-1389:17 13 | 2DROPHIGH:-4082:-2183:-19589:-67:-215:1180:16 14 | 2DROP:-4082:-2420:-19116:-53:-215:1180:8 15 | TESTPICK:-2294:-2117:-21125:358:-129:-1646:7 16 | -------------------------------------------------------------------------------- /example/run.rbt: -------------------------------------------------------------------------------- 1 | GRIPPER OPEN 2 | GOTO 1PREPICK 3 | GOTO 1PICKLIFT 4 | GOTO 1PICK 5 | GRIPPER CLOSE 6 | SLEEP 1 7 | GOTO 1PICKLIFT 8 | GOTO 1PICKHIGH 9 | GOTO MIDDLEHIGH 10 | GOTO 1DROPHIGH 11 | GOTO 1DROP 12 | GRIPPER OPEN 13 | SLEEP 1 14 | GOTO MIDDLEHIGH 15 | GOTO 2PREPICK 16 | GOTO 2PICKLIFT 17 | GOTO 2PICK 18 | GRIPPER CLOSE 19 | SLEEP 1 20 | GOTO 2PICKLIFT 21 | GOTO 2PICKHIGH 22 | GOTO MIDDLEHIGH 23 | GOTO 2DROPHIGH 24 | GOTO 2DROP 25 | GRIPPER OPEN 26 | SLEEP 1 27 | GOTO MIDDLEHIGH 28 | GOTO 1DROP 29 | GRIPPER CLOSE 30 | SLEEP 1 31 | GOTO 1DROPHIGH 32 | GOTO MIDDLEHIGH 33 | GOTO 1PICKHIGH 34 | GOTO 1PICKLIFT 35 | GOTO 1PICK 36 | GRIPPER OPEN 37 | SLEEP 1 38 | GOTO 1PICKLIFT 39 | GOTO 1PREPICK 40 | GOTO MIDDLEHIGH 41 | GOTO 2DROP 42 | GRIPPER CLOSE 43 | SLEEP 1 44 | GOTO 2DROPHIGH 45 | GOTO MIDDLEHIGH 46 | GOTO 2PICKHIGH 47 | GOTO 2PICKLIFT 48 | GOTO 2PICK 49 | GRIPPER OPEN 50 | SLEEP 1 51 | GOTO 2PICKLIFT 52 | GOTO 2PREPICK 53 | GOTO HOME 54 | -------------------------------------------------------------------------------- /robot.py: -------------------------------------------------------------------------------- 1 | 2 | from inputs import get_gamepad 3 | import RPi.GPIO as GPIO 4 | import Slush 5 | import math 6 | import time 7 | 8 | 9 | #setup all of the axis for the SlushEngine 10 | b = Slush.sBoard() 11 | joints = [Slush.Motor(0), Slush.Motor(1), Slush.Motor(2), Slush.Motor(3), Slush.Motor(4), Slush.Motor(5)] 12 | 13 | #reset the joints to clear previous errors 14 | for joint in joints: 15 | joint.resetDev() 16 | joint.setMicroSteps(16) 17 | 18 | #some initalization stuff that needs cleanup 19 | joints[0].setMaxSpeed(150) 20 | joints[1].setMaxSpeed(150) 21 | joints[2].setMaxSpeed(250) 22 | joints[3].setMaxSpeed(150) 23 | joints[4].setMaxSpeed(150) 24 | joints[5].setMaxSpeed(150) 25 | 26 | #joint current limits. Still setting manually becuase testing (hold A, run A, acc A, dec, A) 27 | joints[0].setCurrent(65, 85, 75, 70) 28 | joints[1].setCurrent(65, 85, 85, 65) 29 | joints[2].setCurrent(50, 50, 50, 50) 30 | joints[3].setCurrent(75, 75, 75, 75) 31 | joints[4].setCurrent(85, 85, 85, 85) 32 | joints[5].setCurrent(65,65, 65, 65) 33 | 34 | #setup the gripper 35 | GPIO.setmode(GPIO.BCM) 36 | GPIO.setup(18, GPIO.OUT) 37 | pwm = GPIO.PWM(18, 100) 38 | 39 | 40 | def waitForRobot(): 41 | for joint in joints: 42 | while joint.isBusy(): continue 43 | 44 | def robotMove(speed, points): 45 | 46 | #wait for the robot to stop doing things 47 | for joint in joints: 48 | while joint.isBusy(): continue 49 | 50 | #get the current location of the robot 51 | currentpos = [] 52 | for joint in joints: 53 | currentpos.append(joint.getPosition()) 54 | 55 | #make a list of the difference 56 | differencepose = [points - currentpos for points, currentpos in zip(points, currentpos)] 57 | maxmove = (max(map(abs, differencepose))) 58 | i = 0 59 | for joint in joints: 60 | try: 61 | jointspeed = speed * (abs(differencepose[i])/maxmove) 62 | except: 63 | jointspeed = 1 64 | if jointspeed < 1: jointspeed = 1 65 | joint.setMaxSpeed(math.ceil(jointspeed)) 66 | joint.setMinSpeed(0) 67 | joint.goTo(int(points[i])) 68 | i = i + 1 69 | 70 | 71 | def moveFilePoint(name): 72 | if name == "LIST": 73 | with open("example/points.ini") as pointfile: 74 | for line in pointfile: 75 | print (line) 76 | with open("example/points.ini") as pointfile: 77 | namesfound = 0 78 | for line in pointfile: 79 | if line.startswith(name): 80 | namesfound = 1 81 | points = line.split(':') 82 | if points[0] == name: 83 | intpoints = [] 84 | for point in points[1:len(points)]: 85 | intpoints.append(int(point)) 86 | robotMove(80, intpoints) 87 | if not namesfound: print("Point Data not Found") 88 | 89 | def runProgram(): 90 | with open("example/run.rbt") as programfile: 91 | i = 0 92 | for line in programfile: 93 | print("N" + str(i) + ":" + line) 94 | i += 1 95 | lineinfo = line.rstrip('\n').split(' ') 96 | if lineinfo[0] == "GOTO": 97 | moveFilePoint(lineinfo[1]) 98 | if lineinfo[0] == "SLEEP": 99 | waitForRobot() 100 | time.sleep(int(lineinfo[1])) 101 | if lineinfo[0] == "GRIPPER": 102 | waitForRobot() 103 | if lineinfo[1] == "OPEN": 104 | pwm.start(7) 105 | if lineinfo[1] == "CLOSE": 106 | pwm.start(17) 107 | if lineinfo[0] == "EXIT": 108 | break 109 | 110 | #start reading the inputs from the gamepad and putting them out the joints 111 | gripper = 7 112 | while 1: 113 | events = get_gamepad() 114 | for event in events: 115 | if event.code == 'BTN_MODE': 116 | value = event.state 117 | if value == 1: 118 | for joint in joints: 119 | joint.free() 120 | 121 | if event.code == 'ABS_X': 122 | value = event.state 123 | if value < -1500: 124 | if not joints[0].isBusy(): joints[0].run(1, 35) 125 | elif value > 5000: 126 | if not joints[0].isBusy(): joints[0].run(0, 35) 127 | else: 128 | if not joints[0].isBusy(): joints[0].softStop() 129 | if event.code == 'ABS_Y': 130 | value = event.state 131 | if value < -1500: 132 | if not joints[1].isBusy(): joints[1].run(1, 20) 133 | elif value > 5000: 134 | if not joints[1].isBusy(): joints[1].run(0, 20) 135 | else: 136 | if not joints[1].isBusy(): joints[1].softStop() 137 | if event.code == 'ABS_RX': 138 | value = event.state 139 | if value < -3500: 140 | if not joints[2].isBusy(): joints[2].run(1, 100) 141 | elif value > 3500: 142 | if not joints[2].isBusy(): joints[2].run(0, 100) 143 | else: 144 | if not joints[2].isBusy(): joints[2].softStop() 145 | if event.code == 'ABS_RY': 146 | value = event.state 147 | if value < -3500: 148 | if not joints[3].isBusy(): joints[3].run(1, 10) 149 | elif value > 3500: 150 | if not joints[3].isBusy(): joints[3].run(0, 10) 151 | else: 152 | if not joints[3].isBusy(): joints[3].softStop() 153 | if event.code == 'ABS_HAT0Y': 154 | value = event.state 155 | if value == 1: 156 | if not joints[4].isBusy(): joints[4].run(1, 20) 157 | elif value == -1: 158 | if not joints[4].isBusy(): joints[4].run(0, 20) 159 | else: 160 | if not joints[4].isBusy(): joints[4].softStop() 161 | if event.code == 'ABS_HAT0X': 162 | value = event.state 163 | if value == 1: 164 | if not joints[5].isBusy(): joints[5].run(1, 20) 165 | elif value == -1: 166 | if not joints[5].isBusy(): joints[5].run(0, 20) 167 | else: 168 | if not joints[5].isBusy(): joints[5].softStop() 169 | if event.code == 'BTN_TL': 170 | if event.state == 1: 171 | gripper = gripper - 1 172 | if gripper < 7: 173 | gripper = 7 174 | pwm.start(gripper) 175 | if event.code == 'BTN_TR': 176 | if event.state == 1: 177 | gripper = gripper + 1 178 | if gripper > 17: 179 | gripper = 17 180 | pwm.start(gripper) 181 | #calibrate all axis if on point 182 | if event.code == 'BTN_START': 183 | if event.state == 1: 184 | for joint in joints: 185 | joint.setAsHome() 186 | if event.code == 'BTN_SOUTH': 187 | if event.state == 1: 188 | print ("no function") 189 | if event.code == 'BTN_NORTH': 190 | if event.state == 1: 191 | runProgram() 192 | if event.code == 'BTN_EAST': 193 | if event.state == 1: 194 | name = input('Name Point (no spaces): ') 195 | if name == 'EXIT': break 196 | with open("example/points.ini", "a") as pointfile: 197 | for joint in joints: 198 | name += (':'+str(joint.getPosition())) 199 | name +=(':' + str(gripper)) 200 | name +=('\n') 201 | pointfile.write(name) 202 | if event.code == 'BTN_WEST': 203 | if event.state == 1: 204 | name = input('Go To Point (no spaced): ') 205 | moveFilePoint(name) 206 | --------------------------------------------------------------------------------