Forcely stopping and re-starting PTP command Fails - Dobot unresponsive afterwards


#1

I’m using the provided Dobot_Magician_ROS_DEMO to drive the Dobot (API V1.0.0).
I want to execute a PTP command that I have to interrupt from time to time. So the sequence would be like this:

  • Sending PTP command
  • Stopping the execution of the current command
  • Clear the command Queue
  • continue operation
  • Send a new PTP command that should be executed

I’m facing issues with the interruption of the command, since either the command cannot be interrupted, or Dobot is not responding to any commands after the interruption anymore. Here is what I tried and discovered:

  1. Sending the SetQueuedCmdClear command had no effect at all, the Dobot continued executing the current command.

  2. Sending the Set SetQueuedCmdForceStopExec successfully stops the execution. But when the ** SetQueuedCmdStartExec** is issued again, the latest command will continue. So the queue is not cleared at all - only the execution is paused.

  3. Sending the SetQueuedCmdForceStopExec successfully stops the execution. The SetQueuedCMDClear command seems to clear the command queue. Afterwards I issue the SetQueuedCmdStartExec. The issue here is that DOBOT is not responding to any commands anymore - it is totally unresponsive. The only way I found is to reboot Dobot which is not usable at all.

Can someone advise on how to interrupt an instruction, clear the command queue and resume operation with a new instruction afterwards. What would be the correct sequence of commands, respectively why is SetQueuedCmdClear either not working at all, or causing Dobot to be completely unresponsive?

Any tips highly appreciated


#2

From my observations it appears that the Dobot works like this. But have you tried immediate (not-queued) intructions after stopping, and clearing?

I have 1 more idea (not the best, but that’s something):

  1. Change move mode to CP (in CP arm do not stops beetwen given points).
  2. Divide every path beetwen 2 neightboring points to f.e. 5 smaller paths.
  3. Make a queue inside you controlling unit.
  4. Send next queued point to Dobot each time there is a space in queue for next command on Dobot .
  5. Now if you will clear queued commands on Dobot, let it make his last queued 1/5th of the move.

#3

Hi !

I know this reply is over a year later :frowning: … but maybe it will help someone.

This functionality seems now to be working.

Here is the code


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Program Purpose and instructions:
#   (Purpose): Purpose is to check whether the synchronous functionality works. This is checked using keyboard commands
#   (Instructions): Follow the instructions in the terminal
#   (Notes): Please note, this program sources the DLL from the cri_dobot library, but it doesn't use any cri_dobot library functionality

# Author: Ben Money-Coomes

# **Version control**

# v1    Inital commit (Copy of asynchronous code)
# v2    Comments updated
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#


# ------------------------------------------#
# Imports                                   #
# ------------------------------------------#

# Import the dobot dll
from cri_dobot.dobotMagician.dll_files import DobotDllType as dType
import time  # For sleeping
import keyboard  # For keyboard input

# Load Dll
api = dType.load()  # Load the dll to allow it to be used

# ------------------------------------------#
# Variables                                 #
# ------------------------------------------#

# Error terms
CON_STR = {
    dType.DobotConnect.DobotConnect_NoError:  "DobotConnect_NoError",
    dType.DobotConnect.DobotConnect_NotFound: "DobotConnect_NotFound",
    dType.DobotConnect.DobotConnect_Occupied: "DobotConnect_Occupied"}  # a dictionary of error terms as defined a C++ enum in 'DobotType.h file'


# ------------------------------------------#
# Helper functions                          #
# ------------------------------------------#

def yes_or_no(question):
    """ Get a y/n answer from the user
    """
    while "the answer is invalid":
        reply = str(input(question+' (y/n): ')).lower().strip()
        if reply[:1] == 'y':
            return True
        if reply[:1] == 'n':
            return False


# ------------------------------------------#
# Start of main program                     #
# ------------------------------------------#

print("")
print("========================")
print("")
print("Hello! This program will:")
print("")
print(" 1. Home the dobot magician robot (if selected)")
print(" 2. Demonstrate if synchronous mode interupts the last command (it doesn't)")
print("")
print(" Let's begin...")
print("")
print("========================")
print("")


# Connect Dobot
# Try and connect to dobot with automatic search, returns enumerate type
state = dType.ConnectDobot(api, "", 115200)[0]
print("Returned value from ConnectDobot command: {}".format(state))  # print result
print("Connect status meaning:", CON_STR[state])

