ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
robotics.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file robotics.h
6 * @brief OPC UA for Robotics (OPC 40010-1) MotionDevice information model (PC_ENABLE_ROBOTICS).
7 *
8 * OPC 40010-1 "OPC UA for Robotics - Part 1: Vertical Integration" (VDMA / OPC Foundation, namespace
9 * `http://opcfoundation.org/UA/Robotics/`) standardizes how an industrial robot / motion device exposes
10 * its identity and live motion state so any OPC UA client (UaExpert, python `asyncua`, open62541, ...)
11 * reads the same MotionDeviceSystem structure across vendors.
12 *
13 * This module builds the MotionDeviceSystem address space on top of the OPC UA Binary server
14 * (`services/opcua`, PC_ENABLE_OPCUA): it registers a Browse + Read resolver that answers for the
15 * MotionDeviceSystem node hierarchy and serves live values out of a caller-owned @ref
16 * RoboticsMotionDeviceSystem struct you refresh in your loop. Same pattern as `services/umati`
17 * (OPC 40501-1); no heap, no stdlib - the model is a fixed node table, the values are pointers/scalars
18 * in your struct.
19 *
20 * Model exposed (BrowseNames per OPC 40010-1), under the Objects folder:
21 *
22 * MotionDeviceSystem
23 * MotionDevices (Folder)
24 * MotionDevice Manufacturer, Model, ProductCode, SerialNumber, MotionDeviceCategory
25 * ParameterSet OnPath, InControl, SpeedOverride
26 * Axes (Folder)
27 * Axis_1..N ActualPosition, ActualSpeed, ActualAcceleration, MotionProfile
28 * Controllers (Folder)
29 * Controller Manufacturer, Model, ProductCode, SerialNumber
30 * Software Manufacturer, Model, SoftwareRevision
31 * SafetyStates (Folder)
32 * SafetyState
33 * ParameterSet OperationalMode, EmergencyStop, ProtectiveStop
34 *
35 * The model is read-only (a monitoring model - the robot reports, the client observes). Scope note: one
36 * MotionDevice / Controller / SafetyState and PC_ROBOTICS_AXES parametric axes are exposed (the common
37 * embedded robot); the values carry faithful BrowseNames, but the companion-spec TypeDefinitions,
38 * PowerTrains, and the NamespaceArray entry for the Robotics URI (which needs array-Variant support in
39 * the base server) are a documented follow-on - a generic OPC UA client still browses the structure and
40 * reads every value by BrowseName today.
41 *
42 * @author Douglas Quigg (dstroy0)
43 * @date 2026
44 */
45
46#ifndef PROTOCORE_ROBOTICS_H
47#define PROTOCORE_ROBOTICS_H
48
49#include "protocore_config.h"
50
51#if PC_ENABLE_ROBOTICS
52
53#include "services/fieldbus/opcua/opcua.h" // OpcUaVariant / OpcUaReference / handler typedefs (shares the OPC UA codec)
54#include <stdint.h>
55
56/** @brief The OPC UA for Robotics companion-spec namespace URI (OPC 40010-1). */
57#define ROBOTICS_NS_URI "http://opcfoundation.org/UA/Robotics/"
58
59/**
60 * @brief MotionDeviceCategory (OPC 40010-1 MotionDeviceCategoryEnumeration). Exposed as Int32; the
61 * numeric values follow the companion-spec enumeration.
62 */
63enum class RoboticsMotionDeviceCategory : int32_t
64{
65 ROBOTICS_CAT_OTHER = 0, ///< a category outside the ones below.
66 ROBOTICS_CAT_ARTICULATED_ROBOT = 1, ///< articulated (jointed-arm) robot.
67 ROBOTICS_CAT_SCARA_ROBOT = 2, ///< SCARA robot.
68 ROBOTICS_CAT_CARTESIAN_ROBOT = 3, ///< cartesian / gantry robot.
69 ROBOTICS_CAT_SPHERICAL_ROBOT = 4, ///< spherical / polar robot.
70 ROBOTICS_CAT_PARALLEL_ROBOT = 5, ///< parallel (delta) robot.
71 ROBOTICS_CAT_CYLINDRICAL_ROBOT = 6, ///< cylindrical robot.
72};
73
74/**
75 * @brief Axis MotionProfile (OPC 40010-1 AxisMotionProfileEnumeration). Exposed as Int32; the numeric
76 * values follow the companion-spec enumeration.
77 */
78enum class RoboticsMotionProfile : int32_t
79{
80 ROBOTICS_PROFILE_OTHER = 0, ///< a profile outside the ones below.
81 ROBOTICS_PROFILE_ROTARY = 1, ///< rotary axis (bounded travel).
82 ROBOTICS_PROFILE_ROTARY_ENDLESS = 2, ///< rotary axis with endless rotation.
83 ROBOTICS_PROFILE_LINEAR = 3, ///< linear axis (bounded travel).
84 ROBOTICS_PROFILE_LINEAR_ENDLESS = 4, ///< linear axis with endless travel.
85};
86
87/**
88 * @brief SafetyState OperationalMode (OPC 40010-1 OperationalModeEnumeration). Exposed as Int32; the
89 * numeric values follow the companion-spec enumeration.
90 */
91enum class RoboticsOperationalMode : int32_t
92{
93 ROBOTICS_MODE_OTHER = 0, ///< a mode outside the ones below.
94 ROBOTICS_MODE_MANUAL_REDUCED_SPEED = 1, ///< manual jog, reduced speed (T1).
95 ROBOTICS_MODE_MANUAL_HIGH_SPEED = 2, ///< manual, high speed (T2).
96 ROBOTICS_MODE_AUTOMATIC = 3, ///< automatic program execution.
97 ROBOTICS_MODE_AUTOMATIC_EXTERNAL = 4, ///< automatic, externally commanded.
98};
99
100/** @brief One axis' live monitoring values (OPC 40010-1 AxisType, common subset). */
101struct RoboticsAxis
102{
103 double actual_position; ///< ActualPosition (mm or deg).
104 double actual_speed; ///< ActualSpeed.
105 double actual_acceleration; ///< ActualAcceleration.
106 RoboticsMotionProfile motion_profile; ///< MotionProfile.
107};
108
109/** @brief The Controller identity + software (OPC 40010-1 ControllerType + SoftwareType). */
110struct RoboticsController
111{
112 const char *manufacturer; ///< Manufacturer (LocalizedText -> String).
113 const char *model; ///< Model (LocalizedText -> String).
114 const char *product_code; ///< ProductCode (String).
115 const char *serial_number; ///< SerialNumber (String).
116 const char *sw_manufacturer; ///< Software.Manufacturer (String).
117 const char *sw_model; ///< Software.Model (String).
118 const char *sw_revision; ///< Software.SoftwareRevision (String).
119};
120
121/** @brief The SafetyState (OPC 40010-1 SafetyStateType, common subset). */
122struct RoboticsSafetyState
123{
124 RoboticsOperationalMode operational_mode; ///< ParameterSet.OperationalMode.
125 bool emergency_stop; ///< ParameterSet.EmergencyStop.
126 bool protective_stop; ///< ParameterSet.ProtectiveStop.
127};
128
129/** @brief One MotionDevice: identity + live motion state (OPC 40010-1 MotionDeviceType, common subset). */
130struct RoboticsMotionDevice
131{
132 const char *manufacturer; ///< Manufacturer (LocalizedText -> String).
133 const char *model; ///< Model (LocalizedText -> String).
134 const char *product_code; ///< ProductCode (String).
135 const char *serial_number; ///< SerialNumber (String).
136 RoboticsMotionDeviceCategory category; ///< MotionDeviceCategory.
137 bool on_path; ///< ParameterSet.OnPath.
138 bool in_control; ///< ParameterSet.InControl.
139 double speed_override; ///< ParameterSet.SpeedOverride (%).
140 uint32_t axis_count; ///< number of Axes exposed (<= PC_ROBOTICS_AXES).
141 RoboticsAxis axes[PC_ROBOTICS_AXES]; ///< the axes (axes[0..axis_count-1] are live).
142};
143
144/**
145 * @brief The whole MotionDeviceSystem the server exposes. Own it in your sketch and refresh its fields
146 * each loop from your robot I/O; the robotics resolvers read straight out of it (no copy). String
147 * fields may be null (served as an empty String).
148 */
149struct RoboticsMotionDeviceSystem
150{
151 const char *name; ///< MotionDeviceSystem BrowseName / DisplayName.
152 RoboticsMotionDevice device; ///< the MotionDevice.
153 RoboticsController controller; ///< the Controller.
154 RoboticsSafetyState safety; ///< the SafetyState.
155};
156
157/**
158 * @brief Bind the MotionDeviceSystem the resolvers serve. @p mds must outlive the server (own it
159 * statically). Refresh its fields any time; each Read returns the current values.
160 */
161void pc_robotics_bind(const RoboticsMotionDeviceSystem *mds);
162
163/**
164 * @brief Read resolver for the MotionDeviceSystem model (an @ref OpcUaReadHandler): fills @p out for a
165 * robotics node's Value attribute. Returns false for a node outside the model (the server answers
166 * BadNodeIdUnknown). Install with `pc_opcua_set_read_handler(pc_robotics_read)`.
167 */
168bool pc_robotics_read(uint16_t ns, uint32_t id, uint32_t attribute, OpcUaVariant *out);
169
170/**
171 * @brief Browse resolver for the MotionDeviceSystem model (an @ref OpcUaBrowseHandler): writes the child
172 * references of a robotics node (and of the Objects folder, which organizes the
173 * MotionDeviceSystem) into @p out. Returns the count, or -1 for a node outside the model. Install
174 * with `pc_opcua_set_browse_handler(pc_robotics_browse)`.
175 */
176int32_t pc_robotics_browse(uint16_t ns, uint32_t id, OpcUaReference *out, uint32_t max);
177
178/**
179 * @brief Convenience: bind @p mds and register both resolvers on the OPC UA server in one call
180 * (`pc_opcua_set_read_handler` + `pc_opcua_set_browse_handler`). Call before `server.begin()`.
181 */
182void pc_robotics_install(const RoboticsMotionDeviceSystem *mds);
183
184#endif // PC_ENABLE_ROBOTICS
185#endif // PROTOCORE_ROBOTICS_H
OPC UA Binary server: handshake + SecureChannel + Session + Read/Write + Browse (PC_ENABLE_OPCUA).
User-facing configuration for ProtoCore.
#define PC_ROBOTICS_AXES
Number of Axes the robotics MotionDevice exposes (default 6; must fit PC_OPCUA_REF_MAX).