/* ========================================================================
* Copyright (c) 2005-2026 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using Opc.Ua;
namespace Robotics
{
///
/// Fixed geometry of the sample cell, matching the prims authored in
/// Cell.usda.
///
///
/// The separations here are what make the cell collision free, so they are stated once
/// and asserted by the choreography tests rather than being spread through the code.
///
public static class CellLayout
{
///
/// The X position of the western transfer station, in metres.
///
public const double TableAX = -2.6;
///
/// The X position of the eastern transfer station, in metres.
///
public const double TableBX = 2.6;
///
/// The Y position of both transfer stations, in metres.
///
public const double TableY = 1.2;
///
/// The height of a table top's surface, in metres.
///
public const double TableSurfaceZ = 0.770;
///
/// The X offsets of the three part slots on a table, in metres.
///
///
/// Held as a single immutable value rather than rebuilt per access: slot positions
/// are resolved throughout the simulation, and an ArrayOf can be shared
/// safely where a cached double[] would hand every caller a writable
/// reference to the one copy.
///
public static ArrayOf SlotOffsetsX { get; } = new double[] { -0.22, 0.0, 0.22 };
///
/// The Y position a robot parks at to work a table, in metres.
///
public const double TableApproachY = 0.35;
///
/// The Y position of the eastbound travel lane, in metres.
///
public const double EastboundLaneY = 0.35;
///
/// The Y position of the westbound travel lane, in metres.
///
public const double WestboundLaneY = -1.15;
///
/// The half width of the shared corridor along X, in metres.
///
///
/// Everything beyond this on either side is an end zone, which only one robot may
/// occupy. A robot working a table at keeps its arm within
/// , so a deployed arm never reaches the corridor.
///
public const double CorridorHalfWidthX = 1.3;
///
/// The bounding radius of the platform with the arm folded for transport, in metres.
///
public const double TransportRadius = 0.65;
///
/// The furthest a deployed arm is allowed to reach along X from its platform, in
/// metres.
///
public const double DeployedArmHalfWidthX = 0.45;
///
/// The X position of the western charging dock, in metres.
///
public const double DockD1X = -0.8;
///
/// The X position of the eastern charging dock, in metres.
///
public const double DockD2X = 0.8;
///
/// The Y position of both charging docks, in metres.
///
public const double DockY = -2.0;
///
/// Returns the cell position of a part resting in a table slot.
///
/// The station the slot belongs to.
/// The zero based slot index.
/// The slot centre, in metres.
public static (double X, double Y, double Z) SlotPosition(CellStation table, int slot)
{
ArrayOf offsets = SlotOffsetsX;
int index = slot < 0 ? 0 : slot % offsets.Count;
double tableX = table == CellStation.TableA ? TableAX : TableBX;
return (tableX + offsets[index], TableY, TableSurfaceZ + 0.0175);
}
}
///
/// The transfer stations a part can rest on.
///
public enum CellStation
{
///
/// The western station.
///
TableA,
///
/// The eastern station.
///
TableB
}
///
/// The exclusive areas of the cell a robot has to reserve before entering.
///
public enum CellZone
{
///
/// No reservation held.
///
None,
///
/// The western end of the cell, including table A.
///
EndZoneA,
///
/// The eastbound lane of the shared corridor.
///
CorridorEastbound,
///
/// The westbound lane of the shared corridor.
///
CorridorWestbound,
///
/// The eastern end of the cell, including table B.
///
EndZoneB,
///
/// The western charging dock, which sits clear of table A's working area so a robot
/// waiting for work does not block the station.
///
DockA,
///
/// The eastern charging dock, which sits clear of table B's working area.
///
DockB
}
///
/// The step a robot is currently performing.
///
public enum RobotCycleState
{
///
/// Waiting for work.
///
Idle,
///
/// Waiting for a zone reservation another robot holds.
///
Blocked,
///
/// Driving to the station it collects from.
///
TravelToSource,
///
/// Reaching the arm over the source slot.
///
ReachToSource,
///
/// Closing the jaws on the part.
///
Grip,
///
/// Lifting the part clear and folding the arm for transport.
///
Lift,
///
/// Driving to the station it delivers to.
///
TravelToTarget,
///
/// Reaching the arm over the target slot.
///
ReachToTarget,
///
/// Opening the jaws to release the part.
///
Release,
///
/// Folding the arm back for transport.
///
Retreat,
///
/// Driving to the charging dock.
///
TravelToDock,
///
/// Sitting on the dock taking charge.
///
Charging
}
}