FIRST Robot Simulator - ActuatorObject


What Is Simulated

ActuatorObject simulates a moving element. And example would be a robotic arm. If desired ActuatorObject can simulate the analog feedback indicating the position of the element. If desired ActuatorObject can simulate limit switches.

Graphically, ActuatorObject can take one of three forms: horizontal bar, vertical bar, or rotary. These forms are strictly for esthetic appeal. Functionally, the three forms are equivalent. In each case, ActuatorObject is intended to have limited motion. Motion is defined as going between zero and 100. The horizontal and vertical bar should be asked to move only as far as the box they are specified in, which is 100. The rotary representation should be asked to rotate less than 360 degrees, which is also 100. Similarly, do not ask for reverse motion beyond the zero position. Motions beyond these limits may result in undefined behavior.

ActuatorObject takes one analog input, the SpeedExpr, representing the motor channel. The element moves in one dimension.

ActuatorObject uses a callback mechanism to simulate analog feedback and limit switches. Standard functions are defined to provide this functionality.


Where Used

ActuatorObject.tcl will typically be sourced in TheRobot.tcl. The declaration for Actuator_new will then also be created in TheRobot.tcl.


GUI View

This Horizontal Actuator is shown without any feedback mechanism. (No analog or limit switches). This is legal, but probably not a good idea.

Shown at position 0.

This Vertical Actuator is shown without any feedback mechanism. (No analog or limit switches). This is legal, but probably not a good idea.

Shown at position 20.

This Rotary Actuator is shown without any feedback mechanism. (No analog or limit switches). This is legal, but probably not a good idea.

Shown at position 20.

Which view you choose will be a combination of esthetics (perhaps looking somewhat like your physical robot actuator) and of practicality (fitting the simulation well onto the computer screen).


Programmers View

