예제 #1
0
class AnimateRobot(object):

    def __init__(self, obj, view):
        self.obj = obj
        self.view = view
        self.timer = TimerCallback(targetFps=60)
        self.timer.callback = self.tick

    def start(self):
        self.startTime = time.time()
        self.timer.start()

    def stop(self):
        self.timer.stop()

    def tick(self):
        tNow = time.time()
        elapsed = tNow - self.startTime

        x, y = np.sin(elapsed), np.cos(elapsed)
        angle = -elapsed

        t = vtk.vtkTransform()
        t.PostMultiply()
        t.RotateZ(np.degrees(angle))
        t.Translate(x, y, 0)
        self.obj.getChildFrame().copyFrame(t)
        self.view.render()
예제 #2
0
class AnimateRobot(object):

    def __init__(self, obj, view):
        self.obj = obj
        self.view = view
        self.timer = TimerCallback(targetFps=60)
        self.timer.callback = self.tick

    def start(self):
        self.startTime = time.time()
        self.timer.start()

    def stop(self):
        self.timer.stop()

    def tick(self):
        tNow = time.time()
        elapsed = tNow - self.startTime

        x, y = np.sin(elapsed), np.cos(elapsed)
        angle = -elapsed

        t = vtk.vtkTransform()
        t.PostMultiply()
        t.RotateZ(np.degrees(angle))
        t.Translate(x, y, 0)
        self.obj.getChildFrame().copyFrame(t)
        self.view.render()
예제 #3
0
class KinectSource(TimerCallback):
    def __init__(self, view, _KinectQueue):
        self.view = view
        self.KinectQueue = _KinectQueue

        self.visible = True

        self.p = vtk.vtkPolyData()
        utime = KinectQueue.getPointCloudFromKinect(self.p)
        self.polyDataObj = vis.PolyDataItem('kinect source',
                                            shallowCopy(self.p), view)
        self.polyDataObj.actor.SetPickable(1)
        self.polyDataObj.initialized = False

        om.addToObjectModel(self.polyDataObj)

        self.queue = PythonQt.dd.ddBotImageQueue(lcmUtils.getGlobalLCMThread())
        self.queue.init(lcmUtils.getGlobalLCMThread(),
                        drcargs.args().config_file)

        self.targetFps = 30
        self.timerCallback = TimerCallback(targetFps=self.targetFps)
        self.timerCallback.callback = self._updateSource
        #self.timerCallback.start()

    def start(self):
        self.timerCallback.start()

    def stop(self):
        self.timerCallback.stop()

    def setFPS(self, framerate):
        self.targetFps = framerate
        self.timerCallback.stop()
        self.timerCallback.targetFps = framerate
        self.timerCallback.start()

    def setVisible(self, visible):
        self.polyDataObj.setProperty('Visible', visible)

    def _updateSource(self):
        p = vtk.vtkPolyData()
        utime = self.KinectQueue.getPointCloudFromKinect(p)

        if not p.GetNumberOfPoints():
            return

        cameraToLocalFused = vtk.vtkTransform()
        self.queue.getTransform('KINECT_RGB', 'local', utime,
                                cameraToLocalFused)
        p = filterUtils.transformPolyData(p, cameraToLocalFused)
        self.polyDataObj.setPolyData(p)

        if not self.polyDataObj.initialized:
            self.polyDataObj.setProperty('Color By', 'rgb_colors')
            self.polyDataObj.initialized = True
예제 #4
0
파일: kinectlcm.py 프로젝트: caomw/director
class KinectSource(TimerCallback):

    def __init__(self, view, _KinectQueue):
        self.view = view
        self.KinectQueue = _KinectQueue

        self.visible = True
        
        self.p = vtk.vtkPolyData()
        utime = KinectQueue.getPointCloudFromKinect(self.p)
        self.polyDataObj = vis.PolyDataItem('kinect source', shallowCopy(self.p), view)
        self.polyDataObj.actor.SetPickable(1)
        self.polyDataObj.initialized = False

        om.addToObjectModel(self.polyDataObj)

        self.queue = PythonQt.dd.ddBotImageQueue(lcmUtils.getGlobalLCMThread())
        self.queue.init(lcmUtils.getGlobalLCMThread(), drcargs.args().config_file)

        self.targetFps = 30
        self.timerCallback = TimerCallback(targetFps=self.targetFps)
        self.timerCallback.callback = self._updateSource
        #self.timerCallback.start()
        
    def start(self):
        self.timerCallback.start()

    def stop(self):
        self.timerCallback.stop()

    def setFPS(self, framerate):
        self.targetFps = framerate
        self.timerCallback.stop()
        self.timerCallback.targetFps = framerate
        self.timerCallback.start()

    def setVisible(self, visible):
        self.polyDataObj.setProperty('Visible', visible)

    def _updateSource(self):
        p = vtk.vtkPolyData()
        utime = self.KinectQueue.getPointCloudFromKinect(p)

        if not p.GetNumberOfPoints():
            return

        cameraToLocalFused = vtk.vtkTransform()
        self.queue.getTransform('KINECT_RGB', 'local', utime, cameraToLocalFused)
        p = filterUtils.transformPolyData(p,cameraToLocalFused)
        self.polyDataObj.setPolyData(p)

        if not self.polyDataObj.initialized:
            self.polyDataObj.setProperty('Color By', 'rgb_colors')
            self.polyDataObj.initialized = True
예제 #5
0
class TaskRunner(object):
    def __init__(self):
        self.interval = 1 / 60.0
        sys.setcheckinterval(1000)
        #sys.setswitchinterval(self.interval)			# sys.setswitchinterval is only Python 3
        self.taskQueue = asynctaskqueue.AsyncTaskQueue()
        self.pendingTasks = []
        self.threads = []
        self.timer = TimerCallback(callback=self._onTimer,
                                   targetFps=1 / self.interval)

    def _onTimer(self):
        # Give up control to another python thread in self.threads
        # that might be running
        time.sleep(self.interval)

        # add all tasks in self.pendingTasks to the AsyncTaskQueue
        if self.pendingTasks:
            while True:
                try:
                    self.taskQueue.addTask(self.pendingTasks.pop(0))
                except IndexError:
                    break

            # start the AsyncTaskQueue if it's not already running
            if self.taskQueue.tasks and not self.taskQueue.isRunning:
                self.taskQueue.start()

        # check which threads are live
        liveThreads = []
        for t in self.threads:
            if t.is_alive():
                liveThreads.append(t)

        # only retain the live threads
        self.threads = liveThreads

        # if no liveThreads then stop the timer
        if len(self.threads) == 0:
            self.timer.stop()

    def callOnMain(self, func, *args, **kwargs):
        self.pendingTasks.append(lambda: func(*args, **kwargs))
        self.timer.start()

    def callOnThread(self, func, *args, **kwargs):
        t = Thread(target=lambda: func(*args, **kwargs))
        self.threads.append(t)
        t.start()
        self.timer.start()
예제 #6
0
class SpindleSpinChecker(object):

    def __init__(self, spindleMonitor):

        self.spindleMonitor = spindleMonitor
        self.timer = TimerCallback(targetFps=3)
        self.timer.callback = self.update
        self.warningButton = None
        self.action = None

    def update(self):        
        if abs(self.spindleMonitor.getAverageSpindleVelocity()) < 0.2:
            self.notifyUserStatusBar()
        else:
            self.clearStatusBarWarning()

    def start(self):
        self.action.checked = True
        self.timer.start()

    def stop(self):
        self.action.checked = False
        self.timer.stop()

    def setupMenuAction(self):
        self.action = app.addMenuAction('Tools', 'Spindle Stuck Warning')
        self.action.setCheckable(True)
        self.action.checked = self.timer.isActive()
        self.action.connect('triggered()', self.onActionChanged)

    def onActionChanged(self):
        if self.action.checked:
            self.start()
        else:
            self.stop()

    def clearStatusBarWarning(self):
        if self.warningButton:
            self.warningButton.deleteLater()
            self.warningButton = None

    def notifyUserStatusBar(self):
        if self.warningButton:
            return
        self.warningButton = QtGui.QPushButton('Spindle Stuck Warning')
        self.warningButton.setStyleSheet("background-color:red")
        app.getMainWindow().statusBar().insertPermanentWidget(0, self.warningButton)
예제 #7
0
class SpindleSpinChecker(object):
    def __init__(self, spindleMonitor):

        self.spindleMonitor = spindleMonitor
        self.timer = TimerCallback(targetFps=3)
        self.timer.callback = self.update
        self.warningButton = None
        self.action = None

    def update(self):
        if abs(self.spindleMonitor.getAverageSpindleVelocity()) < 0.2:
            self.notifyUserStatusBar()
        else:
            self.clearStatusBarWarning()

    def start(self):
        self.action.checked = True
        self.timer.start()

    def stop(self):
        self.action.checked = False
        self.timer.stop()

    def setupMenuAction(self):
        self.action = app.addMenuAction('Tools', 'Spindle Stuck Warning')
        self.action.setCheckable(True)
        self.action.checked = self.timer.isActive()
        self.action.connect('triggered()', self.onActionChanged)

    def onActionChanged(self):
        if self.action.checked:
            self.start()
        else:
            self.stop()

    def clearStatusBarWarning(self):
        if self.warningButton:
            self.warningButton.deleteLater()
            self.warningButton = None

    def notifyUserStatusBar(self):
        if self.warningButton:
            return
        self.warningButton = QtGui.QPushButton('Spindle Stuck Warning')
        self.warningButton.setStyleSheet("background-color:red")
        app.getMainWindow().statusBar().insertPermanentWidget(
            0, self.warningButton)
예제 #8
0
class EstRobotStatePublisher(object):
    def __init__(self, robotSystem):
        self.robotSystem = robotSystem
        self.timer = TimerCallback(targetFps=25)
        self.timer.callback = self.publishEstRobotState

    def publishEstRobotState(self):
        q = self.robotSystem.robotStateJointController.q
        stateMsg = robotstate.drakePoseToRobotState(q)
        stateMsg.utime = utimeUtil.getUtime()
        lcmUtils.publish("EST_ROBOT_STATE", stateMsg)

    def start(self):
        self.timer.start()

    def stop(self):
        self.timer.stop()
예제 #9
0
class SpindleAxisDebug(vis.PolyDataItem):
    def __init__(self, frameProvider):
        vis.PolyDataItem.__init__(self,
                                  "spindle axis",
                                  vtk.vtkPolyData(),
                                  view=None)
        self.frameProvider = frameProvider
        self.timer = TimerCallback()
        self.timer.callback = self.update
        self.setProperty("Color", QtGui.QColor(0, 255, 0))
        self.setProperty("Visible", False)

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)

        if propertyName == "Visible":
            if self.getProperty(propertyName):
                self.timer.start()
            else:
                self.timer.stop()

    def onRemoveFromObjectModel(self):
        vis.PolyDataItem.onRemoveFromObjectModel(self)
        self.timer.stop()

    def update(self):

        t = self.frameProvider.getFrame("MULTISENSE_SCAN")

        p1 = [0.0, 0.0, 0.0]
        p2 = [2.0, 0.0, 0.0]

        p1 = t.TransformPoint(p1)
        p2 = t.TransformPoint(p2)

        d = DebugData()
        d.addSphere(p1, radius=0.01, color=[0, 1, 0])
        d.addLine(p1, p2, color=[0, 1, 0])
        self.setPolyData(d.getPolyData())
예제 #10
0
class PointerTracker(object):
    """
    See segmentation.estimatePointerTip() documentation.
    """

    def __init__(self, robotModel, stereoPointCloudItem):
        self.robotModel = robotModel
        self.stereoPointCloudItem = stereoPointCloudItem
        self.timer = TimerCallback(targetFps=5)
        self.timer.callback = self.updateFit

    def start(self):
        self.timer.start()

    def stop(self):
        self.timer.stop()

    def cleanup(self):
        om.removeFromObjectModel(om.findObjectByName("segmentation"))

    def updateFit(self, polyData=None):

        # if not self.stereoPointCloudItem.getProperty('Visible'):
        #    return

        if not polyData:
            self.stereoPointCloudItem.update()
            polyData = self.stereoPointCloudItem.polyData

        if not polyData or not polyData.GetNumberOfPoints():
            self.cleanup()
            return

        self.tipPosition = segmentation.estimatePointerTip(self.robotModel, polyData)
        if self.tipPosition is None:
            self.cleanup()

    def getPointerTip(self):
        return self.tipPosition
예제 #11
0
class PointerTracker(object):
    '''
    See segmentation.estimatePointerTip() documentation.
    '''
    def __init__(self, robotModel, stereoPointCloudItem):
        self.robotModel = robotModel
        self.stereoPointCloudItem = stereoPointCloudItem
        self.timer = TimerCallback(targetFps=5)
        self.timer.callback = self.updateFit

    def start(self):
        self.timer.start()

    def stop(self):
        self.timer.stop()

    def cleanup(self):
        om.removeFromObjectModel(om.findObjectByName('segmentation'))

    def updateFit(self, polyData=None):

        #if not self.stereoPointCloudItem.getProperty('Visible'):
        #    return

        if not polyData:
            self.stereoPointCloudItem.update()
            polyData = self.stereoPointCloudItem.polyData

        if not polyData or not polyData.GetNumberOfPoints():
            self.cleanup()
            return

        self.tipPosition = segmentation.estimatePointerTip(self.robotModel, polyData)
        if self.tipPosition is None:
            self.cleanup()

    def getPointerTip(self):
        return self.tipPosition
예제 #12
0
class SpindleAxisDebug(vis.PolyDataItem):

    def __init__(self, frameProvider):
        vis.PolyDataItem.__init__(self, 'spindle axis', vtk.vtkPolyData(), view=None)
        self.frameProvider = frameProvider
        self.timer = TimerCallback()
        self.timer.callback = self.update
        self.setProperty('Color', QtGui.QColor(0, 255, 0))
        self.setProperty('Visible', False)

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)

        if propertyName == 'Visible':
            if self.getProperty(propertyName):
                self.timer.start()
            else:
                self.timer.stop()

    def onRemoveFromObjectModel(self):
        vis.PolyDataItem.onRemoveFromObjectModel(self)
        self.timer.stop()

    def update(self):

        t = self.frameProvider.getFrame('SCAN')

        p1 = [0.0, 0.0, 0.0]
        p2 = [2.0, 0.0, 0.0]

        p1 = t.TransformPoint(p1)
        p2 = t.TransformPoint(p2)

        d = DebugData()
        d.addSphere(p1, radius=0.01, color=[0,1,0])
        d.addLine(p1, p2, color=[0,1,0])
        self.setPolyData(d.getPolyData())
예제 #13
0
class FootLockEstimator(object):

    def __init__(self):
        self.footBias = 0.5
        self.timer = TimerCallback(targetFps=1.0)
        self.timer.callback = self.publishCorrection
        self.clear()


    def capture(self):

        self.pelvisFrame = robotStateModel.getLinkFrame('pelvis')
        self.lfootFrame = robotStateModel.getLinkFrame('l_foot')
        self.rfootFrame = robotStateModel.getLinkFrame('r_foot')

    def clear(self):

        self.lfootFrame = None
        self.rfootFrame = None
        self.pelvisFrame = None

    def printCaptured(self):

        print '--------------------'
        print 'l_foot yaw:', self.lfootFrame.GetOrientation()[2]
        print 'r_foot yaw:', self.rfootFrame.GetOrientation()[2]
        print 'pelvis yaw:', self.pelvisFrame.GetOrientation()[2]

    def getPelvisEstimateFromFoot(self, pelvisFrame, footFrame, previousFootFrame):

        pelvisToWorld = pelvisFrame
        footToWorld = footFrame
        oldFootToWorld = previousFootFrame
        worldToFoot = footToWorld.GetLinearInverse()
        pelvisToFoot = concat(pelvisToWorld, worldToFoot)

        return concat(pelvisToFoot, oldFootToWorld)


    def getPelvisEstimate(self):

        p = robotStateModel.getLinkFrame('pelvis')
        lf = robotStateModel.getLinkFrame('l_foot')
        rf = robotStateModel.getLinkFrame('r_foot')

        pelvisLeft = self.getPelvisEstimateFromFoot(p, lf, self.lfootFrame)
        pelvisRight = self.getPelvisEstimateFromFoot(p, rf, self.rfootFrame)

        return transformUtils.frameInterpolate(pelvisLeft, pelvisRight, self.footBias)

    def onRobotStateModelChanged(self, model=None):

        if self.lfootFrame is None:
            return

        newPelvisToWorld = self.getPelvisEstimate()

        q = robotStateJointController.q.copy()
        q[0:3] = newPelvisToWorld.GetPosition()
        q[3:6] = transformUtils.rollPitchYawFromTransform(newPelvisToWorld)
        playbackJointController.setPose('lock_pose', q)

    def initVisualization(self):
        robotStateModel.connectModelChanged(self.onRobotStateModelChanged)
        playbackRobotModel.setProperty('Visible', True)

    def publishCorrection(self, channel='POSE_YAW_LOCK'):

        pelvisToWorld = self.getPelvisEstimate()

        position, quat = transformUtils.poseFromTransform(pelvisToWorld)

        msg = lcmbot.pose_t()
        msg.utime = robotStateJointController.lastRobotStateMessage.utime
        msg.pos = [0.0, 0.0, 0.0]
        msg.orientation = quat.tolist()

        lcmUtils.publish(channel, msg)

    def enable(self):
        self.capture()
        self.timer.start()

    def disable(self):
        self.timer.stop()
        self.clear()
예제 #14
0
class AffordanceInCameraUpdater(object):

    def __init__(self, affordanceManager, imageView):
        self.affordanceManager = affordanceManager
        self.prependImageName = False
        self.projectFootsteps = False
        self.projectAffordances = True
        self.extraObjects = []
        self.imageView = imageView
        self.imageQueue = imageView.imageManager.queue
        self.timer = TimerCallback(targetFps=10)
        self.timer.callback = self.update

    def getOverlayRenderer(self, imageView):

        if not hasattr(imageView, 'overlayRenderer'):
            renWin = imageView.view.renderWindow()
            renWin.SetNumberOfLayers(2)
            ren = vtk.vtkRenderer()
            ren.SetLayer(1)
            ren.SetActiveCamera(imageView.view.camera())
            renWin.AddRenderer(ren)
            imageView.overlayRenderer = ren
        return imageView.overlayRenderer

    def addActorToImageOverlay(self, obj, imageView):

        obj.addToView(imageView.view)
        imageView.view.renderer().RemoveActor(obj.actor)

        renderers = obj.extraViewRenderers.setdefault(imageView.view, [])
        overlayRenderer = self.getOverlayRenderer(imageView)
        if overlayRenderer not in renderers:
            overlayRenderer.AddActor(obj.actor)
            renderers.append(overlayRenderer)

    def getFolderName(self):
        if self.prependImageName:
            return self.imageView.imageName + ' camera overlay'
        else:
            return 'camera overlay'


    def setupObjectInCamera(self, obj):
        imageView = self.imageView
        obj = vis.updatePolyData(vtk.vtkPolyData(), self.getTransformedName(obj), view=imageView.view, color=obj.getProperty('Color'), parent=self.getFolderName(), visible=obj.getProperty('Visible'))
        self.addActorToImageOverlay(obj, imageView)
        return obj

    def getTransformedName(self, obj):
        if self.prependImageName:
            return 'overlay ' + self.imageView.imageName + ' ' + obj.getProperty('Name')
        else:
            return 'overlay ' + obj.getProperty('Name')


    def getFootsteps(self):
        plan = om.findObjectByName('footstep plan')
        if plan:
            return [child for child in plan.children() if child.getProperty('Name').startswith('step ')]
        else:
            return []

    def getObjectsToUpdate(self):
        objs = []

        if self.projectAffordances:
            objs += self.affordanceManager.getAffordances()
        if self.projectFootsteps:
            objs += self.getFootsteps()
        objs += self.extraObjects
        return objs

    def getObjectInCamera(self, obj):
        overlayObj = om.findObjectByName(self.getTransformedName(obj))
        return overlayObj or self.setupObjectInCamera(obj)

    def cleanUp(self):
        self.timer.stop()
        om.removeFromObjectModel(om.findObjectByName(self.getFolderName()))

    def update(self):
        imageView = self.imageView

        if not imageView.imageInitialized:
            return

        if not imageView.view.isVisible():
            return

        updated = set()

        for obj in self.getObjectsToUpdate():
            cameraObj = self.getObjectInCamera(obj)
            self.updateObjectInCamera(obj, cameraObj)
            updated.add(cameraObj)

        folder = om.findObjectByName(self.getFolderName())
        if folder:
            for child in folder.children():
                if child not in updated:
                    om.removeFromObjectModel(child)

    def updateObjectInCamera(self, obj, cameraObj):

        imageView = self.imageView

        objToLocalT = transformUtils.copyFrame(obj.actor.GetUserTransform() or vtk.vtkTransform())

        localToCameraT = vtk.vtkTransform()
        self.imageQueue.getTransform('local', imageView.imageName, localToCameraT)

        t = vtk.vtkTransform()
        t.PostMultiply()
        t.Concatenate(objToLocalT)
        t.Concatenate(localToCameraT)

        pd = filterUtils.transformPolyData(obj.polyData, t)

        '''
        normals = pd.GetPointData().GetNormals()
        cameraToImageT = vtk.vtkTransform()
        imageQueue.getCameraProjectionTransform(imageView.imageName, cameraToImageT)
        pd = filterUtils.transformPolyData(pd, cameraToImageT)
        pts = vnp.getNumpyFromVtk(pd, 'Points')
        pts[:,0] /= pts[:,2]
        pts[:,1] /= pts[:,2]
        pd.GetPointData().SetNormals(normals)
        '''

        self.imageQueue.projectPoints(imageView.imageName, pd)

        cameraObj.setPolyData(pd)

        self.addActorToImageOverlay(cameraObj, imageView)
예제 #15
0
class ValueSlider(object):

    events = Flags('VALUE_CHANGED')

    def __init__(self, minValue=0.0, maxValue=1.0, resolution=1000):
        self._value = 0.0
        self.spinbox = QtGui.QDoubleSpinBox()
        self.spinbox.setSuffix('s')
        self.slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.playButton = QtGui.QPushButton('Play')
        self.setValueRange(minValue, maxValue)
        self.setResolution(resolution)
        self.slider.connect('valueChanged(int)', self._onSliderValueChanged)
        self.spinbox.connect('valueChanged(double)',
                             self._onSpinboxValueChanged)
        self.playButton.connect('clicked()', self._onPlayClicked)
        self.widget = QtGui.QWidget()
        layout = QtGui.QHBoxLayout(self.widget)
        layout.addWidget(self.playButton)
        layout.addWidget(self.spinbox)
        layout.addWidget(self.slider)

        self.animationPrevTime = 0.0
        self.animationRate = 1.0
        self.animationRateTarget = 1.0
        self.animationRateAlpha = 1.0
        self.animationTimer = TimerCallback(callback=self._tick, targetFps=60)
        self.useRealTime = True

        self.callbacks = callbacks.CallbackRegistry(self.events._fields)

        self.eventFilter = PythonQt.dd.ddPythonEventFilter()
        self.eventFilter.connect('handleEvent(QObject*, QEvent*)',
                                 self._filterEvent)
        self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseButtonPress)
        self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseMove)
        self.slider.installEventFilter(self.eventFilter)

    def _tick(self):
        if self.useRealTime:
            tnow = time.time()
            dt = tnow - self.animationPrevTime
            self.animationPrevTime = tnow
        else:
            dt = (1.0 / self.animationTimer.targetFps)

        self.animationRate = (
            1.0 - self.animationRateAlpha
        ) * self.animationRate + self.animationRateAlpha * self.animationRateTarget

        valueChange = dt * self.animationRate
        value = self.getValue() + valueChange
        if value > self.maxValue:
            self.setValue(self.maxValue)
            self.playButton.setText('Play')
            return False
        self.setValue(value)

    def setAnimationRate(self, animationRate, rateAlpha=1.0):
        self.animationRateTarget = animationRate
        self.animationRateAlpha = rateAlpha

    def play(self):
        self.playButton.setText('Pause')
        self.animationPrevTime = time.time()
        self.animationTimer.start()

    def pause(self):
        self.playButton.setText('Play')
        self.animationTimer.stop()

    def _onPlayClicked(self):
        if self.animationTimer.isActive():
            self.pause()
        else:
            self.play()

    def _filterEvent(self, obj, event):
        if event.type() == QtCore.QEvent.MouseButtonPress and event.button(
        ) == QtCore.Qt.LeftButton:
            val = QtGui.QStyle.sliderValueFromPosition(obj.minimum,
                                                       obj.maximum, event.x(),
                                                       obj.width)
            self.eventFilter.setEventHandlerResult(True)
            obj.setValue(val)
        elif event.type() == QtCore.QEvent.MouseMove:
            val = QtGui.QStyle.sliderValueFromPosition(obj.minimum,
                                                       obj.maximum, event.x(),
                                                       obj.width)
            self.eventFilter.setEventHandlerResult(True)
            obj.setValue(val)

    def setResolution(self, resolution):
        with qtutils.BlockSignals(self.slider):
            self.slider.maximum = resolution
        self._syncSlider()

    def setValueRange(self, minValue, maxValue):
        newValue = np.clip(self._value, minValue, maxValue)
        changed = newValue != self._value
        self.minValue = minValue
        self.maxValue = maxValue
        self._value = newValue
        with qtutils.BlockSignals(self.spinbox):
            self.spinbox.minimum = minValue
            self.spinbox.maximum = maxValue
        self._syncSpinBox()
        self._syncSlider()
        if changed:
            self._notifyValueChanged()

    def getValue(self):
        return self._value

    def setValue(self, value):
        self._value = np.clip(value, self.minValue, self.maxValue)
        self._syncSlider()
        self._syncSpinBox()
        self._notifyValueChanged()

    def connectValueChanged(self, callback):
        return self.callbacks.connect(self.events.VALUE_CHANGED, callback)

    def _notifyValueChanged(self):
        self.callbacks.process(self.events.VALUE_CHANGED, self._value)

    def _syncSlider(self):
        with qtutils.BlockSignals(self.slider):
            self.slider.value = self.slider.maximum * (
                self._value - self.minValue) / float(self.maxValue -
                                                     self.minValue)

    def _syncSpinBox(self):
        with qtutils.BlockSignals(self.spinbox):
            self.spinbox.value = self._value

    def _onSpinboxValueChanged(self, spinboxValue):
        self._value = spinboxValue
        self._syncSlider()
        self._notifyValueChanged()

    def _onSliderValueChanged(self, sliderValue):
        self._value = (self.minValue + (self.maxValue - self.minValue) *
                       (sliderValue / float(self.slider.maximum)))
        self._syncSpinBox()
        self._notifyValueChanged()
