示例#1
0
    def __init__(self,
                 virtualMachine=None,
                 virtualNode=None,
                 axes=None,
                 kinematics=None,
                 machinePosition=None,
                 defaultAcceleration=coordinates.uFloat(2000, "steps/s^2"),
                 pullInSpeed=4000,
                 planner=None):
        '''Configures the move object.'''

        #convert inputs to lists where appropriate
        if type(axes) != list: axes = [axes]

        self.virtualMachine = virtualMachine  #a reference to the virtual machine which owns this function.
        self.virtualNode = virtualNode  #a list of nodes which will be used by the function.
        self.axes = axes  #a list of axes which connect physical actuators to the machine kinematics. Some nodes support multiple axes.
        self.kinematics = kinematics  #a kinematics object which will transform between axis coordinates and machine coordinates
        self.machinePosition = machinePosition  #the positional state of the machine.
        self.defaultAcceleration = defaultAcceleration  #if no units are provided, it will be assumed in mm/s^2.
        #However, the default is in steps/s^2, corresponding to motor inertia dominance.
        self.pullInSpeed = pullInSpeed  #this is the maximum step rate at which the motors can change direction instantaneously.
        #Eventually, this should support different rates for each motor.
        #The default was chosen because a 400 step/rev stepper motor with 51oz-in driven at 24V and driving a small mechanical
        #load thru an 18T MXL pulley could pull in at 200mm/s or 2200 steps/sec. Assuming microstepping of 4, the pull-in speed
        #derated by 50% is 4000 uSteps/sec.

        #configure and start motion planner
        if planner == 'null':
            self.planner = self.nullMotionPlanner(self)
        else:  #use default planner
            self.planner = self.motionPlanner(
                self)  #multi-block lookahead motion planner instance

        self.planner.daemon = True
        self.planner.start()
示例#2
0
	def __init__(self, virtualMachine = None, virtualNode = None, axes = None, kinematics = None, machinePosition = None, defaultAcceleration = coordinates.uFloat(2000, "steps/s^2"), pullInSpeed = 4000, planner = None):
		'''Configures the move object.'''
		
		#convert inputs to lists where appropriate
		if type(axes) != list: axes = [axes]
		
		self.virtualMachine = virtualMachine #a reference to the virtual machine which owns this function.
		self.virtualNode = virtualNode #a list of nodes which will be used by the function.
		self.axes = axes #a list of axes which connect physical actuators to the machine kinematics. Some nodes support multiple axes.
		self.kinematics = kinematics #a kinematics object which will transform between axis coordinates and machine coordinates
		self.machinePosition = machinePosition #the positional state of the machine.
		self.defaultAcceleration = defaultAcceleration	#if no units are provided, it will be assumed in mm/s^2.
														#However, the default is in steps/s^2, corresponding to motor inertia dominance.
		self.pullInSpeed = pullInSpeed	#this is the maximum step rate at which the motors can change direction instantaneously.
										#Eventually, this should support different rates for each motor.
										#The default was chosen because a 400 step/rev stepper motor with 51oz-in driven at 24V and driving a small mechanical
										#load thru an 18T MXL pulley could pull in at 200mm/s or 2200 steps/sec. Assuming microstepping of 4, the pull-in speed
										#derated by 50% is 4000 uSteps/sec. 

		#configure and start motion planner										
		if planner == 'null':
			self.planner = self.nullMotionPlanner(self)
		else:	#use default planner
			self.planner = self.motionPlanner(self)	#multi-block lookahead motion planner instance

		self.planner.daemon = True
		self.planner.start()