There are six proc[edures] in ActuatorObject.tcl. The first few lines of each proc lists the parameters required.

    proc Actuator_new { {ActuatorName} {NameOnCanv} {XorYs} \
			{InitialPositionValue} {SpeedExpr} {fastratio} \
			{shape} {BackColor} {Comment} {CallbackList} } \
  {
    # ActuatorName = Unique name for the Actuator.
    # NameOnCanv = 
    # XorYs = The greatest dimension of actuator.  Note: linear actuators
    #   are always 20 in the smaller dimension.  XorYs should be at least
    #   40.  A good value is 100.
    # InitialPositionValue = PositionValue at time 0.
    #   Value must be between 0 and 100.
    # SpeedExpr = Signed value indicating how fast the wheel should move.
    # fastratio = ratio of fast to slow cycles.
    # shape = horizontal|vertical|rotary graphic object.
    # BackColor = Background color the actuator sits on.
    # Comment = Text to be displayed with the graphic object.
    # CallbackList = List of functions to be called any time the
    #	internal analog state of the Actuator changes.
    #   Note that the PositionValue will be appended to each functions
    #   call.  Callbacks will be called every time Actuator_new is called.
    #   PositionValue is a number which goes from 0 to 100 corresponding
    #   to the limits of the Actuator motion as shown on the GUI.
    #   Motion beyond those limits is undefined.
  

The parameters ActuatorName and NameOnCanv are constants.

SpeedExpr is the power to the actuator.

SpeedExpr
value
ActuatorObject
horizontal
ActuatorObject
vertical
ActuatorObject
rotary
positive to 100 right up clockwise
negative to 0 left down counter-clockwise
  proc Actuator_update { {ActuatorName} }\
  {
  

Actuator_update needs to be called, typically in Updates.tcl.

  proc ActuatorMeasure_new { {ActuatorMeasureName} \
	{ParentActuatorName} {MeasureExpr} {OutputReg} {BackColor} } \
  {
    # ActuatorMeasureName = Unique name for the ActuatorMeasure.
    # ParentActuatorName = Name of the Actuator we are measuring.
    # MeasureExpr = Expression in terms of $PositionValue.
    # OutputReg = Name of register to be controlled.
    # BackColor = Background color the actuator sits on.
  
  proc ActuatorMeasure_update { {ActuatorMeasureName} {PositionValue} }\
  {
  

ActuatorMeasure_update is designed to be used in a callback from Actuator, which will provide the PostitionValue.

  proc ActuatorLimit_new { {ActuatorLimitName} {NameOnCanv} \
	{ParentActuatorName} {Limit1} {Limit2} \
        {OutputReg} {BitPt} } \
  {
    # ActuatorLimitName = Unique name for the ActuatorLimit.
    # NameOnCanv = Child of its respective ActuatorLimit.
    # ParentActuatorName = Name of the Actuator we are measuring.
    # Limit1 = If $PositionValue <= $Limit1 then output=true
    # Limit2 = If $PositionValue >= $Limit1 then output=true
    #		If $Limit1>$Limit2, middle true, else middle false
    # OutputReg = Name of register to be controlled.
    # BitPt = Mask bits to determine what bits of $OutputReg are set.
  
  proc ActuatorLimit_update { {ActuatorLimitName} {PositionValue} }\
  {
  

ActuatorLimit_update is designed to be used in a callback from Actuator, which will provide the PostitionValue.


Example

We can put two actuators stacked above a tractor using code like this:

  source {ActuatorObject.tcl}

  toplevel .robot; wm group .robot .
  frame .robot.actuates
  Actuator_new actuateL .robot.actuates.actuateL 80 0 {$::pwm08-127} \
    {$::fastratio} horizontal "#af7f7f" "L" {}
  Actuator_new actuateR .robot.actuates.actuateR 80 0 {127-$::pwm11} \
    {$::fastratio} horizontal "#af7f7f" "R" {}
  pack .robot.actuates.actuateL .robot.actuates.actuateR -side left

  pack .robot.actuates .robot.motors -side top
  

Notice the callback parameter must be specified "{}" even if it is empty.

The declaration above is in TheRobot.tcl. The double colons in front of each variable name makes it operate at the root namespace of the Tcl program. In this example, the left actuator responds to motor commands in reverse.

  Actuator_update actuator
  

The update code above is in Updates.tcl. Each time it is called, the Actuator image is updated based on the values of the root scope variables $::pwm09 and $::pwm11.


ActuatorMeasure

An actuator is not very interesting if the robot has no way to sense where it is. ActuatorMeasure and ActuatorLimit provide ways to do that. ActuatorMeasure simulates a potentiometer or similar linear device which can indicate the absolute position of the actuator. ActuatorMeasure is specifically designed to work closely with Actuator, and must be attached to one. An Actuator can have any number of ActuatorMeasure or ActuatorLimit objects attached to it. Lets look at an example based on the actuator above.

  source {ActuatorObject.tcl}

  toplevel .robot; wm group .robot .
  frame .robot.actuates
  Actuator_new actuateL .robot.actuates.actuateL 80 0 {$::pwm08-127} \
    {$::fastratio} horizontal "#af7f7f" "L" {{ActuatorMeasure_update actmeasL}}
  ActuatorMeasure_new actmeasL actuateL \
    {($PositionValue-50.0)/50*127} ::rc_ana_in01 "#3f7f7f"
  pack .robot.actuates.actuateL -side left
  pack .robot.actuates .robot.motors -side top
  

We have created an ActivateMeasure named actmeasL and attached it to the Actuator acuateL. The PostionValue (ranging from 0 to 100) is converted to a range from -127 to 127. The resulting number is shown in a box on the screen and output to the global variable rc_ana_in01. The resulting Actuator+ActuatorMeasure looks like this:


ActuatorLimit

An actuator is not very interesting if the robot has no way to sense where it is. ActuatorLimit simulates a limit switch to indicate the absolute position of the actuator. ActuatorLimit is specifically designed to work closely with Actuator, and must be attached to one. An Actuator can have any number of ActuatorMeasure or ActuatorLimit objects attached to it. Lets look at an example based on the actuator+measure above.

  source {ActuatorObject.tcl}

  toplevel .robot; wm group .robot .
  frame .robot.actuates
  Actuator_new actuateL .robot.actuates.actuateL 80 0 {$::pwm08-127} \
    {$::fastratio} horizontal "#af7f7f" "L" {{ActuatorLimit_update actmeasL}}
  ActuatorMeasure_new actmeasL actuateL \
    {($PositionValue-50.0)/50*127} ::rc_ana_in01 "#3f7f7f"
  ActuatorLimit_new actlimL .robot.actuates.actuateL.actlimL actuateL \
    45 30 ::portbb 1
  pack .robot.actuates.actuateL -side left
  pack .robot.actuates .robot.motors -side top
  

We have created an ActivateLimit named actlimL and attached it to the Actuator acuateL. If PostionValue (ranging from 0 to 100) is between 55 and 40 the limit switch is depressed, resulting in a 0 output. Outside of the limits 40 and 55, the output is 1. The output is sent to the global portbb on bit 1. The other bits of portbb are not touched. The resulting Actuator+ActuatorMeasure+ActuatorLimit looks like this:

The black rectangle just to the left of the "L" is the image if the ActuatorLimit object. It is black when the output is zero, and red when it is one.



Last modified 10 Dec 2006
http://brown.armoredpenguin.com/~abrown/contact.html
http://brown.armoredpenguin.com/~abrown/first/first2005/Simulator2005/ActuatorObject.html