How to solve the problem of RVIZ freezing?



  • Question:
    The main content of this post is that the robotic arm starts RVIZ in the ROS environment, which will cause the system to freeze, affecting the program's crash. Is there any way to improve the stability of RVIZ and enable it to operate normally?
    Operation:
    I run the program with two versions of myCobot280 series robotic arm. One is the robotic arm with M5Stack master control, and another is the robotic arm with Raspberry Pi 4B master control.
    The M5Stack's robotic arm runs in a laptop configuration, and the Raspberry Pi's robotic arm runs in its own Raspberry Pi 4B (64-bit 1.5GHz quad-core).
    alt text
    Figure is myCobot280-M5Stack
    alt text
    Figure is myCobot280-Pi
    Here are a few ways to use myCobot280 with RVIZ.
    Slider Control:

    Move the slider to control the movement of myCobot280, and the movement of myCobot280 will be fed into the RVIZ interface in real time.
    0_1661500522007_slider control.png
    Movement Planning:
    Given two positions, one is position A, and the other is position B, send commands to the myCobot280 to move from A to B.
    alt text
    Artificial Intelligence Kit:
    Guide the robot through robot vision and realize intelligent grabbing simultaneously. The intellectual grabbing of wood blocks and the intelligent grabbing of image objects have been developed.
    0_1661500670214_1234.png
    0_1661500692158_aikit.jpg
    Problems
    1: After the myCobot280 generally runs for a while, the machine heats up, and the RVIZ cannot run normally.
    2: On the Raspberry Pi version, after opening the RVIZ, I found that the computer's CPU was instantly occupied and could not run stably.
    Try to solve

    1. At first, I thought that the file (URDF) of the built model was too large, which made RVIZ freeze. We optimized the model file (URDF) and found little improvement.
      Reflections:
      1: It is relatively stable to run programs with a small amount of code, so is it possible to optimize the code to improve the stability of RVIZ? We are currently trying to migrate its adaptation environment from ROS1 to ROS2 to see if the whole will be more stable.
      2: When the RVIZ is turned on, the CPU is full. We try to start with the CPU to see if we can improve the performance of the CPU processing to be more stable.
    2. After I modified the CPU processing capability of the virtual machine, it was much more stable when I used it again. You may think that Raspberry Pi is a computer. How to upgrade the CPU? Is it going to have to change the motherboard? We use a socket method to connect to the Raspberry Pi (like a TCP/IP connection) to solve this problem.
      Socket function:
      The principle of the socket method is to use its virtual machine to establish a connection with myCobot280-Pi (remote control), and the virtual machine sends instructions to myCobot280-Pi instead of sending instructions to the robotic arm in its Pi motherboard. This solves the problem of low CPU performance.
      code:
    def get_logger(name):
        logger = logging.getLogger(name)
        logger.setLevel(logging.DEBUG)
    
        LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
        #DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
    
        formatter = logging.Formatter(LOG_FORMAT)
        # console = logging.StreamHandler()
        # console.setFormatter(formatter)
    
        save = logging.handlers.RotatingFileHandler(
            "/home/ubuntu/mycobot_server.log", maxBytes=10485760, backupCount=1)
        save.setFormatter(formatter)
    
        logger.addHandler(save)
        # logger.addHandler(console)
        return logger
    
    
    class MycobotServer(object):
    
        def __init__(self, host, port):
            try:
                GPIO.setwarnings(False)
            except:
                pass
            self.logger = get_logger("AS")
            self.mc = None
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s.bind((host, port))
            print "Binding succeeded!"
            self.s.listen(1)
            self.connect()
    
        def connect(self):
            while True:
                try:
                    print "waiting connect!------------------"
                    conn, addr = self.s.accept()
                    port_baud = []
                    while True:
                        try:
                            print "waiting data--------"
                            data = conn.recv(1024)
                            command = data.decode('utf-8')
                            if data.decode('utf-8') == "":
                                print("close disconnect!")
                                break
                            res = b'1'
                            command = command.replace(" ", "")
                            if len(port_baud) < 3:
    
                                port_baud.append(command)
                                if len(port_baud) == 3:
                                    self.mc = serial.Serial(
                                        port_baud[0], port_baud[1], timeout=float(port_baud[1]))
                                    port_baud.append(1)
                            else:
                                self.logger.info(command)
                                command = self.re_data_2(command)
                                if command[3] == 170:
                                    if command[4] == 0:
                                        GPIO.setmode(GPIO.BCM)
                                    else:
                                        GPIO.setmode(GPIO.BOARD)
                                elif command[3] == 171:
                                    if command[5]:
                                        GPIO.setup(command[4], GPIO.OUT)
                                    else:
                                        GPIO.setup(command[4], GPIO.IN)
    
                                elif command[3] == 172:
                                    GPIO.output(command[4], command[5])
    
                                elif command[3] == 173:
                                    res = bytes(GPIO.input(command[4]))
    
                                self.write(command)
                                res = self.read()
                                if res == None:
                                    res = b'1'
                            conn.sendall(res)
                        except Exception as e:
                            self.logger.error(str(e))
                            conn.sendall(str.encode("ERROR:"+str(e)))
                            break
                except Exception as e:
                    self.logger.error(str(e))
                    conn.close()
    
        def write(self, command):
            self.mc.write(command)
            self.mc.flush()
            time.sleep(0.05)
    
        def read(self):
            data = None
            if self.mc.inWaiting() > 0:
                data = self.mc.read(self.mc.inWaiting())
            return data
    
        def re_data_2(self, command):
            r2 = re.compile(r'[[](.*?)[]]')
            data_str = re.findall(r2, command)[0]
            data_list = data_str.split(",")
            data_list = [int(i) for i in data_list]
            return data_list
    

    (The essence of the socket approach is to use a virtual machine to connect to the Raspberry Pi, and we then boost the CPU processing power of the virtual machine.)
    Discuss:
    For now, our solution for RVIZ is just this. I am wondering whether there is a better way to handle your RVIZ related issues. Everyone is welcome to discuss, and I will learn from your opinions and put them into practice.



  • Please check that you are using gpu acceleration and not just software rendering. This can be seen in the output of rviz at startup for example



  • This looks like a good suggestion.