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. And if you do that with your actual robot you are liable to break something.

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 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 update { {ActuatorName} }\
  {
  

::Actuator::update needs to be called, typically by Notify. You will need to tell notify to do this using:

::Notify::Subscribe Cycle ::Actuator::update YourActuatorName

Once you have subscribed for updates in this manner, the actuator will be notified every cycle.

You can get feedback from your actuator in either of two ways: Measure or Limit. These will be described in more detail below. But for now lets just define their parameters.

  proc Measure_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.
  

::Actuator::Measure provides a value to indicate the position of its Actuator. The range of the value is determined by MeasureExpr. That value is then stuffed into OutputReg.

  proc Measure_update { {ActuatorMeasureName} {PositionValue} }\
  {
  

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

  proc Limit_new { {ActuatorLimitName} {NameOnCanv} \
	{ParentActuatorName} {Limit1} {Limit2} \
        {OutputReg} {BitPt} } \
  {
    # ActuatorLimitName = Unique name for the ::Actuator::Limit.
    # NameOnCanv = Child of its respective ::Actuator::Limit.
    # ParentActuatorName = Name of the Actuator we are measuring.
    # Limit1 = If $PositionValue <= $Limit1 then output=true
    # Limit2 = If $PositionValue >= $Limit2 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.
  

::Actuator::Limit gives a yes/no response indicating whether its Actuator is between two limits or not.

  proc Limit_update { {ActuatorLimitName} {PositionValue} }\
  {
  

::Actuator::Limit_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.

  ::Notify::Subscribe Cycle ::Actuator::update actuator
  

The line above, from TheRobot.tcl, tells the simulation to notify the actuator to update itself every cycle based on the values of the root scope variables $::pwm09 and $::pwm11.


::Actuator::Measure

An actuator is not very interesting if the robot has no way to sense where it is. ::Actuator::Measure and ::Actuator::Limit provide ways to do that. ::Actuator::Measure simulates a potentiometer or similar linear device which can indicate the absolute position of the actuator. ::Actuator::Measure is specifically designed to work closely with Actuator, and must be attached to one. An Actuator can have any number of ::Actuator::Measure or ::Actuator::Limit 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" {{::Actuator::Measure_update actmeasL}}
  ::Actuator::Measure_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 ::Actuator::Measure 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:


::Actuator::Limit

An actuator is not very interesting if the robot has no way to sense where it is. ::Actuator::Limit simulates a limit switch to indicate the absolute position of the actuator. ::Actuator::Limit is specifically designed to work closely with Actuator, and must be attached to one. An Actuator can have any number of ::Actuator::Measure or ::Actuator::Limit 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" {{::Actuator::Limit_update actmeasL}}
  ::Actuator::Measure_new actmeasL actuateL \
    {($PositionValue-50.0)/50*127} ::rc_ana_in01 "#3f7f7f"
  ::Actuator::Limit_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 of the ::Actuator::Limit object. It is black when the output is zero, and red when it is one.

The figure above shows how to set the two limits to simulate pretty much any limit switch behavior you might encounter in real life. Choose whatever will work for you.



Last modified 11 Dec 2006
http://brown.armoredpenguin.com/~abrown/contact.html
http://brown.armoredpenguin.com/~abrown/first/first2006/Scalawags/Simulator2006/ActuatorObject.html