Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

Question about Motion Command via C3 Bridge Interface client

#1
Hello, I am writing to ask a few questions about communication using the C3 Bridge Interface.

As I understand, ‘Dmitry’ is the author of this program, so I would especially like to address this to him. 
While this is not directly related to RoboDK, I am trying to use the C3 Bridge, a communication interface employed when working with KUKA through RoboDK, to send motion commands to a KUKA robot. 
To achieve this, I referenced the C3 Bridge documentation and developed a Python client program for communication. The code is as follows:

Code:
import sys
import struct
import random
import socket
import time
from rdk_config import Config_host
__version__ = '1.1.0'
ENCODING = 'UTF-8'
# Message Tpyes (flag)
# 0 - CommandReadVariableAscii
# 1 - CommandWriteVariableAscii
# 11 - CommandMotion
class kukaClient:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.msg_id = random.randint(1, 100)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.ip, self.port))
        except socket.error as e:
            print(f"Socket error: {e}")
            sys.exit(-1)
    def test_connection(self):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            ret = sock.connect_ex((self.ip, self.port))
            sock.close()
            return ret == 0
        except socket.error as e:
            print(f"Socket error: {e}")
            return False
    @property
    def can_connect(self):
        return self.test_connection()
    def move(self, motion_type, position, debug=True):
        if not isinstance(position, str):
            raise TypeError('Position values must be STRING.')
        print("Position (original): ", position)
        self.position = position.encode('utf-16le')  # Wide format (UTF-16LE)
        self.motion_type = motion_type
        print("Position (encoded): ", self.position.hex())  # Print encoded position in hex for debugging
        return self._move_robot(debug)
    def _move_robot(self, debug):
        req = self._pack_move_req()
        print("req ready!")
        self._send_req(req)
        print("send ok")
        _value = self._read_rsp_move(debug)
        if debug:
            print(_value)
        return _value
    def _pack_move_req(self):
        position_len = len(self.position) // 2
        flag = 11  # Wide format version of CommandMotion
        req_len = 3 + 2 + len(self.position)
        return struct.pack(
            '!HHBBH' + str(len(self.position)) + 's',
            self.msg_id,  # Tag ID
            req_len,  # Message Length
            flag,  # Message Type
            self.motion_type,  # Motion Type
            position_len,  # Length of Position String (in characters)
            self.position  # Positon String
        )
    def _send_req(self, req):
        print("_send_req: ", req)
        self.rsp = None
        try:
            self.sock.sendall(req)
            print("sock.sendall(req)")
            self.rsp = self.sock.recv(1024)
            print("self.rsp: ", self.rsp)
        except socket.timeout:
            print("Socket timeout occurred. No response received.")
        except socket.error as e:
            print(f"Socket error: {e}")
    def _read_rsp_move(self, debug=False):
        if self.rsp is None:
            return None
        header_format = '!HHBH'
        header_size = struct.calcsize(header_format)
        body = self.rsp[header_size:-3]  # Exclude the 3-byte end marker
        is_ok = self.rsp[-3:]
        if debug:
            print('Response:', self.rsp)
        if is_ok.endswith(b'\x01'):
            self.msg_id = (self.msg_id + 1) % 65536
            return body.decode('utf-16le')
    def close(self):
        self.sock.close()
if __name__ == "__main__":
    ip = 'xxx.xx.x.xxx'  # C3 Bridge Interface Server IP address
    port = 7000
   
    client = kukaClient(ip, port)
    if client.can_connect:
        print("Connecting Success.")
        stop_message = client.read('$STOPMESS')
        if stop_message:
            print(f"Robot is Stop Status: {stop_message}")
        else:
            print("Robot is Not Stop Status.")
        # motion command example (PTP)
        position = '{AXIS: A1 0, A2 -90, A3 90, A4 0, A5 0, A6 0}'
        #position = '{POS: X 0, Y 0, Z 0, A 0, B 0, C 0}'
        client.move(1, position, debug=True)
    else:
        print("Server Connecting Fail.")
    client.close()


