예제 #1
0
def main():

    port = "/dev/tty.usbserial-AL034G1T"

    serial = ServoSerial(port=port)
    serial.open()

    servo = Packet(pyservos.AX12)
    # servo = Packet(pyservos.XL320)

    # build
    # 59 rpm max
    data = []
    ids = [1, 2, 3]
    pos = [150, 200, 90]
    vel = [200, 100, 300]  # 0.111 rpm

    for i, p, v in zip(ids, pos, vel):
        data.append([i] + angle2int(p) + le(v))

    pkt = servo.makeSyncWritePacket(pyservos.AX12.GOAL_POSITION, data)
    print(pkt)

    ans = serial.sendPkt(pkt)  # send packet to servo
    ans = servo.processStatusPacket(ans)

    if ans:
        print('status: {}'.format(ans))
예제 #2
0
    def __init__(self, data, servoType):
        """
        data: serial port to use, if none, then use dummy port
        servoType: AX12 or XL320 or other servo type
        curr_pos: current leg position
        bcm_pin: which gpio pin is used for the comm
            {
                0: [(t0,t1,t2,t3,speed), ...]
                1: [...]
                ...
                3: [...]
            }
        """
        if 'bcm_pin' in data:
            bcm_pin = data['bcm_pin']
        else:
            bcm_pin = None

        # self.wait = wait
        # determine serial port
        # default to fake serial port
        if 'serialPort' in data:
            try:
                self.serial = ServoSerial(data['serialPort'], pi_pin=bcm_pin)
                print('Using servo serial port: {}'.format(data['serialPort']))
                self.serial.open()

            except Exception as e:
                print(e)
                print('Engine::init(): bye ...')
                exit(1)
        else:
            print('*** Using dummy serial port!!! ***')
            self.serial = ServoSerial('dummy')
            # raise Exception('No serial port given')

        # handle servos ... how does it know how many servos???
        self.servos_up = {}  # check servos are operating
        self.servos = []
        for ID, seg in enumerate(['coxa', 'femur', 'tibia', 'tarsus']):
            length, offset = data[seg]
            self.servos.append(Servo(ID, offset))
            # resp = self.pingServo(ID)  # return: (T/F, servo_angle)
            # self.servos[ID] = resp[0]
            # curr_angle[ID] =
        # for s, val in self.servos.items():
        #     if val is False:
        #         print("*** Engine.__init__(): servo[{}] has failed".format(s))

        self.packet = Packet(servoType)

        # keep track of last location, this is servo angle space
        # self.last_move = {
        #     0: curr_pos[0][0],
        #     1: curr_pos[1][0],
        #     2: curr_pos[2][0],
        #     3: curr_pos[3][0]
        # }
        self.last_move = self.getCurrentAngles()
예제 #3
0
def get(port, IDs, bcm_pin, retry=3):
    """
    Sends a ping packet to ID's from 0 to maximum and prints out any returned
    messages.
    Actually send a broadcast and will retry (resend) the ping 3 times ...
    """
    valid_return = False

    s = ServoSerial(port, pi_pin=bcm_pin)

    try:
        s.open()
    except Exception as e:
        print('-' * 40)
        print(sys.argv[0], ':')
        print(e)
        exit(1)

    servo = Packet(pyservos.AX12)

    found_servos = {}

    # print("read:")
    for id in IDs:
        # print(id, end=' ')
        pkt = makeAngleReadPacket(id)
        s.write(pkt)

        valid_return = False

        # as more servos add up, I might need to increase the cnt number???
        for cnt in range(retry):
            ans = s.read()

            if ans:
                valid_return = True
                pkts = servo.decodePacket(ans)
                # print(pkts)
                for pkt in pkts:
                    if pkt[:5] == [0xff, 0xff, id, 4, 0]:
                        angle = ((pkt[6] << 8) + pkt[5]) * 0.29  # cnts to deg
                        found_servos[id] = angle
                # print('Found')
                break
            if not valid_return:
                print(id, 'ERROR: Could not read servo angle')

            time.sleep(0.1)

    s.close()

    return valid_return, found_servos