示例#3
0
	def __init__(self, move, position = None, velocity = None, acceleration = None):
		#store parameters
		self.move = move	#the calling move class
		self.positionCommand = position
		self.velocityCommand = float(velocity)
		if acceleration:
			self.accelerationCommand = acceleration
		else:
			self.accelerationCommand = self.move.defaultAcceleration

		if type(self.accelerationCommand) != coordinates.uFloat:
			self.accelerationCommand = coordinates.uFloat(self.accelerationCommand, "mm/s^2")
		#note: need to decide here whether rotor inertia or stage inertia is dominant.
		# If rotor inertia, the accel rate should be specified in steps/sec^2 rather than mm/sec^2
		# Default accel can be set in steps/sec^2
		# The typical stepper motor (I = 0.3 oz-in^2) has an equivalent inertia of 134kg thru a 10TPI leadscrew, or 0.6kg thru an 18T MXL pulley
		
		
		#calculate deltas
		currentMachinePosition = self.move.machinePosition.future()	#get the current machine position
		
		requestedMachinePosition = []	#build up the requested machine position based on what is provided and what is left as 'None'.
		for axisIndex, axisPosition in enumerate(self.positionCommand):
			requestedMachinePosition += [coordinates.uFloat(axisPosition if axisPosition != None else currentMachinePosition[axisIndex], currentMachinePosition[axisIndex].units)]	#anything left as none is unchanged
		
		#transform between machine and axis coordinates
		transformedCurrentAxisPositions = self.move.kinematics.reverse(currentMachinePosition)	#calculates the current axis positions based on the kinematics transformation matrix
		transformedRequestedAxisPositions = self.move.kinematics.reverse(requestedMachinePosition)	#calculates the requested axis positions based on the kinematics transformation matrix

		currentMotorPositions = []
		for axisIndex, axisPosition in enumerate(transformedCurrentAxisPositions):
			currentMotorPositions += [self.move.axes[axisIndex].reverse(axisPosition)]

		requestedMotorPositions = []
		for axisIndex, axisPosition in enumerate(transformedRequestedAxisPositions):
			requestedMotorPositions += [self.move.axes[axisIndex].reverse(axisPosition)]


		machineDeltas = [end - start for end, start in zip(requestedMachinePosition, currentMachinePosition)]
		machineLength = math.sqrt(sum([math.pow(position, 2) for position in machineDeltas]))	#gets cartesian length of move


		motorDeltas = [coordinates.uFloat(x - y, x.units) for (x,y) in zip(requestedMotorPositions, currentMotorPositions)]
		self.actualMotorDeltas = [coordinates.uFloat(int(round(delta,0)), delta.units) for delta in motorDeltas]	#rounds steps down.
		self.majorSteps = max([abs(delta) for delta in self.actualMotorDeltas])	#note: this gets used by the path planner
		if machineLength != 0:
			parameterRatio = float(self.majorSteps) / float(machineLength)	#this ratio relates velocities and accelerations between the coordinate systems
		else:
			parameterRatio = 0.0
		
		#calculate maximum step rates
		self.segmentMaxStepRate = self.velocityCommand * parameterRatio		#units of steps/sec
		
		#motion planner parameters. These will be modified by the motion planner
		self.entryJunctionMaxStepRate = 0	#default to zero in case this move is the first one
		self.exitJunctionMaxStepRate = 200	#need to fix this eventually, but a minimum rate is necessary to not stall the planner. This is the min exit rate.
		self.forwardPassEntryStepRate = 0	#used by the forward pass of the path planner
		self.forwardPassExitStepRate = 0
		self.reversePassEntryStepRate = 0	#used by the reverse pass of the path planner
		self.reversePassExitStepRate = 0
		self.accelSteps = 0
		self.decelSteps = 0
		
		if self.accelerationCommand.units == "mm/s^2":
			self.segmentAccelRate = self.accelerationCommand * parameterRatio	#transform along major axis, now in steps^s^2
		elif self.accelerationCommand.units == "steps/s^2":
			self.segmentAccelRate = self.accelerationCommand	#motor inertia dominant, don't change.
		
		#create actionObjects and commit to the channel priority queue
		self.actionObjects = self.move.virtualNode.spinRequest(axesSteps = tuple(self.actualMotorDeltas), accelSteps = 0, decelSteps = 0, accelRate = 0, external = True, majorSteps = self.majorSteps)	#note conversion to tuple.
		self.actionObjects.commit()	#this will lock in their place in the transmit queue, however will not release until this move object is run thru the motion planner
		
		#commit self to the path planner.
		self.commit()
		
		#recalculate future machine position
		newMotorPositions = [coordinates.uFloat(x+y, x.units) for (x,y) in zip(self.actualMotorDeltas, currentMotorPositions)]
		
		transformedNewAxisPositions = []
		for motorIndex, motorPosition in enumerate(newMotorPositions):
			transformedNewAxisPositions += [self.move.axes[motorIndex].forward(motorPosition)]
		
		newMachinePosition = self.move.kinematics.forward(transformedNewAxisPositions)
		self.move.machinePosition.future.set(newMachinePosition)
