Adding Global Position

Hi everybody,

I am working with KUKA Sim Pro 3 and trying to create some robot program routines automatically and adding some predefined global positions at the beginning and end of every routine. And afterwards my aim is to create these programs using a post-processor.

 

Could you please advise how I can add global positions to the robot?

 

Thank you in advance

 

Do you mean Home positions? You can create a script that listens for when new statements are added in which they are never at the very beginning nor end of the routine’s scope – by default new statements are added to end, but the addStatement() method has an optional param for defining index, and then scope of a routine can always be edited.

You can use Python API to create KRL statements (the ones you see in Job Map panel) but I will need to refind an example on how to do this. Basically, you have to use the netCommand() and use something recgonized by a DLL. I will look and attach it when I find it.

Thanks for quick reply. An example of creating KRL statements using PYTHON API would be really helpful.

But No, I don’t mean HOME positions. HOME positions are defined as properties in KUKA SimPro and have joint values not cartesian coordinates.

In our Robot programs we usually use global positions for certain things. Because these positions are used in different movement programs in different scenarios.

 

So let’s say I want to define a position as global and want to use this position in different programs(as I can do with HOME positions in VC). When I change the global position somewhere in the robot Program, It should be updated everywhere in the robot.

 

Visual Components does not allow same Position name to exist more than one as statement. That is the main problem I have now. So i can just not use addStatemen() function in a routine and set the name.

 

I am now trying to add new positions into Robot Properties like default HOME positions(but in cartesian coordinates not joint values) and be able to add these positions everywhere in the sub programs as we can do with HOME positions. Any help would be amazing here.

 

 

You should be able to add a vcProperty of type vcMatrix to a robot, thereby the position matrix of robot position in World coordinates could reference that property.

For position names, a workaround is to add a new vcProperty of type String to motion statement/position, which does not have to a unique value, i.e. app only cares if the native properties are unique.

I will make an example real quick and attach it. Still searching for that KRL example.

Does the attached file and script help? I created the matrix property in GUI to keep things simple.

from vcScript import *

comp = getComponent()

#get property to set its value
point = comp.getProperty("GLOBAL::P1")

#I taught robot a position, and now using that position
#another option is to use the readIn() method in vcMotionStatement
rx = comp.getBehaviour("Executor")
statement = rx.Program.MainRoutine.Statements[0]
s_point = statement.Positions[0].PositionInWorld

#value is now stored in property
point.Value = s_point

new_statement = rx.Program.MainRoutine.addStatement(VC_STATEMENT_LINMOTION)
new_statement.Positions[0].PositionInWorld = point.Value

vcPositionFrame, vcStatement, vcRoutine, vcProgram, and has createProperty() method

Test-Global-Position-Matrix-property-for-robot.vcmx (991 KB)

1 Like

The python API for Kuka.Sim statements is not complete as far as I know. The addStatement method that zesty suggested creates a Visual Components statement that the GUI and the post processor doesn’t fully understand.

As zesty said there should be some level of python api for the Kuka statements that you can use thru netCommand, but I would recommend to ask Kuka support directly. Or let’s see if zesty finds an example for you.

And in general each statement holds the positional data. So the position can’t be shared between statement for now. But a script could make sure that the positions in specific stataments are similar by somehow syncing them. I’ll discuss with zesty.

Thank you guys, that was really helpful.

I edited the program as follows:

from vcScript import *

comp = getComponent()

#get property to set its value
point = comp.getProperty("GLOBAL::Job1_PickUp")

#I taught robot a position, and now using that position
#another option is to use the readIn() method in vcMotionStatement
rx = comp.getBehaviour("Executor")
statement = rx.Program.MainRoutine.Statements[0]
s_point = statement.Positions[0].PositionInWorld

#value is now stored in property
point.Value = s_point

new_statement = rx.Program.MainRoutine.addStatement(VC_STATEMENT_LINMOTION)
new_statement.Positions[0].PositionInWorld = point.Value
prop = new_statement.createProperty(VC_STRING, "GLOBAL::PosName")
prop.Value = "Job1_PickUp"

Now I can add a VC_STRING type property to new_statement. Even though statement names are different, under global section, I can set the name of this PosName variable as I want.

new property

 

As you guys also mentioned nex step would be following:

In Job Map section , If I select a position with GLOBAL::PosName property and click on touch up button or change value of it manually, I should update all positions in robot program with the same GLOBAL::PosName property.

 

I think that could be possible. What kind of event handler should I use in this case?

 

Thank you in advance…

For adding KRL statements, I attached a sample layout. The script is in the robot. Here is the script, which can you modify into a module that you can import in other scripts:

from vcScript import *