예제 #16
0
class AsyncTaskQueue(object):

    QUEUE_STARTED_SIGNAL = "QUEUE_STARTED_SIGNAL"
    QUEUE_STOPPED_SIGNAL = "QUEUE_STOPPED_SIGNAL"
    TASK_STARTED_SIGNAL = "TASK_STARTED_SIGNAL"
    TASK_ENDED_SIGNAL = "TASK_ENDED_SIGNAL"
    TASK_PAUSED_SIGNAL = "TASK_PAUSED_SIGNAL"
    TASK_FAILED_SIGNAL = "TASK_FAILED_SIGNAL"
    TASK_EXCEPTION_SIGNAL = "TASK_EXCEPTION_SIGNAL"

    class PauseException(Exception):
        pass

    class FailException(Exception):
        pass

    def __init__(self):
        self.tasks = []
        self.generators = []
        self.timer = TimerCallback(targetFps=10)
        self.timer.callback = self.callbackLoop
        self.callbacks = callbacks.CallbackRegistry([
            self.QUEUE_STARTED_SIGNAL,
            self.QUEUE_STOPPED_SIGNAL,
            self.TASK_STARTED_SIGNAL,
            self.TASK_ENDED_SIGNAL,
            self.TASK_PAUSED_SIGNAL,
            self.TASK_FAILED_SIGNAL,
            self.TASK_EXCEPTION_SIGNAL,
        ])
        self.currentTask = None
        self.isRunning = False

    def reset(self):
        assert not self.isRunning
        assert not self.generators
        self.tasks = []

    def start(self):
        self.isRunning = True
        self.callbacks.process(self.QUEUE_STARTED_SIGNAL, self)
        self.timer.start()

    def stop(self):
        self.isRunning = False
        self.currentTask = None
        self.generators = []
        self.timer.stop()
        self.callbacks.process(self.QUEUE_STOPPED_SIGNAL, self)

    def wrapGenerator(self, generator):
        def generatorWrapper():
            return generator

        return generatorWrapper

    def addTask(self, task):

        if isinstance(task, types.GeneratorType):
            task = self.wrapGenerator(task)

        assert hasattr(task, "__call__")
        self.tasks.append(task)

    def callbackLoop(self):

        try:
            for i in xrange(10):
                self.doWork()
            if not self.tasks:
                self.stop()

        except AsyncTaskQueue.PauseException:
            assert self.currentTask
            self.callbacks.process(self.TASK_PAUSED_SIGNAL, self,
                                   self.currentTask)
            self.stop()
        except AsyncTaskQueue.FailException:
            assert self.currentTask
            self.callbacks.process(self.TASK_FAILED_SIGNAL, self,
                                   self.currentTask)
            self.stop()
        except:
            assert self.currentTask
            self.callbacks.process(self.TASK_EXCEPTION_SIGNAL, self,
                                   self.currentTask)
            self.stop()
            raise

        return self.isRunning

    def popTask(self):
        assert not self.isRunning
        assert not self.currentTask
        if self.tasks:
            self.tasks.pop(0)

    def completePreviousTask(self):
        assert self.currentTask
        self.tasks.remove(self.currentTask)
        self.callbacks.process(self.TASK_ENDED_SIGNAL, self, self.currentTask)
        self.currentTask = None

    def startNextTask(self):
        self.currentTask = self.tasks[0]
        self.callbacks.process(self.TASK_STARTED_SIGNAL, self,
                               self.currentTask)
        result = self.currentTask()
        if isinstance(result, types.GeneratorType):
            self.generators.insert(0, result)

    def doWork(self):
        if self.generators:
            self.handleGenerator(self.generators[0])
        else:
            if self.currentTask:
                self.completePreviousTask()
            if self.tasks:
                self.startNextTask()

    def handleGenerator(self, generator):
        try:
            result = generator.next()
        except StopIteration:
            self.generators.remove(generator)
        else:
            if isinstance(result, types.GeneratorType):
                self.generators.insert(0, result)

    def connectQueueStarted(self, func):
        return self.callbacks.connect(self.QUEUE_STARTED_SIGNAL, func)

    def disconnectQueueStarted(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectQueueStopped(self, func):
        return self.callbacks.connect(self.QUEUE_STOPPED_SIGNAL, func)

    def disconnectQueueStopped(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskStarted(self, func):
        return self.callbacks.connect(self.TASK_STARTED_SIGNAL, func)

    def disconnectTaskStarted(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskEnded(self, func):
        return self.callbacks.connect(self.TASK_ENDED_SIGNAL, func)

    def disconnectTaskEnded(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskPaused(self, func):
        return self.callbacks.connect(self.TASK_PAUSED_SIGNAL, func)

    def disconnectTaskPaused(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskFailed(self, func):
        return self.callbacks.connect(self.TASK_FAILED_SIGNAL, func)

    def disconnectTaskFailed(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskException(self, func):
        return self.callbacks.connect(self.TASK_EXCEPTION_SIGNAL, func)

    def disconnectTaskException(self, callbackId):
        self.callbacks.disconnect(callbackId)
예제 #17
0
class CameraTrackerManager(object):
    def __init__(self):
        self.target = None
        self.targetFrame = None
        self.trackerClass = None
        self.camera = None
        self.view = None
        self.timer = TimerCallback()
        self.timer.callback = self.updateTimer
        self.addTrackers()
        self.initTracker()

    def updateTimer(self):

        tNow = time.time()
        dt = tNow - self.tLast
        if dt < self.timer.elapsed / 2.0:
            return

        self.update()

    def setView(self, view):
        self.view = view
        self.camera = view.camera()

    def setTarget(self, target):
        '''
        target should be an instance of TargetFrameConverter or
        any object that provides a method getTargetFrame().
        '''

        if target == self.target:
            return

        self.disableActiveTracker()

        if not target:
            return

        self.target = target
        self.targetFrame = target.getTargetFrame()
        self.callbackId = self.targetFrame.connectFrameModified(
            self.onTargetFrameModified)

        self.initTracker()

    def disableActiveTracker(self):

        if self.targetFrame:
            self.targetFrame.disconnectFrameModified(self.callbackId)

        self.target = None
        self.targetFrame = None
        self.initTracker()

    def update(self):

        tNow = time.time()
        dt = tNow - self.tLast
        self.tLast = tNow

        if self.activeTracker:
            self.activeTracker.dt = dt
            self.activeTracker.update()

    def reset(self):
        self.tLast = time.time()
        if self.activeTracker:
            self.activeTracker.reset()

    def getModeActions(self):
        if self.activeTracker:
            return self.activeTracker.actions
        return []

    def onModeAction(self, actionName):
        if self.activeTracker:
            self.activeTracker.onAction(actionName)

    def getModeProperties(self):
        if self.activeTracker:
            return self.activeTracker.properties
        return None

    def onTargetFrameModified(self, frame):
        self.update()

    def initTracker(self):

        self.timer.stop()
        self.activeTracker = self.trackerClass(
            self.view, self.targetFrame) if (self.trackerClass
                                             and self.targetFrame) else None
        self.reset()
        self.update()

        if self.activeTracker:
            minimumUpdateRate = self.activeTracker.getMinimumUpdateRate()
            if minimumUpdateRate > 0:
                self.timer.targetFps = minimumUpdateRate
                self.timer.start()

    def addTrackers(self):
        self.trackers = OrderedDict([
            ['Off', None],
            ['Position', PositionTracker],
            ['Position & Orientation', PositionOrientationTracker],
            ['Smooth Follow', SmoothFollowTracker],
            ['Look At', LookAtTracker],
            ['Orbit', OrbitTracker],
        ])

    def setTrackerMode(self, modeName):
        assert modeName in self.trackers
        self.trackerClass = self.trackers[modeName]
        self.initTracker()
예제 #18
0
class Simulator(object):
    def __init__(self,
                 percentObsDensity=20,
                 endTime=40,
                 randomizeControl=False,
                 nonRandomWorld=False,
                 circleRadius=0.7,
                 worldScale=1.0,
                 supervisedTrainingTime=500,
                 autoInitialize=True,
                 verbose=True,
                 sarsaType="discrete"):
        self.verbose = verbose
        self.randomizeControl = randomizeControl
        self.startSimTime = time.time()
        self.collisionThreshold = 1.3
        self.randomSeed = 5
        self.Sarsa_numInnerBins = 4
        self.Sarsa_numOuterBins = 4
        self.Sensor_rayLength = 8
        self.sarsaType = sarsaType

        self.percentObsDensity = percentObsDensity
        self.supervisedTrainingTime = 10
        self.learningRandomTime = 10
        self.learningEvalTime = 10
        self.defaultControllerTime = 10
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale
        # create the visualizer object
        self.app = ConsoleApp()
        # view = app.createView(useGrid=False)
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()
        if autoInitialize:
            self.initialize()

    def initializeOptions(self):
        self.options = dict()

        self.options['Reward'] = dict()
        self.options['Reward']['actionCost'] = 0.1
        self.options['Reward']['collisionPenalty'] = 100.0
        self.options['Reward']['raycastCost'] = 20.0

        self.options['SARSA'] = dict()
        self.options['SARSA']['type'] = "discrete"
        self.options['SARSA']['lam'] = 0.7
        self.options['SARSA']['alphaStepSize'] = 0.2
        self.options['SARSA']['useQLearningUpdate'] = False
        self.options['SARSA']['epsilonGreedy'] = 0.2
        self.options['SARSA']['burnInTime'] = 500
        self.options['SARSA']['epsilonGreedyExponent'] = 0.3
        self.options['SARSA'][
            'exponentialDiscountFactor'] = 0.05  #so gamma = e^(-rho*dt)
        self.options['SARSA']['numInnerBins'] = 5
        self.options['SARSA']['numOuterBins'] = 4
        self.options['SARSA']['binCutoff'] = 0.5

        self.options['World'] = dict()
        self.options['World']['obstaclesInnerFraction'] = 0.85
        self.options['World']['randomSeed'] = 40
        self.options['World']['percentObsDensity'] = 7.5
        self.options['World']['nonRandomWorld'] = True
        self.options['World']['circleRadius'] = 1.75
        self.options['World']['scale'] = 1.0

        self.options['Sensor'] = dict()
        self.options['Sensor']['rayLength'] = 10
        self.options['Sensor']['numRays'] = 20

        self.options['Car'] = dict()
        self.options['Car']['velocity'] = 12

        self.options['dt'] = 0.05

        self.options['runTime'] = dict()
        self.options['runTime']['supervisedTrainingTime'] = 10
        self.options['runTime']['learningRandomTime'] = 10
        self.options['runTime']['learningEvalTime'] = 10
        self.options['runTime']['defaultControllerTime'] = 10

    def setDefaultOptions(self):

        defaultOptions = dict()

        defaultOptions['Reward'] = dict()
        defaultOptions['Reward']['actionCost'] = 0.1
        defaultOptions['Reward']['collisionPenalty'] = 100.0
        defaultOptions['Reward']['raycastCost'] = 20.0

        defaultOptions['SARSA'] = dict()
        defaultOptions['SARSA']['type'] = "discrete"
        defaultOptions['SARSA']['lam'] = 0.7
        defaultOptions['SARSA']['alphaStepSize'] = 0.2
        defaultOptions['SARSA']['useQLearningUpdate'] = False
        defaultOptions['SARSA']['useSupervisedTraining'] = True
        defaultOptions['SARSA']['epsilonGreedy'] = 0.2
        defaultOptions['SARSA']['burnInTime'] = 500
        defaultOptions['SARSA']['epsilonGreedyExponent'] = 0.3
        defaultOptions['SARSA'][
            'exponentialDiscountFactor'] = 0.05  #so gamma = e^(-rho*dt)
        defaultOptions['SARSA']['numInnerBins'] = 5
        defaultOptions['SARSA']['numOuterBins'] = 4
        defaultOptions['SARSA']['binCutoff'] = 0.5
        defaultOptions['SARSA']['forceDriveStraight'] = True

        defaultOptions['World'] = dict()
        defaultOptions['World']['obstaclesInnerFraction'] = 0.85
        defaultOptions['World']['randomSeed'] = 40
        defaultOptions['World']['percentObsDensity'] = 7.5
        defaultOptions['World']['nonRandomWorld'] = True
        defaultOptions['World']['circleRadius'] = 1.75
        defaultOptions['World']['scale'] = 1.0

        defaultOptions['Sensor'] = dict()
        defaultOptions['Sensor']['rayLength'] = 10
        defaultOptions['Sensor']['numRays'] = 20

        defaultOptions['Car'] = dict()
        defaultOptions['Car']['velocity'] = 12

        defaultOptions['dt'] = 0.05

        defaultOptions['runTime'] = dict()
        defaultOptions['runTime']['supervisedTrainingTime'] = 10
        defaultOptions['runTime']['learningRandomTime'] = 10
        defaultOptions['runTime']['learningEvalTime'] = 10
        defaultOptions['runTime']['defaultControllerTime'] = 10

        for k in defaultOptions:
            self.options.setdefault(k, defaultOptions[k])

        for k in defaultOptions:
            if not isinstance(defaultOptions[k], dict):
                continue

            for j in defaultOptions[k]:
                self.options[k].setdefault(j, defaultOptions[k][j])

    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap['defaultRandom'] = [0, 0, 1]
        self.colorMap['learnedRandom'] = [1.0, 0.54901961,
                                          0.]  # this is orange
        self.colorMap['learned'] = [0.58039216, 0.0,
                                    0.82745098]  # this is yellow
        self.colorMap['default'] = [0, 1, 0]

    def initialize(self):

        self.dt = self.options['dt']
        self.controllerTypeOrder = [
            'defaultRandom', 'learnedRandom', 'learned', 'default'
        ]

        self.setDefaultOptions()

        self.Sensor = SensorObj(rayLength=self.options['Sensor']['rayLength'],
                                numRays=self.options['Sensor']['numRays'])
        self.Controller = ControllerObj(self.Sensor)
        self.Car = CarPlant(controller=self.Controller,
                            velocity=self.options['Car']['velocity'])
        self.Reward = Reward(
            self.Sensor,
            collisionThreshold=self.collisionThreshold,
            actionCost=self.options['Reward']['actionCost'],
            collisionPenalty=self.options['Reward']['collisionPenalty'],
            raycastCost=self.options['Reward']['raycastCost'])
        self.setSARSA()

        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName('world'))
        self.world = World.buildCircleWorld(
            percentObsDensity=self.options['World']['percentObsDensity'],
            circleRadius=self.options['World']['circleRadius'],
            nonRandom=self.options['World']['nonRandomWorld'],
            scale=self.options['World']['scale'],
            randomSeed=self.options['World']['randomSeed'],
            obstaclesInnerFraction=self.options['World']
            ['obstaclesInnerFraction'])

        om.removeFromObjectModel(om.findObjectByName('robot'))
        self.robot, self.frame = World.buildRobot()
        self.locator = World.buildCellLocator(self.world.visObj.polyData)
        self.Sensor.setLocator(self.locator)
        self.frame = self.robot.getChildFrame()
        self.frame.setProperty('Scale', 3)
        self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.supervisedTrainingTime = self.options['runTime'][
            'supervisedTrainingTime']
        self.learningRandomTime = self.options['runTime']['learningRandomTime']
        self.learningEvalTime = self.options['runTime']['learningEvalTime']
        self.defaultControllerTime = self.options['runTime'][
            'defaultControllerTime']

        self.Car.setFrame(self.frame)
        print "Finished initialization"

    def setSARSA(self, type=None):
        if type is None:
            type = self.options['SARSA']['type']

        if type == "discrete":
            self.Sarsa = SARSADiscrete(
                sensorObj=self.Sensor,
                actionSet=self.Controller.actionSet,
                collisionThreshold=self.collisionThreshold,
                alphaStepSize=self.options['SARSA']['alphaStepSize'],
                useQLearningUpdate=self.options['SARSA']['useQLearningUpdate'],
                lam=self.options['SARSA']['lam'],
                numInnerBins=self.options['SARSA']['numInnerBins'],
                numOuterBins=self.options['SARSA']['numOuterBins'],
                binCutoff=self.options['SARSA']['binCutoff'],
                burnInTime=self.options['SARSA']['burnInTime'],
                epsilonGreedy=self.options['SARSA']['epsilonGreedy'],
                epsilonGreedyExponent=self.options['SARSA']
                ['epsilonGreedyExponent'],
                forceDriveStraight=self.options['SARSA']['forceDriveStraight'])
        elif type == "continuous":
            self.Sarsa = SARSAContinuous(
                sensorObj=self.Sensor,
                actionSet=self.Controller.actionSet,
                lam=self.options['SARSA']['lam'],
                alphaStepSize=self.options['SARSA']['alphaStepSize'],
                collisionThreshold=self.collisionThreshold,
                burnInTime=self.options['SARSA']['burnInTime'],
                epsilonGreedy=self.options['SARSA']['epsilonGreedy'],
                epsilonGreedyExponent=self.options['SARSA']
                ['epsilonGreedyExponent'])
        else:
            raise ValueError(
                "sarsa type must be either discrete or continuous")

    def runSingleSimulation(self,
                            updateQValues=True,
                            controllerType='default',
                            simulationCutoff=None):

        if self.verbose:
            print "using QValue based controller = ", useQValueController

        self.setCollisionFreeInitialState()

        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1],
                                currentCarState[2])
        currentRaycast = self.Sensor.raycastAll(self.frame)
        nextRaycast = np.zeros(self.Sensor.numRays)
        self.Sarsa.resetElibilityTraces()

        # record the reward data
        runData = dict()
        reward = 0
        discountedReward = 0
        avgReward = 0
        startIdx = self.counter

        while (self.counter < self.numTimesteps - 1):
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx, :] = currentCarState
            x = self.stateOverTime[idx, 0]
            y = self.stateOverTime[idx, 1]
            theta = self.stateOverTime[idx, 2]
            self.setRobotFrameState(x, y, theta)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])
            currentRaycast = self.Sensor.raycastAll(self.frame)
            self.raycastData[idx, :] = currentRaycast
            S_current = (currentCarState, currentRaycast)

            if controllerType not in self.colorMap.keys():
                print
                raise ValueError("controller of type " + controllerType +
                                 " not supported")

            if controllerType in ["default", "defaultRandom"]:
                if controllerType == "defaultRandom":
                    controlInput, controlInputIdx = self.Controller.computeControlInput(
                        currentCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=currentRaycast,
                        randomize=True)
                else:
                    controlInput, controlInputIdx = self.Controller.computeControlInput(
                        currentCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=currentRaycast,
                        randomize=False)

            if controllerType in ["learned", "learnedRandom"]:
                if controllerType == "learned":
                    randomizeControl = False
                else:
                    randomizeControl = True

                counterForGreedyDecay = self.counter - self.idxDict[
                    "learnedRandom"]
                controlInput, controlInputIdx, emptyQValue = self.Sarsa.computeGreedyControlPolicy(
                    S_current,
                    counter=counterForGreedyDecay,
                    randomize=randomizeControl)

                self.emptyQValue[idx] = emptyQValue
                if emptyQValue and self.options['SARSA'][
                        'useSupervisedTraining']:
                    controlInput, controlInputIdx = self.Controller.computeControlInput(
                        currentCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=currentRaycast,
                        randomize=False)

            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput,
                                                    dt=self.dt)

            # want to compute nextRaycast so we can do the SARSA algorithm
            x = nextCarState[0]
            y = nextCarState[1]
            theta = nextCarState[2]
            self.setRobotFrameState(x, y, theta)
            nextRaycast = self.Sensor.raycastAll(self.frame)

            # Compute the next control input
            S_next = (nextCarState, nextRaycast)

            if controllerType in ["default", "defaultRandom"]:
                if controllerType == "defaultRandom":
                    nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(
                        nextCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=nextRaycast,
                        randomize=True)
                else:
                    nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(
                        nextCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=nextRaycast,
                        randomize=False)

            if controllerType in ["learned", "learnedRandom"]:
                if controllerType == "learned":
                    randomizeControl = False
                else:
                    randomizeControl = True

                counterForGreedyDecay = self.counter - self.idxDict[
                    "learnedRandom"]
                nextControlInput, nextControlInputIdx, emptyQValue = self.Sarsa.computeGreedyControlPolicy(
                    S_next,
                    counter=counterForGreedyDecay,
                    randomize=randomizeControl)

                if emptyQValue and self.options['SARSA'][
                        'useSupervisedTraining']:
                    nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(
                        nextCarState,
                        currentTime,
                        self.frame,
                        raycastDistance=nextRaycast,
                        randomize=False)

            # if useQValueController:
            #     nextControlInput, nextControlInputIdx, emptyQValue = self.Sarsa.computeGreedyControlPolicy(S_next)
            #
            # if not useQValueController or emptyQValue:
            #     nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(nextCarState, currentTime, self.frame,
            #                                                                             raycastDistance=nextRaycast)

            # compute the reward
            reward = self.Reward.computeReward(S_next, controlInput)
            self.rewardData[idx] = reward

            discountedReward += self.Sarsa.gamma**(self.counter -
                                                   startIdx) * reward
            avgReward += reward

            ###### SARSA update
            if updateQValues:
                self.Sarsa.sarsaUpdate(S_current, controlInputIdx, reward,
                                       S_next, nextControlInputIdx)

            #bookkeeping
            currentCarState = nextCarState
            currentRaycast = nextRaycast
            self.counter += 1
            # break if we are in collision
            if self.checkInCollision(nextRaycast):
                if self.verbose:
                    print "Had a collision, terminating simulation"
                break

            if self.counter >= simulationCutoff:
                break

        # fill in the last state by hand
        self.stateOverTime[self.counter, :] = currentCarState
        self.raycastData[self.counter, :] = currentRaycast

        # return the total reward
        avgRewardNoCollisionPenalty = avgReward - reward
        avgReward = avgReward * 1.0 / max(1, self.counter - startIdx)
        avgRewardNoCollisionPenalty = avgRewardNoCollisionPenalty * 1.0 / max(
            1, self.counter - startIdx)
        # this extra multiplication is so that it is in the same "units" as avgReward
        runData['discountedReward'] = discountedReward * (1 - self.Sarsa.gamma)
        runData['avgReward'] = avgReward
        runData['avgRewardNoCollisionPenalty'] = avgRewardNoCollisionPenalty

        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        # for use in playback
        self.dt = self.options['dt']
        self.Sarsa.setDiscountFactor(dt)

        self.endTime = self.supervisedTrainingTime + self.learningRandomTime + self.learningEvalTime + self.defaultControllerTime

        self.t = np.arange(0.0, self.endTime, dt)
        maxNumTimesteps = np.size(self.t)
        self.stateOverTime = np.zeros((maxNumTimesteps + 1, 3))
        self.raycastData = np.zeros((maxNumTimesteps + 1, self.Sensor.numRays))
        self.controlInputData = np.zeros(maxNumTimesteps + 1)
        self.rewardData = np.zeros(maxNumTimesteps + 1)
        self.emptyQValue = np.zeros(maxNumTimesteps + 1, dtype='bool')
        self.numTimesteps = maxNumTimesteps

        self.controllerTypeOrder = [
            'defaultRandom', 'learnedRandom', 'learned', 'default'
        ]
        self.counter = 0
        self.simulationData = []

        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0

        # three while loops for different phases of simulation, supervisedTraining, learning, default
        self.idxDict['defaultRandom'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.supervisedTrainingTime / dt,
                        self.numTimesteps)
        while ((self.counter - loopStartIdx < self.supervisedTrainingTime / dt)
               and self.counter < self.numTimesteps):
            self.printStatusBar()
            useQValueController = False
            startIdx = self.counter
            runData = self.runSingleSimulation(updateQValues=True,
                                               controllerType='defaultRandom',
                                               simulationCutoff=simCutoff)

            runData['startIdx'] = startIdx
            runData['controllerType'] = "defaultRandom"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter += 1
            self.simulationData.append(runData)

        self.idxDict['learnedRandom'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.learningRandomTime / dt,
                        self.numTimesteps)
        while ((self.counter - loopStartIdx < self.learningRandomTime / dt)
               and self.counter < self.numTimesteps):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(updateQValues=True,
                                               controllerType='learnedRandom',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "learnedRandom"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter += 1
            self.simulationData.append(runData)

        self.idxDict['learned'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.learningEvalTime / dt,
                        self.numTimesteps)
        while ((self.counter - loopStartIdx < self.learningEvalTime / dt)
               and self.counter < self.numTimesteps):

            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(updateQValues=False,
                                               controllerType='learned',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "learned"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter += 1
            self.simulationData.append(runData)

        self.idxDict['default'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime / dt,
                        self.numTimesteps)
        while ((self.counter - loopStartIdx < self.defaultControllerTime / dt)
               and self.counter < self.numTimesteps - 1):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(updateQValues=False,
                                               controllerType='default',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "default"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter += 1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0:self.counter + 1, :]
        self.raycastData = self.raycastData[0:self.counter + 1, :]
        self.controlInputData = self.controlInputData[0:self.counter + 1]
        self.rewardData = self.rewardData[0:self.counter + 1]
        self.endTime = 1.0 * self.counter / self.numTimesteps * self.endTime

    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"

    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime
            estimatedTimeLeft_sec = (1 -
                                     fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (
                self.numTicks - self.nextTickIdx
            ), "estimated", estimatedTimeLeft_minutes, "minutes left"

    def setCollisionFreeInitialState(self):
        tol = 5

        while True:
            x = np.random.uniform(self.world.Xmin + tol, self.world.Xmax - tol,
                                  1)[0]
            y = np.random.uniform(self.world.Ymin + tol, self.world.Ymax - tol,
                                  1)[0]
            theta = np.random.uniform(0, 2 * np.pi, 1)[0]
            self.Car.setCarState(x, y, theta)
            self.setRobotFrameState(x, y, theta)

            if not self.checkInCollision():
                break

        # if self.checkInCollision():
        #     print "IN COLLISION"
        # else:
        #     print "COLLISION FREE"

        return x, y, theta

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0 / self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        playButton = QtGui.QPushButton('Play/Pause')
        playButton.connect('clicked()', self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect('valueChanged(int)', self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        l.addWidget(playButton)
        l.addWidget(slider)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        l.addWidget(panel)
        w.showMaximized()

        self.frame.connectFrameModified(self.updateDrawIntersection)
        self.updateDrawIntersection(self.frame)

        applogic.resetCamera(viewDirection=[0.2, 0, -1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter / elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.app.start()

    def run(self, launchApp=True):
        self.counter = 1
        self.runBatchSimulation()
        # self.Sarsa.plotWeights()

        if launchApp:
            self.setupPlayback()

    def updateDrawIntersection(self, frame):

        origin = np.array(frame.transform.GetPosition())
        #print "origin is now at", origin
        d = DebugData()

        sliderIdx = self.slider.value

        controllerType = self.getControllerTypeFromCounter(sliderIdx)
        colorMaxRange = self.colorMap[controllerType]

        # if the QValue was empty then color it green
        if self.emptyQValue[sliderIdx]:
            colorMaxRange = [1, 1, 0]  # this is yellow

        for i in xrange(self.Sensor.numRays):
            ray = self.Sensor.rays[:, i]
            rayTransformed = np.array(frame.transform.TransformNormal(ray))
            #print "rayTransformed is", rayTransformed
            intersection = self.Sensor.raycast(
                self.locator, origin,
                origin + rayTransformed * self.Sensor.rayLength)

            if intersection is not None:
                d.addLine(origin, intersection, color=[1, 0, 0])
            else:
                d.addLine(origin,
                          origin + rayTransformed * self.Sensor.rayLength,
                          color=colorMaxRange)

        vis.updatePolyData(d.getPolyData(), 'rays', colorByName='RGB255')

        #camera = self.view.camera()
        #camera.SetFocalPoint(frame.transform.GetPosition())
        #camera.SetPosition(frame.transform.TransformPoint((-30,0,10)))

    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name

    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x, y, 0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self, raycastDistance=None):
        if raycastDistance is None:
            self.setRobotFrameState(self.Car.state[0], self.Car.state[1],
                                    self.Car.state[2])
            raycastDistance = self.Sensor.raycastAll(self.frame)

        if np.min(raycastDistance) < self.collisionThreshold:
            return True
        else:
            return False

    def tick(self):
        #print timer.elapsed
        #simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x, y, 0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x, y, 0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps * (1.0 * value / self.sliderMax)))
        idx = min(idx, numSteps - 1)
        x, y, theta = self.stateOverTime[idx]
        self.setRobotFrameState(x, y, theta)
        self.sliderMovedByPlayTimer = False

    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print 'play'
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print 'pause'
        self.playTimer.stop()

    def computeRunStatistics(self):
        numRuns = len(self.simulationData)
        runStart = np.zeros(numRuns)
        runDuration = np.zeros(numRuns)
        grid = np.arange(1, numRuns + 1)
        discountedReward = np.zeros(numRuns)
        avgReward = np.zeros(numRuns)
        avgRewardNoCollisionPenalty = np.zeros(numRuns)

        idxMap = dict()

        for controllerType, color in self.colorMap.iteritems():
            idxMap[controllerType] = np.zeros(numRuns, dtype=bool)

        for idx, val in enumerate(self.simulationData):
            runStart[idx] = val['startIdx']
            runDuration[idx] = val['duration']
            discountedReward[idx] = val['discountedReward']
            avgReward[idx] = val['avgReward']
            avgRewardNoCollisionPenalty[idx] = val[
                'avgRewardNoCollisionPenalty']
            controllerType = val['controllerType']
            idxMap[controllerType][idx] = True

    def plotRunData(self,
                    controllerTypeToPlot=None,
                    showPlot=True,
                    onlyLearned=False):

        if controllerTypeToPlot == None:
            controllerTypeToPlot = self.colorMap.keys()

        if onlyLearned:
            controllerTypeToPlot = ['learnedRandom', 'learned']

        numRuns = len(self.simulationData)
        runStart = np.zeros(numRuns)
        runDuration = np.zeros(numRuns)
        grid = np.arange(1, numRuns + 1)
        discountedReward = np.zeros(numRuns)
        avgReward = np.zeros(numRuns)
        avgRewardNoCollisionPenalty = np.zeros(numRuns)

        idxMap = dict()

        for controllerType, color in self.colorMap.iteritems():
            idxMap[controllerType] = np.zeros(numRuns, dtype=bool)

        for idx, val in enumerate(self.simulationData):
            runStart[idx] = val['startIdx']
            runDuration[idx] = val['duration']
            discountedReward[idx] = val['discountedReward']
            avgReward[idx] = val['avgReward']
            avgRewardNoCollisionPenalty[idx] = val[
                'avgRewardNoCollisionPenalty']
            controllerType = val['controllerType']
            idxMap[controllerType][idx] = True

            # usedQValueController[idx] = (val['controllerType'] == "QValue")
            # usedDefaultController[idx] = (val['controllerType'] == "default")
            # usedDefaultRandomController[idx] = (val['controllerType'] == "defaultRandom")
            # usedQValueRandomController[idx] = (val['controllerType'] == "QValueRandom")

        self.runStatistics = dict()
        dataMap = {
            'duration': runDuration,
            'discountedReward': discountedReward,
            'avgReward': avgReward,
            'avgRewardNoCollisionPenalty': avgRewardNoCollisionPenalty
        }

        def computeRunStatistics(dataMap):
            for controllerType, idx in idxMap.iteritems():
                d = dict()
                for dataName, dataSet in dataMap.iteritems():
                    # average the appropriate values in dataset
                    d[dataName] = np.sum(
                        dataSet[idx]) / (1.0 * np.size(dataSet[idx]))

                self.runStatistics[controllerType] = d

        computeRunStatistics(dataMap)

        if not showPlot:
            return

        plt.figure()

        #
        # idxDefaultRandom = np.where(usedDefaultRandomController==True)[0]
        # idxQValueController = np.where(usedQValueController==True)[0]
        # idxQValueControllerRandom = np.where(usedQValueControllerRandom==True)[0]
        # idxDefault = np.where(usedDefaultController==True)[0]
        #
        # plotData = dict()
        # plotData['defaultRandom'] = {'idx': idxDefaultRandom, 'color': 'b'}
        # plotData['QValue'] = {'idx': idxQValueController, 'color': 'y'}
        # plotData['default'] = {'idx': idxDefault, 'color': 'g'}

        def scatterPlot(dataToPlot):
            for controllerType in controllerTypeToPlot:
                idx = idxMap[controllerType]
                plt.scatter(grid[idx],
                            dataToPlot[idx],
                            color=self.colorMap[controllerType])

        def barPlot(dataName):
            plt.title(dataName)
            barWidth = 0.5
            barCounter = 0
            index = np.arange(len(controllerTypeToPlot))

            for controllerType in controllerTypeToPlot:
                val = self.runStatistics[controllerType]
                plt.bar(barCounter,
                        val[dataName],
                        barWidth,
                        color=self.colorMap[controllerType],
                        label=controllerType)
                barCounter += 1

            plt.xticks(index + barWidth / 2.0, controllerTypeToPlot)

        plt.subplot(4, 1, 1)
        plt.title('run duration')
        scatterPlot(runDuration)
        # for controllerType, idx in idxMap.iteritems():
        #     plt.scatter(grid[idx], runDuration[idx], color=self.colorMap[controllerType])

        # plt.scatter(runStart[idxDefaultRandom], runDuration[idxDefaultRandom], color='b')
        # plt.scatter(runStart[idxQValueController], runDuration[idxQValueController], color='y')
        # plt.scatter(runStart[idxDefault], runDuration[idxDefault], color='g')
        plt.xlabel('run #')
        plt.ylabel('episode duration')

        plt.subplot(2, 1, 2)
        plt.title('discounted reward')
        scatterPlot(discountedReward)
        # for key, val in plotData.iteritems():
        #     plt.scatter(grid[idx], discountedReward[idx], color=self.colorMap[controllerType])

        # plt.subplot(3,1,3)
        # plt.title("average reward")
        # scatterPlot(avgReward)
        # for key, val in plotData.iteritems():
        #     plt.scatter(grid[val['idx']],avgReward[val['idx']], color=val['color'])

        # plt.subplot(4,1,4)
        # plt.title("average reward no collision penalty")
        # scatterPlot(avgRewardNoCollisionPenalty)
        # # for key, val in plotData.iteritems():
        # #     plt.scatter(grid[val['idx']],avgRewardNoCollisionPenalty[val['idx']], color=val['color'])

        ## plot summary statistics
        plt.figure()

        plt.subplot(2, 1, 1)
        barPlot("duration")

        plt.subplot(2, 1, 2)
        barPlot("discountedReward")

        # plt.subplot(3,1,3)
        # barPlot("avgReward")
        #
        # plt.subplot(4,1,4)
        # barPlot("avgRewardNoCollisionPenalty")

        plt.show()

    def plotMultipleRunData(self,
                            simList,
                            toPlot=['duration', 'discountedReward'],
                            controllerType='learned'):

        plt.figure()
        numPlots = len(toPlot)

        grid = np.arange(len(simList))

        def plot(fieldToPlot, plotNum):
            plt.subplot(numPlots, 1, plotNum)
            plt.title(fieldToPlot)
            val = 0 * grid
            barWidth = 0.5
            barCounter = 0
            for idx, sim in enumerate(simList):
                value = sim.runStatistics[controllerType][fieldToPlot]
                plt.bar(idx, value, barWidth)

        counter = 1
        for fieldToPlot in toPlot:
            plot(fieldToPlot, counter)
            counter += 1

        plt.show()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = 'data/' + filename + ".out"
        my_shelf = shelve.open(filename, 'n')

        my_shelf['options'] = self.options

        if self.options['SARSA']['type'] == "discrete":
            my_shelf['SARSA_QValues'] = self.Sarsa.QValues

        my_shelf['simulationData'] = self.simulationData
        my_shelf['stateOverTime'] = self.stateOverTime
        my_shelf['raycastData'] = self.raycastData
        my_shelf['controlInputData'] = self.controlInputData
        my_shelf['emptyQValue'] = self.emptyQValue
        my_shelf['numTimesteps'] = self.numTimesteps
        my_shelf['idxDict'] = self.idxDict
        my_shelf['counter'] = self.counter
        my_shelf.close()

    @staticmethod
    def loadFromFile(filename):
        filename = 'data/' + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf['options']
        sim.initialize()

        if sim.options['SARSA']['type'] == "discrete":
            sim.Sarsa.QValues = np.array(my_shelf['SARSA_QValues'])

        sim.simulationData = my_shelf['simulationData']
        # sim.runStatistics = my_shelf['runStatistics']
        sim.stateOverTime = np.array(my_shelf['stateOverTime'])
        sim.raycastData = np.array(my_shelf['raycastData'])
        sim.controlInputData = np.array(my_shelf['controlInputData'])
        sim.emptyQValue = np.array(my_shelf['emptyQValue'])
        sim.numTimesteps = my_shelf['numTimesteps']
        sim.idxDict = my_shelf['idxDict']
        sim.counter = my_shelf['counter']

        my_shelf.close()

        return sim
예제 #19
0
class AffordanceInCameraUpdater(object):
    def __init__(self, affordanceManager, imageView):
        self.affordanceManager = affordanceManager
        self.prependImageName = False
        self.projectFootsteps = False
        self.projectAffordances = True
        self.extraObjects = []
        self.imageView = imageView
        self.imageQueue = imageView.imageManager.queue
        self.timer = TimerCallback(targetFps=10)
        self.timer.callback = self.update

    def getOverlayRenderer(self, imageView):

        if not hasattr(imageView, "overlayRenderer"):
            renWin = imageView.view.renderWindow()
            renWin.SetNumberOfLayers(2)
            ren = vtk.vtkRenderer()
            ren.SetLayer(1)
            ren.SetActiveCamera(imageView.view.camera())
            renWin.AddRenderer(ren)
            imageView.overlayRenderer = ren
        return imageView.overlayRenderer

    def addActorToImageOverlay(self, obj, imageView):

        obj.addToView(imageView.view)
        imageView.view.renderer().RemoveActor(obj.actor)

        renderers = obj.extraViewRenderers.setdefault(imageView.view, [])
        overlayRenderer = self.getOverlayRenderer(imageView)
        if overlayRenderer not in renderers:
            overlayRenderer.AddActor(obj.actor)
            renderers.append(overlayRenderer)

    def getFolderName(self):
        if self.prependImageName:
            return self.imageView.imageName + " camera overlay"
        else:
            return "camera overlay"

    def setupObjectInCamera(self, obj):
        imageView = self.imageView
        obj = vis.updatePolyData(
            vtk.vtkPolyData(),
            self.getTransformedName(obj),
            view=imageView.view,
            color=obj.getProperty("Color"),
            parent=self.getFolderName(),
            visible=obj.getProperty("Visible"),
        )
        self.addActorToImageOverlay(obj, imageView)
        return obj

    def getTransformedName(self, obj):
        if self.prependImageName:
            return "overlay " + self.imageView.imageName + " " + obj.getProperty(
                "Name")
        else:
            return "overlay " + obj.getProperty("Name")

    def getFootsteps(self):
        plan = om.findObjectByName("footstep plan")
        if plan:
            return [
                child for child in plan.children()
                if child.getProperty("Name").startswith("step ")
            ]
        else:
            return []

    def getObjectsToUpdate(self):
        objs = []

        if self.projectAffordances:
            objs += self.affordanceManager.getAffordances()
        if self.projectFootsteps:
            objs += self.getFootsteps()
        objs += self.extraObjects
        return objs

    def getObjectInCamera(self, obj):
        overlayObj = om.findObjectByName(self.getTransformedName(obj))
        return overlayObj or self.setupObjectInCamera(obj)

    def cleanUp(self):
        self.timer.stop()
        om.removeFromObjectModel(om.findObjectByName(self.getFolderName()))

    def update(self):
        imageView = self.imageView

        if not imageView.imageInitialized:
            return

        if not imageView.view.isVisible():
            return

        updated = set()

        for obj in self.getObjectsToUpdate():
            cameraObj = self.getObjectInCamera(obj)
            self.updateObjectInCamera(obj, cameraObj)
            updated.add(cameraObj)

        folder = om.findObjectByName(self.getFolderName())
        if folder:
            for child in folder.children():
                if child not in updated:
                    om.removeFromObjectModel(child)

    def updateObjectInCamera(self, obj, cameraObj):

        imageView = self.imageView

        objToLocalT = transformUtils.copyFrame(obj.actor.GetUserTransform()
                                               or vtk.vtkTransform())

        localToCameraT = vtk.vtkTransform()
        self.imageQueue.getTransform("local", imageView.imageName,
                                     localToCameraT)

        t = vtk.vtkTransform()
        t.PostMultiply()
        t.Concatenate(objToLocalT)
        t.Concatenate(localToCameraT)

        pd = filterUtils.transformPolyData(obj.polyData, t)
        """
        normals = pd.GetPointData().GetNormals()
        cameraToImageT = vtk.vtkTransform()
        imageQueue.getCameraProjectionTransform(imageView.imageName, cameraToImageT)
        pd = filterUtils.transformPolyData(pd, cameraToImageT)
        pts = vnp.getNumpyFromVtk(pd, 'Points')
        pts[:,0] /= pts[:,2]
        pts[:,1] /= pts[:,2]
        pd.GetPointData().SetNormals(normals)
        """

        self.imageQueue.projectPoints(imageView.imageName, pd)

        cameraObj.setPolyData(pd)

        self.addActorToImageOverlay(cameraObj, imageView)
예제 #20
0
class Simulator(object):


    def __init__(self, percentObsDensity=20, endTime=40, nonRandomWorld=False,
                 circleRadius=0.7, worldScale=1.0, autoInitialize=True, verbose=True):
        self.verbose = verbose
        self.startSimTime = time.time()
        self.collisionThreshold = 0.4
        self.randomSeed = 5
        self.Sensor_rayLength = 8

        self.percentObsDensity = percentObsDensity
        self.defaultControllerTime = 1000
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale

        # create the visualizer object
        self.app = ConsoleApp()
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()
        
        if autoInitialize:
            self.initialize()

    def initializeOptions(self):
        self.options = dict()

        self.options['World'] = dict()
        self.options['World']['obstaclesInnerFraction'] = 0.98
        self.options['World']['randomSeed'] = 40
        self.options['World']['percentObsDensity'] = 10
        self.options['World']['nonRandomWorld'] = True
        self.options['World']['circleRadius'] = 1.0
        self.options['World']['scale'] = 1

        self.options['Sensor'] = dict()
        self.options['Sensor']['rayLength'] = 20
        self.options['Sensor']['numRays'] = 21


        self.options['Car'] = dict()
        self.options['Car']['velocity'] = 4.0

        self.options['dt'] = 0.05

        self.options['runTime'] = dict()
        self.options['runTime']['defaultControllerTime'] = 100


    def setDefaultOptions(self):

        defaultOptions = dict()


        defaultOptions['World'] = dict()
        defaultOptions['World']['obstaclesInnerFraction'] = 0.98
        defaultOptions['World']['randomSeed'] = 40
        defaultOptions['World']['percentObsDensity'] = 30
        defaultOptions['World']['nonRandomWorld'] = True
        defaultOptions['World']['circleRadius'] = 1.75
        defaultOptions['World']['scale'] = 2.5


        defaultOptions['Sensor'] = dict()
        defaultOptions['Sensor']['rayLength'] = 20
        defaultOptions['Sensor']['numRays'] = 41


        defaultOptions['Car'] = dict()
        defaultOptions['Car']['velocity'] = 20

        defaultOptions['dt'] = 0.05


        defaultOptions['runTime'] = dict()
        defaultOptions['runTime']['defaultControllerTime'] = 100


        for k in defaultOptions:
            self.options.setdefault(k, defaultOptions[k])


        for k in defaultOptions:
            if not isinstance(defaultOptions[k], dict):
                continue

            for j in defaultOptions[k]:
                self.options[k].setdefault(j, defaultOptions[k][j])


    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap['default'] = [0,1,0]

    def initialize(self):

        self.dt = self.options['dt']
        self.controllerTypeOrder = ['default']

        self.setDefaultOptions()

        self.Sensor = SensorObj(rayLength=self.options['Sensor']['rayLength'],
                                numRays=self.options['Sensor']['numRays'])

        self.SensorApproximator = SensorApproximatorObj(numRays=self.options['Sensor']['numRays'], circleRadius=self.options['World']['circleRadius'], )

        self.Controller = ControllerObj(self.Sensor, self.SensorApproximator)

        self.Car = CarPlant(controller=self.Controller,
                            velocity=self.options['Car']['velocity'])

        self.Controller.initializeVelocity(self.Car.v)



        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName('world'))
        self.world = World.buildLineSegmentTestWorld(percentObsDensity=self.options['World']['percentObsDensity'],
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=self.options['World']['nonRandomWorld'],
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'])

        om.removeFromObjectModel(om.findObjectByName('robot'))
        self.robot, self.frame = World.buildRobot()
        self.locator = World.buildCellLocator(self.world.visObj.polyData)
        self.Sensor.setLocator(self.locator)
        self.frame = self.robot.getChildFrame()
        self.frame.setProperty('Scale', 3)
        #self.frame.setProperty('Visible', False)
        #self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.defaultControllerTime = self.options['runTime']['defaultControllerTime']

        self.Car.setFrame(self.frame)
        print "Finished initialization"


    def runSingleSimulation(self, controllerType='default', simulationCutoff=None):


        #self.setRandomCollisionFreeInitialState()
        self.setInitialStateAtZero()

        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1], currentCarState[2])
        
        firstRaycast = self.Sensor.raycastAll(self.frame)
        firstRaycastLocations = self.Sensor.raycastAllLocations(self.frame)

        self.LineSegmentWorld = World.buildLineSegmentWorld(firstRaycastLocations)
        self.LineSegmentLocator = World.buildCellLocator(self.LineSegmentWorld.visObj.polyData)
        self.Sensor.setLocator(self.LineSegmentLocator)

        nextRaycast = np.zeros(self.Sensor.numRays)

        # record the reward data
        runData = dict()
        startIdx = self.counter

        thisRunIndex = 0
        NMaxSteps = 100

        while (self.counter < self.numTimesteps - 1):
            thisRunIndex += 1
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx,:] = currentCarState
            x = self.stateOverTime[idx,0]
            y = self.stateOverTime[idx,1]
            theta = self.stateOverTime[idx,2]
            self.setRobotFrameState(x,y,theta)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])
            currentRaycast = self.Sensor.raycastAll(self.frame)
            print "current Raycast ", currentRaycast
            self.raycastData[idx,:] = currentRaycast
            S_current = (currentCarState, currentRaycast)


            if controllerType not in self.colorMap.keys():
                print
                raise ValueError("controller of type " + controllerType + " not supported")


            if controllerType in ["default", "defaultRandom"]:
                controlInput, controlInputIdx = self.Controller.computeControlInput(currentCarState,
                                                                            currentTime, self.frame,
                                                                            raycastDistance=currentRaycast,
                                                                            randomize=False)

            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput, dt=self.dt)

        
            x = nextCarState[0]
            y = nextCarState[1]
            theta = nextCarState[2]
            self.setRobotFrameState(x,y,theta)
            nextRaycast = self.Sensor.raycastAll(self.frame)


            # Compute the next control input
            S_next = (nextCarState, nextRaycast)

            if controllerType in ["default", "defaultRandom"]:
                nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(nextCarState,
                                                                            currentTime, self.frame,
                                                                            raycastDistance=firstRaycast,
                                                                            randomize=False)


            #bookkeeping
            currentCarState = nextCarState
            currentRaycast = nextRaycast
            self.counter+=1

            # break if we are in collision
            if self.checkInCollision(nextRaycast):
                if self.verbose: print "Had a collision, terminating simulation"
                break

            if thisRunIndex > NMaxSteps:
                print "was safe during N steps"
                break

            if self.counter >= simulationCutoff:
                break


        # fill in the last state by hand
        self.stateOverTime[self.counter,:] = currentCarState
        self.raycastData[self.counter,:] = currentRaycast


        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        # for use in playback
        self.dt = self.options['dt']

        self.endTime = self.defaultControllerTime # used to be the sum of the other times as well

        self.t = np.arange(0.0, self.endTime, dt)
        maxNumTimesteps = np.size(self.t)
        self.stateOverTime = np.zeros((maxNumTimesteps+1, 3))
        self.raycastData = np.zeros((maxNumTimesteps+1, self.Sensor.numRays))
        self.controlInputData = np.zeros(maxNumTimesteps+1)
        self.numTimesteps = maxNumTimesteps

        self.controllerTypeOrder = ['default']
        self.counter = 0
        self.simulationData = []
    
        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0


        self.idxDict['default'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime/dt, self.numTimesteps)
        
        while ((self.counter - loopStartIdx < self.defaultControllerTime/dt) and self.counter < self.numTimesteps-1):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(controllerType='default',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "default"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter+=1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0:self.counter+1, :]
        self.raycastData = self.raycastData[0:self.counter+1, :]
        self.controlInputData = self.controlInputData[0:self.counter+1]
        self.endTime = 1.0*self.counter/self.numTimesteps*self.endTime



    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"
    
    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime 
            estimatedTimeLeft_sec = (1 - fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (self.numTicks - self.nextTickIdx), "estimated", estimatedTimeLeft_minutes, "minutes left"


    def setCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = 0.0
            y =   -5.0
            theta = 0 #+ np.random.uniform(0,2*np.pi,1)[0] * 0.01
            
            self.Car.setCarState(x,y,theta)
            self.setRobotFrameState(x,y,theta)

            print "In loop"

            if not self.checkInCollision():
                break
                
        return x,y,theta


    
    def setInitialStateAtZero(self):
        
        x = 0.0
        y = 0.0
        theta = 0.0
        
        self.Car.setCarState(x,y,theta)
        self.setRobotFrameState(x,y,theta)

        return x,y,theta



    def setRandomCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = np.random.uniform(self.world.Xmin+tol, self.world.Xmax-tol, 1)[0]
            y = np.random.uniform(self.world.Ymin+tol, self.world.Ymax-tol, 1)[0]
            theta = np.random.uniform(0,2*np.pi,1)[0]
            
            self.Car.setCarState(x,y,theta)
            self.setRobotFrameState(x,y,theta)

            if not self.checkInCollision():
                break

        return x,y,theta

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0/self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        playButton = QtGui.QPushButton('Play/Pause')
        playButton.connect('clicked()', self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect('valueChanged(int)', self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        l.addWidget(playButton)
        l.addWidget(slider)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        self.view.orientationMarkerWidget().Off()
        l.addWidget(panel)
        w.showMaximized()

        self.frame.connectFrameModified(self.updateDrawIntersection)
        self.updateDrawIntersection(self.frame)
        
        applogic.resetCamera(viewDirection=[0.2,0,-1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        cameracontrolpanel.CameraControlPanel(self.view).widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter/elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.app.start()

    def run(self, launchApp=True):
        self.counter = 1
        self.runBatchSimulation()

        if launchApp:
            self.setupPlayback()    

    def updateDrawIntersection(self, frame):

        origin = np.array(frame.transform.GetPosition())
        #print "origin is now at", origin
        d = DebugData()

        sliderIdx = self.slider.value

        controllerType = self.getControllerTypeFromCounter(sliderIdx)
        colorMaxRange = self.colorMap[controllerType]

        for i in xrange(self.Sensor.numRays):
            ray = self.Sensor.rays[:,i]
            rayTransformed = np.array(frame.transform.TransformNormal(ray))
            #print "rayTransformed is", rayTransformed
            intersection = self.Sensor.raycast(self.LineSegmentLocator, origin, origin + rayTransformed*self.Sensor.rayLength)

            if intersection is not None:
                d.addLine(origin, intersection, color=[1,0,0])
            else:
                d.addLine(origin, origin+rayTransformed*self.Sensor.rayLength, color=colorMaxRange)

        vis.updatePolyData(d.getPolyData(), 'rays', colorByName='RGB255')

        #camera = self.view.camera()
        #camera.SetFocalPoint(frame.transform.GetPosition())
        #camera.SetPosition(frame.transform.TransformPoint((-30,0,10)))


    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name


    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x,y,0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self, raycastDistance=None):
        if raycastDistance is None:
            self.setRobotFrameState(self.Car.state[0],self.Car.state[1],self.Car.state[2])
            raycastDistance = self.Sensor.raycastAll(self.frame)

        if np.min(raycastDistance) < self.collisionThreshold:
            return True
        else:
            return False

        # if raycastDistance[(len(raycastDistance)+1)/2] < self.collisionThreshold:
        #     return True
        # else:
        #     return False

    def tick(self):
        #print timer.elapsed
        #simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x,y,0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x,y,0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps*(1.0*value/self.sliderMax)))
        idx = min(idx, numSteps-1)
        x,y,theta = self.stateOverTime[idx]
        self.setRobotFrameState(x,y,theta)
        self.sliderMovedByPlayTimer = False

    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print 'play'
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print 'pause'
        self.playTimer.stop()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = 'data/' + filename + ".out"
        my_shelf = shelve.open(filename,'n')

        my_shelf['options'] = self.options

        my_shelf['simulationData'] = self.simulationData
        my_shelf['stateOverTime'] = self.stateOverTime
        my_shelf['raycastData'] = self.raycastData
        my_shelf['controlInputData'] = self.controlInputData
        my_shelf['numTimesteps'] = self.numTimesteps
        my_shelf['idxDict'] = self.idxDict
        my_shelf['counter'] = self.counter
        my_shelf.close()


    @staticmethod
    def loadFromFile(filename):
        filename = 'data/' + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf['options']
        sim.initialize()

        sim.simulationData = my_shelf['simulationData']
        sim.stateOverTime = np.array(my_shelf['stateOverTime'])
        sim.raycastData = np.array( my_shelf['raycastData'])
        sim.controlInputData = np.array(my_shelf['controlInputData'])
        sim.numTimesteps = my_shelf['numTimesteps']
        sim.idxDict = my_shelf['idxDict']
        sim.counter = my_shelf['counter']

        my_shelf.close()

        return sim
예제 #21
0
class AtlasCommandStream(object):
    def __init__(self):
        self.timer = TimerCallback(targetFps=10)
        #self.timer.disableScheduledTimer()
        self.app = ConsoleApp()
        self.robotModel, self.jointController = roboturdf.loadRobotModel(
            'robot model')
        self.fpsCounter = simpletimer.FPSCounter()
        self.drakePoseJointNames = robotstate.getDrakePoseJointNames()
        self.fpsCounter.printToConsole = True
        self.timer.callback = self._tick
        self._initialized = False
        self.publishChannel = 'JOINT_POSITION_GOAL'
        # self.lastCommandMessage = newAtlasCommandMessageAtZero()
        self._numPositions = len(robotstate.getDrakePoseJointNames())
        self._previousElapsedTime = 100
        self._baseFlag = 0
        self.jointLimitsMin = np.array([
            self.robotModel.model.getJointLimits(jointName)[0]
            for jointName in robotstate.getDrakePoseJointNames()
        ])
        self.jointLimitsMax = np.array([
            self.robotModel.model.getJointLimits(jointName)[1]
            for jointName in robotstate.getDrakePoseJointNames()
        ])
        self.useControllerFlag = False
        self.drivingGainsFlag = False
        self.applyDefaults()

    def initialize(self, currentRobotPose):
        assert not self._initialized
        self._currentCommandedPose = np.array(currentRobotPose)
        self._previousCommandedPose = np.array(currentRobotPose)
        self._goalPose = np.array(currentRobotPose)
        self._initialized = True

    def useController(self):
        self.useControllerFlag = True
        self.publishChannel = 'QP_CONTROLLER_INPUT'

    def setKp(self, Kp, jointName=None):
        if jointName is None:
            self._Kp = Kp * np.ones(self._numPositions)
        else:
            idx = robotstate.getDrakePoseJointNames().index(jointName)
            self._maxSpeed[idx] = Kp

        self.updateKd()

    def setMaxSpeed(self, speed, jointName=None):
        if jointName is None:
            self._maxSpeed = np.deg2rad(speed) * np.ones(self._numPositions)
        else:
            idx = robotstate.getDrakePoseJointNames().index(jointName)
            self._maxSpeed[idx] = np.deg2rad(speed)

    def updateKd(self):
        self._dampingRatio = 1
        self._Kd = 2 * self._dampingRatio * np.sqrt(self._Kp)

    def applyDefaults(self):
        self.setKp(10)
        self.setMaxSpeed(10)

        if self.drivingGainsFlag:
            self.setMaxSpeed(70, 'l_arm_lwy')
            self.setKp(50, 'l_arm_lwy')
            self.setMaxSpeed(100, 'l_leg_aky')
            self.setKp(100, 'l_leg_aky')

    def applyDrivingDefaults(self):
        self.drivingGainsFlag = True
        self.applyDefaults()

    def applyPlanDefaults(self):
        self.setKp(10)
        self.setMaxSpeed(60)

    def startStreaming(self):
        assert self._initialized
        if not self.timer.isActive():
            self.timer.start()

    def stopStreaming(self):
        self.timer.stop()

    def setGoalPose(self, pose):
        self._goalPose = self.clipPoseToJointLimits(pose)

    def setIndividualJointGoalPose(self, pose, jointName):
        jointIdx = self.drakePoseJointNames.index(jointName)
        self._goalPose[jointIdx] = pose

    def clipPoseToJointLimits(self, pose):
        pose = np.array(pose)
        pose = np.clip(pose, self.jointLimitsMin, self.jointLimitsMax)
        return pose

    def waitForRobotState(self):
        msg = lcmUtils.captureMessage('EST_ROBOT_STATE',
                                      lcmbotcore.robot_state_t)
        pose = robotstate.convertStateMessageToDrakePose(msg)
        pose[:6] = np.zeros(6)
        self.initialize(pose)

    def _updateAndSendCommandMessage(self):
        self._currentCommandedPose = self.clipPoseToJointLimits(
            self._currentCommandedPose)
        if self._baseFlag:
            msg = robotstate.drakePoseToRobotState(self._currentCommandedPose)
        else:
            msg = drakePoseToAtlasCommand(self._currentCommandedPose)

        if self.useControllerFlag:
            msg = drakePoseToQPInput(self._currentCommandedPose)

        lcmUtils.publish(self.publishChannel, msg)

    def _tick(self):

        self.fpsCounter.tick()

        elapsed = self.timer.elapsed  # time since last tick
        #nominalElapsed = (1.0 / self.timer.targetFps)
        #if elapsed > 2*nominalElapsed:
        #    elapsed = nominalElapsed

        # move current pose toward goal pose
        previousPose = self._previousCommandedPose.copy()
        currentPose = self._currentCommandedPose.copy()
        goalPose = self.clipPoseToJointLimits(self._goalPose.copy())
        nextPose = self._computeNextPose(previousPose, currentPose, goalPose,
                                         elapsed, self._previousElapsedTime,
                                         self._maxSpeed)
        self._currentCommandedPose = nextPose

        # have the base station directly send the command through
        if self._baseFlag:
            self._currentCommandedPose = goalPose

        # publish
        self._updateAndSendCommandMessage()

        # bookkeeping
        self._previousElapsedTime = elapsed
        self._previousCommandedPose = currentPose

    def _computeNextPose(self, previousPose, currentPose, goalPose, elapsed,
                         elapsedPrevious, maxSpeed):
        v = 1.0 / elapsedPrevious * (currentPose - previousPose)
        u = -self._Kp * (currentPose - goalPose) - self._Kd * v  # u = -K*x
        v_next = v + elapsed * u
        v_next = np.clip(v_next, -maxSpeed, maxSpeed)  # velocity clamp
        nextPose = currentPose + v_next * elapsed
        nextPose = self.clipPoseToJointLimits(nextPose)
        return nextPose
예제 #22
0
class DirectorROSVisualizer(object):
    def __init__(self, tf_buffer=None):
        self.taskRunner = TaskRunner()

        if tf_buffer is None:
            self.setup_TF()
        else:
            self._tf_buffer = tf_buffer

        self.clear_visualization()
        self._subscribers = dict()
        self._expressed_in_frame = "base"

    def setup_TF(self):
        """
        Sets up TF
        :return:
        :rtype:
        """
        if self._tf_buffer is None:
            self._tf_buffer = tf2_ros.Buffer()
        self._tf_listener = tf2_ros.TransformListener(self._tf_buffer)

    def clear_visualization(self):
        """
        Clears the visualization
        :return:
        :rtype:
        """
        container_name = "ROS"
        self._vis_container = om.getOrCreateContainer(container_name)
        om.removeFromObjectModel(self._vis_container)
        self._vis_container = om.getOrCreateContainer(container_name)

    def add_subscriber(self,
                       topic,
                       name=None,
                       call_in_thread=True,
                       visualize=False,
                       msg_type=None):
        """
        Adds a subscriber
        :param topic:
        :type topic:
        :param call_in_thread:
        :type call_in_thread:
        :return:
        :rtype:
        """

        if call_in_thread:
            self.add_subscriber(topic,
                                name=name,
                                call_in_thread=False,
                                visualize=visualize,
                                msg_type=msg_type)
            return

        if msg_type is None:
            msg_type = sensor_msgs.msg.PointCloud2

        if name is None:
            name = topic

        subscriber = ros_utils.SimpleSubscriber(topic, msg_type)
        subscriber.start()

        d = dict()
        d['subscriber'] = subscriber
        d['topic'] = topic
        d['visualize'] = visualize
        d['name'] = name

        self._subscribers[topic] = d

    def update(self, snapshot=False):
        """
        Visualizes the pointclouds set to true. This should be called from the main thread
        :return:
        :rtype:
        """

        for topic, data in self._subscribers.iteritems():

            if not data['visualize']:
                continue

            msg = data['subscriber'].lastMsg
            if msg is None:
                continue

            # get frame
            # TransformStamped
            # this might need to be called in thread
            try:
                T_W_pointcloud_stamped = self._tf_buffer.lookup_transform(
                    self._expressed_in_frame, msg.header.frame_id,
                    msg.header.stamp)
            except:
                continue

            T_W_pointcloud = ros_numpy.numpify(
                T_W_pointcloud_stamped.transform)
            T_W_pointcloud_vtk = transformUtils.getTransformFromNumpy(
                T_W_pointcloud)
            pointcloud_numpy = DirectorROSVisualizer.numpy_from_pointcloud2_msg(
                msg)
            pointcloud_vtk = vnp.getVtkPolyDataFromNumpyPoints(
                pointcloud_numpy)
            pointcloud_vtk = filterUtils.transformPolyData(
                pointcloud_vtk, T_W_pointcloud_vtk)

            data['pointcloud'] = pointcloud_vtk
            if snapshot:
                name = data["name"] + " snapshot"
                vis.showPolyData(pointcloud_vtk,
                                 name,
                                 parent=self._vis_container)
            else:
                vis.updatePolyData(pointcloud_vtk,
                                   data['name'],
                                   parent=self._vis_container)

    def start(self, rate_hz=30):
        """
        Launches a timercallback that just calls update()
        :param rate_hz:
        :type rate_hz:
        :return:
        :rtype:
        """
        self._timercallback = TimerCallback(targetFps=rate_hz,
                                            callback=self.update)
        self._timercallback.start()

    def stop(self):
        """
        Stops the visualization callback
        :return:
        :rtype:
        """
        self._timercallback.stop()

    def snapshot(self):
        self.update(snapshot=True)

    def save_snapshot(self):
        save_dir = os.path.join(spartan_utils.get_sandbox_dir(), "pointclouds")
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)

        for topic, data in self._subscribers.iteritems():
            filename = os.path.join(save_dir, "%s.ply" % (data['name']))
            filename.replace(" ", "_")
            ioUtils.writePolyData(data['pointcloud'], filename)

    @staticmethod
    def numpy_from_pointcloud2_msg(msg):
        """

        :param msg: sensor_msgs/PointCloud2
        :type msg:
        :return:
        :rtype:
        """

        pc = ros_numpy.numpify(msg)
        num_points = msg.width * msg.height

        points = np.zeros((num_points, 3))
        points[:, 0] = pc['x'].flatten()
        points[:, 1] = pc['y'].flatten()
        points[:, 2] = pc['z'].flatten()

        return points

    @staticmethod
    def pointcloud2_msg_from_numpy(pc_numpy):
        """

        :param pc_numpy: N x 3
        :type pc_numpy:
        :return:
        :rtype:
        """

        N = pc_numpy.shape[0]

        pc = np.zeros(N,
                      dtype=[('x', np.float64), ('y', np.float64),
                             ('z', np.float64)])
        pc['x'] = pc_numpy[:, 0]
        pc['y'] = pc_numpy[:, 1]
        pc['z'] = pc_numpy[:, 2]

        msg = ros_numpy.msgify(sensor_msgs.msg.PointCloud2, pc)

        return msg
예제 #23
0
class DataCollectionPlanRunner(object):
    def __init__(self,
                 dataCollection,
                 robotSystem,
                 targetFrames,
                 configFilename=None):
        self.robotSystem = robotSystem
        self.dataCollection = dataCollection
        self.timer = TimerCallback(targetFps=5)
        self.timer.callback = self.callback
        self.targetFrames = targetFrames
        self.counter = 0
        self.configFilename = configFilename
        self.initialized = False
        self.loadConfig(self.configFilename)

    def loadConfig(self, configFilename):
        if configFilename is None:
            configFilename = 'data_collection.yaml'

        fullFilename = os.path.join(CorlUtils.getCorlBaseDir(), 'config',
                                    configFilename)
        self.config = CorlUtils.getDictFromYamlFilename(fullFilename)

    def start(self):
        print "starting data collection plan runner"
        self.timer.start()
        os.system(
            "cd /home/robot-lab/newdata && sleep 4 && auto_start_data_collect &"
        )

    def stop(self):
        print "stopping data collection plan runner"
        self.timer.stop()

    def callback(self):

        if self.initialized:
            utime = self.getUtime()
            if utime < self.planData['endUTime']:
                return

        self.initialized = True

        if self.counter >= len(self.targetFrames):
            print "finished reaching all target frames"
            self.stop()
            return

        planData = self.makeNextPlan()
        if planData['info'] == 1:
            self.commitNextPlan()
        else:
            self.stop()
            raise ValueError(' plan info was not 1, stopping execution')

    def makeNextPlan(self):
        targetFrame = self.targetFrames[self.counter].transform
        graspToHandLinkFrame = CorlUtils.getCameraToKukaEndEffectorFrame()
        maxDegreesPerSecond = self.config['planning']['maxDegreesPerSecond']
        self.planData = self.dataCollection.runIK(
            targetFrame,
            graspToHandLinkFrame=graspToHandLinkFrame,
            maxDegreesPerSecond=maxDegreesPerSecond)
        return self.planData

    def getUtime(self):
        return self.robotSystem.robotStateJointController.lastRobotStateMessage.utime

    def commitNextPlan(self):
        print "committed a new plan"
        self.robotSystem.manipPlanner.commitManipPlan(self.planData['plan'])
        planDuration = self.planData['plan'].plan[-1].utime
        self.planData['endUTime'] = self.getUtime() + 1.1 * planDuration
        self.counter += 1
예제 #24
0
class LcmLogPlayer(object):
    def __init__(self, lcmHandle=None):
        if not lcmHandle:
            lcmHandle = lcmUtils.getGlobalLCM()
        self.lcmHandle = lcmHandle
        self.log = None
        self.filePositions = []
        self.playbackFactor = 1.0
        self.timer = TimerCallback()
        self.timestamps = np.array([])
        self.timestampOffset = 0.0

    def findEventIndex(self, timestampRequest):
        requestIndex = self.timestamps.searchsorted(timestampRequest)
        if requestIndex >= len(self.timestamps):
            requestIndex = len(self.timestamps) - 1
        return requestIndex

    def resetPlayPosition(self, playTime):
        self.nextEventIndex = self.findEventIndex(playTime * 1e6)
        filepos = self.filePositions[self.nextEventIndex]
        self.log.seek(filepos)

    def advanceTime(self, playLength, onFrame=None):

        numEvents = len(self.timestamps)
        if self.nextEventIndex >= numEvents:
            return

        startTimestamp = self.timestamps[self.nextEventIndex]
        endTimestamp = startTimestamp + playLength * 1e6

        good = True

        while good:

            event = self.log.read_next_event()
            self.nextEventIndex += 1

            self.lcmHandle.publish(event.channel, event.data)

            good = (self.nextEventIndex < numEvents
                    and self.timestamps[self.nextEventIndex] <= endTimestamp)
            if onFrame and good:
                onFrame(self.timestamps[self.nextEventIndex] / 1.e6)

    def skipToTime(self, timeRequest, playLength=0.0):
        self.resetPlayPosition(timeRequest)
        self.advanceTime(playLength)

    def getEndTime(self):
        assert len(self.timestamps)
        return self.timestamps[-1] * 1e-6

    def stop(self):
        self.timer.stop()

    def playback(self, startTime, playLength, onFrame=None, onStop=None):

        self.resetPlayPosition(startTime)

        startTimestamp = self.timestamps[self.nextEventIndex]
        endTimestamp = startTimestamp + playLength * 1e6

        def onTick():
            elapsed = self.timer.elapsed * self.playbackFactor
            self.advanceTime(elapsed, onFrame)

            good = (self.nextEventIndex < len(self.timestamps)
                    and self.timestamps[self.nextEventIndex] <= endTimestamp)

            if onFrame and good:
                onFrame(self.timestamps[self.nextEventIndex] / 1.e6)
            if onStop and not good:
                onStop()

            return bool(good)  #convert numpy.bool to bool

        self.timer.callback = onTick
        self.timer.start()

    def readLog(self, filename, eventTimeFunction=None, progressFunction=None):
        log = lcm.EventLog(filename, 'r')
        self.log = log

        timestamps = []
        filePositions = []
        offsetIsDefined = False
        timestampOffset = 0
        lastEventTimestamp = 0
        nextProgressTime = 0.0

        while True:

            filepos = log.tell()

            event = log.read_next_event()
            if not event:
                break

            if eventTimeFunction:
                eventTimestamp = eventTimeFunction(event)
            else:
                eventTimestamp = event.timestamp

            if eventTimestamp is None:
                eventTimestamp = lastEventTimestamp
            elif not offsetIsDefined:
                timestampOffset = eventTimestamp
                offsetIsDefined = True

            lastEventTimestamp = eventTimestamp
            timestamp = eventTimestamp - timestampOffset

            if progressFunction:
                progressTime = timestamp * 1e-6
                if progressTime >= nextProgressTime:
                    nextProgressTime += 1.0
                    if not progressFunction(timestamp * 1e-6):
                        break

            filePositions.append(filepos)
            timestamps.append(timestamp)

        self.filePositions = filePositions
        self.timestamps = np.array(timestamps)
        self.timestampOffset = timestampOffset
예제 #25
0
class ExternalForce(object):
    def __init__(self,
                 robotSystem,
                 configFilename="contact_particle_filter_config.yaml"):
        self.robotSystem = robotSystem
        self.robotStateModel = robotSystem.robotStateModel
        self.robotStateModel.connectModelChanged(self.onModelChanged)
        self.options = cfUtils.loadConfig(configFilename)

        self.loadDrakeModelFromFilename()
        self.initializeRobotPoseTranslator()
        self.initializeJointNamesList()

        # keys = linkNames, wrench = 6 x 1 Torque-Force vector, all in body frame
        self.externalForces = dict()
        self.publishChannel = 'EXTERNAL_FORCE_TORQUE'
        self.captureMode = False
        self.captureModeCounter = 0
        self.showContactRay = True
        self.showContactFilterEstimate = True
        self.addSubscribers()
        self.createPlunger()
        self.createMeshDataAndLocators()

        self.createTwoStepEstimator(configFilename)

        self.visObjectDrawTime = dict()
        self.timeout = 1.5

        # setup timercallback to publish, lets say at 5 hz
        self.timer = TimerCallback(targetFps=25)
        self.timer.callback = self.publish
        self.startPublishing()
        # self.startPublishing() # this now gets activated when you start linkSelection

        self.visObjectCleanupTimer = TimerCallback(targetFps=1)
        self.visObjectCleanupTimer.callback = self.removeStaleVisObjects
        self.visObjectCleanupTimer.start()

        self.initializationTime = time.time()

        self.trueResidual = None
        self.estimatedResidual = None

    def addSubscribers(self):
        # lcmUtils.addSubscriber('CONTACT_FILTER_POINT_ESTIMATE', cpf_lcmtypes.contact_filter_estimate_t, self.onContactEstimate)
        lcmUtils.addSubscriber(
            'RESIDUAL_OBSERVER_STATE',
            robotlocomotion_lcmtypes.residual_observer_state_t,
            self.onResidualObserverState)

        # lcmUtils.addSubscriber("CONTACT_FILTER_BODY_WRENCH_ESTIMATE", cpf_lcmtypes.contact_filter_body_wrench_estimate_t, self.onActiveLinkContactEstimate)
        # lcmUtils.addSubscriber("EXTERNAL_FORCE_TORQUE", lcmdrake.lcmt_external_force_torque(), self.onActiveLinkContactEstimate)

    def createMeshDataAndLocators(self):
        self.linkMeshData = dict()

        drakeModelLinkNames = self.robotStateModel.model.getLinkNames()

        for linkName in drakeModelLinkNames:
            linkName = str(linkName)
            data = dict()

            polyData = vtk.vtkPolyData()
            self.robotStateModel.model.getLinkModelMesh(linkName, polyData)
            transform = self.robotStateModel.getLinkFrame(linkName)

            data['linkName'] = linkName
            data['polyData'] = polyData
            data['transform'] = transformUtils.copyFrame(
                self.robotStateModel.getLinkFrame(linkName))
            if (polyData.GetNumberOfCells() == 0):
                print linkName + " mesh has no cells, not building a locator for it"
                continue
            data['locator'] = self.buildCellLocator(polyData)
            self.linkMeshData[linkName] = data

    def createTwoStepEstimator(self, configFilename):
        self.twoStepEstimator = TwoStepEstimator(
            self.robotStateModel, self.robotSystem.robotStateJointController,
            self.linkMeshData, configFilename)

    # either get the EST_ROBOT_STATE utime or just use the wall clock
    def getUtime(self):
        msg = self.robotSystem.robotStateJointController.lastRobotStateMessage
        utime = 0

        if msg is not None:
            utime = msg.utime
        else:
            utime = utimeUtil.getUtime() / 5.0  # slow down time by factor of 5

        return utime

    def loadDrakeModelFromFilename(self, filename=None):
        urdf_filename = self.options['robot']['urdf']
        floatingBaseTypeString = self.options['robot']['floatingBaseType']

        self.drakeModel = PythonDrakeModel(floatingBaseTypeString,
                                           urdf_filename)

    def initializeJointNamesList(self):
        jointNamesTuple = self.drakeModel.model.getJointNames()
        jointNames = []
        for idx, val in enumerate(jointNamesTuple):
            jointNames.append(str(val))

        self.jointNames = jointNames

    def initializeRobotPoseTranslator(self):
        self.robotPoseTranslator = cfUtils.RobotPoseTranslator(
            self.robotSystem.robotStateModel.model, self.drakeModel.model)

    # linkName is a string, wrench is an np.array
    def addForce(self,
                 linkName,
                 wrench=None,
                 forceDirection=None,
                 forceMagnitude=None,
                 forceLocation=None,
                 inWorldFrame=False):

        linkName = str(linkName)  # getting a weird u in front otherwise
        d = dict()
        # need at least one of wrench, or forceDirection and forceMagnitude
        assert (wrench is not None) or ((forceDirection is not None) and
                                        (forceMagnitude is not None) and
                                        (forceLocation is not None))

        if self.captureMode:
            self.captureModeCounter += 1
            key = linkName + "_" + str(self.captureModeCounter)
        else:
            key = linkName

        # check to see if a force on this body already exists, if so then use that as the forceMagnitude
        if self.externalForces.has_key(key):
            forceMagnitude = self.externalForces[key]['forceMagnitude']

        visName = key + ' external force'
        om.removeFromObjectModel(om.findObjectByName(visName))

        if wrench is not None:
            if inWorldFrame:
                raise ValueError(
                    'do not support specifying wrench in world frame')
            d['wrench'] = wrench
            d['forceLocation'] = np.array([0, 0, 0])
            d['forceDirection'] = wrench[3:] / np.linalg.norm(wrench[3:])
            d['forceMagnitude'] = np.linalg.norm(wrench[3:])
            d['isWrench'] = True
            d['linkName'] = linkName
        else:
            if inWorldFrame:
                linkToWorld = self.robotStateModel.getLinkFrame(linkName)
                worldToLink = linkToWorld.GetLinearInverse()
                forceLocation = np.array(
                    worldToLink.TransformPoint(forceLocation))
                forceDirection = np.array(
                    worldToLink.TransformDoubleVector(forceDirection))

            # this should all be in link frame
            forceDirection = forceDirection / np.linalg.norm(forceDirection)
            d['forceDirection'] = forceDirection
            d['forceMagnitude'] = forceMagnitude
            d['forceLocation'] = forceLocation
            d['isWrench'] = False
            d['linkName'] = linkName

        d['time'] = time.time()
        self.externalForces[key] = d
        self.updateContactWrench(key)
        self.drawForces()

    def computeWrench(self, linkName, forceDirection, forceMagnitude,
                      forceLocation):
        outputFrame = vtk.vtkTransform()
        wrenchFrame = vtk.vtkTransform()
        wrenchFrame.Translate(forceLocation)

        forceMomentTransform = transformUtils.forceMomentTransformation(
            wrenchFrame, outputFrame)

        wrench = np.zeros(6)
        wrench[3:] = forceMagnitude * forceDirection
        wrenchTransformed = np.dot(forceMomentTransform, wrench)

        return wrenchTransformed

    # WARNING: make sure you call doKinematics before you get here
    def computeSingleContactPointResidual(self, linkName, wrench):
        linkId = self.drakeModel.model.findLinkID(linkName)
        geometricJacobian = self.drakeModel.geometricJacobian(
            0, linkId, linkId, 0, False)
        singleContactResidual = np.dot(geometricJacobian.transpose(), wrench)
        return singleContactResidual

    def removeForce(self, key, callFromFrameObj=False):
        if not self.externalForces.has_key(key):
            return

        visObjectName = key + ' external force'
        self.externalForces.pop(key, None)

        if not callFromFrameObj:
            om.removeFromObjectModel(om.findObjectByName(visObjectName))

    def removeAllForces(self):
        keyList = list(self.externalForces.keys())

        for key in keyList:
            self.removeForce(key)

    # remove forces from dict that haven't been refreshed in at least self.timeout seconds
    def removeStaleExternalForces(self):
        keysToRemove = []
        for key, value in self.externalForces.iteritems():
            elapsed = time.time() - value['time']

            if elapsed > self.timeout:
                keysToRemove.append(key)

        for key in keysToRemove:
            self.removeForce(key)

    def removeStaleVisObjects(self):
        keysToRemove = []
        for key, val in self.visObjectDrawTime.iteritems():
            elapsed = time.time() - val
            if elapsed > self.timeout:
                keysToRemove.append(key)

        for key in keysToRemove:
            om.removeFromObjectModel(om.findObjectByName(key))
            del self.visObjectDrawTime[key]

    # be careful here if director and this use different models
    # for example if we are FIXED base and director has ROLLPITCHYAW
    def getCurrentPose(self):
        q_director = self.robotSystem.robotStateJointController.q
        q = self.robotPoseTranslator.translateDirectorPoseToRobotPose(
            q_director)
        return q

    def publish(self):

        # if len(self.externalForces) == 0:
        #     return

        tol = 1e-3
        numExternalForces = 0
        msg = cpf_lcmtypes.external_force_torque_t()

        msgMultipleContactLocations = cpf_lcmtypes.multiple_contact_location_t(
        )
        trueResidual = np.zeros((self.drakeModel.numJoints, ))

        # make sure we call doKinematics before we do all the geometricJacobian stuff
        if self.options['debug']['publishTrueResidual']:
            q = self.getCurrentPose()
            self.drakeModel.model.setJointPositions(q)

            # alternatively can just do setJointPositions
            # self.drakeModel.model.setJointPositions(q)

        for key, val in self.externalForces.iteritems():
            # don't publish it if the force is very small
            if np.linalg.norm(val['wrench']) < tol:
                continue

            numExternalForces += 1

            msg.body_names.append(val['linkName'])
            msg.tx.append(val['wrench'][0])
            msg.ty.append(val['wrench'][1])
            msg.tz.append(val['wrench'][2])
            msg.fx.append(val['wrench'][3])
            msg.fy.append(val['wrench'][4])
            msg.fz.append(val['wrench'][5])

            linkName = val['linkName']
            linkFrame = self.robotStateModel.getLinkFrame(linkName)
            contactLocationInWorld = linkFrame.TransformPoint(
                val['forceLocation'])
            contactNormalInWorld = linkFrame.TransformVector(
                val['forceDirection'])

            force = val['forceMagnitude'] * val['forceDirection']
            forceInWorld = linkFrame.TransformPoint(force)

            msgContactLocation = cpf_lcmtypes.single_contact_filter_estimate_t(
            )
            msgContactLocation.body_name = linkName
            msgContactLocation.contact_position = val['forceLocation']
            msgContactLocation.contact_force = force
            msgContactLocation.contact_normal = val['forceDirection']
            msgContactLocation.contact_position_in_world = contactLocationInWorld
            msgContactLocation.contact_force_in_world = forceInWorld
            msgContactLocation.contact_normal_in_world = contactNormalInWorld

            msgMultipleContactLocations.contacts.append(msgContactLocation)

            # compute the true residual if we are asked to publish it
            if self.options['debug']['publishTrueResidual']:
                singleContactResidual = self.computeSingleContactPointResidual(
                    val['linkName'], val['wrench'])
                trueResidual += singleContactResidual

        # this message goes to the simulator
        msg.num_external_forces = numExternalForces
        lcmUtils.publish(self.publishChannel, msg)

        # this message is for analysis
        msgMultipleContactLocations.num_contacts = numExternalForces
        lcmUtils.publish("EXTERNAL_CONTACT_LOCATION",
                         msgMultipleContactLocations)

        # this message is for debugging
        if self.options['debug']['publishTrueResidual']:
            self.trueResidual = trueResidual
            residualMsg = robotlocomotion_lcmtypes.residual_observer_state_t()
            residualMsg.utime = self.getUtime()
            residualMsg.num_joints = len(self.jointNames)
            residualMsg.joint_name = self.jointNames
            residualMsg.residual = trueResidual

            # these are just placeholders so lcm doesn't complain
            # we are not actually populating them
            residualMsg.gravity = 0 * trueResidual
            residualMsg.internal_torque = 0 * trueResidual
            residualMsg.foot_contact_torque = 0 * trueResidual

            lcmUtils.publish("RESIDUAL_ACTUAL", residualMsg)

        if self.options['twoStepEstimator']['computeEstimate']:
            twoStepEstimateData = self.computeTwoStepEstimate()

            # if twoStepEstimateData is None it means that some criterion
            # wasn't satisfied and we didn't actually perform the estimation
            if twoStepEstimateData is not None:
                self.publishTwoStepEstimateData(twoStepEstimateData,
                                                msgMultipleContactLocations)

                if self.options['twoStepEstimator']['visualize']:
                    self.visualizeTwoStepEstimate(twoStepEstimateData)

    def visualizeTwoStepEstimate(self, data):
        for linkName, singleContactData in data.iteritems():
            self.visualizeTwoStepEstimateSingleContact(singleContactData)

    def visualizeTwoStepEstimateSingleContact(self, data):

        # draw the contact ray if that option is set
        if self.options['twoStepEstimator']['showContactRay']:
            d = DebugData()
            d.addLine(data['contactRay']['rayOriginInWorld'],
                      data['contactRay']['rayEndInWorld'],
                      radius=0.005)
            color = data['contactRay']['color']
            visName = data['contactRay']['visObjectName']
            obj = vis.updatePolyData(d.getPolyData(), visName, color=color)
            self.visObjectDrawTime[visName] = time.time()

        # draw the actual contact point if it exists
        if data['pt'] is not None:
            visName = data['linkName'] + " active link estimated external force"
            self.drawForce(visName,
                           data['linkName'],
                           data['pt'],
                           data['force'],
                           color=[1, 0, 0])
            self.visObjectDrawTime[visName] = time.time()

    def publishTwoStepEstimateData(self, twoStepEstimateData,
                                   actualContactLocationsMsg):
        msg = cpf_lcmtypes.actual_and_estimated_contact_locations_t()
        msg.utime = self.getUtime()
        msg.actual_contact_location = actualContactLocationsMsg

        estMsg = cpf_lcmtypes.multiple_contact_location_t()
        estMsg.num_contacts = len(twoStepEstimateData)

        for linkName, data in twoStepEstimateData.iteritems():
            tmpMsg = cpf_lcmtypes.single_contact_filter_estimate_t()
            tmpMsg.body_name = linkName
            tmpMsg.contact_normal = data['force']

            if data['pt'] is None:
                tmpMsg.utime = -1  # signifies that no intersection was found
            else:
                tmpMsg.contact_position = data['contactLocation']
                tmpMsg.contact_position_in_world = data[
                    'contactLocationInWorld']

            tmpMsg.contact_force = data['force']
            tmpMsg.contact_force_in_world = data['forceInWorld']
            estMsg.contacts.append(tmpMsg)

        msg.estimated_contact_location = estMsg

        lcmUtils.publish(self.options['twoStepEstimator']['publishChannel'],
                         msg)

    def startPublishing(self):
        self.captureMode = False
        self.captureModeCounter = 0
        self.removeAllForces()
        self.timer.start()

    def stopPublishing(self):
        print "stopping publishing"
        self.timer.stop()

    def startCaptureMode(self):
        self.stopPublishing()
        print "starting capture mode"
        self.removeAllForces()
        self.captureMode = True
        self.captureModeCounter = 0

    def onResidualObserverState(self, msg):
        msgJointNames = msg.joint_name
        msgData = msg.residual
        residual = self.drakeModel.extractDataFromMessage(
            msgJointNames, msgData)
        self.estimatedResidual = residual

    def onContactEstimate(self, msg):

        if not self.showContactFilterEstimate:
            return

        name = 'estimated external force'

        for i in xrange(0, msg.num_contact_points):
            subMsg = msg.single_contact_estimate[i]
            forceLocation = np.array(subMsg.contact_position)
            force = np.array(subMsg.contact_force)

            eps = 0.5
            name = 'estimated external force ' + str(i)
            if np.linalg.norm(force) < eps:
                # om.removeFromObjectModel(om.findObjectByName(name))
                return

            self.drawForce(name,
                           subMsg.body_name,
                           forceLocation,
                           force,
                           color=[0, 0, 1])
            self.visObjectDrawTime[name] = time.time()

    def drawForce(self, name, linkName, forceLocation, force, color, key=None):

        forceDirection = force / np.linalg.norm(force)
        # om.removeFromObjectModel(om.findObjectByName(name))

        linkToWorld = self.robotStateModel.getLinkFrame(linkName)
        forceLocationInWorld = np.array(
            linkToWorld.TransformPoint(forceLocation))
        forceDirectionInWorld = np.array(
            linkToWorld.TransformDoubleVector(forceDirection))

        # point = forceLocationInWorld - 0.1*forceDirectionInWorld

        # d = DebugData()
        # # d.addArrow(point, forceLocationInWorld, headRadius=0.025, tubeRadius=0.005, color=color)
        # d.addSphere(forceLocationInWorld, radius=0.01)
        # d.addLine(point, forceLocationInWorld, radius=0.005)

        transformForVis = transformUtils.getTransformFromOriginAndNormal(
            forceLocationInWorld, forceDirectionInWorld)

        obj = vis.updatePolyData(self.plungerPolyData, name, color=color)
        obj.actor.SetUserTransform(transformForVis)

        if key is not None and om.findObjectByName(name) is not None:
            obj.addProperty('magnitude',
                            self.externalForces[key]['forceMagnitude'])
            obj.addProperty('linkName', linkName)
            obj.addProperty('key', key)
            obj.connectRemovedFromObjectModel(self.removeForceFromFrameObject)

        obj.properties.connectPropertyChanged(
            functools.partial(self.onPropertyChanged, obj))
        return obj

    # connect this with an on model changed
    def drawForces(self):
        if len(self.externalForces) == 0:
            return

        for key, val in self.externalForces.iteritems():
            linkName = val['linkName']
            name = key + ' external force'
            #Green is for a force, red is for a wrench
            color = [0, 1, 0]
            if val['isWrench']:
                color = [1, 0, 0]

            # linkToWorld = self.robotStateModel.getLinkFrame(linkName)

            # forceLocationInWorld = np.array(linkToWorld.TransformPoint(val['forceLocation']))
            # forceDirectionInWorld = np.array(linkToWorld.TransformDoubleVector(val['forceDirection']))

            # point = forceLocationInWorld - 0.1*forceDirectionInWorld

            # d = DebugData()
            # # d.addArrow(point, forceLocationInWorld, headRadius=0.025, tubeRadius=0.005, color=color)
            # d.addSphere(forceLocationInWorld, radius=0.01)
            # d.addLine(point, forceLocationInWorld, radius=0.005)

            obj = self.drawForce(name,
                                 linkName,
                                 val['forceLocation'],
                                 val['forceDirection'],
                                 color,
                                 key=key)

    def onModelChanged(self, model):
        self.drawForces()

    def onPropertyChanged(self, frameObj, propertySet, propertyName):
        if propertyName != 'magnitude':
            return
        key = frameObj.getProperty('key')
        linkName = frameObj.getProperty('linkName')
        magnitude = frameObj.getProperty('magnitude')
        if magnitude < 0:
            print "you must specify a positive magnitude"
            print "external forces can only PUSH, NOT PULL"
            return

        self.externalForces[key]['forceMagnitude'] = magnitude
        self.updateContactWrench(key)

    def updateContactWrench(self, key):
        if not self.externalForces.has_key(key):
            return

        val = self.externalForces[key]

        # if it was specified as a wrench, then don't overwrite it
        if val['isWrench']:
            return

        val['wrench'] = self.computeWrench(val['linkName'],
                                           val['forceDirection'],
                                           val['forceMagnitude'],
                                           val['forceLocation'])

    def removeForceFromFrameObject(self, tree_, frameObj):
        key = frameObj.getProperty('key')
        self.removeForce(key, callFromFrameObj=True)

    def computeTwoStepEstimate(self):
        residual = None
        if self.options['debug']['useTrueResidual']:
            residual = self.trueResidual
        else:
            residual = self.estimatedResidual

        # this means we haven't gotten any data yet
        # so just return an empty dict which means no data
        if residual is None:
            return None

        if self.options['noise']['addNoise']:
            residualSize = np.size(residual)
            residual = residual + np.random.normal(
                scale=self.options['noise']['stddev'], size=residualSize)

        if self.options['twoStepEstimator']['provideLinkContactInfo']:
            # only do this if we are using fake residual
            linksWithContactForce = []
            for key, val in self.externalForces.iteritems():
                if val['forceMagnitude'] > 0.1:
                    linksWithContactForce.append(key)
        else:
            linksWithContactForce = None

        return self.twoStepEstimator.computeTwoStepEstimate(
            residual, linksWithContactForce)

    def printForces(self):
        for key in self.externalForces.keys():
            print key

    # deprecated
    def saveForceLocationsToFileOld(self,
                                    filename=None,
                                    verbose=False,
                                    overwrite=False):

        spartan_source_dir = os.getenv('SPARTAN_SOURCE_DIR')

        if filename is None:
            fullFilename = spartan_source_dir + self.options['data'][
                'contactCells']
        else:
            fullFilename = spartan_source_dir + \
                           "/src/ContactParticleFilter/config/" + filename

        print "saving initial particle locations to ", filename

        if os.path.isfile(fullFilename) and not overwrite:
            print "FILE ALREADY EXISTS, set the overwrite flag to true to overwrite"
            return

        fileObject = open(fullFilePath, 'w')
        for key, val in self.externalForces.iteritems():
            line = str(val['linkName']) + ","

            for i in range(0, 3):
                line += str(val['forceLocation'][i]) + ","

            for i in range(0, 3):
                line += str(val['forceDirection'][i]) + ","

            line += "\n"

            if verbose:
                print line

            fileObject.write(line)

        fileObject.close()

    def saveForceLocationsToFile(self,
                                 filename=None,
                                 verbose=False,
                                 overwrite=False):

        spartan_source_dir = os.getenv('SPARTAN_SOURCE_DIR')

        if filename is None:
            fullFilename = spartan_source_dir + self.options['data'][
                'contactCells']
        else:
            fullFilename = spartan_source_dir + \
                           "/src/ContactParticleFilter/config/" + filename

        print "saving initial particle locations to ", fullFilename

        if os.path.isfile(fullFilename) and not overwrite:
            print "FILE ALREADY EXISTS, set the overwrite flag to true to overwrite"
            return

        ioUtils.saveDataToFile(fullFilename,
                               self.externalForces,
                               overwrite=overwrite)

    def addForcesFromFile(self, filename=None):
        self.startCaptureMode()
        spartan_source_dir = os.getenv('SPARTAN_SOURCE_DIR')

        if filename is None:
            fullFilename = spartan_source_dir + self.options['data'][
                'initialParticleLocations']
        else:
            fullFilename = spartan_source_dir + \
                           "/src/ContactParticleFilter/config/" + filename

        dataDict = ioUtils.readDataFromFile(fullFilename)
        for key, val in dataDict.iteritems():
            linkName = val['linkName']
            forceLocation = val['forceLocation']
            forceDirection = val['forceDirection']
            self.addForce(linkName,
                          wrench=None,
                          forceDirection=forceDirection,
                          forceMagnitude=0.0,
                          forceLocation=forceLocation,
                          inWorldFrame=False)

    def createPlunger(self):
        forceLocationInWorld = np.array([0, 0, 0])
        forceDirectionInWorld = np.array([0, 0, 1])

        point = forceLocationInWorld - 0.1 * forceDirectionInWorld
        color = [1, 0, 0]
        d = DebugData()
        # d.addArrow(point, forceLocationInWorld, headRadius=0.025, tubeRadius=0.005, color=color)
        d.addSphere(forceLocationInWorld, radius=0.01)
        d.addLine(point, forceLocationInWorld, radius=0.005)
        self.plungerPolyData = d.getPolyData()

    @staticmethod
    def buildCellLocator(polyData):
        print "building cell locator"
        loc = vtk.vtkCellLocator()
        loc.SetDataSet(polyData)
        loc.BuildLocator()
        return loc

    @staticmethod
    def raycast(locator, rayOrigin, rayEnd):
        tolerance = 0.0  # intersection tolerance
        pt = [0.0, 0.0, 0.0]  # data coordinate where intersection occurs
        lineT = vtk.mutable(
            0.0
        )  # parametric distance along line segment where intersection occurs
        pcoords = [
            0.0, 0.0, 0.0
        ]  # parametric location within cell (triangle) where intersection occurs
        subId = vtk.mutable(0)  # sub id of cell intersection

        result = locator.IntersectWithLine(rayOrigin, rayEnd, tolerance, lineT,
                                           pt, pcoords, subId)

        return pt if result else None

    def visualizeMesh(self, linkName):
        if linkName not in self.linkMeshData:
            print "I can't find a mesh corresponding to " + linkName
            return

        vis.showPolyData(self.linkMeshData[linkName]['polyData'],
                         linkName + ' mesh')

    # these are test methods
    def setupTest(self):
        w = np.array([1, 2, 3, 4, 5, 6])
        self.addForce('pelvis', wrench=w)
        self.startPublishing()

    def test1(self):
        forceDirection = np.array([0, 0, 1])
        forceMagnitude = 100
        forceLocation = np.array([0, 0, 0])
        linkName = 'pelvis'

        self.addForce(linkName,
                      forceDirection=forceDirection,
                      forceMagnitude=forceMagnitude,
                      forceLocation=forceLocation)
        self.drawForces()

    def test2(self):
        wrench = np.array([0, 0, 0, 0, 0, 100])
        linkName = 'pelvis'
        self.addForce(linkName, wrench=wrench)

    def constructTestFrames(self):
        T = vtk.vtkTransform()
        S = vtk.vtkTransform()
        S.Translate([1, 2, 0])
        FM = transformUtils.forceMomentTransformation(S, T)
        print FM
        return T, S, FM
예제 #26
0
class Simulator(object):


    def __init__(self, percentObsDensity=20, endTime=40, nonRandomWorld=False,
                 circleRadius=0.7, worldScale=1.0, autoInitialize=True, verbose=True):
        self.verbose = verbose
        self.startSimTime = time.time()
        self.collisionThreshold = 1.0
        self.randomSeed = 5

        self.percentObsDensity = percentObsDensity
        self.defaultControllerTime = 1000
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale

        # create the visualizer object
        self.app = ConsoleApp()
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()

        self.initial_XVelocity = 0.0
        self.initial_YVelocity = 0.0

        self.running_sim = True

        self.currentIdx = 0;
        
        if autoInitialize:
            self.initialize()

    def initializeOptions(self):
        self.options = dict()

        self.options['World'] = dict()
        self.options['World']['obstaclesInnerFraction'] = 0.98
        self.options['World']['randomSeed'] = 40
        self.options['World']['percentObsDensity'] = 15.0
        self.options['World']['nonRandomWorld'] = True
        self.options['World']['circleRadius'] = 0.6
        self.circleRadius = self.options['World']['circleRadius']
        self.options['World']['scale'] = 2.0


        self.options['Car'] = dict()
        self.options['Car']['velocity'] = 20

        self.options['dt'] = 0.05

        self.options['runTime'] = dict()
        self.options['runTime']['defaultControllerTime'] = 100


    def setDefaultOptions(self):

        defaultOptions = dict()


        defaultOptions['World'] = dict()
        defaultOptions['World']['obstaclesInnerFraction'] = 0.98
        defaultOptions['World']['randomSeed'] = 40
        defaultOptions['World']['percentObsDensity'] = 30
        defaultOptions['World']['nonRandomWorld'] = True
        defaultOptions['World']['circleRadius'] = 1.75
        defaultOptions['World']['scale'] = 2.5


        defaultOptions['Car'] = dict()
        defaultOptions['Car']['velocity'] = 20

        defaultOptions['dt'] = 0.05


        defaultOptions['runTime'] = dict()
        defaultOptions['runTime']['defaultControllerTime'] = 100


        for k in defaultOptions:
            self.options.setdefault(k, defaultOptions[k])


        for k in defaultOptions:
            if not isinstance(defaultOptions[k], dict):
                continue

            for j in defaultOptions[k]:
                self.options[k].setdefault(j, defaultOptions[k][j])


    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap['default'] = [0,1,0]

    def initialize(self):

        self.dt = self.options['dt']
        self.controllerTypeOrder = ['default']

        self.setDefaultOptions()

        self.Controller = ControllerObj()

        self.Car = CarPlant(controller=self.Controller,
                            velocity=self.options['Car']['velocity'])

        self.Controller.initializeVelocity(self.Car.v)

        self.ActionSet = ActionSetObj()

        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName('world'))
        self.world = World.buildCircleWorld(percentObsDensity=self.options['World']['percentObsDensity'],
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=self.options['World']['nonRandomWorld'],
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'])

        om.removeFromObjectModel(om.findObjectByName('robot'))
        self.robot, self.frame = World.buildRobot()
        self.locator = World.buildCellLocator(self.world.visObj.polyData)
        
        #will need to set locator for purple trajectories
        #self.Sensor.setLocator(self.locator)
        self.frame = self.robot.getChildFrame()
        self.frame.setProperty('Scale', 3)
        #self.frame.setProperty('Visible', False)
        #self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.defaultControllerTime = self.options['runTime']['defaultControllerTime']

        self.Car.setFrame(self.frame)
        print "Finished initialization"


    def rankTrajectories(self):
        # access the trajectories
        x_traj = self.ActionSet.p_x_trajectories
        y_traj = self.ActionSet.p_y_trajectories


        final_x_positions = x_traj[:,-1]
        final_y_positions = y_traj[:,-1]

        #access the global goal
        global_goal_x = self.globalGoal.global_goal_x
        global_goal_y = self.globalGoal.global_goal_y

        ranks_with_indices = []

        def getKey(item):
            return item[1]

        final_distances_squared = np.zeros((len(final_x_positions),len(final_y_positions)))
        for i in xrange(len(final_x_positions)):
            for j in xrange(len(final_y_positions)):
                distance = (final_x_positions[i] - global_goal_x)**2 + (final_y_positions[j] - global_goal_y)**2
                ranks_with_indices.append(((i,j), distance))


        sorted_ranks_with_indices = sorted(ranks_with_indices,key=getKey)

        return sorted_ranks_with_indices

    def CheckIfCollisionFreeTrajectoryIndex(self, traj_index):
        # accessing the right trajectory
        x_trajectory_to_check = self.ActionSet.p_x_trajectories[traj_index[0]]
        y_trajectory_to_check = self.ActionSet.p_y_trajectories[traj_index[1]]


        #check if anything is too close to the center of the circles
        #print self.world.list_of_circles
        for i in range(len(x_trajectory_to_check)):
            point = ( x_trajectory_to_check[i], y_trajectory_to_check[i]  )
            if not self.CheckIfCollisionFreePoint(point):
                #print "trajectory wasn't free"
                return False 


        return True

    def CheckIfCollisionFreePoint(self, point):

        for circle_center in self.world.list_of_circles:
            #print "circle centers first"
            #print circle_center[0], circle_center[1]
            #print self.circleRadius
            #print point[0], point[1]
            #print (circle_center[0] - point[0])**2 + (circle_center[1]-point[1])**2
            if  ( (circle_center[0] - point[0])**2 + (circle_center[1]-point[1])**2 < self.circleRadius**2):
                #print "I found a point in a circle"
                return False

        if point[0] > self.world.Xmax:
            #print "I would have gone past top wall"
            return False
        if point[0] < self.world.Xmin:
            #print "I would have gone below bottom wall"
            return False
        if point[1] > self.world.Ymax:
            #print "I would have gone to the right of the side wall"
            return False    
        if point[1] < self.world.Ymin:
            #print "I would have gone to the left of the side wall"
            return False

        return True




    def runSingleSimulation(self, controllerType='default', simulationCutoff=None):


        self.Car.setCarState(0.0,0.0,self.initial_XVelocity,self.initial_YVelocity)
        self.setRobotFrameState(0.0,0.0,0.0)


        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1], currentCarState[2])

        # record the reward data
        runData = dict()
        startIdx = self.counter


        while (self.counter < self.numTimesteps - 1):
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx,:] = currentCarState
            x = self.stateOverTime[idx,0]
            y = self.stateOverTime[idx,1]
            self.setRobotFrameState(x,y,0.0)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])
            


            if controllerType not in self.colorMap.keys():
                print
                raise ValueError("controller of type " + controllerType + " not supported")

            # compute all trajectories from action set
            self.ActionSet.computeAllPositions(currentCarState[0], currentCarState[1],currentCarState[2],currentCarState[3])


            sorted_ranks_with_indices = self.rankTrajectories()
            #method
            #inputs: trajectories, global goal
            #outputs: sorted list of indexes by desirability global goal


            #method
            #input: trajectory
            #output: is collision free or not
            for traj in sorted_ranks_with_indices:
                if self.CheckIfCollisionFreeTrajectoryIndex(traj[0]):
                    traj_to_use_index = traj[0]
                    break
                traj_to_use_index = traj[0]

            x_index_to_use = traj_to_use_index[0]
            y_index_to_use = traj_to_use_index[1]

            x_accel = self.ActionSet.a_x[x_index_to_use]
            y_accel = self.ActionSet.a_y[y_index_to_use]

            controlInput = [x_accel, y_accel]


            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput, dt=self.dt)

        
            x = nextCarState[0]
            y = nextCarState[1]
            theta = nextCarState[2]
            self.setRobotFrameState(x,y,theta)
            

            #bookkeeping
            currentCarState = nextCarState
            
            self.counter+=1

            # break if we are in collision

            if self.counter >= simulationCutoff:
                break


        # fill in the last state by hand
        self.stateOverTime[self.counter,:] = currentCarState


        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        # for use in playback
        self.dt = self.options['dt']

        self.endTime = self.defaultControllerTime # used to be the sum of the other times as well

        self.t = np.arange(0.0, self.endTime, dt)
        maxNumTimesteps = np.size(self.t)
        self.stateOverTime = np.zeros((maxNumTimesteps+1, 4))
        self.controlInputData = np.zeros((maxNumTimesteps+1,2))
        self.numTimesteps = maxNumTimesteps

        self.controllerTypeOrder = ['default']
        self.counter = 0
        self.simulationData = []
    
        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0


        self.idxDict['default'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime/dt, self.numTimesteps)
        
        while ((self.counter - loopStartIdx < self.defaultControllerTime/dt) and self.counter < self.numTimesteps-1):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(controllerType='default',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "default"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter+=1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0:self.counter+1, :]
        self.controlInputData = self.controlInputData[0:self.counter+1]
        self.endTime = 1.0*self.counter/self.numTimesteps*self.endTime



    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"
    
    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime 
            estimatedTimeLeft_sec = (1 - fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (self.numTicks - self.nextTickIdx), "estimated", estimatedTimeLeft_minutes, "minutes left"


    def setCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = 0.0
            y =   -5.0
            theta = 0 #+ np.random.uniform(0,2*np.pi,1)[0] * 0.01
            
            self.Car.setCarState(x,y,theta)
            self.setRobotFrameState(x,y,theta)

            print "In loop"

            if not self.checkInCollision():
                break
                
        return x,y,theta


    def setRandomCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = np.random.uniform(self.world.Xmin+tol, self.world.Xmax-tol, 1)[0]
            y = np.random.uniform(self.world.Ymin+tol, self.world.Ymax-tol, 1)[0]
            #theta = np.random.uniform(0,2*np.pi,1)[0]
            theta = 0 #always forward

            self.Car.setCarState(x,y,self.initial_XVelocity,self.initial_YVelocity)
            self.setRobotFrameState(x,y,theta)

            if not self.checkInCollision():
                break

        self.firstRandomCollisionFreeInitialState_x = x
        self.firstRandomCollisionFreeInitialState_y = y

        return x,y,0,0

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0/self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        self.max_velocity = 20.0

        sliderXVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderXVelocity.connect('valueChanged(int)', self.onXVelocityChanged)
        sliderXVelocity.setMaximum(self.max_velocity)
        sliderXVelocity.setMinimum(-self.max_velocity)

        l.addWidget(sliderXVelocity)

        sliderYVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderYVelocity.connect('valueChanged(int)', self.onYVelocityChanged)
        sliderYVelocity.setMaximum(self.max_velocity)
        sliderYVelocity.setMinimum(-self.max_velocity)
        l.addWidget(sliderYVelocity)

        randomGlobalGoalButton = QtGui.QPushButton('Initialize Random Global Goal')
        randomGlobalGoalButton.connect('clicked()', self.onRandomGlobalGoalButton)
        l.addWidget(randomGlobalGoalButton)

        drawActionSetButton = QtGui.QPushButton('Draw Action Set')
        drawActionSetButton.connect('clicked()', self.onDrawActionSetButton)
        l.addWidget(drawActionSetButton)

        runSimButton = QtGui.QPushButton('Simulate')
        runSimButton.connect('clicked()', self.onRunSimButton)
        l.addWidget(runSimButton)

        playButton = QtGui.QPushButton('Play/Pause')
        playButton.connect('clicked()', self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect('valueChanged(int)', self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        l.addWidget(playButton)
        l.addWidget(slider)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        self.view.orientationMarkerWidget().Off()
        l.addWidget(panel)
        w.showMaximized()

        # need to connect frames with DrawActionSet
        self.frame.connectFrameModified(self.updateDrawActionSet)
        self.updateDrawActionSet(self.frame)
        # self.frame.connectFrameModified(self.updateDrawIntersection)
        # self.updateDrawIntersection(self.frame)
        
        applogic.resetCamera(viewDirection=[0.2,0,-1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        cameracontrolpanel.CameraControlPanel(self.view).widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter/elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.app.start()

    def run(self, launchApp=True):
        self.running_sim = True
        self.onRandomGlobalGoalButton()
        self.counter = 1
        self.runBatchSimulation()
        self.running_sim = False
        print "my state over time is", self.stateOverTime

        if launchApp:
            self.setupPlayback()



    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name


    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x,y,0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self):

        return False

    def updateDrawActionSet(self, frame):

        origin = np.array(frame.transform.GetPosition())

        if not self.running_sim:
            self.ActionSet.computeAllPositions(self.stateOverTime[self.currentIdx,0], self.stateOverTime[self.currentIdx,1], self.stateOverTime[self.currentIdx,2],self.stateOverTime[self.currentIdx,3])
            #self.ActionSet.drawActionSetFinal()
            self.ActionSet.drawActionSetFull()


    def tick(self):
        #print timer.elapsed
        #simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x,y,0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x,y,0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onXVelocityChanged(self, value):
        self.initial_XVelocity = value
        print "initial x velocity changed to ", value

    def onYVelocityChanged(self, value):
        self.initial_YVelocity = -value
        print "initial y velocity changed to ", -value

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps*(1.0*value/self.sliderMax)))
        idx = min(idx, numSteps-1)
        self.currentIdx = idx
        x,y, xdot, ydot = self.stateOverTime[idx]
        self.setRobotFrameState(x,y,0)
        self.sliderMovedByPlayTimer = False

    def onRandomGlobalGoalButton(self):
        print "random global goal button pressed"
        self.globalGoal = World.buildGlobalGoal(scale=self.options['World']['scale'])

    def onDrawActionSetButton(self):
        print "drawing action set"
        #self.ActionSet.computeFinalPositions(self.XVelocity_drawing,self.YVelocity_drawing)
        self.ActionSet.computeAllPositions(self.Car.state[0], self.Car.state[1], self.initial_XVelocity, self.initial_YVelocity)
        #self.ActionSet.drawActionSetFinal()
        self.ActionSet.drawActionSetFull()

    def onRunSimButton(self):
        self.running_sim = True
        self.runBatchSimulation()
        print "my state over time is", self.stateOverTime
        self.running_sim = False
        #self.saveToFile("latest")

    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print 'play'
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print 'pause'
        self.playTimer.stop()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = 'data/' + filename + ".out"
        my_shelf = shelve.open(filename,'n')

        my_shelf['options'] = self.options

        my_shelf['simulationData'] = self.simulationData
        my_shelf['stateOverTime'] = self.stateOverTime
        my_shelf['controlInputData'] = self.controlInputData
        my_shelf['numTimesteps'] = self.numTimesteps
        my_shelf['idxDict'] = self.idxDict
        my_shelf['counter'] = self.counter
        my_shelf.close()


    @staticmethod
    def loadFromFile(filename):
        filename = 'data/' + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf['options']
        sim.initialize()

        sim.simulationData = my_shelf['simulationData']
        sim.stateOverTime = np.array(my_shelf['stateOverTime'])
        sim.controlInputData = np.array(my_shelf['controlInputData'])
        sim.numTimesteps = my_shelf['numTimesteps']
        sim.idxDict = my_shelf['idxDict']
        sim.counter = my_shelf['counter']

        my_shelf.close()

        return sim
예제 #27
0
class Simulator(object):
    def __init__(
        self,
        percentObsDensity=20,
        endTime=40,
        nonRandomWorld=False,
        circleRadius=0.7,
        worldScale=1.0,
        autoInitialize=True,
        verbose=True,
    ):
        self.verbose = verbose
        self.startSimTime = time.time()
        self.collisionThreshold = 0.4
        self.randomSeed = 5
        self.Sensor_rayLength = 8

        self.percentObsDensity = percentObsDensity
        self.defaultControllerTime = 1000
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale

        # create the visualizer object
        self.app = ConsoleApp()
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()

        if autoInitialize:
            self.initialize()

        self.XVelocity_drawing = 0.0
        self.YVelocity_drawing = 0.0

    def initializeOptions(self):
        self.options = dict()

        self.options["World"] = dict()
        self.options["World"]["obstaclesInnerFraction"] = 0.98
        self.options["World"]["randomSeed"] = 40
        self.options["World"]["percentObsDensity"] = 0.0
        self.options["World"]["nonRandomWorld"] = True
        self.options["World"]["circleRadius"] = 1.0
        self.options["World"]["scale"] = 1

        self.options["Sensor"] = dict()
        self.options["Sensor"]["rayLength"] = 10
        self.options["Sensor"]["numRays"] = 50

        self.options["Car"] = dict()
        self.options["Car"]["velocity"] = 4.0

        self.options["dt"] = 0.05

        self.options["runTime"] = dict()
        self.options["runTime"]["defaultControllerTime"] = 100

    def setDefaultOptions(self):

        defaultOptions = dict()

        defaultOptions["World"] = dict()
        defaultOptions["World"]["obstaclesInnerFraction"] = 0.98
        defaultOptions["World"]["randomSeed"] = 40
        defaultOptions["World"]["percentObsDensity"] = 30
        defaultOptions["World"]["nonRandomWorld"] = True
        defaultOptions["World"]["circleRadius"] = 1.75
        defaultOptions["World"]["scale"] = 2.5

        defaultOptions["Sensor"] = dict()
        defaultOptions["Sensor"]["rayLength"] = 10
        defaultOptions["Sensor"]["numRays"] = 51

        defaultOptions["Car"] = dict()
        defaultOptions["Car"]["velocity"] = 20

        defaultOptions["dt"] = 0.05

        defaultOptions["runTime"] = dict()
        defaultOptions["runTime"]["defaultControllerTime"] = 100

        for k in defaultOptions:
            self.options.setdefault(k, defaultOptions[k])

        for k in defaultOptions:
            if not isinstance(defaultOptions[k], dict):
                continue

            for j in defaultOptions[k]:
                self.options[k].setdefault(j, defaultOptions[k][j])

    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap["default"] = [0, 1, 0]

    def initialize(self):

        self.dt = self.options["dt"]
        self.controllerTypeOrder = ["default"]

        self.setDefaultOptions()

        self.Sensor = SensorObj(
            rayLength=self.options["Sensor"]["rayLength"], numRays=self.options["Sensor"]["numRays"]
        )

        self.SensorApproximator = SensorApproximatorObj(
            numRays=self.options["Sensor"]["numRays"], circleRadius=self.options["World"]["circleRadius"]
        )

        self.Controller = ControllerObj(self.Sensor, self.SensorApproximator)

        self.Car = CarPlant(controller=self.Controller, velocity=self.options["Car"]["velocity"])

        self.Controller.initializeVelocity(self.Car.v)

        self.ActionSet = ActionSetObj()

        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName("world"))
        self.world = World.buildLineSegmentTestWorld(
            percentObsDensity=self.options["World"]["percentObsDensity"],
            circleRadius=self.options["World"]["circleRadius"],
            nonRandom=self.options["World"]["nonRandomWorld"],
            scale=self.options["World"]["scale"],
            randomSeed=self.options["World"]["randomSeed"],
            obstaclesInnerFraction=self.options["World"]["obstaclesInnerFraction"],
        )

        om.removeFromObjectModel(om.findObjectByName("robot"))
        self.robot, self.frame = World.buildRobot()

        self.frame = self.robot.getChildFrame()
        self.frame.setProperty("Scale", 3)
        # self.frame.setProperty('Visible', False)
        # self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.defaultControllerTime = self.options["runTime"]["defaultControllerTime"]

        self.Car.setFrame(self.frame)
        print "Finished initialization"

    def runSingleSimulation(self, controllerType="default", simulationCutoff=None):

        # self.setRandomCollisionFreeInitialState()
        self.setInitialStateAtZero()

        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1], currentCarState[2])

        firstRaycast = self.Sensor.raycastAll(self.frame)
        firstRaycastLocations = self.Sensor.raycastAllLocations(self.frame)

        # self.LineSegmentWorld = World.buildLineSegmentWorld(firstRaycastLocations)
        # self.LineSegmentLocator = World.buildCellLocator(self.LineSegmentWorld.visObj.polyData)
        # self.Sensor.setLocator(self.LineSegmentLocator)

        nextRaycast = np.zeros(self.Sensor.numRays)

        # record the reward data
        runData = dict()
        startIdx = self.counter

        thisRunIndex = 0
        NMaxSteps = 100

        while self.counter < self.numTimesteps - 1:
            thisRunIndex += 1
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx, :] = currentCarState
            x = self.stateOverTime[idx, 0]
            y = self.stateOverTime[idx, 1]

            self.setRobotFrameState(x, y, 0.0)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])
            currentRaycast = self.Sensor.raycastAll(self.frame)
            self.raycastData[idx, :] = currentRaycast
            S_current = (currentCarState, currentRaycast)

            if controllerType not in self.colorMap.keys():
                print
                raise ValueError("controller of type " + controllerType + " not supported")

            if controllerType in ["default", "defaultRandom"]:
                controlInput, controlInputIdx = self.Controller.computeControlInput(
                    currentCarState, currentTime, self.frame, raycastDistance=currentRaycast, randomize=False
                )

            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput, dt=self.dt)
            print "NEXTCARSTATE is ", nextCarState

            x = nextCarState[0]
            y = nextCarState[1]

            self.setRobotFrameState(x, y, 0.0)
            nextRaycast = self.Sensor.raycastAll(self.frame)

            # Compute the next control input
            S_next = (nextCarState, nextRaycast)

            if controllerType in ["default", "defaultRandom"]:
                nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(
                    nextCarState, currentTime, self.frame, raycastDistance=firstRaycast, randomize=False
                )

            # bookkeeping
            currentCarState = nextCarState
            currentRaycast = nextRaycast
            self.counter += 1

            # break if we are in collision
            if self.checkInCollision(nextRaycast):
                if self.verbose:
                    print "Had a collision, terminating simulation"
                break

            if thisRunIndex > NMaxSteps:
                print "was safe during N steps"
                break

            if self.counter >= simulationCutoff:
                break

        # fill in the last state by hand
        self.stateOverTime[self.counter, :] = currentCarState
        self.raycastData[self.counter, :] = currentRaycast

        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        self.controllerTypeOrder = ["default"]
        self.counter = 0
        self.simulationData = []

        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0

        self.idxDict["default"] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime / dt, self.numTimesteps)

        while (self.counter - loopStartIdx < self.defaultControllerTime / dt) and self.counter < self.numTimesteps - 1:
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(controllerType="default", simulationCutoff=simCutoff)
            runData["startIdx"] = startIdx
            runData["controllerType"] = "default"
            runData["duration"] = self.counter - runData["startIdx"]
            runData["endIdx"] = self.counter
            runData["runNumber"] = numRunsCounter
            numRunsCounter += 1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0 : self.counter + 1, :]
        self.raycastData = self.raycastData[0 : self.counter + 1, :]
        self.controlInputData = self.controlInputData[0 : self.counter + 1]
        self.endTime = 1.0 * self.counter / self.numTimesteps * self.endTime

    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"

    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime
            estimatedTimeLeft_sec = (1 - fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (
                self.numTicks - self.nextTickIdx
            ), "estimated", estimatedTimeLeft_minutes, "minutes left"

    def setCollisionFreeInitialState(self):
        tol = 5

        while True:

            x = 0.0
            y = -5.0
            theta = 0  # + np.random.uniform(0,2*np.pi,1)[0] * 0.01

            self.Car.setCarState(x, y, 0.0, 0.0)
            self.setRobotFrameState(x, y, theta)

            print "In loop"

            if not self.checkInCollision():
                break

        return x, y, theta

    def setInitialStateAtZero(self):

        x = 0.0
        y = 0.0
        theta = 0.0

        self.Car.setCarState(x, y, 0.0, 0.0)
        self.setRobotFrameState(x, y, theta)

        return x, y, theta

    def setRandomCollisionFreeInitialState(self):
        tol = 5

        while True:

            x = np.random.uniform(self.world.Xmin + tol, self.world.Xmax - tol, 1)[0]
            y = np.random.uniform(self.world.Ymin + tol, self.world.Ymax - tol, 1)[0]
            theta = np.random.uniform(0, 2 * np.pi, 1)[0]

            self.Car.setCarState(x, y, theta)
            self.setRobotFrameState(x, y, theta)

            if not self.checkInCollision():
                break

        return x, y, theta

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0 / self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        self.max_velocity = 20.0

        sliderXVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderXVelocity.connect("valueChanged(int)", self.onXVelocityChanged)
        sliderXVelocity.setMaximum(self.max_velocity)
        sliderXVelocity.setMinimum(-self.max_velocity)

        l.addWidget(sliderXVelocity)

        sliderYVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderYVelocity.connect("valueChanged(int)", self.onYVelocityChanged)
        sliderYVelocity.setMaximum(self.max_velocity)
        sliderYVelocity.setMinimum(-self.max_velocity)
        l.addWidget(sliderYVelocity)

        firstRaycast = np.ones((self.Sensor.numRays, 1)) * 10.0 + np.random.randn(self.Sensor.numRays, 1) * 1.0
        self.drawFirstIntersections(self.frame, firstRaycast)

        randomGlobalGoalButton = QtGui.QPushButton("Initialize Random Global Goal")
        randomGlobalGoalButton.connect("clicked()", self.onRandomGlobalGoalButton)
        l.addWidget(randomGlobalGoalButton)

        randomObstaclesButton = QtGui.QPushButton("Initialize Random Obstacles")
        randomObstaclesButton.connect("clicked()", self.onRandomObstaclesButton)
        l.addWidget(randomObstaclesButton)

        buildWorldFromRandomObstaclesButton = QtGui.QPushButton("Generate Polygon World")
        buildWorldFromRandomObstaclesButton.connect("clicked()", self.onBuildWorldFromRandomObstacles)
        l.addWidget(buildWorldFromRandomObstaclesButton)

        findLocalGoalButton = QtGui.QPushButton("Find Local Goal (Heuristic)")
        findLocalGoalButton.connect("clicked()", self.onFindLocalGoalButton)
        l.addWidget(findLocalGoalButton)

        drawActionSetButton = QtGui.QPushButton("Draw Action Set")
        drawActionSetButton.connect("clicked()", self.onDrawActionSetButton)
        l.addWidget(drawActionSetButton)

        runSimButton = QtGui.QPushButton("Simulate")
        runSimButton.connect("clicked()", self.onRunSimButton)
        l.addWidget(runSimButton)

        playButton = QtGui.QPushButton("Play/Pause")
        playButton.connect("clicked()", self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect("valueChanged(int)", self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        # slider4 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider4.setMaximum(self.sliderMax)
        # l.addWidget(slider4)

        # slider5 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider5.setMaximum(self.sliderMax)
        # l.addWidget(slider5)

        # slider5 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider5.setMaximum(self.sliderMax)
        # l.addWidget(slider5)

        # slider6 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider6.setMaximum(self.sliderMax)
        # l.addWidget(slider6)

        # slider7 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider7.setMaximum(self.sliderMax)
        # l.addWidget(slider7)

        l.addWidget(playButton)
        l.addWidget(slider)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        self.view.orientationMarkerWidget().Off()
        l.addWidget(panel)
        w.showMaximized()

        self.frame.connectFrameModified(self.updateDrawIntersection)
        self.updateDrawIntersection(self.frame)

        applogic.resetCamera(viewDirection=[0.2, 0, -1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        cameracontrolpanel.CameraControlPanel(self.view).widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter / elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.onRandomObstaclesButton()
        self.app.start()

    def drawFirstIntersections(self, frame, firstRaycast):
        origin = np.array(frame.transform.GetPosition())
        d = DebugData()

        firstRaycastLocations = self.Sensor.invertRaycastsToLocations(self.frame, firstRaycast)

        for i in xrange(self.Sensor.numRays):
            endpoint = firstRaycastLocations[i, :]

            if firstRaycast[i] >= self.Sensor.rayLength - 0.1:
                d.addLine(origin, endpoint, color=[0, 1, 0])
            else:
                d.addLine(origin, endpoint, color=[1, 0, 0])

        vis.updatePolyData(d.getPolyData(), "rays", colorByName="RGB255")

        self.LineSegmentWorld = World.buildLineSegmentWorld(firstRaycastLocations)
        self.LineSegmentLocator = World.buildCellLocator(self.LineSegmentWorld.visObj.polyData)
        self.locator = self.LineSegmentLocator
        self.Sensor.setLocator(self.LineSegmentLocator)

    def updateDrawIntersection(self, frame, locator="None"):
        if locator == "None":
            locator = self.locator

        origin = np.array(frame.transform.GetPosition())
        # print "origin is now at", origin
        d = DebugData()

        sliderIdx = self.slider.value

        controllerType = self.getControllerTypeFromCounter(sliderIdx)
        colorMaxRange = self.colorMap[controllerType]

        for i in xrange(self.Sensor.numRays):
            ray = self.Sensor.rays[:, i]
            rayTransformed = np.array(frame.transform.TransformNormal(ray))
            # print "rayTransformed is", rayTransformed
            intersection = self.Sensor.raycast(locator, origin, origin + rayTransformed * self.Sensor.rayLength)

            if intersection is not None:
                d.addLine(origin, intersection, color=[1, 0, 0])
            else:
                d.addLine(origin, origin + rayTransformed * self.Sensor.rayLength, color=colorMaxRange)

        vis.updatePolyData(d.getPolyData(), "rays", colorByName="RGB255")

        # camera = self.view.camera()
        # camera.SetFocalPoint(frame.transform.GetPosition())
        # camera.SetPosition(frame.transform.TransformPoint((-30,0,10)))

    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name

    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x, y, 0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self, raycastDistance=None):
        if raycastDistance is None:
            self.setRobotFrameState(self.Car.state[0], self.Car.state[1], self.Car.state[2])
            raycastDistance = self.Sensor.raycastAll(self.frame)

        if np.min(raycastDistance) < self.collisionThreshold:
            return True
        else:
            return False

        # if raycastDistance[(len(raycastDistance)+1)/2] < self.collisionThreshold:
        #     return True
        # else:
        #     return False

    def tick(self):
        # print timer.elapsed
        # simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x, y, 0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x, y, 0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps * (1.0 * value / self.sliderMax)))
        idx = min(idx, numSteps - 1)
        x, y, xdot, ydot = self.stateOverTime[idx]
        self.setRobotFrameState(x, y, 0)
        self.sliderMovedByPlayTimer = False

    def onXVelocityChanged(self, value):

        self.XVelocity_drawing = value
        self.onDrawActionSetButton()
        print "x velocity changed to ", value

    def onYVelocityChanged(self, value):
        print value

        self.YVelocity_drawing = -value
        self.onDrawActionSetButton()
        print "y velocity changed to ", -value

    def onShowSensorsButton(self):
        print "I pressed the show sensors button"
        self.setInitialStateAtZero()
        firstRaycast = np.ones((self.Sensor.numRays, 1)) * 10.0 + np.random.randn(self.Sensor.numRays, 1) * 1.0
        self.drawFirstIntersections(self.frame, firstRaycast)

    def onRandomObstaclesButton(self):
        print "random obstacles button pressed"
        self.setInitialStateAtZero()
        self.world = World.buildLineSegmentTestWorld(
            percentObsDensity=8.0,
            circleRadius=self.options["World"]["circleRadius"],
            nonRandom=False,
            scale=self.options["World"]["scale"],
            randomSeed=self.options["World"]["randomSeed"],
            obstaclesInnerFraction=self.options["World"]["obstaclesInnerFraction"],
        )

        self.locator = World.buildCellLocator(self.world.visObj.polyData)
        self.Sensor.setLocator(self.locator)
        self.updateDrawIntersection(self.frame, locator=self.locator)

    def onRandomGlobalGoalButton(self):
        print "random global goal button pressed"
        self.globalGoal = World.buildGlobalGoal()

    def onBuildWorldFromRandomObstacles(self):
        distances = self.Sensor.raycastAll(self.frame)
        firstRaycastLocations = self.Sensor.invertRaycastsToLocations(self.frame, distances)

        self.polygon_initial_distances = distances
        self.polygon_initial_raycastLocations = firstRaycastLocations

        self.LineSegmentWorld = World.buildLineSegmentWorld(firstRaycastLocations)
        self.LineSegmentLocator = World.buildCellLocator(self.LineSegmentWorld.visObj.polyData)
        self.locator = self.LineSegmentLocator
        self.Sensor.setLocator(self.LineSegmentLocator)
        self.updateDrawIntersection(self.frame)

    def onFindLocalGoalButton(self):
        print "find local goal button pressed"

        local_goal = self.findLocalGoal()
        print local_goal, "is my local goal"

        self.localGoal = World.placeLocalGoal(local_goal)

    def findLocalGoal(self):
        biggest_gap_width = 0
        biggest_gap_start_index = 0

        current_gap_width = 0
        current_gap_start_index = 0

        for index, value in enumerate(self.polygon_initial_distances):

            # if still in a gap
            if value == self.Sensor.rayLength:
                current_gap_width += 1

            # else terminate counting for this gap
            else:
                if current_gap_width > biggest_gap_width:
                    biggest_gap_width = current_gap_width
                    biggest_gap_start_index = current_gap_start_index

                current_gap_width = 0
                current_gap_start_index = index + 1

        if current_gap_width > biggest_gap_width:
            biggest_gap_width = current_gap_width
            biggest_gap_start_index = current_gap_start_index

        middle_index_of_gap = biggest_gap_start_index + biggest_gap_width / 2

        return self.polygon_initial_raycastLocations[middle_index_of_gap, :]

    def onDrawActionSetButton(self):
        print "drawing action set"
        # self.ActionSet.computeFinalPositions(self.XVelocity_drawing,self.YVelocity_drawing)
        self.ActionSet.computeAllPositions(self.XVelocity_drawing, self.YVelocity_drawing)
        # self.ActionSet.drawActionSetFinal()
        self.ActionSet.drawActionSetFull()

    def onRunSimButton(self):
        self.runBatchSimulation()
        self.saveToFile("latest")

    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print "play"
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print "pause"
        self.playTimer.stop()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = "data/" + filename + ".out"
        my_shelf = shelve.open(filename, "n")

        my_shelf["options"] = self.options

        my_shelf["simulationData"] = self.simulationData
        my_shelf["stateOverTime"] = self.stateOverTime
        my_shelf["raycastData"] = self.raycastData
        my_shelf["controlInputData"] = self.controlInputData
        my_shelf["numTimesteps"] = self.numTimesteps
        my_shelf["idxDict"] = self.idxDict
        my_shelf["counter"] = self.counter
        my_shelf.close()

    def run(self, launchApp=True):
        self.counter = 1

        # for use in playback
        self.dt = self.options["dt"]
        self.endTime = self.defaultControllerTime  # used to be the sum of the other times as well

        self.t = np.arange(0.0, self.endTime, self.dt)
        maxNumTimesteps = np.size(self.t)

        self.stateOverTime = np.zeros((maxNumTimesteps + 1, 4))
        self.raycastData = np.zeros((maxNumTimesteps + 1, self.Sensor.numRays))
        self.controlInputData = np.zeros((maxNumTimesteps + 1, 2))
        self.numTimesteps = maxNumTimesteps

        # self.runBatchSimulation()

        if launchApp:
            self.setupPlayback()

    @staticmethod
    def loadFromFile(filename):
        filename = "data/" + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf["options"]
        sim.initialize()

        sim.simulationData = my_shelf["simulationData"]
        sim.stateOverTime = np.array(my_shelf["stateOverTime"])
        sim.raycastData = np.array(my_shelf["raycastData"])
        sim.controlInputData = np.array(my_shelf["controlInputData"])
        sim.numTimesteps = my_shelf["numTimesteps"]
        sim.idxDict = my_shelf["idxDict"]
        sim.counter = my_shelf["counter"]

        my_shelf.close()

        return sim
예제 #28
0
class Simulator(object):


    def __init__(self, percentObsDensity=20, endTime=40, nonRandomWorld=False,
                 circleRadius=0.7, worldScale=1.0, autoInitialize=True, verbose=True):
        self.verbose = verbose
        self.startSimTime = time.time()
        self.collisionThreshold = 1.0
        self.randomSeed = 5
        self.Sensor_rayLength = 8

        self.percentObsDensity = percentObsDensity
        self.defaultControllerTime = 1000
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale

        # create the visualizer object
        self.app = ConsoleApp()
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()

        self.initial_XVelocity = 0.0
        self.initial_YVelocity = 0.0

        self.running_sim = True

        self.currentIdx = 0;
        
        if autoInitialize:
            self.initialize()

    def initializeOptions(self):
        self.options = dict()

        self.options['World'] = dict()
        self.options['World']['obstaclesInnerFraction'] = 0.98
        self.options['World']['randomSeed'] = 40
        self.options['World']['percentObsDensity'] = 25.0
        self.options['World']['nonRandomWorld'] = True
        self.options['World']['circleRadius'] = 0.6
        self.circleRadius = self.options['World']['circleRadius']
        self.options['World']['scale'] = 2.0

        self.options['Sensor'] = dict()
        self.options['Sensor']['rayLength'] = 10
        self.options['Sensor']['numRays'] = 40


        self.options['Car'] = dict()
        self.options['Car']['velocity'] = 20

        self.options['dt'] = 0.05

        self.options['runTime'] = dict()
        self.options['runTime']['defaultControllerTime'] = 100


    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap['default'] = [0,1,0]

    def initialize(self):

        self.dt = self.options['dt']
        self.controllerTypeOrder = ['default']

        self.Controller = ControllerObj()

        self.Sensor = SensorObj(rayLength=self.options['Sensor']['rayLength'],
                                numRays=self.options['Sensor']['numRays'])

        self.Car = CarPlant(controller=self.Controller,
                            velocity=self.options['Car']['velocity'])

        self.Controller.initializeVelocity(self.Car.v)

        self.ActionSet = ActionSetObj()

        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName('world'))
        self.world = World.buildCircleWorld(percentObsDensity=self.options['World']['percentObsDensity'],
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=self.options['World']['nonRandomWorld'],
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'])

        om.removeFromObjectModel(om.findObjectByName('robot'))
        self.robot, self.frame = World.buildRobot()
        self.locator = World.buildCellLocator(self.world.visObj.polyData)
        
        #will need to set locator for purple trajectories
        #self.Sensor.setLocator(self.locator)
        self.frame = self.robot.getChildFrame()
        self.frame.setProperty('Scale', 3)
        #self.frame.setProperty('Visible', False)
        #self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.defaultControllerTime = self.options['runTime']['defaultControllerTime']

        self.Car.setFrame(self.frame)
        print "Finished initialization"


    def terminalEuclideanCostForTrajectories(self):
        # access the trajectories
        x_traj = self.ActionSet.p_x_trajectories
        y_traj = self.ActionSet.p_y_trajectories


        final_x_positions = x_traj[:,-1]
        final_y_positions = y_traj[:,-1]

        #access the global goal
        global_goal_x = self.globalGoal.global_goal_x
        global_goal_y = self.globalGoal.global_goal_y

        euclideans_vector = []

        # def getKey(item):
        #     return item[1]

        for i in xrange(self.ActionSet.num_x_bins):
            for j in xrange(self.ActionSet.num_y_bins):
                distance = np.sqrt((final_x_positions[i] - global_goal_x)**2 + (final_y_positions[j] - global_goal_y)**2)
                euclideans_vector.append(distance)


        #sorted_ranks_with_indices = sorted(ranks_with_indices,key=getKey)

        return np.array(euclideans_vector)

    def CheckIfCollisionFreeTrajectoryIndex(self, traj_index):
        # accessing the right trajectory
        x_trajectory_to_check = self.ActionSet.p_x_trajectories[traj_index[0]]
        y_trajectory_to_check = self.ActionSet.p_y_trajectories[traj_index[1]]


        #check if anything is too close to the center of the circles
        #print self.world.list_of_circles
        for i in range(len(x_trajectory_to_check)):
            point = ( x_trajectory_to_check[i], y_trajectory_to_check[i]  )
            if not self.CheckIfCollisionFreePoint(point):
                #print "trajectory wasn't free"
                return False 


        return True

    def CheckIfCollisionFreePoint(self, point):

        for circle_center in self.world.list_of_circles:
            #print "circle centers first"
            #print circle_center[0], circle_center[1]
            #print self.circleRadius
            #print point[0], point[1]
            #print (circle_center[0] - point[0])**2 + (circle_center[1]-point[1])**2
            if  ( (circle_center[0] - point[0])**2 + (circle_center[1]-point[1])**2 < self.circleRadius**2):
                #print "I found a point in a circle"
                return False

        if point[0] > self.world.Xmax:
            #print "I would have gone past top wall"
            return False
        if point[0] < self.world.Xmin:
            #print "I would have gone below bottom wall"
            return False
        if point[1] > self.world.Ymax:
            #print "I would have gone to the right of the side wall"
            return False    
        if point[1] < self.world.Ymin:
            #print "I would have gone to the left of the side wall"
            return False

        return True

    def computeProbabilitiesOfCollisionAllTrajectories(self, currentRaycastIntersectionLocations, speed_allowed_matrix):
        probability_vector = []
        indices_vector = []
        for x_index in xrange(self.ActionSet.num_x_bins):
            for y_index in xrange(self.ActionSet.num_y_bins):
                if not speed_allowed_matrix[x_index, y_index]:
                    probability_vector.append(1.0)

                else:
                    probability_of_collision = self.computeProbabilityOfCollisionOneTrajectory(x_index, y_index, currentRaycastIntersectionLocations)
                    probability_vector.append(probability_of_collision)

                indices_vector.append([x_index, y_index])

        return np.array(probability_vector), indices_vector
        

    def computeProbabilityOfCollisionOneTrajectory(self, x_index, y_index, currentRaycastIntersectionLocations):
        probability_no_collision = 1
        for time_step_index, time_step_value in enumerate(self.ActionSet.t_vector):
            for obstacle_center in currentRaycastIntersectionLocations:

                probability_of_collision_step_k_obstacle_j = self.computeProbabilityOfCollisionOneStepOneObstacle(x_index, y_index, time_step_index, time_step_value, obstacle_center)

                probability_no_collision_step_k_obstacle_j = 1 - probability_of_collision_step_k_obstacle_j

                probability_no_collision = probability_no_collision * probability_no_collision_step_k_obstacle_j

        return float(1.0 - probability_no_collision)

    def computeProbabilityOfCollisionOneStepOneObstacle(self, x_index, y_index, time_step_index, time_step_value, obstacle_center):
        volume = 4.18
        Sigma_sensor = np.zeros((3,3))
        np.fill_diagonal(Sigma_sensor, self.sigma_sensor)

        variance_x = (2.5 + abs(self.current_initial_velocity_x*0.1))*time_step_value+0.01
        variance_y = (2.5 + abs(self.current_initial_velocity_y*0.1))*time_step_value+0.01
        variance_z = (1.5)*time_step_value+0.01

        Sigma_robot = np.zeros((3,3))
        np.fill_diagonal(Sigma_sensor, [variance_x, variance_y, variance_z])


        Sigma_C = Sigma_robot + Sigma_sensor

        denominator = np.sqrt(np.linalg.det(2*np.pi*Sigma_C))

        x = self.ActionSet.p_x_trajectories[x_index, time_step_index]
        y = self.ActionSet.p_y_trajectories[y_index, time_step_index]
        z = 0

        x_robot = np.array([x, y, z])
        obstacle_center = np.array(obstacle_center)

        exponent = - 0.5 * np.matrix((x_robot - obstacle_center)) * np.matrix(np.linalg.inv(Sigma_C)) * np.matrix((x_robot - obstacle_center)).T

        return volume / denominator * np.exp(exponent)

    def computeJerkVector(self,controlInput):
        jerk_vector = []
        for x_index in xrange(self.ActionSet.num_x_bins):
            for y_index in xrange(self.ActionSet.num_y_bins):
                last_x_accel = controlInput[0]
                last_y_accel = controlInput[1]

                this_x_accel = self.ActionSet.a_x[x_index]
                this_y_accel = self.ActionSet.a_y[y_index]

                jerk = np.sqrt( (last_x_accel - this_x_accel)**2 + (last_y_accel - this_y_accel)**2 )
                jerk_vector.append(jerk)

        return np.array(jerk_vector) 


    def identifySpeedAllowedTrajectories(self):
        speed_allowed_matrix = np.ones((self.ActionSet.num_x_bins, self.ActionSet.num_y_bins))

        # for x_index in xrange(self.ActionSet.num_x_bins):
        #     for y_index in xrange(self.ActionSet.num_y_bins):

        #         this_x_accel = self.ActionSet.a_x[x_index]
        #         this_y_accel = self.ActionSet.a_y[y_index]

        #         if np.sqrt( (self.current_initial_velocity_x - this_x_accel)**2 + (self.current_initial_velocity_y - this_y_accel)**2) < self.speed_max:
        #             speed_allowed_matrix[x_index,y_index] = 1

        return speed_allowed_matrix


    def runSingleSimulation(self, controllerType='default', simulationCutoff=None):


        self.Car.setCarState(0.0,0.0,self.initial_XVelocity,self.initial_YVelocity)
        self.setRobotFrameState(0.0,0.0,0.0)


        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1], currentCarState[2])

        self.Sensor.setLocator(self.locator)

        firstRaycast = self.Sensor.raycastAll(self.frame)
        firstRaycastLocations = self.Sensor.raycastAllLocations(self.frame)

        nextRaycast = np.zeros(self.Sensor.numRays)

        # record the reward data
        runData = dict()
        startIdx = self.counter

        controlInput = [0,0]


        while (self.counter < self.numTimesteps - 1):
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx,:] = currentCarState
            x = self.stateOverTime[idx,0]
            y = self.stateOverTime[idx,1]
            self.setRobotFrameState(x,y,0.0)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])

            currentRaycastIntersectionLocations = self.Sensor.raycastLocationsOnlyOfIntersections(self.frame)

            if self.checkInCollision(currentCarState[0], currentCarState[1], currentRaycastIntersectionLocations):
                break
            

            if controllerType not in self.colorMap.keys():
                print
                raise ValueError("controller of type " + controllerType + " not supported")

            # compute all trajectories from action set
            self.ActionSet.computeAllPositions(currentCarState[0], currentCarState[1], currentCarState[2],currentCarState[3])
            self.current_initial_velocity_x = currentCarState[2]
            self.current_initial_velocity_y = currentCarState[3]

            speed_allowed_matrix = self.identifySpeedAllowedTrajectories()

            probability_vector, indices_list = self.computeProbabilitiesOfCollisionAllTrajectories(currentRaycastIntersectionLocations, speed_allowed_matrix)

            euclideans_vector = self.terminalEuclideanCostForTrajectories()

            jerk_vector = self.computeJerkVector(controlInput)

            # k_collision_cost = 10
            # k_terminal_cost = 1
            # k_jerk = 0.1
            # sum_vector = probability_vector*k_collision_cost + euclideans_vector/np.max(euclideans_vector)*k_terminal_cost + k_jerk*jerk_vector/np.max(jerk_vector)
            # min_action_index_in_vector = np.argmin(sum_vector)
            # x_index_to_use = indices_list[min_action_index_in_vector][0]
            # y_index_to_use = indices_list[min_action_index_in_vector][1]

            

            # convert to probability no collision
            probability_vector = np.ones(len(probability_vector)) - probability_vector
            
            # convert distances to amount of progress
            current_distance = np.sqrt((currentCarState[0] - self.globalGoal.global_goal_x)**2 + (currentCarState[1] - self.globalGoal.global_goal_y)**2)
            #print "euclideans vector", euclideans_vector

            euclidean_progress_vector = np.ones(len(euclideans_vector))*current_distance - euclideans_vector
            #print "euclidean progress vector", euclidean_progress_vector
            reward_vector = euclidean_progress_vector - 0.1*jerk_vector/np.max(jerk_vector)
            #print "reward_vector", reward_vector
            
            expected_reward = np.multiply(probability_vector, reward_vector)
            max_action_index_in_vector = np.argmax(expected_reward)
            x_index_to_use = indices_list[max_action_index_in_vector][0]
            y_index_to_use = indices_list[max_action_index_in_vector][1]

        
            self.actionIndicesOverTime[idx,:] = [x_index_to_use, y_index_to_use] 

            x_accel = self.ActionSet.a_x[x_index_to_use]
            y_accel = self.ActionSet.a_y[y_index_to_use]

            controlInput = [x_accel, y_accel]

            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput, dt=self.dt)

        
            x = nextCarState[0]
            y = nextCarState[1]
            theta = nextCarState[2]
            self.setRobotFrameState(x,y,theta)
            

            #bookkeeping
            currentCarState = nextCarState
            
            self.counter+=1

            # break if we are in collision

            if self.counter >= simulationCutoff:
                break


        # fill in the last state by hand
        self.stateOverTime[self.counter,:] = currentCarState
        self.actionIndicesOverTime[self.counter,:] = [x_index_to_use, y_index_to_use]


        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        # for use in playback
        self.dt = self.options['dt']

        self.endTime = self.defaultControllerTime # used to be the sum of the other times as well

        self.t = np.arange(0.0, self.endTime, dt)
        maxNumTimesteps = np.size(self.t)
        self.stateOverTime = np.zeros((maxNumTimesteps+1, 4))
        self.actionIndicesOverTime = np.zeros((maxNumTimesteps+1, 2))
        self.controlInputData = np.zeros((maxNumTimesteps+1,2))
        self.numTimesteps = maxNumTimesteps

        self.controllerTypeOrder = ['default']
        self.counter = 0
        self.simulationData = []
    
        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0


        self.idxDict['default'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime/dt, self.numTimesteps)
        
        while ((self.counter - loopStartIdx < self.defaultControllerTime/dt) and self.counter < self.numTimesteps-1):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(controllerType='default',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "default"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter+=1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0:self.counter+1, :]
        self.actionIndicesOverTime = self.actionIndicesOverTime[0:self.counter+1, :]
        self.controlInputData = self.controlInputData[0:self.counter+1]
        self.endTime = 1.0*self.counter/self.numTimesteps*self.endTime

    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"
    
    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime 
            estimatedTimeLeft_sec = (1 - fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (self.numTicks - self.nextTickIdx), "estimated", estimatedTimeLeft_minutes, "minutes left"


    def setCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = 0.0
            y =   -5.0
            theta = 0 #+ np.random.uniform(0,2*np.pi,1)[0] * 0.01
            
            self.Car.setCarState(x,y,theta)
            self.setRobotFrameState(x,y,theta)

            print "In loop"

            if not self.checkInCollision():
                break
                
        return x,y,theta


    def setRandomCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = np.random.uniform(self.world.Xmin+tol, self.world.Xmax-tol, 1)[0]
            y = np.random.uniform(self.world.Ymin+tol, self.world.Ymax-tol, 1)[0]
            #theta = np.random.uniform(0,2*np.pi,1)[0]
            theta = 0 #always forward

            self.Car.setCarState(x,y,self.initial_XVelocity,self.initial_YVelocity)
            self.setRobotFrameState(x,y,theta)

            if not self.checkInCollision():
                break

        self.firstRandomCollisionFreeInitialState_x = x
        self.firstRandomCollisionFreeInitialState_y = y

        return x,y,0,0

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0/self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        self.max_velocity = 20.0

        sliderXVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderXVelocity.connect('valueChanged(int)', self.onXVelocityChanged)
        sliderXVelocity.setMaximum(self.max_velocity)
        sliderXVelocity.setMinimum(-self.max_velocity)

        l.addWidget(sliderXVelocity)

        sliderYVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderYVelocity.connect('valueChanged(int)', self.onYVelocityChanged)
        sliderYVelocity.setMaximum(self.max_velocity)
        sliderYVelocity.setMinimum(-self.max_velocity)
        l.addWidget(sliderYVelocity)

        randomGlobalGoalButton = QtGui.QPushButton('Initialize Random Global Goal')
        randomGlobalGoalButton.connect('clicked()', self.onRandomGlobalGoalButton)
        l.addWidget(randomGlobalGoalButton)

        drawActionSetButton = QtGui.QPushButton('Draw Action Set')
        drawActionSetButton.connect('clicked()', self.onDrawActionSetButton)
        l.addWidget(drawActionSetButton)

        runSimButton = QtGui.QPushButton('Simulate')
        runSimButton.connect('clicked()', self.onRunSimButton)
        l.addWidget(runSimButton)

        playButton = QtGui.QPushButton('Play/Pause')
        playButton.connect('clicked()', self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect('valueChanged(int)', self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        l.addWidget(playButton)
        l.addWidget(slider)

        toggleSensorNoiseButton = QtGui.QPushButton('Toggle Sensor Noise')
        toggleSensorNoiseButton.connect('clicked()', self.onToggleSensorNoise)
        l.addWidget(toggleSensorNoiseButton)

        showObstaclesButton = QtGui.QPushButton('Show Obsatacles')
        showObstaclesButton.connect('clicked()', self.onShowObstacles)
        l.addWidget(showObstaclesButton)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        self.view.orientationMarkerWidget().Off()
        l.addWidget(panel)
        w.showMaximized()

        # need to connect frames with DrawActionSet
        self.frame.connectFrameModified(self.updateDrawActionSet)
        self.updateDrawActionSet(self.frame)
        self.frame.connectFrameModified(self.updateDrawIntersection)
        self.updateDrawIntersection(self.frame)
        
        applogic.resetCamera(viewDirection=[0.2,0,-1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        cameracontrolpanel.CameraControlPanel(self.view).widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter/elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.app.start()

    def run(self, launchApp=True):
        self.sphere_toggle = False
        self.sigma_sensor = 0.5
        self.speed_max = 10.0


        self.running_sim = True
        self.onRandomGlobalGoalButton()
        self.counter = 1
        self.runBatchSimulation()
        self.running_sim = False

        if launchApp:
            self.setupPlayback()

    def onToggleSensorNoise(self):
        self.sphere_toggle = not self.sphere_toggle

    def onShowObstacles(self):
        print "time to show obstacles"
        A = World.buildCircleWorld(percentObsDensity=self.options['World']['percentObsDensity'],
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=self.options['World']['nonRandomWorld'],
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'], alpha=1.0)


    def drawFirstIntersections(self, frame, firstRaycast):
        origin = np.array(frame.transform.GetPosition())
        d = DebugData()

        firstRaycastLocations = self.Sensor.invertRaycastsToLocations(self.frame, firstRaycast)

        for i in xrange(self.Sensor.numRays):
            endpoint = firstRaycastLocations[i,:]

            if firstRaycast[i] >= self.Sensor.rayLength - 0.1:
                d.addLine(origin, endpoint, color=[0,1,0])
            else:
                d.addLine(origin, endpoint, color=[1,0,0])

        vis.updatePolyData(d.getPolyData(), 'rays', colorByName='RGB255')

        self.LineSegmentWorld = World.buildLineSegmentWorld(firstRaycastLocations)
        self.LineSegmentLocator = World.buildCellLocator(self.LineSegmentWorld.visObj.polyData)
        self.locator = self.LineSegmentLocator
        self.Sensor.setLocator(self.LineSegmentLocator)


    def updateDrawIntersection(self, frame, locator="None"):
        if locator=="None":
            locator = self.locator

        if self.sphere_toggle:
            sphere_radius=self.sigma_sensor
        else:
            sphere_radius=0.0


        origin = np.array(frame.transform.GetPosition())
        #print "origin is now at", origin
        d = DebugData()
        d_sphere=DebugData()

        sliderIdx = self.slider.value

        controllerType = self.getControllerTypeFromCounter(sliderIdx)
        colorMaxRange = self.colorMap[controllerType]

        for i in xrange(self.Sensor.numRays):
            ray = self.Sensor.rays[:,i]
            rayTransformed = np.array(frame.transform.TransformNormal(ray))
            #print "rayTransformed is", rayTransformed
            intersection = self.Sensor.raycast(locator, origin, origin + rayTransformed*self.Sensor.rayLength)

            if intersection is not None:
                d.addLine(origin, intersection, color=[1,0,0])
                d_sphere.addSphere(intersection, radius=sphere_radius, color=[1,0,0])

            else:
                d.addLine(origin, origin+rayTransformed*self.Sensor.rayLength, color=colorMaxRange)
                d_sphere.addSphere(origin, radius=0.0, color=[0,1,0])

        vis.updatePolyData(d.getPolyData(), 'rays', colorByName='RGB255')
        vis.updatePolyData(d_sphere.getPolyData(), 'spheres', colorByName='RGB255', alpha=0.3)



    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name


    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x,y,0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self, x, y, raycastLocations):
        return False

        # carState = [x,y,0]
        # for raycastLocation in raycastLocations:
        #     if np.linalg.norm(carState - raycastLocation) < 0.3:
        #         return True

        # return False

    def updateDrawActionSet(self, frame):

        origin = np.array(frame.transform.GetPosition())

        if not self.running_sim:
            self.ActionSet.computeAllPositions(self.stateOverTime[self.currentIdx,0], self.stateOverTime[self.currentIdx,1], self.stateOverTime[self.currentIdx,2],self.stateOverTime[self.currentIdx,3])
            #self.ActionSet.drawActionSetFinal()
            self.ActionSet.drawActionSetFull()
            self.drawChosenFunnel()

    def drawChosenFunnel(self):
        velocity_initial_x = self.stateOverTime[self.currentIdx,2]
        velocity_initial_y = self.stateOverTime[self.currentIdx,3]

        variance_x = 2.5 + abs(velocity_initial_x*0.1)
        variance_y = 2.5 + abs(velocity_initial_y*0.1)
        variance_z = 1.5

        x_index = self.actionIndicesOverTime[self.currentIdx,0]
        y_index = self.actionIndicesOverTime[self.currentIdx,1]

        for i in xrange(0,10):
            time = 0.5/10.0*i
            x_center = self.ActionSet.p_x_trajectories[x_index, i]
            y_center = self.ActionSet.p_y_trajectories[y_index, i]
            z_center = 0.0
            World.buildEllipse(i, [x_center,y_center,z_center], variance_x*time, variance_y*time, variance_z*time, alpha=0.3)


    def tick(self):
        #print timer.elapsed
        #simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x,y,0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x,y,0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onXVelocityChanged(self, value):
        self.initial_XVelocity = value
        print "initial x velocity changed to ", value

    def onYVelocityChanged(self, value):
        self.initial_YVelocity = -value
        print "initial y velocity changed to ", -value

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps*(1.0*value/self.sliderMax)))
        idx = min(idx, numSteps-1)
        self.currentIdx = idx
        x,y, xdot, ydot = self.stateOverTime[idx]
        self.setRobotFrameState(x,y,0)
        self.sliderMovedByPlayTimer = False

    def onRandomGlobalGoalButton(self):
        print "random global goal button pressed"
        self.globalGoal = World.buildGlobalGoal(scale=self.options['World']['scale'])

    def onDrawActionSetButton(self):
        print "drawing action set"
        #self.ActionSet.computeFinalPositions(self.XVelocity_drawing,self.YVelocity_drawing)
        self.ActionSet.computeAllPositions(self.Car.state[0], self.Car.state[1], self.initial_XVelocity, self.initial_YVelocity)
        #self.ActionSet.drawActionSetFinal()
        self.ActionSet.drawActionSetFull()

    def onRunSimButton(self):
        self.running_sim = True
        self.runBatchSimulation()
        self.running_sim = False
        #self.saveToFile("latest")

    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print 'play'
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print 'pause'
        self.playTimer.stop()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = 'data/' + filename + ".out"
        my_shelf = shelve.open(filename,'n')

        my_shelf['options'] = self.options

        my_shelf['simulationData'] = self.simulationData
        my_shelf['stateOverTime'] = self.stateOverTime
        my_shelf['controlInputData'] = self.controlInputData
        my_shelf['numTimesteps'] = self.numTimesteps
        my_shelf['idxDict'] = self.idxDict
        my_shelf['counter'] = self.counter
        my_shelf.close()


    @staticmethod
    def loadFromFile(filename):
        filename = 'data/' + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf['options']
        sim.initialize()

        sim.simulationData = my_shelf['simulationData']
        sim.stateOverTime = np.array(my_shelf['stateOverTime'])
        sim.controlInputData = np.array(my_shelf['controlInputData'])
        sim.numTimesteps = my_shelf['numTimesteps']
        sim.idxDict = my_shelf['idxDict']
        sim.counter = my_shelf['counter']

        my_shelf.close()

        return sim
예제 #29
0
class Simulator(object):


    def __init__(self, percentObsDensity=20, endTime=40, nonRandomWorld=False,
                 circleRadius=0.7, worldScale=1.0, autoInitialize=True, verbose=True):
        self.verbose = verbose
        self.startSimTime = time.time()
        self.collisionThreshold = 0.4
        self.randomSeed = 5

        self.percentObsDensity = percentObsDensity
        self.defaultControllerTime = 1000
        self.nonRandomWorld = nonRandomWorld
        self.circleRadius = circleRadius
        self.worldScale = worldScale

        # create the visualizer object
        self.app = ConsoleApp()
        self.view = self.app.createView(useGrid=False)

        self.initializeOptions()
        self.initializeColorMap()
        
        if autoInitialize:
            self.initialize()

        self.XVelocity_drawing = 0.0
        self.YVelocity_drawing = 0.0

    def initializeOptions(self):
        self.options = dict()

        self.options['World'] = dict()
        self.options['World']['obstaclesInnerFraction'] = 0.98
        self.options['World']['randomSeed'] = 40
        self.options['World']['percentObsDensity'] = 0.0
        self.options['World']['nonRandomWorld'] = True
        self.options['World']['circleRadius'] = 1.0
        self.options['World']['scale'] = 1


        self.options['Car'] = dict()
        self.options['Car']['velocity'] = 4.0

        self.options['dt'] = 0.05

        self.options['runTime'] = dict()
        self.options['runTime']['defaultControllerTime'] = 100


    def setDefaultOptions(self):

        defaultOptions = dict()


        defaultOptions['World'] = dict()
        defaultOptions['World']['obstaclesInnerFraction'] = 0.98
        defaultOptions['World']['randomSeed'] = 40
        defaultOptions['World']['percentObsDensity'] = 30
        defaultOptions['World']['nonRandomWorld'] = True
        defaultOptions['World']['circleRadius'] = 1.75
        defaultOptions['World']['scale'] = 2.5


        defaultOptions['Car'] = dict()
        defaultOptions['Car']['velocity'] = 20

        defaultOptions['dt'] = 0.05


        defaultOptions['runTime'] = dict()
        defaultOptions['runTime']['defaultControllerTime'] = 100


        for k in defaultOptions:
            self.options.setdefault(k, defaultOptions[k])


        for k in defaultOptions:
            if not isinstance(defaultOptions[k], dict):
                continue

            for j in defaultOptions[k]:
                self.options[k].setdefault(j, defaultOptions[k][j])


    def initializeColorMap(self):
        self.colorMap = dict()
        self.colorMap['default'] = [0,1,0]

    def initialize(self):

        self.dt = self.options['dt']
        self.controllerTypeOrder = ['default']

        self.setDefaultOptions()


        self.Controller = ControllerObj()

        self.Car = CarPlant(controller=self.Controller,
                            velocity=self.options['Car']['velocity'])

        self.Controller.initializeVelocity(self.Car.v)

        self.ActionSet = ActionSetObj()



        # create the things needed for simulation
        om.removeFromObjectModel(om.findObjectByName('world'))
        self.world = World.buildLineSegmentTestWorld(percentObsDensity=self.options['World']['percentObsDensity'],
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=self.options['World']['nonRandomWorld'],
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'])

        om.removeFromObjectModel(om.findObjectByName('robot'))
        self.robot, self.frame = World.buildRobot()
        

        self.frame = self.robot.getChildFrame()
        self.frame.setProperty('Scale', 3)
        #self.frame.setProperty('Visible', False)
        #self.frame.setProperty('Edit', True)
        self.frame.widget.HandleRotationEnabledOff()
        rep = self.frame.widget.GetRepresentation()
        rep.SetTranslateAxisEnabled(2, False)
        rep.SetRotateAxisEnabled(0, False)
        rep.SetRotateAxisEnabled(1, False)

        self.defaultControllerTime = self.options['runTime']['defaultControllerTime']

        self.Car.setFrame(self.frame)
        print "Finished initialization"


    def runSingleSimulation(self, controllerType='default', simulationCutoff=None):


        #self.setRandomCollisionFreeInitialState()
        self.setInitialStateAtZero()

        currentCarState = np.copy(self.Car.state)
        nextCarState = np.copy(self.Car.state)
        self.setRobotFrameState(currentCarState[0], currentCarState[1], currentCarState[2])
        
        # DELETED FIRST RAYCAST AND RAYCAST LOCATIONS



        # record the reward data
        runData = dict()
        startIdx = self.counter

        thisRunIndex = 0
        NMaxSteps = 100

        while (self.counter < self.numTimesteps - 1):
            thisRunIndex += 1
            idx = self.counter
            currentTime = self.t[idx]
            self.stateOverTime[idx,:] = currentCarState
            x = self.stateOverTime[idx,0]
            y = self.stateOverTime[idx,1]
            
            self.setRobotFrameState(x,y,0.0)
            # self.setRobotState(currentCarState[0], currentCarState[1], currentCarState[2])



            if controllerType in ["default"]:
                controlInput, controlInputIdx = self.Controller.computeControlInput(currentCarState,
                                                                            currentTime, self.frame,
                                                                            randomize=False)

            self.controlInputData[idx] = controlInput

            nextCarState = self.Car.simulateOneStep(controlInput=controlInput, dt=self.dt)
            print "NEXTCARSTATE is ", nextCarState

        
            x = nextCarState[0]
            y = nextCarState[1]
            
            self.setRobotFrameState(x,y,0.0)


            if controllerType in ["default", "defaultRandom"]:
                nextControlInput, nextControlInputIdx = self.Controller.computeControlInput(nextCarState,
                                                                            currentTime, self.frame,
                                                                            randomize=False)


            #bookkeeping
            self.counter+=1

            # break if we are in collision


            if self.counter >= simulationCutoff:
                break


        # fill in the last state by hand
        self.stateOverTime[self.counter,:] = currentCarState


        # this just makes sure we don't get stuck in an infinite loop.
        if startIdx == self.counter:
            self.counter += 1

        return runData

    def setNumpyRandomSeed(self, seed=1):
        np.random.seed(seed)

    def runBatchSimulation(self, endTime=None, dt=0.05):

        
        self.controllerTypeOrder = ['default']
        self.counter = 0
        self.simulationData = []
    
        self.initializeStatusBar()

        self.idxDict = dict()
        numRunsCounter = 0


        self.idxDict['default'] = self.counter
        loopStartIdx = self.counter
        simCutoff = min(loopStartIdx + self.defaultControllerTime/dt, self.numTimesteps)
        
        while ((self.counter - loopStartIdx < self.defaultControllerTime/dt) and self.counter < self.numTimesteps-1):
            self.printStatusBar()
            startIdx = self.counter
            runData = self.runSingleSimulation(controllerType='default',
                                               simulationCutoff=simCutoff)
            runData['startIdx'] = startIdx
            runData['controllerType'] = "default"
            runData['duration'] = self.counter - runData['startIdx']
            runData['endIdx'] = self.counter
            runData['runNumber'] = numRunsCounter
            numRunsCounter+=1
            self.simulationData.append(runData)

        # BOOKKEEPING
        # truncate stateOverTime, raycastData, controlInputs to be the correct size
        self.numTimesteps = self.counter + 1
        self.stateOverTime = self.stateOverTime[0:self.counter+1, :]
        self.controlInputData = self.controlInputData[0:self.counter+1]
        self.endTime = 1.0*self.counter/self.numTimesteps*self.endTime




    def initializeStatusBar(self):
        self.numTicks = 10
        self.nextTickComplete = 1.0 / float(self.numTicks)
        self.nextTickIdx = 1
        print "Simulation percentage complete: (", self.numTicks, " # is complete)"
    
    def printStatusBar(self):
        fractionDone = float(self.counter) / float(self.numTimesteps)
        if fractionDone > self.nextTickComplete:

            self.nextTickIdx += 1
            self.nextTickComplete += 1.0 / self.numTicks

            timeSoFar = time.time() - self.startSimTime 
            estimatedTimeLeft_sec = (1 - fractionDone) * timeSoFar / fractionDone
            estimatedTimeLeft_minutes = estimatedTimeLeft_sec / 60.0

            print "#" * self.nextTickIdx, "-" * (self.numTicks - self.nextTickIdx), "estimated", estimatedTimeLeft_minutes, "minutes left"


    def setCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = 0.0
            y =   -5.0
            theta = 0 #+ np.random.uniform(0,2*np.pi,1)[0] * 0.01
            
            self.Car.setCarState(x,y,0.0,0.0)
            self.setRobotFrameState(x,y,theta)

            print "In loop"

            if not self.checkInCollision():
                break
                
        return x,y,theta


    
    def setInitialStateAtZero(self):
        
        x = 0.0
        y = 0.0
        theta = 0.0
        
        self.Car.setCarState(x,y,0.0,0.0)
        self.setRobotFrameState(x,y,theta)

        return x,y,theta



    def setRandomCollisionFreeInitialState(self):
        tol = 5

        while True:
            
            x = np.random.uniform(self.world.Xmin+tol, self.world.Xmax-tol, 1)[0]
            y = np.random.uniform(self.world.Ymin+tol, self.world.Ymax-tol, 1)[0]
            theta = np.random.uniform(0,2*np.pi,1)[0]
            
            self.Car.setCarState(x,y,theta)
            self.setRobotFrameState(x,y,theta)

            if not self.checkInCollision():
                break

        return x,y,theta

    def setupPlayback(self):

        self.timer = TimerCallback(targetFps=30)
        self.timer.callback = self.tick

        playButtonFps = 1.0/self.dt
        print "playButtonFPS", playButtonFps
        self.playTimer = TimerCallback(targetFps=playButtonFps)
        self.playTimer.callback = self.playTimerCallback
        self.sliderMovedByPlayTimer = False

        panel = QtGui.QWidget()
        l = QtGui.QHBoxLayout(panel)

        self.max_velocity = 20.0

        sliderXVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderXVelocity.connect('valueChanged(int)', self.onXVelocityChanged)
        sliderXVelocity.setMaximum(self.max_velocity)
        sliderXVelocity.setMinimum(-self.max_velocity)

        l.addWidget(sliderXVelocity)

        sliderYVelocity = QtGui.QSlider(QtCore.Qt.Horizontal)
        sliderYVelocity.connect('valueChanged(int)', self.onYVelocityChanged)
        sliderYVelocity.setMaximum(self.max_velocity)
        sliderYVelocity.setMinimum(-self.max_velocity)
        l.addWidget(sliderYVelocity)


        randomGlobalGoalButton = QtGui.QPushButton('Initialize Random Global Goal')
        randomGlobalGoalButton.connect('clicked()', self.onRandomGlobalGoalButton)
        l.addWidget(randomGlobalGoalButton)

        randomObstaclesButton = QtGui.QPushButton('Initialize Random Obstacles')
        randomObstaclesButton.connect('clicked()', self.onRandomObstaclesButton)
        l.addWidget(randomObstaclesButton)

        drawActionSetButton = QtGui.QPushButton('Draw Action Set')
        drawActionSetButton.connect('clicked()', self.onDrawActionSetButton)
        l.addWidget(drawActionSetButton)

        runSimButton = QtGui.QPushButton('Simulate')
        runSimButton.connect('clicked()', self.onRunSimButton)
        l.addWidget(runSimButton)

        playButton = QtGui.QPushButton('Play/Pause')
        playButton.connect('clicked()', self.onPlayButton)

        slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        slider.connect('valueChanged(int)', self.onSliderChanged)
        self.sliderMax = self.numTimesteps
        slider.setMaximum(self.sliderMax)
        self.slider = slider

        

        # slider4 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider4.setMaximum(self.sliderMax)
        # l.addWidget(slider4)

        # slider5 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider5.setMaximum(self.sliderMax)
        # l.addWidget(slider5)

        # slider5 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider5.setMaximum(self.sliderMax)
        # l.addWidget(slider5)

        # slider6 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider6.setMaximum(self.sliderMax)
        # l.addWidget(slider6)

        # slider7 = QtGui.QSlider(QtCore.Qt.Horizontal)
        # slider7.setMaximum(self.sliderMax)
        # l.addWidget(slider7)



        l.addWidget(playButton)
        l.addWidget(slider)

        w = QtGui.QWidget()
        l = QtGui.QVBoxLayout(w)
        l.addWidget(self.view)
        self.view.orientationMarkerWidget().Off()
        l.addWidget(panel)
        w.showMaximized()

        
        # We need to connectFrameModified with updateDrawActionSet
        # self.frame.connectFrameModified(self.updateDrawIntersection)
        # self.updateDrawIntersection(self.frame)
        
        applogic.resetCamera(viewDirection=[0.2,0,-1])
        self.view.showMaximized()
        self.view.raise_()
        panel = screengrabberpanel.ScreenGrabberPanel(self.view)
        panel.widget.show()

        cameracontrolpanel.CameraControlPanel(self.view).widget.show()

        elapsed = time.time() - self.startSimTime
        simRate = self.counter/elapsed
        print "Total run time", elapsed
        print "Ticks (Hz)", simRate
        print "Number of steps taken", self.counter
        self.onRandomObstaclesButton()
        self.app.start()
        
       


    def getControllerTypeFromCounter(self, counter):
        name = self.controllerTypeOrder[0]

        for controllerType in self.controllerTypeOrder[1:]:
            if counter >= self.idxDict[controllerType]:
                name = controllerType

        return name


    def setRobotFrameState(self, x, y, theta):
        t = vtk.vtkTransform()
        t.Translate(x,y,0.0)
        t.RotateZ(np.degrees(theta))
        self.robot.getChildFrame().copyFrame(t)

    # returns true if we are in collision
    def checkInCollision(self, raycastDistance=None):
        
        # We need to re-evaluate this
        return False

        # if raycastDistance[(len(raycastDistance)+1)/2] < self.collisionThreshold:
        #     return True
        # else:
        #     return False

    def tick(self):
        #print timer.elapsed
        #simulate(t.elapsed)
        x = np.sin(time.time())
        y = np.cos(time.time())
        self.setRobotFrameState(x,y,0.0)
        if (time.time() - self.playTime) > self.endTime:
            self.playTimer.stop()

    def tick2(self):
        newtime = time.time() - self.playTime
        print time.time() - self.playTime
        x = np.sin(newtime)
        y = np.cos(newtime)
        self.setRobotFrameState(x,y,0.0)

    # just increment the slider, stop the timer if we get to the end
    def playTimerCallback(self):
        self.sliderMovedByPlayTimer = True
        currentIdx = self.slider.value
        nextIdx = currentIdx + 1
        self.slider.setSliderPosition(nextIdx)
        if currentIdx >= self.sliderMax:
            print "reached end of tape, stopping playTime"
            self.playTimer.stop()

    def onSliderChanged(self, value):
        if not self.sliderMovedByPlayTimer:
            self.playTimer.stop()
        numSteps = len(self.stateOverTime)
        idx = int(np.floor(numSteps*(1.0*value/self.sliderMax)))
        idx = min(idx, numSteps-1)
        x,y, xdot, ydot = self.stateOverTime[idx]
        self.setRobotFrameState(x,y,0)
        self.sliderMovedByPlayTimer = False

    def onXVelocityChanged(self, value):

        self.XVelocity_drawing = value
        self.onDrawActionSetButton()
        print "x velocity changed to ", value

    def onYVelocityChanged(self, value):
        print value

        self.YVelocity_drawing = -value
        self.onDrawActionSetButton()
        print "y velocity changed to ", -value


    def onRandomObstaclesButton(self):
        print "random obstacles button pressed"
        self.setInitialStateAtZero()
        self.world = World.buildLineSegmentTestWorld(percentObsDensity=8.0,
                                            circleRadius=self.options['World']['circleRadius'],
                                            nonRandom=False,
                                            scale=self.options['World']['scale'],
                                            randomSeed=self.options['World']['randomSeed'],
                                            obstaclesInnerFraction=self.options['World']['obstaclesInnerFraction'])
        
        self.locator = World.buildCellLocator(self.world.visObj.polyData)

    def onRandomGlobalGoalButton(self):
        print "random global goal button pressed"
        self.globalGoal = World.buildGlobalGoal()
   

    def onDrawActionSetButton(self):
        print "drawing action set"
        #self.ActionSet.computeFinalPositions(self.XVelocity_drawing,self.YVelocity_drawing)
        self.ActionSet.computeAllPositions(self.XVelocity_drawing,self.YVelocity_drawing)
        #self.ActionSet.drawActionSetFinal()
        self.ActionSet.drawActionSetFull()

    def onRunSimButton(self):
        self.runBatchSimulation()
        self.saveToFile("latest")
        
    def onPlayButton(self):

        if self.playTimer.isActive():
            self.onPauseButton()
            return

        print 'play'
        self.playTimer.start()
        self.playTime = time.time()

    def onPauseButton(self):
        print 'pause'
        self.playTimer.stop()

    def saveToFile(self, filename):

        # should also save the run data if it is available, i.e. stateOverTime, rewardOverTime

        filename = 'data/' + filename + ".out"
        my_shelf = shelve.open(filename,'n')

        my_shelf['options'] = self.options

        my_shelf['simulationData'] = self.simulationData
        my_shelf['stateOverTime'] = self.stateOverTime
        my_shelf['controlInputData'] = self.controlInputData
        my_shelf['numTimesteps'] = self.numTimesteps
        my_shelf['idxDict'] = self.idxDict
        my_shelf['counter'] = self.counter
        my_shelf.close()

    def run(self, launchApp=True):
        self.counter = 1
        
        # for use in playback
        self.dt = self.options['dt']
        self.endTime = self.defaultControllerTime # used to be the sum of the other times as well

        self.t = np.arange(0.0, self.endTime, self.dt)
        maxNumTimesteps = np.size(self.t)

        self.stateOverTime = np.zeros((maxNumTimesteps+1, 4))
        self.controlInputData = np.zeros((maxNumTimesteps+1,2))
        self.numTimesteps = maxNumTimesteps

        self.runBatchSimulation()


        if launchApp:
            self.setupPlayback() 


    @staticmethod
    def loadFromFile(filename):
        filename = 'data/' + filename + ".out"
        sim = Simulator(autoInitialize=False, verbose=False)

        my_shelf = shelve.open(filename)
        sim.options = my_shelf['options']
        sim.initialize()

        sim.simulationData = my_shelf['simulationData']
        sim.stateOverTime = np.array(my_shelf['stateOverTime'])
        sim.raycastData = np.array( my_shelf['raycastData'])
        sim.controlInputData = np.array(my_shelf['controlInputData'])
        sim.numTimesteps = my_shelf['numTimesteps']
        sim.idxDict = my_shelf['idxDict']
        sim.counter = my_shelf['counter']

        my_shelf.close()

        return sim
예제 #30
0
class MultisensePanel(object):

    def __init__(self, multisenseDriver, neckDriver):

        self.multisenseDriver = multisenseDriver
        self.neckDriver = neckDriver
        self.neckPitchChanged = False
        self.multisenseChanged = False

        loader = QtUiTools.QUiLoader()
        uifile = QtCore.QFile(':/ui/ddMultisense.ui')
        assert uifile.open(uifile.ReadOnly)

        self.widget = loader.load(uifile)

        self.ui = WidgetDict(self.widget.children())

        self.updateTimer = TimerCallback(targetFps=2)
        self.updateTimer.callback = self.updatePanel
        self.updateTimer.start()

        self.widget.headCamGainSpinner.setEnabled(False)
        self.widget.headCamExposureSpinner.setEnabled(False)

        #connect the callbacks
        self.widget.neckPitchSpinner.valueChanged.connect(self.neckPitchChange)
        self.widget.spinRateSpinner.valueChanged.connect(self.spinRateChange)
        self.widget.scanDurationSpinner.valueChanged.connect(self.scanDurationChange)
        self.widget.headCamFpsSpinner.valueChanged.connect(self.headCamFpsChange)
        self.widget.headCamGainSpinner.valueChanged.connect(self.headCamGainChange)
        self.widget.headCamExposureSpinner.valueChanged.connect(self.headCamExposureChange)
        self.widget.headAutoGainCheck.clicked.connect(self.headCamAutoGainChange)
        self.widget.ledOnCheck.clicked.connect(self.ledOnCheckChange)
        self.widget.ledBrightnessSpinner.valueChanged.connect(self.ledBrightnessChange)

        self.widget.sendButton.clicked.connect(self.sendButtonClicked)

        self.updatePanel()


    def getCameraFps(self):
        return self.widget.headCamFpsSpinner.value

    def getCameraGain(self):
        return self.widget.headCamGainSpinner.value

    def getCameraExposure(self):
        return self.widget.headCamExposureSpinner.value

    def getCameraLedOn(self):
        return self.widget.ledOnCheck.isChecked()

    def getCameraLedBrightness(self):
        return self.widget.ledBrightnessSpinner.value

    def getCameraAutoGain(self):
        return self.widget.headAutoGainCheck.isChecked()

    def getSpinRate(self):
        return self.widget.spinRateSpinner.value

    def getScanDuration(self):
        return self.widget.scanDurationSpinner.value

    def getNeckPitch(self):
        return self.widget.neckPitchSpinner.value

    def ledBrightnessChange(self, event):
        self.multisenseChanged = True

    def ledOnCheckChange(self, event):
        self.multisenseChanged = True

    def headCamExposureChange(self, event):
        self.multisenseChanged = True

    def headCamAutoGainChange(self, event):
        self.multisenseChanged = True
        self.widget.headCamGainSpinner.setEnabled(not self.getCameraAutoGain())
        self.widget.headCamExposureSpinner.setEnabled(not self.getCameraAutoGain())

    def neckPitchChange(self, event):
        self.neckPitchChanged = True
        self.updateTimer.stop()

    def headCamFpsChange(self, event):
        self.multisenseChanged = True

    def headCamGainChange(self, event):
        self.multisenseChanged = True

    def spinRateChange(self, event):
        self.multisenseChanged = True
        spinRate = self.getSpinRate()

        if spinRate == 0.0:
            scanDuration = 240.0
        else:
            scanDuration = abs(60.0 / (spinRate * 2))
        if scanDuration > 240.0:
            scanDuration = 240.0

        self.widget.scanDurationSpinner.blockSignals(True)
        self.widget.scanDurationSpinner.value = scanDuration
        self.widget.scanDurationSpinner.blockSignals(False)

    def scanDurationChange(self, event):
        self.multisenseChanged = True
        scanDuration = self.getScanDuration()

        spinRate = abs(60.0 / (scanDuration * 2))

        self.widget.spinRateSpinner.blockSignals(True)
        self.widget.spinRateSpinner.value = spinRate
        self.widget.spinRateSpinner.blockSignals(False)


    def sendButtonClicked(self, event):
        self.publishCommand()

    def updatePanel(self):
        if not self.widget.isVisible():
            return

        if not self.neckPitchChanged:
            self.widget.neckPitchSpinner.blockSignals(True)
            self.widget.neckPitchSpinner.setValue(self.neckDriver.getNeckPitchDegrees())
            self.widget.neckPitchSpinner.blockSignals(False)

    def publishCommand(self):

        fps = self.getCameraFps()
        camGain = self.getCameraGain()
        exposure = 1000*self.getCameraExposure()
        ledFlash = self.getCameraLedOn()
        ledDuty = self.getCameraLedBrightness()
        spinRate = self.getSpinRate()
        autoGain = 1 if self.getCameraAutoGain() else 0

        self.multisenseDriver.sendMultisenseCommand(fps, camGain, exposure, autoGain, spinRate, ledFlash, ledDuty)
        self.neckDriver.setNeckPitch(self.getNeckPitch())

        self.multisenseChanged = False
        self.neckPitchChanged = False
        self.updateTimer.start()
예제 #31
0
class CameraTrackerManager(object):

    def __init__(self):
        self.target = None
        self.targetFrame = None
        self.trackerClass = None
        self.camera = None
        self.view = None
        self.timer = TimerCallback()
        self.timer.callback = self.updateTimer
        self.addTrackers()
        self.initTracker()

    def updateTimer(self):

        tNow = time.time()
        dt = tNow - self.tLast
        if dt < self.timer.elapsed/2.0:
            return

        self.update()

    def setView(self, view):
        self.view = view
        self.camera = view.camera()

    def setTarget(self, obj):

        if obj == self.target:
            return

        self.disableActiveTracker()

        if not obj:
            return

        self.target = obj
        self.targetFrame = obj.getChildFrame()
        self.callbackId = self.targetFrame.connectFrameModified(self.onTargetFrameModified)

        self.initTracker()

    def disableActiveTracker(self):

        if self.targetFrame:
            self.targetFrame.disconnectFrameModified(self.callbackId)

        self.target = None
        self.targetFrame = None
        self.trackerClass = None
        self.initTracker()

    def update(self):

        tNow = time.time()
        dt = tNow - self.tLast
        self.tLast = tNow

        if self.activeTracker:
            self.activeTracker.dt = dt
            self.activeTracker.update()

    def reset(self):
        self.tLast = time.time()
        if self.activeTracker:
            self.activeTracker.reset()


    def getModeActions(self):
        if self.activeTracker:
            return self.activeTracker.actions
        return []

    def onModeAction(self, actionName):
        if self.activeTracker:
            self.activeTracker.onAction(actionName)

    def getModeProperties(self):
        if self.activeTracker:
            return self.activeTracker.properties
        return None

    def onTargetFrameModified(self, frame):
        self.update()

    def initTracker(self):

        self.timer.stop()
        self.activeTracker = self.trackerClass(self.view, self.targetFrame) if self.trackerClass else None
        self.reset()
        self.update()

        if self.activeTracker:
            minimumUpdateRate = self.activeTracker.getMinimumUpdateRate()
            if minimumUpdateRate > 0:
                self.timer.targetFps = minimumUpdateRate
                self.timer.start()

    def addTrackers(self):
        self.trackers = OrderedDict([
          ['Off', None],
          ['Position', PositionTracker],
          ['Position & Orientation', PositionOrientationTracker],
          ['Smooth Follow', SmoothFollowTracker],
          ['Look At', LookAtTracker],
          ['Orbit', OrbitTracker],
        ])

    def setTrackerMode(self, modeName):
        assert modeName in self.trackers
        self.trackerClass = self.trackers[modeName]
        self.initTracker()
예제 #32
0
class PointCloudSource(vis.PolyDataItem):

    _requiredProviderClass = perceptionmeta.PointCloudSourceMeta

    def __init__(
        self, name, robotStateJointController, callbackFunc=None, provider=None
    ):
        vis.PolyDataItem.__init__(self, name, vtk.vtkPolyData(), view=None)
        self.firstData = True
        self.robotStateJointController = robotStateJointController
        self.timer = TimerCallback()
        self.timer.callback = self.showPointCloud
        self.timer.start()
        self.callbackFunc = callbackFunc
        if provider:
            self.setProvider(provider)
        else:
            self.provider = None

    def setProvider(self, provider):
        """
        Set the provider for this cloud. This completes the initialisation of the object and displays the cloud by
        pulling data from the provider

        :param provider: An instantiation of the PointCloudSourceMeta abstract class
        :return:
        """
        if not issubclass(provider.__class__, self._requiredProviderClass):
            raise TypeError(
                "Attempted to set {} provider to {}, but it was not a"
                " subclass of {} as is required.".format(
                    self.__class__,
                    provider.__class__,
                    self._requiredProviderClass.__class__,
                )
            )

        self.provider = provider
        self.provider.set_consumer(self)
        self.addProperty("Updates Enabled", True)
        self.addProperty(
            "Number of Point Clouds",
            10,
            attributes=om.PropertyAttributes(
                decimals=0, minimum=1, maximum=100, singleStep=1, hidden=False
            ),
        )
        if self.getProperty("Visible"):
            self.provider.start()

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)
        if propertyName == "Visible" or propertyName == "Updates Enabled":
            if self.getProperty(propertyName):
                self.timer.start()
                if self.provider:
                    self.provider.start()
            else:
                self.timer.stop()
                if self.provider:
                    self.provider.stop()
        elif propertyName == "Number of Point Clouds":
            numberOfPointCloud = self.getProperty(propertyName)
            self.provider.set_num_pointclouds(numberOfPointCloud)

        if self.provider:
            self.provider._on_property_changed(propertySet, propertyName)

    @CheckProvider
    def getPointCloud(self):
        polyData = vtk.vtkPolyData()
        self.provider.get_point_cloud(polyData)
        if polyData.GetNumberOfPoints() == 0:
            return None
        else:
            return polyData

    @CheckProvider
    def resetTime(self):
        self.provider.reset_time()

    @CheckProvider
    def showPointCloud(self):
        polyData = vtk.vtkPolyData()
        self.provider.get_point_cloud(polyData, True)
        if polyData.GetNumberOfPoints() == 0:
            return

        bodyHeight = self.robotStateJointController.q[2]
        self.setRangeMap("z", [bodyHeight - 0.5, bodyHeight + 0.5])

        if self.callbackFunc:
            self.callbackFunc()
        # update view
        self.setPolyData(polyData)

        if self.firstData:
            self.firstData = False
            colorList = self.properties.getPropertyAttribute("Color By", "enumNames")
            zIndex = colorList.index("z") if "z" in colorList else 0
            self.properties.setProperty("Color By", zIndex)
예제 #33
0
class DepthImagePointCloudSource(vis.PolyDataItem):

    _requiredProviderClass = perceptionmeta.DepthImageSourceMeta

    def __init__(
        self, name, cameraName, imageManager, robotStateJointController, provider=None
    ):
        vis.PolyDataItem.__init__(self, name, vtk.vtkPolyData(), view=None)

        self.robotStateJointController = robotStateJointController
        self.addProperty("Camera name", cameraName)

        self.addProperty(
            "Decimation",
            1,
            attributes=om.PropertyAttributes(enumNames=["1", "2", "4", "8", "16"]),
        )
        self.addProperty(
            "Remove Size",
            1000,
            attributes=om.PropertyAttributes(
                decimals=0, minimum=0, maximum=100000.0, singleStep=1000
            ),
        )
        self.addProperty(
            "Target FPS",
            5.0,
            attributes=om.PropertyAttributes(
                decimals=1, minimum=0.1, maximum=30.0, singleStep=0.1
            ),
        )
        self.addProperty(
            "Max Range",
            5.0,
            attributes=om.PropertyAttributes(
                decimals=2, minimum=0.0, maximum=30.0, singleStep=0.25
            ),
        )

        self.imageManager = imageManager
        self.cameraName = cameraName
        self.firstData = True
        self.timer = TimerCallback()
        self.timer.callback = self.update
        self.lastUtime = 0
        self.lastDataReceivedTime = 0

        if provider:
            self.setProvider(provider)
        else:
            self.provider = None

    def setProvider(self, provider):
        """
        Set the provider for this depth image cloud. This completes the initialisation of the object and displays the
        cloud by pulling data from the provider

        :param provider: An instantiation of the DepthImageSourceMeta abstract class
        :return:
        """
        if not issubclass(provider.__class__, self._requiredProviderClass):
            raise TypeError(
                "Attempted to set {} provider to {}, but it was not a"
                " subclass of {} as is required.".format(
                    self.__class__,
                    provider.__class__,
                    self._requiredProviderClass.__class__,
                )
            )

        self.provider = provider
        self.provider.set_consumer(self)

        decimation = int(self.properties.getPropertyEnumValue("Decimation"))
        removeSize = int(self.properties.getProperty("Remove Size"))
        rangeThreshold = float(self.properties.getProperty("Max Range"))
        self.addProperty("Remove Stale Data", False)
        self.addProperty(
            "Stale Data Timeout",
            5.0,
            attributes=om.PropertyAttributes(
                decimals=1, minimum=0.1, maximum=30.0, singleStep=0.1
            ),
        )

        self.provider.set_decimate(int(decimation))
        self.provider.set_remove_size(removeSize)
        self.provider.set_range_threshold(rangeThreshold)
        self.setProperty("Visible", True)
        self.lastDataReceivedTime = time.time()

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)

        if propertyName == "Visible":
            if self.getProperty(propertyName):
                self.timer.start()
                if self.provider:
                    self.provider.start()
            else:
                self.timer.stop()
                if self.provider:
                    self.provider.stop()

        if propertyName in ("Decimation", "Remove outliers", "Max Range"):
            self.lastUtime = 0
        if propertyName == "Decimation":
            decimate = self.getPropertyEnumValue(propertyName)
            self.provider.set_decimate(int(decimate))
        elif propertyName == "Remove Size":
            remove_size = self.getProperty(propertyName)
            self.provider.set_remove_size(remove_size)
        elif propertyName == "Max Range":
            max_range = self.getProperty(propertyName)
            self.provider.set_range_threshold(max_range)

    @CheckProvider
    def getPointCloud(self):
        polyData = vtk.vtkPolyData()
        self.provider.get_point_cloud(polyData)
        if polyData.GetNumberOfPoints() == 0:
            return None
        else:
            return polyData

    def onRemoveFromObjectModel(self):
        vis.PolyDataItem.onRemoveFromObjectModel(self)
        self.timer.stop()

    @CheckProvider
    def resetTime(self):
        self.provider.reset_time()

    @CheckProvider
    def update(self):
        # utime = self.imageManager.queue.getCurrentImageTime(self.cameraName)
        utime = self.provider.get_sec() * 1e6 + round(self.provider.get_nsec() * 1e-3)

        if utime == self.lastUtime:
            if self.getProperty("Remove Stale Data") and (
                (time.time() - self.lastDataReceivedTime)
                > self.getProperty("Stale Data Timeout")
            ):
                if self.polyData.GetNumberOfPoints() > 0:
                    self.setPolyData(vtk.vtkPolyData())
            return

        if utime < self.lastUtime:
            temp = 0  # dummy
        elif utime - self.lastUtime < 1e6 / self.getProperty("Target FPS"):
            return

        polyData = vtk.vtkPolyData()
        new_data = self.provider.get_point_cloud(polyData, True)
        if polyData.GetNumberOfPoints() == 0:
            return

        # currently disabled
        # bodyToLocal = vtk.vtkTransform()
        # self.imageManager.queue.getTransform('body', 'local', utime, bodyToLocal)
        # bodyHeight = bodyToLocal.GetPosition()[2]

        bodyHeight = self.robotStateJointController.q[2]
        self.setRangeMap("z", [bodyHeight - 0.5, bodyHeight + 0.5])

        self.setPolyData(polyData)

        if self.firstData:
            self.firstData = False
            colorList = self.properties.getPropertyAttribute("Color By", "enumNames")
            zIndex = colorList.index("z") if "z" in colorList else 0
            self.properties.setProperty("Color By", zIndex)

        self.lastDataReceivedTime = time.time()
        self.lastUtime = utime
예제 #34
0
class PlaybackPanel(object):

    def __init__(self, planPlayback, playbackRobotModel, playbackJointController, robotStateModel, robotStateJointController, manipPlanner):

        self.planPlayback = planPlayback
        self.playbackRobotModel = playbackRobotModel
        self.playbackJointController = playbackJointController
        self.robotStateModel = robotStateModel
        self.robotStateJointController = robotStateJointController
        self.manipPlanner = manipPlanner
        manipPlanner.connectPlanCommitted(self.onPlanCommitted)
        manipPlanner.connectUseSupports(self.updateButtonColor)

        self.autoPlay = True
        self.useOperationColors()

        self.planFramesObj = None
        self.plan = None
        self.poseInterpolator = None
        self.startTime = 0.0
        self.endTime = 1.0
        self.animationTimer = TimerCallback()
        self.animationTimer.targetFps = 60
        self.animationTimer.callback = self.updateAnimation
        self.animationClock = SimpleTimer()

        loader = QtUiTools.QUiLoader()
        uifile = QtCore.QFile(':/ui/ddPlaybackPanel.ui')
        assert uifile.open(uifile.ReadOnly)

        self.widget = loader.load(uifile)
        uifile.close()

        self.ui = WidgetDict(self.widget.children())

        self.ui.viewModeCombo.connect('currentIndexChanged(const QString&)', self.viewModeChanged)
        self.ui.playbackSpeedCombo.connect('currentIndexChanged(const QString&)', self.playbackSpeedChanged)
        self.ui.interpolationCombo.connect('currentIndexChanged(const QString&)', self.interpolationChanged)

        self.ui.samplesSpinBox.connect('valueChanged(int)', self.numberOfSamplesChanged)
        self.ui.playbackSlider.connect('valueChanged(int)', self.playbackSliderValueChanged)

        self.ui.animateButton.connect('clicked()', self.animateClicked)
        self.ui.hideButton.connect('clicked()', self.hideClicked)
        self.ui.executeButton.connect('clicked()', self.executeClicked)
        self.ui.executeButton.setShortcut(QtGui.QKeySequence('Ctrl+Return'))
        self.ui.stopButton.connect('clicked()', self.stopClicked)

        self.ui.executeButton.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui.executeButton.connect('customContextMenuRequested(const QPoint&)', self.showExecuteContextMenu)


        self.setPlan(None)
        self.hideClicked()


    def useDevelopmentColors(self):
        self.robotStateModelDisplayAlpha = 0.1
        self.playbackRobotModelUseTextures = True
        self.playbackRobotModelDisplayAlpha = 1

    def useOperationColors(self):
        self.robotStateModelDisplayAlpha = 1
        self.playbackRobotModelUseTextures = False
        self.playbackRobotModelDisplayAlpha = 0.5
    def showExecuteContextMenu(self, clickPosition):

        globalPos = self.ui.executeButton.mapToGlobal(clickPosition)

        menu = QtGui.QMenu()
        menu.addAction('Visualization Only')

        if not self.isPlanFeasible():
            menu.addSeparator()
            if self.isPlanAPlanWithSupports():
                menu.addAction('Execute infeasible plan with supports')
            else:
                menu.addAction('Execute infeasible plan')
        elif self.isPlanAPlanWithSupports():
            menu.addSeparator()
            menu.addAction('Execute plan with supports')

        selectedAction = menu.exec_(globalPos)
        if not selectedAction:
            return

        if selectedAction.text == 'Visualization Only':
            self.executePlan(visOnly=True)
        elif selectedAction.text == 'Execute infeasible plan':
            self.executePlan(overrideInfeasibleCheck=True)
        elif selectedAction.text == 'Execute plan with supports':
            self.executePlan(overrideSupportsCheck=True)
        elif selectedAction.text == 'Execute infeasible plan with supports':
            self.executePlan(overrideInfeasibleCheck=True, overrideSupportsCheck=True)


    def getViewMode(self):
        return str(self.ui.viewModeCombo.currentText)

    def setViewMode(self, mode):
        '''
        Set the mode of the view widget. input arg: 'continous', 'frames', 'hidden'
        e.g. can hide all plan playback with 'hidden'
        '''
        self.ui.viewModeCombo.setCurrentIndex(self.ui.viewModeCombo.findText(mode))

    def getPlaybackSpeed(self):
      s = str(self.ui.playbackSpeedCombo.currentText).replace('x', '')
      if '/' in s:
          n, d = s.split('/')
          return float(n)/float(d)
      return float(s)

    def getInterpolationMethod(self):
        return str(self.ui.interpolationCombo.currentText)

    def getNumberOfSamples(self):
        return self.ui.samplesSpinBox.value

    def viewModeChanged(self):
        viewMode = self.getViewMode()
        if viewMode == 'continuous':
            playbackVisible = True
            samplesVisible = False
        else:
            playbackVisible = False
            samplesVisible = True

        self.ui.samplesLabel.setEnabled(samplesVisible)
        self.ui.samplesSpinBox.setEnabled(samplesVisible)

        self.ui.playbackSpeedLabel.setVisible(playbackVisible)
        self.ui.playbackSpeedCombo.setVisible(playbackVisible)
        self.ui.playbackSlider.setEnabled(playbackVisible)
        self.ui.animateButton.setVisible(playbackVisible)
        self.ui.timeLabel.setVisible(playbackVisible)

        if self.plan:

            if self.getViewMode() == 'continuous' and self.autoPlay:
                self.startAnimation()
            else:
                self.ui.playbackSlider.value = 0
                self.stopAnimation()
                self.updatePlanFrames()


    def playbackSpeedChanged(self):
        self.planPlayback.playbackSpeed = self.getPlaybackSpeed()


    def getPlaybackTime(self):
        sliderValue = self.ui.playbackSlider.value
        return (sliderValue / 1000.0) * self.endTime

    def updateTimeLabel(self):
        playbackTime = self.getPlaybackTime()
        self.ui.timeLabel.text = 'Time: %.2f s' % playbackTime

    def playbackSliderValueChanged(self):
        self.updateTimeLabel()
        self.showPoseAtTime(self.getPlaybackTime())

    def interpolationChanged(self):

        methods = {'linear' : 'slinear',
                   'cubic spline' : 'cubic',
                   'pchip' : 'pchip' }
        self.planPlayback.interpolationMethod = methods[self.getInterpolationMethod()]
        self.poseInterpolator = self.planPlayback.getPoseInterpolatorFromPlan(self.plan)
        self.updatePlanFrames()

    def numberOfSamplesChanged(self):
        self.updatePlanFrames()

    def animateClicked(self):
        self.startAnimation()

    def hideClicked(self):

        if self.ui.hideButton.text == 'hide':
            self.ui.playbackFrame.setEnabled(False)
            self.hidePlan()
            self.ui.hideButton.text = 'show'
            self.ui.executeButton.setEnabled(False)

            if not self.plan:
                self.ui.hideButton.setEnabled(False)
        else:
            self.ui.playbackFrame.setEnabled(True)
            self.ui.hideButton.text = 'hide'
            self.ui.hideButton.setEnabled(True)
            self.ui.executeButton.setEnabled(True)

            self.viewModeChanged()

        self.updateButtonColor()


    def executeClicked(self):
        self.executePlan()


    def executePlan(self, visOnly=False, overrideInfeasibleCheck=False, overrideSupportsCheck=False):
        if visOnly:
            _, poses = self.planPlayback.getPlanPoses(self.plan)
            self.onPlanCommitted(self.plan)
            self.robotStateJointController.setPose('EST_ROBOT_STATE', poses[-1])
        else:
            if (self.isPlanFeasible() or overrideInfeasibleCheck) and (not self.isPlanAPlanWithSupports() or overrideSupportsCheck):
                self.manipPlanner.commitManipPlan(self.plan)


    def onPlanCommitted(self, plan):
        self.setPlan(None)
        self.hideClicked()


    def stopClicked(self):
        self.stopAnimation()
        self.manipPlanner.sendPlanPause()


    def isPlanFeasible(self):
        plan = robotstate.asRobotPlan(self.plan)
        return plan is not None and (max(plan.plan_info) < 10 and min(plan.plan_info) >= 0)

    def getPlanInfo(self, plan):
        plan = robotstate.asRobotPlan(self.plan)
        return max(plan.plan_info)


    def isPlanAPlanWithSupports(self):
        return hasattr(self.plan, 'support_sequence') or self.manipPlanner.publishPlansWithSupports

    def updatePlanFrames(self):

        if self.getViewMode() != 'frames':
            return

        numberOfSamples = self.getNumberOfSamples()

        meshes = self.planPlayback.getPlanPoseMeshes(self.plan, self.playbackJointController, self.playbackRobotModel, numberOfSamples)
        d = DebugData()

        startColor = [0.8, 0.8, 0.8]
        endColor = [85/255.0, 255/255.0, 255/255.0]
        colorFunc = scipy.interpolate.interp1d([0, numberOfSamples-1], [startColor, endColor], axis=0, kind='slinear')

        for i, mesh in reversed(list(enumerate(meshes))):
            d.addPolyData(mesh, color=colorFunc(i))

        pd = d.getPolyData()
        clean = vtk.vtkCleanPolyData()
        clean.SetInput(pd)
        clean.Update()
        pd = clean.GetOutput()

        self.planFramesObj = vis.updatePolyData(d.getPolyData(), 'robot plan', alpha=1.0, visible=False, colorByName='RGB255', parent='planning')
        self.showPlanFrames()


    def showPlanFrames(self):
        self.planFramesObj.setProperty('Visible', True)
        self.robotStateModel.setProperty('Visible', False)
        self.playbackRobotModel.setProperty('Visible', False)


    def startAnimation(self):
        self.showPlaybackModel()
        self.stopAnimation()
        self.ui.playbackSlider.value = 0
        self.animationClock.reset()
        self.animationTimer.start()
        self.updateAnimation()


    def stopAnimation(self):
        self.animationTimer.stop()

    def showPlaybackModel(self):
        self.robotStateModel.setProperty('Visible', True)
        self.playbackRobotModel.setProperty('Visible', True)
        self.playbackRobotModel.setProperty('Color Mode', 1 if self.playbackRobotModelUseTextures else 0)
        self.robotStateModel.setProperty('Alpha', self.robotStateModelDisplayAlpha)
        self.playbackRobotModel.setProperty('Alpha', self.playbackRobotModelDisplayAlpha)
        if self.planFramesObj:
            self.planFramesObj.setProperty('Visible', False)

    def hidePlan(self):
        self.stopAnimation()
        if self.planFramesObj:
            self.planFramesObj.setProperty('Visible', False)
        if self.playbackRobotModel:
            self.playbackRobotModel.setProperty('Visible', False)

        self.robotStateModel.setProperty('Visible', True)
        self.robotStateModel.setProperty('Alpha', 1.0)


    def showPoseAtTime(self, time):
        pose = self.poseInterpolator(time)
        self.playbackJointController.setPose('plan_playback', pose)


    def updateAnimation(self):

        tNow = self.animationClock.elapsed() * self.planPlayback.playbackSpeed
        if tNow > self.endTime:
            tNow = self.endTime

        sliderValue = int(1000.0 * tNow / self.endTime)

        self.ui.playbackSlider.blockSignals(True)
        self.ui.playbackSlider.value = sliderValue
        self.ui.playbackSlider.blockSignals(False)
        self.updateTimeLabel()

        self.showPoseAtTime(tNow)
        return tNow < self.endTime


    def updateButtonColor(self):
        if self.ui.executeButton.enabled and self.plan and not self.isPlanFeasible():
            styleSheet = 'background-color:red'
        elif self.ui.executeButton.enabled and self.plan and self.isPlanAPlanWithSupports():
            styleSheet = 'background-color:orange'
        else:
            styleSheet = ''

        self.ui.executeButton.setStyleSheet(styleSheet)


    def setPlan(self, plan):

        self.ui.playbackSlider.value = 0
        self.ui.timeLabel.text = 'Time: 0.00 s'
        self.ui.planNameLabel.text = ''
        self.plan = plan
        self.endTime = 1.0
        self.updateButtonColor()

        if not self.plan:
            return

        planText = 'Plan: %d.  %.2f seconds' % (plan.utime, self.planPlayback.getPlanElapsedTime(plan))
        self.ui.planNameLabel.text = planText

        self.startTime = 0.0
        self.endTime = self.planPlayback.getPlanElapsedTime(plan)
        self.interpolationChanged()
        info = self.getPlanInfo(plan)
        app.displaySnoptInfo(info)

        if self.ui.hideButton.text == 'show':
            self.hideClicked()
        else:
            self.viewModeChanged()

        self.updateButtonColor()

        if self.autoPlay and self.widget.parent() is not None:
            self.widget.parent().show()
예제 #35
0
class AtlasCommandStream(object):

    def __init__(self):
        self.timer = TimerCallback(targetFps=10)
        #self.timer.disableScheduledTimer()
        self.app = ConsoleApp()
        self.robotModel, self.jointController = roboturdf.loadRobotModel('robot model')
        self.fpsCounter = simpletimer.FPSCounter()
        self.drakePoseJointNames = robotstate.getDrakePoseJointNames()
        self.fpsCounter.printToConsole = True
        self.timer.callback = self._tick
        self._initialized = False
        self.publishChannel = 'JOINT_POSITION_GOAL'
        # self.lastCommandMessage = newAtlasCommandMessageAtZero()
        self._numPositions = len(robotstate.getDrakePoseJointNames())
        self._previousElapsedTime = 100
        self._baseFlag = 0;
        self.jointLimitsMin = np.array([self.robotModel.model.getJointLimits(jointName)[0] for jointName in robotstate.getDrakePoseJointNames()])
        self.jointLimitsMax = np.array([self.robotModel.model.getJointLimits(jointName)[1] for jointName in robotstate.getDrakePoseJointNames()])
        self.useControllerFlag = False
        self.drivingGainsFlag = False
        self.applyDefaults()

    def initialize(self, currentRobotPose):
        assert not self._initialized
        self._currentCommandedPose = np.array(currentRobotPose)
        self._previousCommandedPose = np.array(currentRobotPose)
        self._goalPose = np.array(currentRobotPose)
        self._initialized = True

    def useController(self):
        self.useControllerFlag = True
        self.publishChannel = 'QP_CONTROLLER_INPUT'

    def setKp(self, Kp, jointName=None):
        if jointName is None:
            self._Kp = Kp*np.ones(self._numPositions)
        else:
            idx = robotstate.getDrakePoseJointNames().index(jointName)
            self._maxSpeed[idx] = Kp

        self.updateKd()

    def setMaxSpeed(self, speed, jointName=None):
        if jointName is None:
            self._maxSpeed = np.deg2rad(speed)*np.ones(self._numPositions)
        else:
            idx = robotstate.getDrakePoseJointNames().index(jointName)
            self._maxSpeed[idx] = np.deg2rad(speed)

    def updateKd(self):
        self._dampingRatio = 1;
        self._Kd = 2*self._dampingRatio*np.sqrt(self._Kp)

    def applyDefaults(self):
        self.setKp(10)
        self.setMaxSpeed(10)

        if self.drivingGainsFlag:
            self.setMaxSpeed(70,'l_arm_lwy')
            self.setKp(50,'l_arm_lwy')
            self.setMaxSpeed(100,'l_leg_aky')
            self.setKp(100,'l_leg_aky')
    
    def applyDrivingDefaults(self):
        self.drivingGainsFlag = True
        self.applyDefaults()

    def applyPlanDefaults(self):
        self.setKp(10)
        self.setMaxSpeed(60)        
        
    def startStreaming(self):
        assert self._initialized
        if not self.timer.isActive():
            self.timer.start()

    def stopStreaming(self):
        self.timer.stop()

    def setGoalPose(self, pose):         
        self._goalPose = self.clipPoseToJointLimits(pose)

    def setIndividualJointGoalPose(self, pose, jointName):
        jointIdx = self.drakePoseJointNames.index(jointName)
        self._goalPose[jointIdx] = pose

    def clipPoseToJointLimits(self,pose):
        pose = np.array(pose)
        pose = np.clip(pose, self.jointLimitsMin, self.jointLimitsMax)
        return pose

    def waitForRobotState(self):
        msg = lcmUtils.captureMessage('EST_ROBOT_STATE', lcmbotcore.robot_state_t)
        pose = robotstate.convertStateMessageToDrakePose(msg)
        pose[:6] = np.zeros(6)
        self.initialize(pose)

    def _updateAndSendCommandMessage(self):
        self._currentCommandedPose = self.clipPoseToJointLimits(self._currentCommandedPose)
        if self._baseFlag:
            msg = robotstate.drakePoseToRobotState(self._currentCommandedPose)
        else:
            msg = drakePoseToAtlasCommand(self._currentCommandedPose)

        if self.useControllerFlag:
            msg = drakePoseToQPInput(self._currentCommandedPose)

        lcmUtils.publish(self.publishChannel, msg)

    def _tick(self):

        self.fpsCounter.tick()

        elapsed = self.timer.elapsed # time since last tick
        #nominalElapsed = (1.0 / self.timer.targetFps)
        #if elapsed > 2*nominalElapsed:
        #    elapsed = nominalElapsed

        # move current pose toward goal pose
        previousPose = self._previousCommandedPose.copy()
        currentPose = self._currentCommandedPose.copy()
        goalPose = self.clipPoseToJointLimits(self._goalPose.copy())
        nextPose = self._computeNextPose(previousPose,currentPose, goalPose, elapsed,
            self._previousElapsedTime, self._maxSpeed)
        self._currentCommandedPose = nextPose

        # have the base station directly send the command through
        if self._baseFlag:
            self._currentCommandedPose = goalPose

        # publish
        self._updateAndSendCommandMessage()

        # bookkeeping
        self._previousElapsedTime = elapsed
        self._previousCommandedPose = currentPose

    def _computeNextPose(self, previousPose, currentPose, goalPose, elapsed, elapsedPrevious, maxSpeed):
        v = 1.0/elapsedPrevious * (currentPose - previousPose)
        u = -self._Kp*(currentPose - goalPose) - self._Kd*v # u = -K*x
        v_next = v + elapsed*u
        v_next = np.clip(v_next,-maxSpeed,maxSpeed) # velocity clamp
        nextPose = currentPose + v_next*elapsed
        nextPose = self.clipPoseToJointLimits(nextPose)
        return nextPose
예제 #36
0
class AsyncTaskQueue(object):

    QUEUE_STARTED_SIGNAL = 'QUEUE_STARTED_SIGNAL'
    QUEUE_STOPPED_SIGNAL = 'QUEUE_STOPPED_SIGNAL'
    TASK_STARTED_SIGNAL = 'TASK_STARTED_SIGNAL'
    TASK_ENDED_SIGNAL = 'TASK_ENDED_SIGNAL'
    TASK_PAUSED_SIGNAL = 'TASK_PAUSED_SIGNAL'
    TASK_FAILED_SIGNAL = 'TASK_FAILED_SIGNAL'
    TASK_EXCEPTION_SIGNAL = 'TASK_EXCEPTION_SIGNAL'

    class PauseException(Exception):
        pass

    class FailException(Exception):
        pass

    def __init__(self):
        self.tasks = []
        self.generators = []
        self.timer = TimerCallback(targetFps=10)
        self.timer.callback = self.callbackLoop
        self.callbacks = callbacks.CallbackRegistry([self.QUEUE_STARTED_SIGNAL,
                                                     self.QUEUE_STOPPED_SIGNAL,
                                                     self.TASK_STARTED_SIGNAL,
                                                     self.TASK_ENDED_SIGNAL,
                                                     self.TASK_PAUSED_SIGNAL,
                                                     self.TASK_FAILED_SIGNAL,
                                                     self.TASK_EXCEPTION_SIGNAL])
        self.currentTask = None
        self.isRunning = False

    def reset(self):
        assert not self.isRunning
        assert not self.generators
        self.tasks = []

    def start(self):
        self.isRunning = True
        self.callbacks.process(self.QUEUE_STARTED_SIGNAL, self)
        self.timer.start()

    def stop(self):
        self.isRunning = False
        self.currentTask = None
        self.generators = []
        self.timer.stop()
        self.callbacks.process(self.QUEUE_STOPPED_SIGNAL, self)

    def wrapGenerator(self, generator):
        def generatorWrapper():
            return generator
        return generatorWrapper

    def addTask(self, task):

        if isinstance(task, types.GeneratorType):
            task = self.wrapGenerator(task)

        assert hasattr(task, '__call__')
        self.tasks.append(task)

    def callbackLoop(self):

        try:
            for i in xrange(10):
                self.doWork()
            if not self.tasks:
                self.stop()

        except AsyncTaskQueue.PauseException:
            assert self.currentTask
            self.callbacks.process(self.TASK_PAUSED_SIGNAL, self, self.currentTask)
            self.stop()
        except AsyncTaskQueue.FailException:
            assert self.currentTask
            self.callbacks.process(self.TASK_FAILED_SIGNAL, self, self.currentTask)
            self.stop()
        except:
            assert self.currentTask
            self.callbacks.process(self.TASK_EXCEPTION_SIGNAL, self, self.currentTask)
            self.stop()
            raise

        return self.isRunning

    def popTask(self):
        assert not self.isRunning
        assert not self.currentTask
        if self.tasks:
            self.tasks.pop(0)

    def completePreviousTask(self):
        assert self.currentTask
        self.tasks.remove(self.currentTask)
        self.callbacks.process(self.TASK_ENDED_SIGNAL, self, self.currentTask)
        self.currentTask = None

    def startNextTask(self):
        self.currentTask = self.tasks[0]
        self.callbacks.process(self.TASK_STARTED_SIGNAL, self, self.currentTask)
        result = self.currentTask()
        if isinstance(result, types.GeneratorType):
            self.generators.insert(0, result)

    def doWork(self):
        if self.generators:
            self.handleGenerator(self.generators[0])
        else:
            if self.currentTask:
                self.completePreviousTask()
            if self.tasks:
                self.startNextTask()

    def handleGenerator(self, generator):
        try:
            result = generator.next()
        except StopIteration:
            self.generators.remove(generator)
        else:
            if isinstance(result, types.GeneratorType):
                self.generators.insert(0, result)

    def connectQueueStarted(self, func):
        return self.callbacks.connect(self.QUEUE_STARTED_SIGNAL, func)

    def disconnectQueueStarted(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectQueueStopped(self, func):
        return self.callbacks.connect(self.QUEUE_STOPPED_SIGNAL, func)

    def disconnectQueueStopped(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskStarted(self, func):
        return self.callbacks.connect(self.TASK_STARTED_SIGNAL, func)

    def disconnectTaskStarted(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskEnded(self, func):
        return self.callbacks.connect(self.TASK_ENDED_SIGNAL, func)

    def disconnectTaskEnded(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskPaused(self, func):
        return self.callbacks.connect(self.TASK_PAUSED_SIGNAL, func)

    def disconnectTaskPaused(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskFailed(self, func):
        return self.callbacks.connect(self.TASK_FAILED_SIGNAL, func)

    def disconnectTaskFailed(self, callbackId):
        self.callbacks.disconnect(callbackId)

    def connectTaskException(self, func):
        return self.callbacks.connect(self.TASK_EXCEPTION_SIGNAL, func)

    def disconnectTaskException(self, callbackId):
        self.callbacks.disconnect(callbackId)
예제 #37
0
class RosGridMap(vis.PolyDataItem):

    _requiredProviderClass = perceptionmeta.RosGridMapMeta

    def __init__(
        self, robotStateJointController, name, callbackFunc=None, provider=None
    ):
        vis.PolyDataItem.__init__(self, name, vtk.vtkPolyData(), view=None)
        self.firstData = True
        self.robotStateJointController = robotStateJointController
        self.timer = TimerCallback()
        self.timer.callback = self.showMap
        self.timer.start()
        self.callbackFunc = callbackFunc

        if provider:
            self.setProvider(provider)
        else:
            self.provider = None

    def setProvider(self, provider):
        """
        Set the provider for this grid map. This completes the initialisation of the object and displays the grid map
        by pulling data from the provider

        :param provider: An instantiation of the RosGridMapMeta abstract class
        :return:
        """
        if not issubclass(provider.__class__, self._requiredProviderClass):
            raise TypeError(
                "Attempted to set {} provider to {}, but it was not a"
                " subclass of {} as is required.".format(
                    self.__class__,
                    provider.__class__,
                    self._requiredProviderClass.__class__,
                )
            )

        self.provider = provider
        self.provider.set_consumer(self)
        if self.getProperty("Visible"):
            self.provider.start()

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)
        if propertyName == "Visible":
            if self.getProperty(propertyName):
                self.timer.start()
                if self.provider:
                    self.provider.start()
            else:
                self.timer.stop()
                if self.provider:
                    self.provider.stop()
        elif propertyName == "Color By":
            color = self.getPropertyEnumValue(propertyName)
            self.provider.set_color_layer(color)
            # only_new_data = False because the poly_date need to be redraw with the new color layer
            self.showMap(only_new_data=False)
            self._updateColorBy()

        if self.provider:
            self.provider._on_property_changed(propertySet, propertyName)

    @CheckProvider
    def showMap(self, only_new_data=True):

        polyData = vtk.vtkPolyData()
        self.provider.get_mesh(polyData, only_new_data)
        if polyData.GetNumberOfPoints() == 0:
            return

        bodyHeight = self.robotStateJointController.q[2]
        self.setRangeMap("z", [bodyHeight - 0.5, bodyHeight])

        if self.callbackFunc:
            self.callbackFunc()
        # update view
        self.setPolyData(polyData)

        if self.firstData:
            self.firstData = False
            colorList = self.properties.getPropertyAttribute("Color By", "enumNames")
            zIndex = colorList.index("z") if "z" in colorList else 0
            self.properties.setProperty("Color By", zIndex)

    @CheckProvider
    def resetTime(self):
        self.provider.reset_time()

    @CheckProvider
    def getPointCloud(self):
        polyData = vtk.vtkPolyData()
        self.provider.get_point_cloud(polyData)
        if polyData.GetNumberOfPoints() == 0:
            return None
        else:
            return polyData
예제 #38
0
class PlaybackPanel(object):
    def __init__(self, planPlayback, playbackRobotModel,
                 playbackJointController, robotStateModel,
                 robotStateJointController, manipPlanner):

        self.planPlayback = planPlayback
        self.playbackRobotModel = playbackRobotModel
        self.playbackJointController = playbackJointController
        self.robotStateModel = robotStateModel
        self.robotStateJointController = robotStateJointController
        self.manipPlanner = manipPlanner
        manipPlanner.connectPlanCommitted(self.onPlanCommitted)
        manipPlanner.connectUseSupports(self.updateButtonColor)

        self.autoPlay = True
        #self.useOperationColors()
        self.useDevelopmentColors()

        self.planFramesObj = None
        self.plan = None
        self.poseInterpolator = None
        self.startTime = 0.0
        self.endTime = 1.0
        self.animationTimer = TimerCallback()
        self.animationTimer.targetFps = 60
        self.animationTimer.callback = self.updateAnimation
        self.animationClock = SimpleTimer()

        loader = QtUiTools.QUiLoader()
        uifile = QtCore.QFile(':/ui/ddPlaybackPanel.ui')
        assert uifile.open(uifile.ReadOnly)

        self.widget = loader.load(uifile)
        uifile.close()

        self.ui = WidgetDict(self.widget.children())

        self.ui.viewModeCombo.connect('currentIndexChanged(const QString&)',
                                      self.viewModeChanged)
        self.ui.playbackSpeedCombo.connect(
            'currentIndexChanged(const QString&)', self.playbackSpeedChanged)
        self.ui.interpolationCombo.connect(
            'currentIndexChanged(const QString&)', self.interpolationChanged)

        self.ui.samplesSpinBox.connect('valueChanged(int)',
                                       self.numberOfSamplesChanged)
        self.ui.playbackSlider.connect('valueChanged(int)',
                                       self.playbackSliderValueChanged)

        self.ui.animateButton.connect('clicked()', self.animateClicked)
        self.ui.hideButton.connect('clicked()', self.hideClicked)
        self.ui.executeButton.connect('clicked()', self.executeClicked)
        self.ui.executeButton.setShortcut(QtGui.QKeySequence('Ctrl+Return'))
        self.ui.stopButton.connect('clicked()', self.stopClicked)

        self.ui.executeButton.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui.executeButton.connect(
            'customContextMenuRequested(const QPoint&)',
            self.showExecuteContextMenu)

        self.setPlan(None)
        self.hideClicked()

    def useDevelopmentColors(self):
        self.robotStateModelDisplayAlpha = 0.1
        self.playbackRobotModelUseTextures = False
        self.playbackRobotModelDisplayAlpha = 1

    def useOperationColors(self):
        self.robotStateModelDisplayAlpha = 1
        self.playbackRobotModelUseTextures = False
        self.playbackRobotModelDisplayAlpha = 0.5

    def showExecuteContextMenu(self, clickPosition):

        globalPos = self.ui.executeButton.mapToGlobal(clickPosition)

        menu = QtGui.QMenu()
        menu.addAction('Visualization Only')

        if not self.isPlanFeasible():
            menu.addSeparator()
            if self.isPlanAPlanWithSupports():
                menu.addAction('Execute infeasible plan with supports')
            else:
                menu.addAction('Execute infeasible plan')
        elif self.isPlanAPlanWithSupports():
            menu.addSeparator()
            menu.addAction('Execute plan with supports')

        selectedAction = menu.exec_(globalPos)
        if not selectedAction:
            return

        if selectedAction.text == 'Visualization Only':
            self.executePlan(visOnly=True)
        elif selectedAction.text == 'Execute infeasible plan':
            self.executePlan(overrideInfeasibleCheck=True)
        elif selectedAction.text == 'Execute plan with supports':
            self.executePlan(overrideSupportsCheck=True)
        elif selectedAction.text == 'Execute infeasible plan with supports':
            self.executePlan(overrideInfeasibleCheck=True,
                             overrideSupportsCheck=True)

    def getViewMode(self):
        return str(self.ui.viewModeCombo.currentText)

    def setViewMode(self, mode):
        '''
        Set the mode of the view widget. input arg: 'continous', 'frames', 'hidden'
        e.g. can hide all plan playback with 'hidden'
        '''
        self.ui.viewModeCombo.setCurrentIndex(
            self.ui.viewModeCombo.findText(mode))

    def getPlaybackSpeed(self):
        s = str(self.ui.playbackSpeedCombo.currentText).replace('x', '')
        if '/' in s:
            n, d = s.split('/')
            return float(n) / float(d)
        return float(s)

    def getInterpolationMethod(self):
        return str(self.ui.interpolationCombo.currentText)

    def getNumberOfSamples(self):
        return self.ui.samplesSpinBox.value

    def viewModeChanged(self):
        viewMode = self.getViewMode()
        if viewMode == 'continuous':
            playbackVisible = True
            samplesVisible = False
            interpolationVisible = True
        elif viewMode == 'frames':
            playbackVisible = False
            samplesVisible = True
            interpolationVisible = True
        elif viewMode == 'hidden':
            playbackVisible = False
            samplesVisible = False
            interpolationVisible = False
        else:
            raise Exception('Unexpected view mode')

        self.ui.samplesLabel.setVisible(samplesVisible)
        self.ui.samplesSpinBox.setVisible(samplesVisible)

        self.ui.interpolationLabel.setVisible(interpolationVisible)
        self.ui.interpolationCombo.setVisible(interpolationVisible)

        self.ui.playbackSpeedLabel.setVisible(playbackVisible)
        self.ui.playbackSpeedCombo.setVisible(playbackVisible)
        self.ui.playbackSlider.setEnabled(playbackVisible)
        self.ui.animateButton.setVisible(playbackVisible)
        self.ui.timeLabel.setVisible(playbackVisible)

        self.hidePlan()

        if self.plan:

            if viewMode == 'continuous' and self.autoPlay:
                self.startAnimation()
            elif viewMode == 'frames':
                self.updatePlanFrames()

    def playbackSpeedChanged(self):
        self.planPlayback.playbackSpeed = self.getPlaybackSpeed()

    def getPlaybackTime(self):
        sliderValue = self.ui.playbackSlider.value
        return (sliderValue / 1000.0) * self.endTime

    def updateTimeLabel(self):
        playbackTime = self.getPlaybackTime()
        self.ui.timeLabel.text = 'Time: %.2f s' % playbackTime

    def playbackSliderValueChanged(self):
        self.updateTimeLabel()
        self.showPoseAtTime(self.getPlaybackTime())

    def interpolationChanged(self):

        methods = {
            'linear': 'slinear',
            'cubic spline': 'cubic',
            'pchip': 'pchip'
        }
        self.planPlayback.interpolationMethod = methods[
            self.getInterpolationMethod()]
        self.poseInterpolator = self.planPlayback.getPoseInterpolatorFromPlan(
            self.plan)
        self.updatePlanFrames()

    def numberOfSamplesChanged(self):
        self.updatePlanFrames()

    def animateClicked(self):
        self.startAnimation()

    def hideClicked(self):

        if self.ui.hideButton.text == 'hide':
            self.ui.playbackFrame.setEnabled(False)
            self.hidePlan()
            self.ui.hideButton.text = 'show'
            self.ui.executeButton.setEnabled(False)

            if not self.plan:
                self.ui.hideButton.setEnabled(False)
        else:
            self.ui.playbackFrame.setEnabled(True)
            self.ui.hideButton.text = 'hide'
            self.ui.hideButton.setEnabled(True)
            self.ui.executeButton.setEnabled(True)

            self.viewModeChanged()

        self.updateButtonColor()

    def executeClicked(self):
        self.executePlan()

    def executePlan(self,
                    visOnly=False,
                    overrideInfeasibleCheck=False,
                    overrideSupportsCheck=False):
        if visOnly:
            _, poses = self.planPlayback.getPlanPoses(self.plan)
            self.onPlanCommitted(self.plan)
            self.robotStateJointController.setPose('EST_ROBOT_STATE',
                                                   poses[-1])
        else:
            if (self.isPlanFeasible() or overrideInfeasibleCheck) and (
                    not self.isPlanAPlanWithSupports()
                    or overrideSupportsCheck):
                self.manipPlanner.commitManipPlan(self.plan)

    def onPlanCommitted(self, plan):
        self.setPlan(None)
        self.hideClicked()

    def stopClicked(self):
        self.stopAnimation()
        self.manipPlanner.sendPlanPause()

    def isPlanFeasible(self):
        plan = robotstate.asRobotPlan(self.plan)
        return plan is not None and (max(plan.plan_info) < 10
                                     and min(plan.plan_info) >= 0)

    def getPlanInfo(self, plan):
        plan = robotstate.asRobotPlan(self.plan)
        return max(plan.plan_info)

    def isPlanAPlanWithSupports(self):
        return hasattr(
            self.plan,
            'support_sequence') or self.manipPlanner.publishPlansWithSupports

    def updatePlanFrames(self):

        if self.getViewMode() != 'frames':
            return

        numberOfSamples = self.getNumberOfSamples()

        meshes = self.planPlayback.getPlanPoseMeshes(
            self.plan, self.playbackJointController, self.playbackRobotModel,
            numberOfSamples)
        d = DebugData()

        startColor = [0.8, 0.8, 0.8]
        endColor = [85 / 255.0, 255 / 255.0, 255 / 255.0]
        colorFunc = scipy.interpolate.interp1d([0, numberOfSamples - 1],
                                               [startColor, endColor],
                                               axis=0,
                                               kind='slinear')

        for i, mesh in reversed(list(enumerate(meshes))):
            d.addPolyData(mesh, color=colorFunc(i))

        pd = d.getPolyData()
        clean = vtk.vtkCleanPolyData()
        clean.SetInput(pd)
        clean.Update()
        pd = clean.GetOutput()

        self.planFramesObj = vis.updatePolyData(d.getPolyData(),
                                                'robot plan',
                                                alpha=1.0,
                                                visible=False,
                                                colorByName='RGB255',
                                                parent='planning')
        self.showPlanFrames()

    def showPlanFrames(self):
        self.planFramesObj.setProperty('Visible', True)
        self.robotStateModel.setProperty('Visible', False)
        self.playbackRobotModel.setProperty('Visible', False)

    def startAnimation(self):
        self.showPlaybackModel()
        self.stopAnimation()
        self.ui.playbackSlider.value = 0
        self.animationClock.reset()
        self.animationTimer.start()
        self.updateAnimation()

    def stopAnimation(self):
        self.animationTimer.stop()

    def showPlaybackModel(self):
        self.robotStateModel.setProperty('Visible', True)
        self.playbackRobotModel.setProperty('Visible', True)
        self.playbackRobotModel.setProperty(
            'Color Mode', 1 if self.playbackRobotModelUseTextures else 0)
        self.robotStateModel.setProperty('Alpha',
                                         self.robotStateModelDisplayAlpha)
        self.playbackRobotModel.setProperty(
            'Alpha', self.playbackRobotModelDisplayAlpha)
        if self.planFramesObj:
            self.planFramesObj.setProperty('Visible', False)

    def hidePlan(self):
        self.stopAnimation()
        self.ui.playbackSlider.value = 0

        if self.planFramesObj:
            self.planFramesObj.setProperty('Visible', False)
        if self.playbackRobotModel:
            self.playbackRobotModel.setProperty('Visible', False)

        self.robotStateModel.setProperty('Visible', True)
        self.robotStateModel.setProperty('Alpha', 1.0)

    def showPoseAtTime(self, time):
        pose = self.poseInterpolator(time)
        self.playbackJointController.setPose('plan_playback', pose)

    def updateAnimation(self):

        tNow = self.animationClock.elapsed() * self.planPlayback.playbackSpeed
        if tNow > self.endTime:
            tNow = self.endTime

        sliderValue = int(1000.0 * tNow / self.endTime)

        self.ui.playbackSlider.blockSignals(True)
        self.ui.playbackSlider.value = sliderValue
        self.ui.playbackSlider.blockSignals(False)
        self.updateTimeLabel()

        self.showPoseAtTime(tNow)
        return tNow < self.endTime

    def updateButtonColor(self):
        if self.ui.executeButton.enabled and self.plan and not self.isPlanFeasible(
        ):
            styleSheet = 'background-color:red'
        elif self.ui.executeButton.enabled and self.plan and self.isPlanAPlanWithSupports(
        ):
            styleSheet = 'background-color:orange'
        else:
            styleSheet = ''

        self.ui.executeButton.setStyleSheet(styleSheet)

    def setPlan(self, plan):

        self.ui.playbackSlider.value = 0
        self.ui.timeLabel.text = 'Time: 0.00 s'
        self.ui.planNameLabel.text = ''
        self.plan = plan
        self.endTime = 1.0
        self.updateButtonColor()

        if not self.plan:
            return

        planText = 'Plan: %d.  %.2f seconds' % (
            plan.utime, self.planPlayback.getPlanElapsedTime(plan))
        self.ui.planNameLabel.text = planText

        self.startTime = 0.0
        self.endTime = self.planPlayback.getPlanElapsedTime(plan)
        self.interpolationChanged()
        info = self.getPlanInfo(plan)
        app.displaySnoptInfo(info)

        if self.ui.hideButton.text == 'show':
            self.hideClicked()
        else:
            self.viewModeChanged()

        self.updateButtonColor()

        if self.autoPlay and self.widget.parent() is not None:
            self.widget.parent().show()
예제 #39
0
class MarkerSource(vis.PolyDataItem):

    _requiredProviderClass = perceptionmeta.MarkerSourceMeta

    def __init__(self, name, callbackFunc=None, provider=None):
        vis.PolyDataItem.__init__(self, name, vtk.vtkPolyData(), view=None)
        self.timer = TimerCallback()
        self.timer.callback = self.showData
        self.timer.start()

        self.callbackFunc = callbackFunc
        self.resetColor = True

        if provider:
            self.setProvider(provider)
        else:
            self.provider = None

    def setProvider(self, provider):
        """
        Set the provider for this marker. This completes the initialisation of the object and displays the markers
        by pulling data from the provider

        :param provider: An instantiation of the MarkerSourceMeta abstract class
        :return:
        """
        if not issubclass(provider.__class__, self._requiredProviderClass):
            raise TypeError(
                "Attempted to set {} provider to {}, but it was not a"
                " subclass of {} as is required.".format(
                    self.__class__,
                    provider.__class__,
                    self._requiredProviderClass.__class__,
                )
            )

        self.provider = provider
        self.provider.set_consumer(self)
        if self.getProperty("Visible"):
            self.provider.start()

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItem._onPropertyChanged(self, propertySet, propertyName)
        if propertyName == "Visible" or propertyName == "Subscribe":
            if self.getProperty(propertyName):
                self.timer.start()
                if self.provider:
                    self.provider.start()
            else:
                self.timer.stop()
                if self.provider:
                    self.provider.stop()

        if self.provider:
            self.provider._on_property_changed(propertySet, propertyName)

    @CheckProvider
    def resetTime(self):
        self.provider.reset_time()

    @CheckProvider
    def showData(self):
        polyData = vtk.vtkPolyData()
        self.provider.get_mesh(polyData)

        if polyData.GetNumberOfPoints() == 0:
            # if an empty message is received, we will reset the default color when the next message is received
            self.resetColor = True

        if self.callbackFunc:
            self.callbackFunc()

        # update view
        self.setPolyData(polyData)

        if self.resetColor and polyData.GetNumberOfPoints() != 0:
            self.resetColor = False
            colorList = self.properties.getPropertyAttribute("Color By", "enumNames")
            index = colorList.index("color") if "color" in colorList else 0
            self.properties.setProperty("Color By", index)
예제 #40
0
class CameraTrackerManager(object):
    def __init__(self):
        self.target = None
        self.targetFrame = None
        self.trackerClass = None
        self.camera = None
        self.view = None
        self.timer = TimerCallback()
        self.timer.callback = self.updateTimer
        self.addTrackers()
        self.initTracker()

    def updateTimer(self):

        tNow = time.time()
        dt = tNow - self.tLast
        if dt < self.timer.elapsed / 2.0:
            return

        self.update()

    def setView(self, view):
        self.view = view
        self.camera = view.camera()

    def setTarget(self, target):
        """
        target should be an instance of TargetFrameConverter or
        any object that provides a method getTargetFrame().
        """

        if target == self.target:
            return

        self.disableActiveTracker()

        if not target:
            return

        self.target = target
        self.targetFrame = target.getTargetFrame()
        self.callbackId = self.targetFrame.connectFrameModified(self.onTargetFrameModified)

        self.initTracker()

    def disableActiveTracker(self):

        if self.targetFrame:
            self.targetFrame.disconnectFrameModified(self.callbackId)

        self.target = None
        self.targetFrame = None
        self.initTracker()

    def update(self):

        tNow = time.time()
        dt = tNow - self.tLast
        self.tLast = tNow

        if self.activeTracker:
            self.activeTracker.dt = dt
            self.activeTracker.update()

    def reset(self):
        self.tLast = time.time()
        if self.activeTracker:
            self.activeTracker.reset()

    def getModeActions(self):
        if self.activeTracker:
            return self.activeTracker.actions
        return []

    def onModeAction(self, actionName):
        if self.activeTracker:
            self.activeTracker.onAction(actionName)

    def getModeProperties(self):
        if self.activeTracker:
            return self.activeTracker.properties
        return None

    def onTargetFrameModified(self, frame):
        self.update()

    def initTracker(self):

        self.timer.stop()
        self.activeTracker = (
            self.trackerClass(self.view, self.targetFrame) if (self.trackerClass and self.targetFrame) else None
        )
        self.reset()
        self.update()

        if self.activeTracker:
            minimumUpdateRate = self.activeTracker.getMinimumUpdateRate()
            if minimumUpdateRate > 0:
                self.timer.targetFps = minimumUpdateRate
                self.timer.start()

    def addTrackers(self):
        self.trackers = OrderedDict(
            [
                ["Off", None],
                ["Position", PositionTracker],
                ["Position & Orientation", PositionOrientationTracker],
                ["Smooth Follow", SmoothFollowTracker],
                ["Look At", LookAtTracker],
                ["Orbit", OrbitTracker],
            ]
        )

    def setTrackerMode(self, modeName):
        assert modeName in self.trackers
        self.trackerClass = self.trackers[modeName]
        self.initTracker()
예제 #41
0
class MarkerArraySource(vis.PolyDataItemList):

    _requiredProviderClass = perceptionmeta.MarkerArraySourceMeta

    def __init__(self, name, singlePolyData=False, callbackFunc=None, provider=None):
        vis.PolyDataItemList.__init__(self, name, "color")
        # if singlePolyData is True, it means that all the markers received are merged into a single one
        self.singlePolyData = singlePolyData
        self.timer = TimerCallback()
        self.timer.callback = self.showData
        self.timer.start()
        self.callbackFunc = callbackFunc
        # self.topicName = topicName
        if provider:
            self.setProvider(provider)
        else:
            self.provider = None

    def setProvider(self, provider):
        """
        Set the provider for this marker array. This completes the initialisation of the object and displays the marker
        array by pulling data from the provider

        :param provider: An instantiation of the MarkerArraySourceMeta abstract class
        :return:
        """
        if not issubclass(provider.__class__, self._requiredProviderClass):
            raise TypeError(
                "Attempted to set {} provider to {}, but it was not a"
                " subclass of {} as is required.".format(
                    self.__class__,
                    provider.__class__,
                    self._requiredProviderClass.__class__,
                )
            )

        self.provider = provider
        self.provider.set_consumer(self)
        if self.getProperty("Visible"):
            self.provider.start()

    def _onPropertyChanged(self, propertySet, propertyName):
        vis.PolyDataItemList._onPropertyChanged(self, propertySet, propertyName)
        if propertyName == "Visible" or propertyName == "Subscribe":
            if self.getProperty(propertyName):
                self.timer.start()
                if self.provider:
                    self.provider.start()
            else:
                self.timer.stop()
                if self.provider:
                    self.provider.stop()

        if self.provider:
            self.provider._on_property_changed(propertySet, propertyName)

    def resetTime(self):
        self.provider.reset_time()

    @CheckProvider
    def showData(self):
        numPoly = self.provider.get_number_of_mesh()
        polyDataList = []
        if self.singlePolyData:
            polyData = vtk.vtkPolyData()
            self.provider.get_mesh(polyData)
            if polyData.GetNumberOfPoints() > 0:
                polyDataList.append(polyData)
        else:
            for i in range(0, numPoly):
                polyData = vtk.vtkPolyData()
                self.provider.get_mesh(polyData, i)
                polyDataList.append(polyData)

        if self.callbackFunc:
            self.callbackFunc()

        self.setPolyData(polyDataList)