了解脚本

时间:2017-04-24 12:55:01

标签: python math geometry

我有一个参数化圆圈的脚本。这用于模拟程序。但是,我很难理解脚本的某些部分,我想学习这个。我已经参加了一些python在线课程,但我不确定这是否足以理解它。例如,下面的部分。

是否在圆周上找到3个点以确定它是否为圆?整个代码低于其他代码。表达式V1中的V2V3fabs((V1*V2)/(sqrt(V1*V1*V2*V2))) > 0.95是什么意思?

 for i in range(skipCount):
    P1 = points[i]
    P2 = points[i+1]
    if i+2 < skipCount:
      P3 = points[i+2]
    else:
      P3 = points[i-1]
    #endif

整个代码:

       def OnAbort():
  cmd.Checked = False
  pass

#-------------------------------------------------------------------------------

def firstState():

  if selProg.Count != 1:
    print "Circular Move: No program selected. Aborting..."
    return False
  #endif

  cmd.Checked = True

  program = selProg.getItem(0)
  routine = program.CurrentRoutine
  controller = program.Controller
  addLimitProperty( cmd, VC_REAL, "CircularSpeed", True, False, False, 100., None, "Velocity", 0., controller.MaxCartesianSpeed )
  cmp = controller.Component

  # Fix for Main Program selection BUG
  if routine != program.MainRoutine:
    if selStmt.Count:
      stmt = selStmt.getItem(0)
      if stmt.Routine != routine:
        routine = program.MainRoutine
      #endif
    #endif
  #endif

  if not displayPropertyDialog( cmd.Name, "Circular Motion Settings", ''):
    OnAbort()
    return False
  #endif

  phName = 'CircularMove'
  ph = cmp.findBehaviour(phName)
  processName = 'CircularMove'
  if ph != None:
    if ph.Script[:12] != "#VERSION 1.2":
      print "Updating Script " + processName
      ph.delete()
      ph = None
    #endif
  #endif

  if ph == None:
    ph = cmp.createBehaviour(VC_PYTHON_PROCESS_HANDLER, phName)

    # set the bitmap of the process, that appears in the RSL statement grid
    iconuri = getCommandPath()
    iconuri = iconuri[:-3] + ".bmp"
    icon = getApplication().loadBitmap(iconuri)
    ph.Icon = icon

    # register process handler to the rsl executor behavior(s) of the robot
    xl = cmp.findBehavioursByType(VC_RSLEXECUTOR)
    for x in xl:
      phl = x.ProcessHandlers
      phl.append(ph)
      x.ProcessHandlers = phl
    #endfor

    ph.Process = processName
    ph.Script = """#VERSION 1.2
from vcRslProcessHandler import *
from math import *
import vcMatrix

RAD_TO_DEG = 90.0/atan2(1.,0.)

def OnExecuteProcess(executor, process_statement):

  # Check if at end of Circle Move
  skipProp = process_statement.getProperty( "SkipCount" )
  if skipProp != None:
    #delete all dummy statements to trick RSL program pointer
    routine = process_statement.Routine
    s = process_statement.Index - skipProp.Value + 1
    for i in range( skipProp.Value ):
      routine.deleteStatement(s)
    return
    routine.endBatch()
  #endif

  cntr = executor.Controller
  routine = process_statement.Routine
  stmts = routine.Statements

  if process_statement.getProperty( "NumPoints" ):
    skipCount = process_statement.NumPoints
  else:
    skipCount = 2
  #endif

  idx = process_statement.Index
  if idx+skipCount >= routine.StatementCount:
    return
  #endif
  for i in range(skipCount):
    if stmts[idx+1+i].Type not in [VC_STATEMENT_LINMOTION, VC_STATEMENT_PTPMOTION]:
      return
    #endif
  #endfor

  cntr.clearTargets()

  trg = cntr.createTarget()

  points = [ trg.Target ]
  for i in range(skipCount):
    points.append(stmts[idx+1+i].Target )
  #endfor

  for i in range(skipCount):
    P1 = points[i]
    P2 = points[i+1]
    if i+2 < skipCount:
      P3 = points[i+2]
    else:
      P3 = points[i-1]
    #endif

    V1 = P1.P - P2.P
    V2 = P2.P - P3.P
    V3 = P3.P - P1.P
    if fabs((V1*V2)/(sqrt(V1*V1*V2*V2))) > 0.95:
      print "ERROR: CircularMove: Points are colinear"
      getSimulation().halt()
      return
    #endif

    N = V1 ^ V2
    circleRadius = V1.length()*V2.length()*V3.length()/(2.0*N.length())

    alpha = -1.0*(V2*V2)*(V1*V3)
    beta = -1.0*(V3*V3)*(V2*V1)
    gamma = -1.0*(V1*V1)*(V3*V2)

    cP = (alpha*P1.P + beta*P2.P + gamma*P3.P)*(1.0/(2.0*N*N))

    R = P1.P - cP

    xx = P1.P - cP
    xx.normalize()
    N.normalize()

    yy = N ^ xx
    yy.normalize()

    V = P2.P - cP
    V.normalize()
    if process_statement.FullCircle:
      circleAngle = 360.0
      P3 = P1
    else:
      circleAngle = atan2( V*yy, V*xx )*RAD_TO_DEG
      if circleAngle < 0.0 :
        circleAngle += 360.0
      #endif
    #endif

    vel = process_statement.CircularSpeed
    acc = cntr.MaxCartesianAccel

    arg = vel*vel/(4.*circleRadius*acc)
    if arg > 1.0:
      arg = 1.0
    #endif

    dAngle = 2.0*asin( arg ) * RAD_TO_DEG

    i = (int) (circleAngle/dAngle)
    if i < 2:
      i = 2
    #endif

    dAngle = circleAngle/i
    if dAngle < 5.0:
      dAngle = 5.0
    #endif

    trg.MotionType = VC_MOTIONTARGET_MT_LINEAR
    trg.CartesianSpeed = vel
    trg.AccuracyMethod = VC_MOTIONTARGET_AM_VELOCITY
    trg.AccuracyValue = vel

    dC = vcMatrix.new()
    dC.setAxisAngle( N.X, N.Y, N.Z, circleAngle )
    dC.translateAbs( cP.X, cP.Y, cP.Z )

    invP1 = dC*P1
    invP1.invert()
    P12 = invP1*P2

    k12 = P12.getAxisAngle()
    if circleAngle > 180.0 and abs(k12.W) > 0.1:
      k12.W = -(360.0 - k12.W)
    #endif
    if k12.Z < -0.1:
      k12.W *= -1.0
    #endif

    dTheta = k12.W/circleAngle*dAngle
    dP12 = vcMatrix.new()

    C0 = vcMatrix.new(P1)
    C0.translateAbs( -cP.X, -cP.Y, -cP.Z )

    theta = 0.0
    angle = 0.0
    while angle < circleAngle: 

      dC.setAxisAngle( N.X, N.Y, N.Z, angle )
      dP12.setAxisAngle( k12.X, k12.Y, k12.Z, theta )

      C = dC*C0*dP12

      trg.Target = C
      cntr.addTarget(trg)
      angle += dAngle
      theta += dTheta
    #endwhile

  #endif
  trg.AccuracyValue = 0.0
  trg.Target = P2
  cntr.addTarget(trg)
  cntr.move()

  # Mark end of Circle Move 
  routine.beginBatch()
  stmt = routine.createStatement( VC_STATEMENT_PROCESS )
  stmt.Index = process_statement.Index+1
  stmt.Process = "CircularMove"
  prop = stmt.createProperty( VC_INTEGER, "SkipCount" )
  prop.Value = skipCount

  # Add dummy Comment statements to trick RSL program pointer
  for i in range( skipCount-1 ):
    stmt = routine.createStatement( VC_STATEMENT_COMMENT )
    stmt.Index = process_statement.Index+1
  #endfor

#-------------------------------------------------------------------------------
def OnFinalize():
  pass
#-------------------------------------------------------------------------------
def OnReset():
  pass
#-------------------------------------------------------------------------------
"""  
  #endif

  ps = routine.createStatement(VC_STATEMENT_PROCESS)
  ps.Name = "CM1"
  ps.Process = processName
  for p in ps.Properties:
    if p.Name == "Process":
      p.IsVisible = False

  addLimitProperty( ps, VC_INTEGER, "NumPoints", True, False, False, 2, None, "", 2, 8)
  copyProperties( cmd, ps )

  cmd.Checked = False

  stmt = selStmt.getItem(0)
  if stmt:
   ps.Index = stmt.Index+1

  return True

addState(firstState)
#endif

1 个答案:

答案 0 :(得分:0)

提到的代码检查角度P1-P2-P3的余弦的绝对值是否> 0.95,找出这些点是否形成接近0或180度的角度。

代码使用scalar product property