KRLStatements = {
  VC_STATEMENT_CALL:'VisualComponents.Create3D.ICallStatement, Create3D.Shared',
  'CIRMOTION':'KukaBe.Applications.JobMap.JobMapCommands.CircStatement',
  VC_STATEMENT_COMMENT:'KukaBe.Applications.JobMap.JobMapCommands.CommentStatement',
  'FOLD':'KukaBe.Applications.JobMap.JobMapCommands.FoldStatement',
  VC_STATEMENT_WAITBIN:'KukaBe.Applications.JobMap.JobMapCommands.GetInputStatement',
  VC_STATEMENT_HALT:'VisualComponents.Create3D.IHaltStatement, Create3D.Shared',
  VC_STATEMENT_IF:'VisualComponents.Create3D.IIfStatement, Create3D.Shared',
  VC_STATEMENT_LINMOTION:'KukaBe.Applications.JobMap.JobMapCommands.LinStatement',
  VC_STATEMENT_PTPMOTION:'KukaBe.Applications.JobMap.JobMapCommands.PtpStatement',
  'PTPHOME':'KukaBe.Applications.JobMap.JobMapCommands.PtpHomeStatement',
  VC_STATEMENT_DEFINE_BASE:'VisualComponents.Create3D.ISetBaseStatement, Create3D.Shared',
  VC_STATEMENT_SETBIN:'KukaBe.Applications.JobMap.JobMapCommands.SetOutputStatement',
  VC_STATEMENT_SETPROPERTY:'VisualComponents.Create3D.ISetPropertyStatement, Create3D.Shared',
  VC_STATEMENT_DEFINE_TOOL:'VisualComponents.Create3D.ISetToolStatement, Create3D.Shared',
  VC_STATEMENT_DELAY:'KukaBe.Applications.JobMap.JobMapCommands.WaitStatement',
  VC_STATEMENT_WHILE:'VisualComponents.Create3D.IWhileStatement, Create3D.Shared'
  }


def addKRLStatement(scope,type,index=-1,before=False):
  '''
  Adds a KRL statement to a given scope based on the given type of VC statement.
  The default index for new statement in scope is -1, end of scope.
  A placeholder is used to place new statement in scope.
  Afterward, the placeholder is removed.
  If you want new statement to come before placeholder, pass before a True value.
  
  Technical: The netCommand is used to call <LoadStatementAction> to add the KRL statement.
  '''
  
  placeholder = scope.addStatement(VC_STATEMENT_COMMENT,index)
  app.SelectionManager.setSelection(placeholder,True)

  krl_type = KRLStatements[type]
  netCommand = app.findCommand("netCommand")
  netCommand.execute("LoadStatementAction",krl_type, before)
  
  scope.deleteStatement(placeholder)


def testPlacementOfNewKRLStatementInProgram(prop):
  '''
  An event handler used to test the creation of KRL statements in robot program.
  Handler is triggered when button, a component property, is clicked in GUI.
  '''
  rx = comp.findBehavioursByType(VC_ROBOTEXECUTOR)[0]  
  mr = rx.Program.MainRoutine
  mr.clear()

  sr = rx.Program.Routines[0]
  sr.clear()
  
  ##Simple test scenarios
  addKRLStatement(mr,VC_STATEMENT_DELAY)
  addKRLStatement(sr,VC_STATEMENT_DELAY)
  
  ##statement scope test scenario
  addKRLStatement(sr,VC_STATEMENT_WHILE)
  curveball = sr.Statements[-1]

  #current iteration of method requires vcScope not statement
  #createKRLStatement(curveball,VC_STATEMENT_DELAY)
  createKRLStatement(curveball.Scope,VC_STATEMENT_DELAY)
 

app = getApplication()
comp = getComponent()
button = comp.getProperty("TEST::KRL")
button.OnChanged = testPlacementOfNewKRLStatementInProgram

My script is based on the following script developed by someone else:

#-------------------------------------------------------------------------------
# Dictionary which maps VC statements to KRL equivalence
KRLStatements = {
  VC_STATEMENT_CALL:'VisualComponents.Create3D.ICallStatement, Create3D.Shared',
  'CIRMOTION':'KukaBe.Applications.JobMap.JobMapCommands.CircStatement',
  VC_STATEMENT_COMMENT:'KukaBe.Applications.JobMap.JobMapCommands.CommentStatement',
  'FOLD':'KukaBe.Applications.JobMap.JobMapCommands.FoldStatement',
  VC_STATEMENT_WAITBIN:'KukaBe.Applications.JobMap.JobMapCommands.GetInputStatement',
  VC_STATEMENT_HALT:'VisualComponents.Create3D.IHaltStatement, Create3D.Shared',
  VC_STATEMENT_IF:'VisualComponents.Create3D.IIfStatement, Create3D.Shared',
  VC_STATEMENT_LINMOTION:'KukaBe.Applications.JobMap.JobMapCommands.LinStatement',
  VC_STATEMENT_PTPMOTION:'KukaBe.Applications.JobMap.JobMapCommands.PtpStatement',
  'PTPHOME':'KukaBe.Applications.JobMap.JobMapCommands.PtpHomeStatement',
  VC_STATEMENT_DEFINE_BASE:'VisualComponents.Create3D.ISetBaseStatement, Create3D.Shared',
  VC_STATEMENT_SETBIN:'KukaBe.Applications.JobMap.JobMapCommands.SetOutputStatement',
  VC_STATEMENT_SETPROPERTY:'VisualComponents.Create3D.ISetPropertyStatement, Create3D.Shared',
  VC_STATEMENT_DEFINE_TOOL:'VisualComponents.Create3D.ISetToolStatement, Create3D.Shared',
  VC_STATEMENT_DELAY:'KukaBe.Applications.JobMap.JobMapCommands.WaitStatement',
  VC_STATEMENT_WHILE:'VisualComponents.Create3D.IWhileStatement, Create3D.Shared'
  }

def addKRLStatement( scope, VCStatementType ):
  global activeStatement

  if not activeStatement: # dirty trick for special case of an empty program
    dummyStatement = scope.addStatement(VC_STATEMENT_PTPMOTION, -1)
    selectionManager.setSelection(dummyStatement)
  else:
    dummyStatement = None
    selectionManager.setSelection(activeStatement) # This trick is needed so dotNET knows where to add the statement

  statementtype = KRLStatements[VCStatementType] # dictionary lookup to map desired VC statement to the KRL equivalent in dotNET.

  netCommand.execute('LoadStatementAction', statementtype, False ) # False flag operation means AFTER active statement
  activeStatement = selectionManager.getSelection(VC_SELECTION_STATEMENT)[0] # how we get the new statement created in dotNET
  #activeStatement.Index += 1

  if dummyStatement: # clean up the empty program special case
    scope.deleteStatement(dummyStatement)

  selectionManager.setSelection(activeStatement) # Make sure statement is really active for the next round
  return activeStatement

def addPTPStatement( worldPosition, base, tool, speed ):
  global stmtIndex

  if KUKASIM:
    stmt = addKRLStatement(scope, VC_STATEMENT_PTPMOTION )
    stmt.VelPtp = speed
  else:
    stmt = scope.addStatement(VC_STATEMENT_PTPMOTION, stmtIndex )
    stmt.JointSpeed = speed

  stmt.Base = base
  stmt.Tool = tool
  positionFrame = stmt.Positions[0]
  positionFrame.PositionInWorld = worldPosition
  stmtIndex = stmt.Index + 1 # next statement will be added AFTER this one
  return stmt

def addLINStatement( worldPosition, base, tool, speed ):
  global stmtIndex

  if KUKASIM:
    stmt = addKRLStatement(scope, VC_STATEMENT_LINMOTION )
    stmt.VelAbs = speed
  else:
    stmt = scope.addStatement(VC_STATEMENT_LINMOTION, stmtIndex )
    stmt.MaxSpeed = speed

  stmt.Base = base
  stmt.Tool = tool
  positionFrame = stmt.Positions[0]
  positionFrame.PositionInWorld = worldPosition
  stmtIndex = stmt.Index + 1 # next statement will be added AFTER this one
  return stmt

def addDelayStatement( delay ):
  global stmtIndex

  if KUKASIM:
    stmt = addKRLStatement(scope, VC_STATEMENT_DELAY )
    stmt.Time = delay
  else:
    stmt = scope.addStatement(VC_STATEMENT_DELAY, stmtIndex )
    stmt.Delay = delay

  stmtIndex = stmt.Index + 1 # next statement will be added AFTER this one
  return stmt

This is what I know:

  • You cannot use vcTeachContext to make this work. The placement of the statement is dependent on the active statement in robot program, thereby dependent on selection manager. For example, even if you change the active statement in teach context using vcTeachContext methods, it won't update selection manager nor matter to the .NET command called to add the KRL statement.
  • The latter script was checking a lot of stuff, like the active statement in selection manager. I tried that, but it got too complicated when dealing with statements that have one or more scopes like While and If statements. So the former script just adds the placeholder to the given scope and "appends" it to the selection recognized by the manager.
This is what I do not know:
  • Where do we go from here?

Testing-KRL-statements-in-Python-API.vcmx (985 KB)