Position Types
Position variable types for storing and controlling multi-axis motion positions.
Namespace: ControlBee.Variables
Overview
Position types represent multi-dimensional motion coordinates that are mapped to physical motion axes. They provide:
- Axis-mapped Storage - Positions are automatically linked to motion axes
- Motion Control - Built-in methods for moving axes to stored positions
- Position Teaching - Capture current axis positions
- Change Tracking - Notifications when position values change
- Index Access - Direct access to individual axis values
ControlBee provides four position types:
- Position1D - Single-axis position (1 value)
- Position2D - Two-axis position (2 values)
- Position3D - Three-axis position (3 values)
- Position4D - Four-axis position (4 values)
Choosing Position Type
Select the position type based on the number of axes to control:
public class MyActor : Actor
{
// Single axis (X only)
public Variable<Position1D> LoadPosX = new(VariableScope.Local);
public IAxis X;
// Two axes (X, Y)
public Variable<Position2D> ScanPosXY = new(VariableScope.Local);
public IAxis X, Y;
// Three axes (X, Y, Z)
public Variable<Position3D> PickPosXYZ = new(VariableScope.Local);
public IAxis X, Y, Z;
// Four axes (X, Y, Z, R)
public Variable<Position4D> AlignPosXYZR = new(VariableScope.Local);
public IAxis X, Y, Z, R;
public MyActor(ActorConfig config) : base(config)
{
X = config.AxisFactory.Create();
Y = config.AxisFactory.Create();
Z = config.AxisFactory.Create();
R = config.AxisFactory.Create();
// Map positions to axes (in order!)
PositionAxesMap.Add(LoadPosX, [X]);
PositionAxesMap.Add(ScanPosXY, [X, Y]);
PositionAxesMap.Add(PickPosXYZ, [X, Y, Z]);
PositionAxesMap.Add(AlignPosXYZR, [X, Y, Z, R]);
}
}
Properties
Values
public double[] Values { get; set; }
Array of position values for all axes.
Usage Example:
// Get all values
double[] values = pickPos.Value.Values; // [100.5, 200.3, 50.0]
// Set all values at once
pickPos.Value.Values = new double[] { 150.0, 250.0, 75.0 };
Indexer
public double this[int i] { get; set; }
Access individual axis values by index.
Usage Example:
// Get individual values
double x = pickPos.Value[0];
double y = pickPos.Value[1];
double z = pickPos.Value[2];
// Set individual values
pickPos.Value[0] = 100.0; // X position
pickPos.Value[1] = 200.0; // Y position
pickPos.Value[2] = 50.0; // Z position
Axes
public IAxis[] Axes { get; }
Array of axes mapped to this position. Automatically retrieved from PositionAxesMap.
Usage Example:
// Check which axes are mapped
foreach (var axis in pickPos.Value.Axes)
{
Console.WriteLine($"Axis position: {axis.ActualPosition}");
Console.WriteLine($"Axis moving: {axis.IsMoving}");
}
Size
public int Size { get; }
Number of axes/dimensions in this position.
Usage Example:
var size = pickPos.Value.Size; // 3 for Position3D
Motion Methods
Move
public void Move()
public void Move(bool override)
public void Move(IAxis[] axes)
public void Move(IAxis[] axes, bool override)
Commands axes to move to the stored position.
Parameters:
override— If true, bypasses safety checks and moves directlyaxes— Specific subset of axes to move
Usage Example:
// Move all mapped axes to stored position
pickPos.Value.Move();
// Move with override (skip safety checks)
pickPos.Value.Move(override: true);
// Move only X and Y axes
pickPos.Value.Move([X, Y]);
Wait
public void Wait()
public void Wait(IAxis[] axes)
Waits for all (or specified) axes to complete their motion.
Usage Example:
// Wait for all axes
pickPos.Value.Wait();
// Wait for specific axes
pickPos.Value.Wait([X, Y]);
MoveAndWait
public void MoveAndWait()
public void MoveAndWait(IAxis[] axes)
Commands motion and waits for completion.
Usage Example:
// Move all axes and wait
pickPos.Value.MoveAndWait();
// Move specific axes and wait
pickPos.Value.MoveAndWait([X, Z]);
Stop
public void Stop()
Immediately stops all mapped axes.
Usage Example:
// Emergency stop
pickPos.Value.Stop();
Position Teaching
SetPos (TeachCurrent)
public void SetPos()
Teaches the current position by reading all mapped axes.
Usage Example:
[Function]
public void TeachPickPos()
{
// Read current axis positions into variable
PickPos.Value.SetPos();
Console.WriteLine($"Taught position: X={PickPos.Value[0]}, Y={PickPos.Value[1]}, Z={PickPos.Value[2]}");
}
MoveToSavedPos
public void MoveToSavedPos(ActorItemMessage? message = null)
Moves to the saved position with optional custom speed profiles.
Usage Example:
// Move with default speed
PickPos.Value.MoveToSavedPos();
// Move with custom speeds
var message = new ActorItemMessage(this, "PickPos", "MoveToSavedPos", new Dict
{
["Speed"] = new double[] { 100.0, 120.0, 80.0 } // Custom speeds for each axis
});
PickPos.Value.MoveToSavedPos(message);
MoveToHomePos
public void MoveToHomePos()
Moves all axes to their home positions (in reverse order for safety).
Usage Example:
[Function]
public void GoHome()
{
PickPos.Value.MoveToHomePos();
}
Position Comparison
IsNear
public bool IsNear(double range)
Checks if all axes are within the specified range of their target positions.
Usage Example:
// Check if within 0.1mm of target
if (pickPos.Value.IsNear(0.1))
{
Console.WriteLine("Position reached");
}
WaitForPosition
public void WaitForPosition(PositionComparisonType type)
Waits until all axes reach their target positions according to the comparison type.
Usage Example:
pickPos.Value.Move();
pickPos.Value.WaitForPosition(PositionComparisonType.InPosition);
Change Notifications
Position types implement INotifyValueChanged for tracking changes:
public event EventHandler<ValueChangedArgs>? ValueChanged;
public event EventHandler<ValueChangedArgs>? ValueChanging;
Usage Example:
public MyActor(ActorConfig config) : base(config)
{
// ...
PickPos.ValueChanged += (s, e) =>
{
Console.WriteLine($"Position changed: {PickPos.Value[0]}, {PickPos.Value[1]}, {PickPos.Value[2]}");
};
}
Usage Patterns
1. Basic Position Teaching and Motion
public class StageActor : Actor
{
public Variable<Position3D> LoadPos = new(VariableScope.Local);
public Variable<Position3D> UnloadPos = new(VariableScope.Local);
public IAxis X, Y, Z;
public StageActor(ActorConfig config) : base(config)
{
X = config.AxisFactory.Create();
Y = config.AxisFactory.Create();
Z = config.AxisFactory.Create();
PositionAxesMap.Add(LoadPos, [X, Y, Z]);
PositionAxesMap.Add(UnloadPos, [X, Y, Z]);
}
[Function]
public void TeachLoadPosition()
{
LoadPos.Value.SetPos();
}
[Function]
public void TeachUnloadPosition()
{
UnloadPos.Value.SetPos();
}
public void TransferMaterial()
{
// Move to load position
LoadPos.Value.MoveAndWait();
PickUpMaterial();
// Move to unload position
UnloadPos.Value.MoveAndWait();
PlaceMaterial();
}
}
2. Sequential Motion with Verification
public void PickSequence()
{
// Move Z up to safe height
SafeHeightPos.Value.MoveAndWait([Z]);
// Move XY to position
PickPos.Value.MoveAndWait([X, Y]);
// Lower Z to pick height
PickPos.Value.MoveAndWait([Z]);
// Verify position
if (!PickPos.Value.IsNear(0.1))
{
throw new Exception("Position error");
}
// Pick operation
Vacuum.TurnOn();
Thread.Sleep(500);
// Raise Z
SafeHeightPos.Value.MoveAndWait([Z]);
}
3. Position Offset
public void PickWithOffset(double xOffset, double yOffset)
{
// Clone and modify position
var offsetPos = (Position3D)PickPos.Value.Clone();
offsetPos[0] += xOffset; // Add X offset
offsetPos[1] += yOffset; // Add Y offset
// Move to offset position
offsetPos.MoveAndWait();
}
4. Grid Position Calculation
public class TrayActor : Actor
{
public Variable<Position3D> GridStartPos = new(VariableScope.Local);
public Variable<double> GridSpacingX = new(VariableScope.Local, 10.0);
public Variable<double> GridSpacingY = new(VariableScope.Local, 10.0);
public void MoveToGridCell(int row, int col)
{
var pos = (Position3D)GridStartPos.Value.Clone();
pos[0] += col * GridSpacingX.Value; // X offset
pos[1] += row * GridSpacingY.Value; // Y offset
pos.MoveAndWait();
}
}
Best Practices
1. Always Map Positions in Constructor
// ✅ Good
public MyActor(ActorConfig config) : base(config)
{
X = config.AxisFactory.Create();
PositionAxesMap.Add(LoadPos, [X]);
}
// ❌ Bad - Mapping missing
public MyActor(ActorConfig config) : base(config)
{
X = config.AxisFactory.Create();
// Forgot to add mapping - will throw exception!
}
2. Use Correct Axis Order
// ✅ Good - Correct order
PositionAxesMap.Add(PickPos, [X, Y, Z]);
// ❌ Bad - Wrong order
PositionAxesMap.Add(PickPos, [Z, Y, X]); // Will move to wrong positions!
3. Check Position Before Critical Operations
// ✅ Good - Verify position
PickPos.Value.MoveAndWait();
if (!PickPos.Value.IsNear(0.1))
{
throw new Exception("Position error - cannot pick");
}
PickMaterial();
// ❌ Bad - No verification
PickPos.Value.MoveAndWait();
PickMaterial(); // May pick from wrong position!
4. Use Sequential Motion for Safety
// ✅ Good - Safe Z-up first
SafeHeightPos.Value.MoveAndWait([Z]);
PickPos.Value.MoveAndWait([X, Y]);
PickPos.Value.MoveAndWait([Z]);
// ❌ Bad - May collide
PickPos.Value.MoveAndWait(); // All axes move at once!
See Also
- PositionAxesMap - Managing position-axis mappings
- IAxis Interface - Motion axis control
- Variable System Guide - Using position variables
- INotifyValueChanged - Change notifications