# If connection is successful
if (state == dType.DobotConnect.DobotConnect_NoError):  # If we managed to connect to the dobot

    # Then run this code

    # Check if homing is required
    print("")
    homeRobot = yes_or_no("Do you want to home the robot? ")

    # Stop to Execute Command Queued
    dType.SetQueuedCmdStopExec(api)  # Stop running commands in command queue

    # Clean Command Queue
    dType.SetQueuedCmdClear(api)  # Clear queue
    currentIndex = dType.GetQueuedCmdCurrentIndex(
        api)[0]  # Get the current command index

    # Async Motion Params Setting
    dType.SetHOMEParams(api, 250, 0, 50, 0, isQueued=1)  # Set home position
    # Set the velocity and acceleration of the joint co-ordinate axis in the format given in DobotDllType.py
    dType.SetPTPJointParams(api, 200, 200, 200, 200,
                            200, 200, 200, 200, isQueued=1)
    # Set the velocity ratio and acceleration ratio in PTP mode (i guess the amount of time it accelerates to define the velocity profile?)
    dType.SetPTPCommonParams(api, 100, 100, isQueued=1)

    # Execute homing function if homing is desired
    if homeRobot:
        # Start homing function
        print("Start homing function immediately (synchronous)")
        # Execute the homing function. Note temp is not used by Dobot. Returned value is the last index -> "queuedCmdIndex: If this command is added to the queue, queuedCmdIndex indicates the index of this command in the queue. Otherwise, it is invalid."
        lastIndex = dType.SetHOMECmd(api, temp=0, isQueued=0)[0]
        print("ReturnHoming: {}".format(lastIndex))

    # Execute commands up to homing function
    dType.SetQueuedCmdStartExec(api)  # Start running commands in command queue

    # --- Start of Loop Synchronous movements

    print("")
    print("========================")
    print("")
    print("Starting synchronous control:")
    print("")
    print(" 1. Press 'q' on the keyboard to move to position A")
    print(" 2. Press 'w' on the keyboard to move to position B")
    print(" 3. Press 'e' on the keyboard to stop the command queue and clear it")
    print(" 4. Press 'Esc' on the keyboard to exit and disconnect from the dobot magician")
    print("")
    print(" You can visually see with how the schronous control works with python on the dobot magician.")
    print(" Because if you press 'q' then 'w' immediately after each other, the robot arm responds in kind.")
    print(" It is clear that dobot magician arm doesn't respond immediatly. Instead it executes each move,")
    print(" before beginning the next when communicating using python.")
    print("")
    print("========================")
    print("")

    # Initialise keyboard input for loop
    k = ''
    lastIndex = currentIndex = dType.GetQueuedCmdCurrentIndex(
        api)[0]  # Get the current command index

    # loop until escape character is pressed
    while k != 'esc':
        k = keyboard.read_key()

        if k == 'q':
            print("Synchronous movement A starting")
            lastIndex = dType.SetPTPCmd(
                api, dType.PTPMode.PTPMOVLXYZMode, 200, -120, 50, 0, isQueued=0)[0]
        elif k == 'w':
            print("Synchronous movement B starting")
            lastIndex = dType.SetPTPCmd(
                api, dType.PTPMode.PTPMOVLXYZMode, 150, 120, 50, 0, isQueued=0)[0]
        elif k == 'e':
            print("Command Queue force stop and clear...")
            print("Issuing stop command")
            lastIndex = dType.SetQueuedCmdForceStopExec(api)
            print("lastIndex = ", lastIndex)
            print("")
            print("Issuing clear command")
            lastIndex = dType.SetQueuedCmdClear(api)
            print("lastIndex = ", lastIndex)
            print("")
            print("Starting command queue")
            lastIndex = dType.SetQueuedCmdStartExec(api)
            print("lastIndex = ", lastIndex)

        time.sleep(0.2)
        print("loop continuing")
        print("lastIndex = {}".format(lastIndex))


# Disconnect Dobot
dType.DisconnectDobot(api)  # Disconnect the Dobot
print("Dobot disconnected !")


#4

This code above uses Python, I am using the windows operating system. If you install this library (https://github.com/meisben/cri_dobot) in a python environment (or point to the dll correctly) the code should just work on the dobot magician.