Robotics StackExchange | Archived questions

"failed to write bulk data" and "failed to transmit bulk packet"

Hello All!

System: Lenovo Laptop running Ubuntu 20.04.05 ROS: Noetic Robot HW: Robotis 5 axis arm (Dynamixel)

I am VERY new to ROS. I am a master student working on a ROS related capstone project that I inherited from another student. I am trying to get the other student's code to run so I can start the project where he left of and am getting an the following two errors after running a his "testaxisnode" node (rosrun dxllib testaxis_node).

failed to write bulk data

failed to transmit bulk packet

The two errors come down alternating just as fast as the processor can generate them. I was kinda surprised that google turned up nothing for these two errors considering how large the ROS community is. The other nodes testctrlnode, testtrajnode, and testhostnode all seem to run just fine. Im only having issues with the testaxisnode one.

Any advice would be greatly appreciated!

Thanks!

Here is the testaxisnode code:

#include <ros/ros.h>
#include "dxl_cmn.cpp"
#include "dxl_msg/dxlAxis.h"
#include "dxl_msg/dxlTorque.h"

using namespace dynamixel;

//_rsp define the addressing for communicating with your motor.
#define DXL1_ID                 1               // device address
#define DXL_T1_ID               15              // t1 device address
#define DXL_T2_ID               12              // t2 device address
#define DXL_T3_ID               13              // t3 device address
#define DXL_T4_ID               14              // t4 device address
#define DXL_T5_ID               11              // t5 device address
#define T1_IDX                  0
#define T2_IDX                  1
#define T3_IDX                  2
#define T4_IDX                  3

#define DEVICE_NAME             "/dev/ttyUSB0"  // device serial port 
#define PROTOCOL_VERSION        2.0             // device packet protocol version
#define BAUDRATE                3000000         // device baud rate



//_rsp interface class for publishing position data and updating torque set point
class axisInterface {
    public:
        axisInterface() 
        : axGroup(4)
        , getPos(ADDR_PRESENT_POSITION,4)
        , setTrq(ADDR_GOAL_CURRENT,2)
        {
            axGroup.id[T1_IDX] = DXL_T1_ID;     //define motor id
            axGroup.id[T2_IDX] = DXL_T2_ID;
            axGroup.id[T3_IDX] = DXL_T3_ID;
            axGroup.id[T4_IDX] = DXL_T4_ID;
            dxlgrp_initDevice(axGroup,EPM_CURRENT_CONTROL);
            getPos.setParams(axGroup);

            axisPos_pub = nh.advertise<dxl_msg::dxlAxis>("axisPos",1);
            axisTrq_sub = nh.subscribe("axisTrq",1,&axisInterface::update_trq,this);
        }
        void setServo(int mode){
            zero_trq();
            dxlgrp_setGoalTorque(axGroup);      //set torque to zero when doing servo off
            dxlgrp_setTorqueEnb(axGroup, mode); //set enable/disable state on motors
        }
        void setHome(){
            dxlgrp_setDeviceHome(axGroup);      //set the current position to 0 for all axis
        }
        void run(){
            update_pos();
            axisPos_pub.publish(output);
            //dxlgrp_setGoalTorque(axGroup);
            setTrq.sendData(axGroup);
        }
        void enbRuntime(bool isRun){
            if (isRun){
                dxlgrp_setReturnLevel(axGroup,RAM_RETURN_FOR_READ);
            } else {
                dxlgrp_setReturnLevel(axGroup,RAM_RETURN_FOR_ALL);
            }
        }
    private:
        void update_pos(){ 
            //update position within object, in radians
            getPos.readData(axGroup);
            output.axis1Pos = dxl_encCounts2Radian(axGroup.fbkPos[T1_IDX]);     
            output.axis2Pos = dxl_encCounts2Radian(axGroup.fbkPos[T2_IDX]);     
            output.axis3Pos = dxl_encCounts2Radian(axGroup.fbkPos[T3_IDX]);     
            output.axis4Pos = dxl_encCounts2Radian(axGroup.fbkPos[T4_IDX]);     //_rsp worst typo ever T-T
            ROS_DEBUG("ax pos: [ %d, %d, %d, %d ]",axGroup.fbkPos[T1_IDX],axGroup.fbkPos[T2_IDX],axGroup.fbkPos[T3_IDX],axGroup.fbkPos[T4_IDX]);
        }
        void update_trq(const dxl_msg::dxlTorque::ConstPtr& command){
            //update torque within object. let run() func do the actual write so we avoid data collision.
            axGroup.cmnTrq[T1_IDX] = command->axis1Trq; 
            axGroup.cmnTrq[T2_IDX] = command->axis2Trq; 
            axGroup.cmnTrq[T3_IDX] = command->axis3Trq; 
            axGroup.cmnTrq[T4_IDX] = command->axis4Trq; 
            dxlgrp_convertGoalTrq(axGroup);
        }
        void zero_trq(){
            axGroup.cmnTrq[T1_IDX] = 0; 
            axGroup.cmnTrq[T2_IDX] = 0; 
            axGroup.cmnTrq[T3_IDX] = 0; 
            axGroup.cmnTrq[T4_IDX] = 0; 
        }
        ros::NodeHandle     nh;
        ros::Publisher      axisPos_pub;
        ros::Subscriber     axisTrq_sub;
        dxl_msg::dxlAxis    output;
        axisGroup           axGroup;
        bulkReadData        getPos;
        bulkWriteData       setTrq;
};

int main(int argc, char ** argv)
{
    ros::init(argc, argv, "test_axis_node");
    ROS_INFO("started test_AXIS_node");                             // print to consol so we know the node has started

    dxlcmn_openPort(DEVICE_NAME,PROTOCOL_VERSION,BAUDRATE);         //open the usb port 
    axisInterface interfaceObj;                                     //create interface object
    interfaceObj.setServo(ENABLED);
    //interfaceObj.setServo(DISABLED);  //debug or test
    interfaceObj.enbRuntime(true);

    while (ros::ok()){
        interfaceObj.run();
        ros::spinOnce();
    }

    interfaceObj.enbRuntime(false);
    interfaceObj.setServo(DISABLED);            //set torque back to zero and turn off motor
    dxlcmn_closePort();                         //close out the serial port
    return 0;
}

Asked by LyleKosinski on 2022-11-01 00:39:18 UTC

Comments

Seeing as you mention Dynamixels, and those are typically connected using USB<->RS232/RS485: it's possible (likely even) this is not ROS related, but an error from within the library you're using: dxl_cmn / dxl_msg. Those are not OSS AFAICT (or at least: I can't find them), so I can't check.

I was kinda surprised that google turned up nothing for these two errors considering how large the ROS community is.

"bulk packet" sounds like a USB protocol error to me. I don't recognise it as something in/from ROS.

I'd suggest you take a look at the library/ies you're using to interface with the Dynamixels.

Asked by gvdhoorn on 2022-11-01 03:17:27 UTC

Also just noticed:

#define DEVICE_NAME             "/dev/ttyUSB0"  // device serial port 

this seems like it could cause problems.

If your Dynamixels/USB-serial converter isn't also registered as /dev/ttyUSB0 with your OS, DEVICE_NAME will be incorrect, and nothing would work. dxlcmn_openPort(..) would likely complain, but I don't see any error checking code surrounding it.

Asked by gvdhoorn on 2022-11-01 03:20:29 UTC

Answers