My main question is that although I use the ‘move’ method in my code to send motion commands through this program, the robot does not execute the command. 
I have successfully read and assigned KUKA system variables through this example, but the process of sending motion commands is not going smoothly. 
Could you please review the code I wrote and let me know what might be causing the issue?

Additionally, I am curious about the example in the documentation where the ‘position string’ in the 'payload' for a PTP command is formatted as:
‘{POS: X 0, Y 0, Z 0, A 0, B 0, C 0}’.

However, I want to send a PTP command using joint values instead of coordinates, so I formatted it as:
‘{AXIS: A1 0, A2 -90, A3 90, A4 0, A5 0, A6 0}’.

Could you tell me if this is an appropriate method?

Lastly, when sending motion commands to the C3 Bridge using a client program, what mode should the robot controller be in? 
For instance, when using RoboDK, the KRL program is executed in ‘AUT’ mode after connecting with RoboDK via the communication driver. I am unsure about the proper setup when using a client program like mine to send commands to the C3 Bridge.

I apologize for asking a question not directly related to RoboDK, but I would greatly appreciate any response. Thank you for your continuous support.

Best regards.
#2
Consider the motion command you send as a motion instruction to the KRL. Therefore, the argument can be the same as for the corresponding commands (PTP, LIN, PTP_REL, LIN_REL). In this case, no KRL program must be selected on the robot and the robot must be ready to move. It is not sufficient to send a motion command. It is necessary to ensure this movement by holding down the Start Forward button on the Teach Pendant. Or simulate this pressing with the Start (Program Control) command in the C3 Bridge: http://c3.ulsu.tech/protocol/latest/#com...ramcontrol
Note that on modern KRC4 systems, the Program Control instruction will need to be sent continuously until the movement is complete. On older KRC2 systems this is not required and everything works immediately.

The mode of operation of the robot (T1, T2 or AUT) does not make much difference. The only difference is that T modes require holding the rear switches on the Teach Pendant.
#3
(11-11-2024, 11:11 AM)Dmitry Wrote: Consider the motion command you send as a motion instruction to the KRL. Therefore, the argument can be the same as for the corresponding commands (PTP, LIN, PTP_REL, LIN_REL). In this case, no KRL program must be selected on the robot and the robot must be ready to move. It is not sufficient to send a motion command. It is necessary to ensure this movement by holding down the Start Forward button on the Teach Pendant. Or simulate this pressing with the Start (Program Control) command in the C3 Bridge: http://c3.ulsu.tech/protocol/latest/#com...ramcontrol
Note that on modern KRC4 systems, the Program Control instruction will need to be sent continuously until the movement is complete. On older KRC2 systems this is not required and everything works immediately.

The mode of operation of the robot (T1, T2 or AUT) does not make much difference. The only difference is that T modes require holding the rear switches on the Teach Pendant.

Sorry for the delayed reply to your answer.
Thank you very much for the helpful information, Dmitry!
I understand most of the points, but I am still a bit unclear on the statement:

"Note that on modern KRC4 systems, the Program Control instruction will need to be sent continuously until the movement is complete."

Does this mean that in my C3Bridge client program, I need to keep sending the same command to the C3Bridge until the robot finishes the movement?
Could you please clarify how I can continuously send commands until the movement is complete? 
It would be a huge help to understand this part better.

Thank you again for your support, and have a nice day!
#4
Quote:Does this mean that in my C3Bridge client program, I need to keep sending the same command to the C3Bridge until the robot finishes the movement?
Precisely.

An approximate sequence of queries might be as follows:
  1. Send Move Command (PTP, LIN, PTP_REL, or LIN_REL) with an argument like {AXIS: A1 0, A2 -90, A3 90, A4 0, A5 0, A6 0}
  2. Send Start Command
  3. Check robot is moving by requesting $PRO_MOVE, $ROB_STOPPED or similar variables.
  4. If robot is moving then go to #2 and send Start Command again else go to #5
  5. The robot has reached the path
  




Users browsing this thread:
2 Guest(s)