├── requirements.txt
├── app
├── bin
│ └── plcnext-ros-bridge
├── compose.yml
├── app_info.json
└── initscript.sh
├── phoenix_bridge
├── phoenix_bridge
│ ├── __init__.py
│ ├── param_parser.py
│ └── msg_parser.py
├── config
│ ├── services_params.yaml
│ ├── liveliness_config.yaml
│ └── interface_description.yaml
├── include
│ └── phoenix_bridge
│ │ ├── ServiceStubs
│ │ ├── Includes
│ │ │ ├── ArpTypes.pb.h
│ │ │ ├── DateTime.pb.h
│ │ │ ├── DataType.pb.h
│ │ │ ├── Severity.pb.h
│ │ │ ├── VariableInfo.pb.h
│ │ │ ├── SecurityToken.pb.h
│ │ │ └── AuthenticationError.pb.h
│ │ ├── ArpTypes.grpc.pb.cc
│ │ ├── Plc
│ │ │ ├── DataType.grpc.pb.cc
│ │ │ ├── Gds
│ │ │ │ ├── ReadItem.grpc.pb.cc
│ │ │ │ ├── ForceItem.grpc.pb.cc
│ │ │ │ ├── WriteItem.grpc.pb.cc
│ │ │ │ ├── VariableInfo.grpc.pb.cc
│ │ │ │ ├── DataAccessError.grpc.pb.cc
│ │ │ │ ├── SubscriptionKind.grpc.pb.cc
│ │ │ │ ├── ReadItem.grpc.pb.h
│ │ │ │ ├── ForceItem.grpc.pb.h
│ │ │ │ ├── WriteItem.grpc.pb.h
│ │ │ │ ├── VariableInfo.grpc.pb.h
│ │ │ │ ├── DataAccessError.grpc.pb.h
│ │ │ │ ├── SubscriptionKind.grpc.pb.h
│ │ │ │ ├── SubscriptionKind.pb.cc
│ │ │ │ ├── DataAccessError.pb.cc
│ │ │ │ ├── SubscriptionKind.pb.h
│ │ │ │ ├── DataAccessError.pb.h
│ │ │ │ └── VariableInfo.pb.h
│ │ │ ├── DataType.grpc.pb.h
│ │ │ ├── DataType.pb.cc
│ │ │ └── DataType.pb.h
│ │ └── ArpTypes.grpc.pb.h
│ │ ├── include_types.h
│ │ ├── phoenix_comm.hpp
│ │ ├── phoenix_io_services.hpp
│ │ ├── bridge_type.hpp
│ │ └── read_conversions.hpp
├── test
│ ├── scripts
│ │ ├── pub_string.py
│ │ ├── pub_twist.py
│ │ ├── single_get_io.py
│ │ ├── read_analog_io.py
│ │ ├── single_set_io.py
│ │ ├── write_analog_io.py
│ │ ├── batch_get_io.py
│ │ ├── batch_set_io.py
│ │ └── pub_odom.py
│ ├── launch_test_bridge.test.py
│ └── test_write_conversions.cpp
├── src
│ ├── phoenix_io_services_node.cpp
│ ├── phoenix_bridge_node.cpp
│ ├── liveliness_check.cpp
│ └── phoenix_io_services.cpp
├── package.xml
├── launch
│ └── launch_phoenix_bridge.py
└── CMakeLists.txt
├── phoenix_interfaces
├── msg
│ └── SetIO.msg
├── srv
│ ├── BatchSetIO.srv
│ ├── SingleGetIO.srv
│ ├── SingleSetIO.srv
│ ├── BatchGetIO.srv
│ └── AnalogIO.srv
├── CMakeLists.txt
└── package.xml
├── .dockerignore
├── dep.repo
├── dockerfile_manually
├── Dockerfile
├── dockerfile
├── .gitignore
├── ci
└── gitlab_templates
│ └── RULES.yml
├── .gitlab-ci.yml
└── LICENSE
/requirements.txt:
--------------------------------------------------------------------------------
1 | cogapp
2 |
--------------------------------------------------------------------------------
/app/bin/plcnext-ros-bridge:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
--------------------------------------------------------------------------------
/phoenix_bridge/phoenix_bridge/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/phoenix_interfaces/msg/SetIO.msg:
--------------------------------------------------------------------------------
1 | string datapath
2 | bool value
3 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .gitignore
3 | .gitlab-ci.yml
4 | .dockerignore
5 |
--------------------------------------------------------------------------------
/phoenix_interfaces/srv/BatchSetIO.srv:
--------------------------------------------------------------------------------
1 | SetIO[] payload
2 | ---
3 | bool status # If status=false, operation failed
4 |
5 |
--------------------------------------------------------------------------------
/phoenix_interfaces/srv/SingleGetIO.srv:
--------------------------------------------------------------------------------
1 | string datapath
2 | ---
3 | bool value
4 | bool status # If status=false, operation failed
5 |
--------------------------------------------------------------------------------
/phoenix_interfaces/srv/SingleSetIO.srv:
--------------------------------------------------------------------------------
1 | string datapath
2 | bool value
3 | ---
4 | bool status # If status=false, operation failed
5 |
--------------------------------------------------------------------------------
/phoenix_interfaces/srv/BatchGetIO.srv:
--------------------------------------------------------------------------------
1 | string[] datapaths
2 | ---
3 | bool[] values
4 | bool status # If status=false, operation failed
5 |
--------------------------------------------------------------------------------
/dep.repo:
--------------------------------------------------------------------------------
1 | repositories:
2 | ${DEP_REPO_NAME}:
3 | type: git
4 | url: ${DEP_REPO_URL}
5 | version: heads/${ROS_DISTRO}/devel
6 |
--------------------------------------------------------------------------------
/phoenix_interfaces/srv/AnalogIO.srv:
--------------------------------------------------------------------------------
1 | string instance_path
2 | float64 value
3 | ---
4 | string instance_path
5 | float64 value
6 | bool status
7 |
--------------------------------------------------------------------------------
/phoenix_bridge/config/services_params.yaml:
--------------------------------------------------------------------------------
1 | # Params for services
2 |
3 | phoenix_services:
4 | ros__parameters:
5 | grpc:
6 | address: "unix:/run/plcnext/grpc.sock"
7 | type: "tcp"
8 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/ArpTypes.pb.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright PHOENIX CONTACT Electronics GmbH
4 | //
5 | ///////////////////////////////////////////////////////////////////////////////
6 | #pragma once
7 | #include "../ArpTypes.pb.h"
8 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/DateTime.pb.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright PHOENIX CONTACT Electronics GmbH
4 | //
5 | ///////////////////////////////////////////////////////////////////////////////
6 | #pragma once
7 | #include "../DateTime.pb.h"
8 |
9 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/DataType.pb.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright PHOENIX CONTACT Electronics GmbH
4 | //
5 | ///////////////////////////////////////////////////////////////////////////////
6 | #pragma once
7 | #include "../Plc/DataType.pb.h"
8 |
9 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/Severity.pb.h:
--------------------------------------------------------------------------------
1 |
2 | ///////////////////////////////////////////////////////////////////////////////
3 | //
4 | // Copyright PHOENIX CONTACT Electronics GmbH
5 | //
6 | ///////////////////////////////////////////////////////////////////////////////
7 | #pragma once
8 | #include "../System/Nm/Severity.pb.h"
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/VariableInfo.pb.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright PHOENIX CONTACT Electronics GmbH
4 | //
5 | ///////////////////////////////////////////////////////////////////////////////
6 | #pragma once
7 | #include "../Plc/Gds/VariableInfo.pb.h"
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/SecurityToken.pb.h:
--------------------------------------------------------------------------------
1 |
2 | ///////////////////////////////////////////////////////////////////////////////
3 | //
4 | // Copyright PHOENIX CONTACT Electronics GmbH
5 | //
6 | ///////////////////////////////////////////////////////////////////////////////
7 | #pragma once
8 | #include "../System/Security/SecurityToken.pb.h"
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Includes/AuthenticationError.pb.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright PHOENIX CONTACT Electronics GmbH
4 | //
5 | ///////////////////////////////////////////////////////////////////////////////
6 | #pragma once
7 | #include "../System/Um/AuthenticationError.pb.h"
8 |
9 |
--------------------------------------------------------------------------------
/phoenix_bridge/config/liveliness_config.yaml:
--------------------------------------------------------------------------------
1 |
2 | liveliness_check:
3 | ros__parameters:
4 | grpc:
5 | address: "unix:/run/plcnext/grpc.sock"
6 | type: "tcp"
7 | liveliness_bool: "Arp.Plc.Eclr/xLiveliness"
8 | liveliness_timeout_s: 1.0 # Timeout in seconds. If no response recevied in this interval, shout a warning
9 | poll_rate_hz: 1 # Poll rate in Hz to check the bool
10 |
--------------------------------------------------------------------------------
/phoenix_interfaces/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8)
2 | project(phoenix_interfaces)
3 |
4 | find_package(ament_cmake REQUIRED)
5 | find_package(rosidl_default_generators REQUIRED)
6 |
7 | rosidl_generate_interfaces(${PROJECT_NAME}
8 | "msg/SetIO.msg"
9 | "srv/BatchGetIO.srv"
10 | "srv/BatchSetIO.srv"
11 | "srv/SingleGetIO.srv"
12 | "srv/SingleSetIO.srv"
13 | "srv/AnalogIO.srv"
14 | )
15 |
16 | install(DIRECTORY
17 | msg
18 | srv
19 | DESTINATION share/${PROJECT_NAME}
20 | )
21 |
22 | ament_package()
23 |
--------------------------------------------------------------------------------
/app/compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | rosbridge:
3 | # add _${APP_UNIQUE_NAME} to all of your container_name
4 | container_name: rosbridge_${APP_UNIQUE_NAME}
5 | # Use the Image ID or fully qualified path incl. sha256 to avoid conflicts
6 | image: §§IMAGE_ID§§
7 | stdin_open: true # podman run -i
8 | tty: true # podman run -t
9 | volumes:
10 | - /run/plcnext/grpc.sock:/run/plcnext/grpc.sock
11 | restart: unless-stopped
12 | network_mode: host
13 | environment:
14 | - ROS_DOMAIN_ID=0
15 | command: bash -c "ros2 launch phoenix_bridge launch_phoenix_bridge.py"
--------------------------------------------------------------------------------
/app/app_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "plcnextapp": {
3 | "name": "plcnext-ros-bridge",
4 | "identifier": "60002172000613",
5 | "version": "§§ROS_BRIDGE_VERSION§§ §§ROS_DISTRO§§",
6 | "target": "§§TARGETS§§",
7 | "minfirmware_version": "22.6.0",
8 | "manufacturer": "Phoenix Contact Electronics"
9 | },
10 | "datastorage": {
11 | "persistentdata": true,
12 | "temporarydata": true
13 | },
14 | "linuxdaemons" :
15 | [
16 | {
17 | "path": "/bin/plcnext-ros-bridge",
18 | "cmdargs" : "",
19 | "starttime": "99",
20 | "initScriptTemplate": "initscript.sh"
21 | }
22 | ],
23 | "plcnextservices" :[]
24 | }
25 |
--------------------------------------------------------------------------------
/phoenix_interfaces/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | phoenix_interfaces
5 | 0.6.2
6 | ROS2 Phoenix interfaces
7 |
8 | todo
9 | Tejas
10 |
11 | Apache 2.0
12 |
13 | ament_cmake
14 |
15 | rosidl_default_generators
16 |
17 | rosidl_default_runtime
18 |
19 | rosidl_interface_packages
20 |
21 |
22 | ament_cmake
23 |
24 |
25 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/pub_string.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import rclpy
4 |
5 | from random import randint
6 | from rclpy.node import Node
7 | from std_msgs.msg import String
8 |
9 |
10 | class MinimalPublisher(Node):
11 |
12 | def __init__(self):
13 | super().__init__('twist_publisher')
14 | self.publisher_ = self.create_publisher(String, '/sub_string_1', 10)
15 | timer_period = 1 # seconds
16 | self.timer = self.create_timer(timer_period, self.timer_callback)
17 |
18 | def timer_callback(self):
19 | msg = String()
20 | msg.data = "hi" + str(randint(1,100))
21 |
22 | self.publisher_.publish(msg)
23 |
24 | def main(args=None):
25 | rclpy.init(args=args)
26 |
27 | minimal_publisher = MinimalPublisher()
28 |
29 | rclpy.spin(minimal_publisher)
30 |
31 | minimal_publisher.destroy_node()
32 | rclpy.shutdown()
33 |
34 | if __name__ == '__main__':
35 | main()
36 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/ArpTypes.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ArpTypes.proto
4 |
5 | #include "ArpTypes.pb.h"
6 | #include "ArpTypes.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Type {
24 | namespace Grpc {
25 |
26 | } // namespace Arp
27 | } // namespace Type
28 | } // namespace Grpc
29 |
30 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/DataType.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: DataType.proto
4 |
5 | #include "DataType.pb.h"
6 | #include "DataType.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Grpc {
25 |
26 | } // namespace Arp
27 | } // namespace Plc
28 | } // namespace Grpc
29 |
30 |
--------------------------------------------------------------------------------
/phoenix_bridge/src/phoenix_io_services_node.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2022 Fraunhofer IPA
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | #include
18 |
19 | #include "phoenix_bridge/phoenix_io_services.hpp"
20 |
21 | int main(int argc, char ** argv)
22 | {
23 | rclcpp::init(argc, argv);
24 |
25 | rclcpp::executors::MultiThreadedExecutor mte;
26 | rclcpp::NodeOptions options;
27 | auto node = std::make_shared("phoenix_services", options);
28 | mte.add_node(node);
29 | mte.spin();
30 | rclcpp::shutdown();
31 | return 0;
32 | }
33 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/pub_twist.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import rclpy
4 |
5 | from random import randint
6 | from rclpy.node import Node
7 | from geometry_msgs.msg import Twist
8 |
9 |
10 | class MinimalPublisher(Node):
11 |
12 | def __init__(self):
13 | super().__init__('twist_publisher')
14 | self.publisher_ = self.create_publisher(Twist, '/sub_twist_1', 10)
15 | timer_period = 1 # seconds
16 | self.timer = self.create_timer(timer_period, self.timer_callback)
17 |
18 | def timer_callback(self):
19 | msg = Twist()
20 | msg.linear.x = randint(1, 500)/100
21 | msg.linear.y = randint(1, 500)/100
22 | msg.linear.z = randint(1, 500)/100
23 | msg.angular.x = randint(1, 314)/100
24 | msg.angular.y = randint(1, 314)/100
25 | msg.angular.z = randint(1, 314)/100
26 |
27 | self.publisher_.publish(msg)
28 |
29 | def main(args=None):
30 | rclpy.init(args=args)
31 |
32 | minimal_publisher = MinimalPublisher()
33 |
34 | rclpy.spin(minimal_publisher)
35 |
36 | minimal_publisher.destroy_node()
37 | rclpy.shutdown()
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/ReadItem.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ReadItem.proto
4 |
5 | #include "ReadItem.pb.h"
6 | #include "ReadItem.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/ForceItem.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ForceItem.proto
4 |
5 | #include "ForceItem.pb.h"
6 | #include "ForceItem.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/WriteItem.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: WriteItem.proto
4 |
5 | #include "WriteItem.pb.h"
6 | #include "WriteItem.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/VariableInfo.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: VariableInfo.proto
4 |
5 | #include "VariableInfo.pb.h"
6 | #include "VariableInfo.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/single_get_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import time
5 |
6 | from phoenix_interfaces.srv import SingleGetIO
7 | import rclpy
8 | from rclpy.node import Node
9 |
10 | class MinimalClientAsync(Node):
11 |
12 | def __init__(self):
13 | super().__init__('single_get_IO')
14 | self.cli = self.create_client(SingleGetIO, '/single_get_IO')
15 | while not self.cli.wait_for_service(timeout_sec=1.0):
16 | self.get_logger().info('service not available, waiting again...')
17 | self.req = SingleGetIO.Request()
18 |
19 | while True:
20 | try:
21 | self.req.datapath = 'Arp.Plc.Eclr/MainInstance.gRPC_Obj.bool_data'
22 | self.future = self.cli.call_async(self.req)
23 | rclpy.spin_until_future_complete(self, self.future)
24 | response = self.future.result()
25 | print("Get from", self.req.datapath, ", status", response.status, "value", response.value)
26 | time.sleep(1)
27 | except KeyboardInterrupt:
28 | break
29 |
30 | def main(args=None):
31 | rclpy.init(args=args)
32 | minimal_client = MinimalClientAsync()
33 | minimal_client.destroy_node()
34 | rclpy.shutdown()
35 |
36 | if __name__ == '__main__':
37 | main()
38 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/read_analog_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import time
5 |
6 | from phoenix_interfaces.srv import AnalogIO
7 | import rclpy
8 | from rclpy.node import Node
9 |
10 | class MinimalClientAsync(Node):
11 |
12 | def __init__(self):
13 | super().__init__('read_analog_IO')
14 | self.cli = self.create_client(AnalogIO, '/read_analog_IO')
15 | while not self.cli.wait_for_service(timeout_sec=1.0):
16 | self.get_logger().info('service not available, waiting again...')
17 | self.req = AnalogIO.Request()
18 |
19 | while True:
20 | try:
21 | self.req.instance_path = 'Arp.Plc.Eclr/MainInstance.gRPC_Obj.double_data'
22 | self.future = self.cli.call_async(self.req)
23 | rclpy.spin_until_future_complete(self, self.future)
24 | response = self.future.result()
25 | print("Got from", self.req.instance_path, "result ", response.status, "value", response.value)
26 | time.sleep(1)
27 | except KeyboardInterrupt:
28 | break
29 |
30 | def main(args=None):
31 | rclpy.init(args=args)
32 | minimal_client = MinimalClientAsync()
33 | minimal_client.destroy_node()
34 | rclpy.shutdown()
35 |
36 | if __name__ == '__main__':
37 | main()
38 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/DataAccessError.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: DataAccessError.proto
4 |
5 | #include "DataAccessError.pb.h"
6 | #include "DataAccessError.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/SubscriptionKind.grpc.pb.cc:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: SubscriptionKind.proto
4 |
5 | #include "SubscriptionKind.pb.h"
6 | #include "SubscriptionKind.grpc.pb.h"
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | namespace Arp {
23 | namespace Plc {
24 | namespace Gds {
25 | namespace Services {
26 | namespace Grpc {
27 |
28 | } // namespace Arp
29 | } // namespace Plc
30 | } // namespace Gds
31 | } // namespace Services
32 | } // namespace Grpc
33 |
34 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/single_set_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import time
5 |
6 | from phoenix_interfaces.srv import SingleSetIO
7 | import rclpy
8 | from rclpy.node import Node
9 |
10 | class MinimalClientAsync(Node):
11 |
12 | def __init__(self):
13 | super().__init__('single_set_io')
14 | self.cli = self.create_client(SingleSetIO, '/single_set_IO')
15 | while not self.cli.wait_for_service(timeout_sec=1.0):
16 | self.get_logger().info('service not available, waiting again...')
17 | self.req = SingleSetIO.Request()
18 | self.bool_ = True
19 |
20 | while True:
21 | try:
22 | self.req.datapath = 'Arp.Plc.Eclr/MainInstance.gRPC_Obj.bool_data'
23 | self.req.value = self.bool_
24 | self.bool_ = not self.bool_
25 | self.future = self.cli.call_async(self.req)
26 | rclpy.spin_until_future_complete(self, self.future)
27 | response = self.future.result()
28 | print("Set ", self.req.value, " to ", self.req.datapath, " and got result ", response.status)
29 | time.sleep(1)
30 | except KeyboardInterrupt:
31 | break
32 |
33 | def main(args=None):
34 | rclpy.init(args=args)
35 | minimal_client = MinimalClientAsync()
36 | minimal_client.destroy_node()
37 | rclpy.shutdown()
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/write_analog_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import time
5 |
6 | from phoenix_interfaces.srv import AnalogIO
7 | import rclpy
8 | from rclpy.node import Node
9 |
10 | class MinimalClientAsync(Node):
11 |
12 | def __init__(self):
13 | super().__init__('write_analog_io')
14 | self.cli = self.create_client(AnalogIO, '/write_analog_IO')
15 | while not self.cli.wait_for_service(timeout_sec=1.0):
16 | self.get_logger().info('service not available, waiting again...')
17 | self.req = AnalogIO.Request()
18 | self.double = 1.0
19 |
20 | while True:
21 | try:
22 | self.req.instance_path = 'Arp.Plc.Eclr/MainInstance.gRPC_Obj.double_data'
23 | self.req.value = self.double
24 | self.double += 1.0
25 | self.future = self.cli.call_async(self.req)
26 | rclpy.spin_until_future_complete(self, self.future)
27 | response = self.future.result()
28 | print("Set ", self.req.value, " to ", self.req.instance_path, " and got result ", response.status)
29 | time.sleep(1)
30 | except KeyboardInterrupt:
31 | break
32 |
33 | def main(args=None):
34 | rclpy.init(args=args)
35 | minimal_client = MinimalClientAsync()
36 | minimal_client.destroy_node()
37 | rclpy.shutdown()
38 |
39 | if __name__ == '__main__':
40 | main()
41 |
--------------------------------------------------------------------------------
/phoenix_bridge/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | phoenix_bridge
5 | 0.6.2
6 | ROS2 Phoenix bridge
7 |
8 | todo
9 | Tejas
10 |
11 | Apache 2.0
12 |
13 | ament_cmake
14 | ament_cmake_python
15 |
16 | rclcpp
17 | rclpy
18 | std_msgs
19 | nav_msgs
20 | geometry_msgs
21 | launch
22 | phoenix_interfaces
23 |
24 | ament_cmake_clang_format
25 | ament_cmake_cpplint
26 | ament_cmake_cppcheck
27 | ament_cmake_lint_cmake
28 | ament_cmake_xmllint
29 | ament_cmake_gtest
30 | launch
31 | python3-pytest
32 |
33 |
34 | ament_cmake
35 |
36 |
37 |
--------------------------------------------------------------------------------
/phoenix_bridge/test/scripts/batch_get_io.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import time
5 |
6 | from phoenix_interfaces.srv import BatchGetIO
7 | import rclpy
8 | from rclpy.node import Node
9 |
10 | class MinimalClientAsync(Node):
11 |
12 | def __init__(self):
13 | super().__init__('batch_get_io')
14 | self.cli = self.create_client(BatchGetIO, '/batch_get_IO')
15 | while not self.cli.wait_for_service(timeout_sec=1.0):
16 | self.get_logger().info('service not available, waiting again...')
17 | self.req = BatchGetIO.Request()
18 |
19 | while True:
20 | try:
21 | self.req.datapaths.clear()
22 | self.req.datapaths.append("Arp.Plc.Eclr/MainInstance.gRPC_Obj.bool_data")
23 | self.req.datapaths.append("Arp.Plc.Eclr/MainInstance.gRPC_Obj.bool_data2")
24 | self.req.datapaths.append("Arp.Plc.Eclr/MainInstance.gRPC_Obj.bool_data3")
25 |
26 | self.future = self.cli.call_async(self.req)
27 | rclpy.spin_until_future_complete(self, self.future)
28 | response = self.future.result()
29 | print("Payload sent: ")
30 | for element in self.req.datapaths:
31 | print(element)
32 | print("Response status: ", response.status)
33 | print("Values: ")
34 | for element in response.values:
35 | print(element)
36 | time.sleep(1)
37 | except KeyboardInterrupt:
38 | break
39 |
40 | def main(args=None):
41 | rclpy.init(args=args)
42 | minimal_client = MinimalClientAsync()
43 | minimal_client.destroy_node()
44 | rclpy.shutdown()
45 |
46 | if __name__ == '__main__':
47 | main()
48 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/DataType.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: DataType.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | #ifndef GRPC_DataType_2eproto__INCLUDED
11 | #define GRPC_DataType_2eproto__INCLUDED
12 |
13 | #include "DataType.pb.h"
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | namespace Arp {
36 | namespace Plc {
37 | namespace Grpc {
38 |
39 | } // namespace Grpc
40 | } // namespace Plc
41 | } // namespace Arp
42 |
43 |
44 | #endif // GRPC_DataType_2eproto__INCLUDED
45 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/ArpTypes.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ArpTypes.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | //
11 | #ifndef GRPC_ArpTypes_2eproto__INCLUDED
12 | #define GRPC_ArpTypes_2eproto__INCLUDED
13 |
14 | #include "ArpTypes.pb.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace Arp {
37 | namespace Type {
38 | namespace Grpc {
39 |
40 | } // namespace Grpc
41 | } // namespace Type
42 | } // namespace Arp
43 |
44 |
45 | #endif // GRPC_ArpTypes_2eproto__INCLUDED
46 |
--------------------------------------------------------------------------------
/dockerfile_manually:
--------------------------------------------------------------------------------
1 | ARG ROS_DISTRO
2 |
3 | FROM public.ecr.aws/docker/library/ros:${ROS_DISTRO}-ros-core as base
4 | FROM ghcr.io/ipa-rwu/builder:latest as builder
5 |
6 |
7 | FROM base as deps
8 | COPY . /root/ws/src
9 | RUN cd /root/ws/src && \
10 | rm /root/ws/src/dep.repo
11 |
12 | COPY --from=builder workspace.bash /builder/workspace.bash
13 | RUN apt-get update -qq && \
14 | apt-get install -y git && \
15 | cd /root/ws/src && \
16 | git clone https://github.com/PLCnext/gRPC-client-deps.git -b ${ROS_DISTRO}/devel
17 | RUN cd /root/ws/src/gRPC-client-deps/plcnext_deps/ && \
18 | /root/ws/src/gRPC-client-deps/plcnext_deps/dep_copy.sh ${ROS_DISTRO} && \
19 | rm -rf /var/lib/apt/lists/*
20 |
21 | FROM deps as pre_build
22 | RUN apt-get update -qq && \
23 | /builder/workspace.bash update_list /root/ws && \
24 | rm -rf /var/lib/apt/lists/*
25 |
26 | FROM pre_build as build
27 | ARG CMAKE_ARGS=
28 | ENV CMAKE_ARGS -DCMAKE_BUILD_TYPE=RELEASE
29 | RUN apt-get update -qq && \
30 | /builder/workspace.bash build_workspace /root/ws && \
31 | rm -rf /var/lib/apt/lists/*
32 |
33 | FROM build as test
34 | RUN apt-get update -qq && \
35 | /builder/workspace.bash test_workspace /root/ws && \
36 | rm -rf /var/lib/apt/lists/*
37 |
38 | FROM test as install
39 | RUN apt-get update -qq && \
40 | /builder/workspace.bash install_workspace /root/ws && \
41 | rm -rf /var/lib/apt/lists/*
42 |
43 | FROM base as deploy
44 | COPY --from=install /root/ws/DEPENDS /root/ws/DEPENDS
45 | COPY --from=builder workspace.bash /builder/workspace.bash
46 | RUN apt-get update -qq && \
47 | /builder/workspace.bash install_depends /root/ws && \
48 | rm -rf /var/lib/apt/lists/*
49 | COPY --from=install /opt/ros/${ROS_DISTRO} /opt/ros/${ROS_DISTRO}
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/ReadItem.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ReadItem.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | //
11 | #ifndef GRPC_ReadItem_2eproto__INCLUDED
12 | #define GRPC_ReadItem_2eproto__INCLUDED
13 |
14 | #include "ReadItem.pb.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace Arp {
37 | namespace Plc {
38 | namespace Gds {
39 | namespace Services {
40 | namespace Grpc {
41 |
42 | } // namespace Grpc
43 | } // namespace Services
44 | } // namespace Gds
45 | } // namespace Plc
46 | } // namespace Arp
47 |
48 |
49 | #endif // GRPC_ReadItem_2eproto__INCLUDED
50 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/ForceItem.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: ForceItem.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | //
11 | #ifndef GRPC_ForceItem_2eproto__INCLUDED
12 | #define GRPC_ForceItem_2eproto__INCLUDED
13 |
14 | #include "ForceItem.pb.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace Arp {
37 | namespace Plc {
38 | namespace Gds {
39 | namespace Services {
40 | namespace Grpc {
41 |
42 | } // namespace Grpc
43 | } // namespace Services
44 | } // namespace Gds
45 | } // namespace Plc
46 | } // namespace Arp
47 |
48 |
49 | #endif // GRPC_ForceItem_2eproto__INCLUDED
50 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/WriteItem.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: WriteItem.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | //
11 | #ifndef GRPC_WriteItem_2eproto__INCLUDED
12 | #define GRPC_WriteItem_2eproto__INCLUDED
13 |
14 | #include "WriteItem.pb.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace Arp {
37 | namespace Plc {
38 | namespace Gds {
39 | namespace Services {
40 | namespace Grpc {
41 |
42 | } // namespace Grpc
43 | } // namespace Services
44 | } // namespace Gds
45 | } // namespace Plc
46 | } // namespace Arp
47 |
48 |
49 | #endif // GRPC_WriteItem_2eproto__INCLUDED
50 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/VariableInfo.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: VariableInfo.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | //
11 | #ifndef GRPC_VariableInfo_2eproto__INCLUDED
12 | #define GRPC_VariableInfo_2eproto__INCLUDED
13 |
14 | #include "VariableInfo.pb.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace Arp {
37 | namespace Plc {
38 | namespace Gds {
39 | namespace Services {
40 | namespace Grpc {
41 |
42 | } // namespace Grpc
43 | } // namespace Services
44 | } // namespace Gds
45 | } // namespace Plc
46 | } // namespace Arp
47 |
48 |
49 | #endif // GRPC_VariableInfo_2eproto__INCLUDED
50 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/DataAccessError.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: DataAccessError.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | #ifndef GRPC_DataAccessError_2eproto__INCLUDED
11 | #define GRPC_DataAccessError_2eproto__INCLUDED
12 |
13 | #include "DataAccessError.pb.h"
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | namespace Arp {
36 | namespace Plc {
37 | namespace Gds {
38 | namespace Services {
39 | namespace Grpc {
40 |
41 | } // namespace Grpc
42 | } // namespace Services
43 | } // namespace Gds
44 | } // namespace Plc
45 | } // namespace Arp
46 |
47 |
48 | #endif // GRPC_DataAccessError_2eproto__INCLUDED
49 |
--------------------------------------------------------------------------------
/phoenix_bridge/include/phoenix_bridge/ServiceStubs/Plc/Gds/SubscriptionKind.grpc.pb.h:
--------------------------------------------------------------------------------
1 | // Generated by the gRPC C++ plugin.
2 | // If you make any local change, they will be lost.
3 | // source: SubscriptionKind.proto
4 | // Original file comments:
5 | // /////////////////////////////////////////////////////////////////////////////
6 | //
7 | // Copyright PHOENIX CONTACT Electronics GmbH
8 | //
9 | // /////////////////////////////////////////////////////////////////////////////
10 | #ifndef GRPC_SubscriptionKind_2eproto__INCLUDED
11 | #define GRPC_SubscriptionKind_2eproto__INCLUDED
12 |
13 | #include "SubscriptionKind.pb.h"
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include