Codesys Ros2 Portable — Extended & Ultimate
This allows for sub-millisecond communication between the motion planner (ROS) and the motor controller (PLC). 🏗️ Implementation Workflow
As of 2025 (and looking beyond), several trends are accelerating this integration:
This is a comprehensive guide to bridging the gap between industrial PLCs (CODESYS) and the robotics world (ROS 2).
executes the motion with industrial-grade precision and triggers the safety stop if the hardware limits are exceeded. Getting Started If you want to experiment, the CODESYS Forge codesys ros2
When the plant clock hit 02:17, the lights in hall B softened to a tired amber and the conveyor belts hummed like a concentrated insect swarm. In the control room, a single screen glowed with the calm, ordered world of CODESYS: ladder logic blocks marching in timed rhythm, timers and counters folded into neat function blocks. To everyone who’d grown up on PLC cycles and deterministic scans, that screen was comfort itself—until the robots started to speak.
import rclpy from rclpy.node import Node from std_msgs.msg import Float64 from asyncua import Client import asyncio class CodesysBridge(Node): def __init__(self): super().__init__('codesys_bridge') self.publisher_ = self.create_publisher(Float64, 'plc_sensor_data', 10) self.loop = asyncio.get_event_loop() self.loop.create_task(self.connect_to_plc()) async join connect_to_plc(self): url = "opc.tcp:// :4840" async with Client(url=url) as client: self.get_logger().info(f"Connected to CODESYS OPC UA at url") # Locate the node ID based on your CODESYS Symbol Configuration path var_node = await client.nodes.root.get_child(["0:Objects", "2:Device", "4:PLC Logic", "4:Application", "4:PLC_PRG", "4:lrSensorValue"]) while rclpy.ok(): value = await var_node.read_value() msg = Float64() msg.data = float(value) self.publisher_.publish(msg) await asyncio.sleep(0.05) # 20 Hz sample rate def main(args=None): rclpy.init(args=args) node = CodesysBridge() try: asyncio.run(node.loop.run_forever()) except KeyboardInterrupt: pass finally: node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main() Use code with caution. Step 4: Run and Verify
// 3. Publish Data (Every 100ms for example) // Assuming you have a timer or cyclic task set to 100ms IF bConnected THEN // Construct a simple JSON payload (String format) // In real apps, use a JSON Serialize library for robustness PublishPayload := CONCAT('"pos":', REAL_TO_STRING(rPosition)); PublishPayload := CONCAT(PublishPayload, ''); Getting Started If you want to experiment, the
On one side, we have , the gold standard for industrial programmable logic controllers (PLCs). It is reliable, deterministic, and governed by strict IEC 61131-3 standards. It is the language of the factory floor—handling sensors, actuators, and safety logic with millisecond precision.
What fits best for your system requirements?
As factories transition to Industry 4.0, these two domains are colliding. Modern manufacturing demands production lines that can adapt dynamically, using Autonomous Mobile Robots (AMRs) and collaborative robots (cobots) that must communicate seamlessly with traditional PLC-controlled conveyor belts and CNC machines. import rclpy from rclpy
We can look into structuring to guarantee high safety compliance between systems.
Create a clean interface documentation sheet. Always map 64-bit floats ( LREAL in CODESYS) directly to float64 in ROS2 to prevent truncation or rounding errors during critical navigation math. 3. Coordinate System Transformation
If your CODESYS runtime and ROS 2 are running on the same Industrial PC (IPC) under a Real-Time Linux kernel (like Preempt-RT).