示例#4
0
    def __init__(self, move, position=None, velocity=None, acceleration=None):
        #store parameters
        self.move = move  #the calling move class
        self.positionCommand = position
        self.velocityCommand = float(velocity)
        if acceleration:
            self.accelerationCommand = acceleration
        else:
            self.accelerationCommand = self.move.defaultAcceleration

        if type(self.accelerationCommand) != coordinates.uFloat:
            self.accelerationCommand = coordinates.uFloat(
                self.accelerationCommand, "mm/s^2")
        #note: need to decide here whether rotor inertia or stage inertia is dominant.
        # If rotor inertia, the accel rate should be specified in steps/sec^2 rather than mm/sec^2
        # Default accel can be set in steps/sec^2
        # The typical stepper motor (I = 0.3 oz-in^2) has an equivalent inertia of 134kg thru a 10TPI leadscrew, or 0.6kg thru an 18T MXL pulley

        #calculate deltas
        currentMachinePosition = self.move.machinePosition.future(
        )  #get the current machine position

        requestedMachinePosition = [
        ]  #build up the requested machine position based on what is provided and what is left as 'None'.
        for axisIndex, axisPosition in enumerate(self.positionCommand):
            requestedMachinePosition += [
                coordinates.uFloat(
                    axisPosition if axisPosition != None else
                    currentMachinePosition[axisIndex],
                    currentMachinePosition[axisIndex].units)
            ]  #anything left as none is unchanged

        #transform between machine and axis coordinates
        transformedCurrentAxisPositions = self.move.kinematics.reverse(
            currentMachinePosition
        )  #calculates the current axis positions based on the kinematics transformation matrix
        transformedRequestedAxisPositions = self.move.kinematics.reverse(
            requestedMachinePosition
        )  #calculates the requested axis positions based on the kinematics transformation matrix

        currentMotorPositions = []
        for axisIndex, axisPosition in enumerate(
                transformedCurrentAxisPositions):
            currentMotorPositions += [
                self.move.axes[axisIndex].reverse(axisPosition)
            ]

        requestedMotorPositions = []
        for axisIndex, axisPosition in enumerate(
                transformedRequestedAxisPositions):
            requestedMotorPositions += [
                self.move.axes[axisIndex].reverse(axisPosition)
            ]

        machineDeltas = [
            end - start for end, start in zip(requestedMachinePosition,
                                              currentMachinePosition)
        ]
        machineLength = math.sqrt(
            sum([math.pow(position, 2) for position in machineDeltas
                 ]))  #gets cartesian length of move

        motorDeltas = [
            coordinates.uFloat(x - y, x.units)
            for (x, y) in zip(requestedMotorPositions, currentMotorPositions)
        ]
        self.actualMotorDeltas = [
            coordinates.uFloat(int(round(delta, 0)), delta.units)
            for delta in motorDeltas
        ]  #rounds steps down.
        self.majorSteps = max([abs(delta) for delta in self.actualMotorDeltas
                               ])  #note: this gets used by the path planner
        if machineLength != 0:
            parameterRatio = float(self.majorSteps) / float(
                machineLength
            )  #this ratio relates velocities and accelerations between the coordinate systems
        else:
            parameterRatio = 0.0

        #calculate maximum step rates
        self.segmentMaxStepRate = self.velocityCommand * parameterRatio  #units of steps/sec

        #motion planner parameters. These will be modified by the motion planner
        self.entryJunctionMaxStepRate = 0  #default to zero in case this move is the first one
        self.exitJunctionMaxStepRate = 200  #need to fix this eventually, but a minimum rate is necessary to not stall the planner. This is the min exit rate.
        self.forwardPassEntryStepRate = 0  #used by the forward pass of the path planner
        self.forwardPassExitStepRate = 0
        self.reversePassEntryStepRate = 0  #used by the reverse pass of the path planner
        self.reversePassExitStepRate = 0
        self.accelSteps = 0
        self.decelSteps = 0

        if self.accelerationCommand.units == "mm/s^2":
            self.segmentAccelRate = self.accelerationCommand * parameterRatio  #transform along major axis, now in steps^s^2
        elif self.accelerationCommand.units == "steps/s^2":
            self.segmentAccelRate = self.accelerationCommand  #motor inertia dominant, don't change.

        #create actionObjects and commit to the channel priority queue
        self.actionObjects = self.move.virtualNode.spinRequest(
            axesSteps=tuple(self.actualMotorDeltas),
            accelSteps=0,
            decelSteps=0,
            accelRate=0,
            external=True,
            majorSteps=self.majorSteps)  #note conversion to tuple.
        self.actionObjects.commit(
        )  #this will lock in their place in the transmit queue, however will not release until this move object is run thru the motion planner

        #commit self to the path planner.
        self.commit()

        #recalculate future machine position
        newMotorPositions = [
            coordinates.uFloat(x + y, x.units)
            for (x, y) in zip(self.actualMotorDeltas, currentMotorPositions)
        ]

        transformedNewAxisPositions = []
        for motorIndex, motorPosition in enumerate(newMotorPositions):
            transformedNewAxisPositions += [
                self.move.axes[motorIndex].forward(motorPosition)
            ]

        newMachinePosition = self.move.kinematics.forward(
            transformedNewAxisPositions)
        self.move.machinePosition.future.set(newMachinePosition)