예제 #4
0
class Engine(object):
    """
    This class holds the serial port and talks to the hardware. Other classes (
    e.g., gait, legs and servos) do the calculations for walking.
    """

    last_move = None

    def __init__(self, data, servoType):
        """
        data: serial port to use, if none, then use dummy port
        servoType: AX12 or XL320 or other servo type
        curr_pos: current leg position
        bcm_pin: which gpio pin is used for the comm
            {
                0: [(t0,t1,t2,t3,speed), ...]
                1: [...]
                ...
                3: [...]
            }
        """
        if 'bcm_pin' in data:
            bcm_pin = data['bcm_pin']
        else:
            bcm_pin = None

        # self.wait = wait
        # determine serial port
        # default to fake serial port
        if 'serialPort' in data:
            try:
                self.serial = ServoSerial(data['serialPort'], pi_pin=bcm_pin)
                print('Using servo serial port: {}'.format(data['serialPort']))
                self.serial.open()

            except Exception as e:
                print(e)
                print('Engine::init(): bye ...')
                exit(1)
        else:
            print('*** Using dummy serial port!!! ***')
            self.serial = ServoSerial('dummy')
            # raise Exception('No serial port given')

        # handle servos ... how does it know how many servos???
        self.servos_up = {}  # check servos are operating
        self.servos = []
        for ID, seg in enumerate(['coxa', 'femur', 'tibia', 'tarsus']):
            length, offset = data[seg]
            self.servos.append(Servo(ID, offset))
            # resp = self.pingServo(ID)  # return: (T/F, servo_angle)
            # self.servos[ID] = resp[0]
            # curr_angle[ID] =
        # for s, val in self.servos.items():
        #     if val is False:
        #         print("*** Engine.__init__(): servo[{}] has failed".format(s))

        self.packet = Packet(servoType)

        # keep track of last location, this is servo angle space
        # self.last_move = {
        #     0: curr_pos[0][0],
        #     1: curr_pos[1][0],
        #     2: curr_pos[2][0],
        #     3: curr_pos[3][0]
        # }
        self.last_move = self.getCurrentAngles()

    def getCurrentAngles(self):
        """
        Returns the current angles for all servos in DH space as a dictionary.
        angles = {
            0: [0.0, 130.26, -115.73, -104.52],
            1: [0.0, 130.26, -115.73, -104.52],
            2: [0.0, 130.26, -115.73, -104.52],
            3: [0.0, 130.26, -115.73, -104.52],
        }

        FIXME: actually query the servos and get there angles in DH space
        """
        angles = {
            0: [0.0, 130.26, -115.73, -104.52],
            1: [0.0, 130.26, -115.73, -104.52],
            2: [0.0, 130.26, -115.73, -104.52],
            3: [0.0, 130.26, -115.73, -104.52],
        }
        return angles

    def DH2Servo(self, angle, num):
        return self.servos[num].DH2Servo(angle)

    def moveLegsGait4(self, legs):
        """
        gait or sequence?
        speed = 1 - 1023 (scalar, all servos move at same rate)
        {      step 0          step 1         ...
            0: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg0
            2: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg2
            ...
        } where t=theta
        NOTE: each leg needs the same number of steps and servos per leg
        WARNING: these angles are in servo space [0-300 deg]

        [Join Mode]
        0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm.
        If it is set to 0, it means the maximum rpm of the motor is used
        without controlling the speed. If it is 1023, it is about 114rpm.
        For example, if it is set to 300, it is about 33.3 rpm.

        AX12 max rmp is 59 (max speed 532)
        rev  min     360 deg      deg
        --- -------  ------- = 6 ----
        min  60 sec    rev        sec

        sleep time = | (new_angle - old_angle) /(0.111 * min_speed * 6) |
        """
        # get the keys and figure out some stuff
        keys = list(legs.keys())  # which legs are we moving
        numSteps = len(legs[keys[0]])  # how many steps in the cycle
        numServos = len(legs[keys[0]][0])-1  # how many servos per leg, -1 because speed there

        # if self.last_move is None:
        #     # assume we just turned on and was in the sit position
        #     # need a better solution
        #     self.last_move = {
        #         0: legs[0][0],
        #         1: legs[1][0],
        #         2: legs[2][0],
        #         3: legs[3][0]
        #     }

        # curr_move = {}
        # for each step in legs
        for step in range(numSteps):
            # dprint("\nStep[{}]===============================================".format(step))
            data = []

            # find max time we have to wait for all 4 legs to reach their end
            # point.
            max_wait = 0
            for legNum in keys:
                angles = legs[legNum][step][:4]
                speed = legs[legNum][step][4]
                # print(" speed", speed)
                for a, oa in zip(angles, self.last_move[legNum][:4]):
                    da = abs(a-oa)
                    w = calc_wait(da, speed)
                    # print(" calc_wait: {:.3f}".format(w))
                    # print("calc_wait: {}".format(w))
                    max_wait = w if w > max_wait else max_wait

            # print(">> found wait", max_wait, " speed:", speed)

            servo_speeds = [100,125,150,200]

            # for legNum in [0,3,1,2]:
            for legNum in keys:
                # dprint("  leg[{}]--------------".format(legNum))
                leg_angles_speed = legs[legNum][step]
                # print(leg_angles_speed)
                angles = leg_angles_speed[:4]  # 4 servo angles
                speed = leg_angles_speed[4]
                # print("Speed:", speed, "wait", max_wait)

                for i, DH_angle in enumerate(angles):
                    # oldangle = self.last_move[legNum][i]
                    # due to rounding errors, to ensure the other servers finish
                    # BEFORE time.sleep(max_wait) ends, the the function it
                    # has less time
                    # spd = calc_rpm((angle - oldangle), 0.9*max_wait)
                    # now that i am scaling the spd parameter above, I sometimes
                    # exceed the original speed number, so saturate it if
                    # necessary
                    # spd = spd if spd <= speed else speed
                    # sl, sh = le(spd)
                    sl, sh = le(servo_speeds[i])
                    servo_angle = self.DH2Servo(DH_angle, i)
                    al, ah = angle2int(servo_angle)  # angle
                    data.append([legNum*numServos + i+1, al, ah, sl, sh])  # ID, low angle, high angle, low speed, high speed
                    # data.append([legNum*numServos + i+1, al, ah])  # ID, low angle, high angle, low speed, high speed

                self.last_move[legNum] = leg_angles_speed

            pkt = self.packet.makeSyncWritePacket(self.packet.base.GOAL_POSITION, data)
            self.serial.write(pkt)
            dprint("sent serial packet leg: {}".format(legNum))
            data = []
            print('max_wait', max_wait)
            time.sleep(max_wait)
예제 #5
0
def makeAngleReadPacket(id):
    servo = Packet(pyservos.AX12)  # remove
    pkt = servo.makeReadPacket(id, 36, 2)  # self.base.makeReadPacket()
    return pkt
예제 #6
0
# you will need to CHANGE this to the correct port
port = "/dev/ttyS0"
ID = 1
angle = int(sys.argv[1])

print('Setting servo[{}] to {:.2f} on port {}'.format(ID, angle, port))

try:
	serial = ServoSerial(port=port)
	serial.open()
except Exception as e:
	print(e)
	print('Oops, wrong port')
	print('bye ....')
	exit(1)

if True:
	servo = Packet(pyservos.AX12)
	print('We are talking to an AX12 servo')
else:
	servo = Packet(pyservos.XL320)
	print('We are talking to an XL320 servo')

pkt = servo.makeServoMovePacket(ID, angle)
ans = serial.sendPkt(pkt)  # send packet to servo
ans = servo.processStatusPacket(ans)

if ans:
	print('status: {}'.format(ans))
예제 #7
0
        speed = 1024 + abs(speed)

    pkt = servo.makeWritePacket(ID, servo.base.GOAL_VELOCITY, le(speed))
    return pkt


ID = 1

port = "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A904MISU-if00-port0"
# port = "/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0"
serial = ServoSerial(port=port)
serial.open()

print(">> baudrate:", serial.serial.baudrate)

servo = Packet(pyservos.AX12)

pkt = set_wheel_mode(ID)
ans = serial.sendPkt(pkt)  # send packet to servo

for speed in range(-1023, 1023, 10):
    print(">>", speed)
    pkt = set_wheel_speed(ID, speed)
    ans = serial.sendPkt(pkt)  # send packet to servo
    time.sleep(0.1)

speed = 0
# pkt = servo.makeWritePacket(ID, servo.base.GOAL_VELOCITY, le(speed))
pkt = set_wheel_speed(ID, speed)
ans = serial.sendPkt(pkt)  # send packet to servo
예제 #8
0
from pyservos import Packet
from pyservos.servoserial import ServoSerial
import pyservos
from pyservos.utils import angle2int, le
import time

servoType = pyservos.XL320
servoStr = 'XL-320'
port = "/dev/ttyS0"
offset = 5
speed = 312

serial = ServoSerial(port=port)
serial.open()

servo = Packet(servoType)


def set_angle(id, angle):
    val = angle2int(angle, degrees=True) + le(speed)
    pkt = servo.makeWritePacket(id, servo.base.GOAL_POSITION, val)
    serial.sendPkt(pkt)  # send packet to servo


while True:
    set_angle(2, 0)
    set_angle(3, 300 - offset)
    time.sleep(4)
    set_angle(2, 300 - offset)
    set_angle(3, 0)
    time.sleep(4)