Kinova-kortex2_Gen3_G3L

Error management

Table of Contents

Overview

There are three mechanisms available to manage errors triggered by the C++ KINOVA KORTEX™ API:

When you use the KINOVA KORTEX™ API, the mechanism to be used depends on the type of called method:

Note that there is a special case explained at the end of this section.

Blocking method

Exceptions are only used if a blocking or async function is used. The code is surrounded with a try/catch statement pair and to catch any exceptions. The KINOVA KORTEX™ API offers its own exception object: Kinova::Api::KDetailedException.

Example

try
{
    // Your code...
}
catch(k_api::KDetailedException& ex)
{
    // You can print the error informations and error codes
    auto error_info = ex.getErrorInfo().getError();
    std::cout << "KDetailedoption detected what:  " << ex.what() << std::endl;
    
    std::cout << "KError error_code: " << error_info.error_code() << std::endl;
    std::cout << "KError sub_code: " << error_info.error_sub_code() << std::endl;
    std::cout << "KError sub_string: " << error_info.error_sub_string() << std::endl;

    // Error codes by themselves are not very verbose if you don't see their corresponding enum value
    // You can use google::protobuf helpers to get the string enum element for every error code and sub-code 
    std::cout << "Error code string equivalent: " << k_api::ErrorCodes_Name(k_api::ErrorCodes(error_info.error_code())) << std::endl;
    std::cout << "Error sub-code string equivalent: " << k_api::SubErrorCodes_Name(k_api::SubErrorCodes     (error_info.error_sub_code())) << std::endl;
}

Here are the details of the object Kinova::Api::KDetailedException thrown by the KINOVA KORTEX™ API.

KDetailedException

class KDetailedException : public KBasicException
{
    public:
        KDetailedException(const KError& error);
        KDetailedException(const KDetailedException &other);

        virtual const char* what() const throw() override;
        virtual std::string toString() override;

        KError&      getErrorInfo() { return m_error; }

    private:
        void init(const HeaderInfo& header, const Error& error);
    
        KError       m_error;
        std::string  m_errorStr;
};

Here are the details of the object KError nested in the exception.

KError

class KError
{
    public:
        KError(Kinova::Api::ErrorCodes errorCode, Kinova::Api::SubErrorCodes errorSubCode, std::string errorDescription);
        KError(const HeaderInfo& header, Kinova::Api::ErrorCodes errorCode, Kinova::Api::SubErrorCodes errorSubCode, std::string errorDescription);
        KError(const Error& error);
        KError(const HeaderInfo& header, const Error& error);

        static Error fillError(Kinova::Api::ErrorCodes errorCode, Kinova::Api::SubErrorCodes errorSubCode, std::string errorDescription);

        std::string toString() const;

        bool            isThereHeaderInfo();
        HeaderInfo      getHeader();
        Error           getError();

        KError& operator =(const KError& other) = default;

    private:
        bool            m_isThereHeaderInfo;
        HeaderInfo      m_header;
        Error           m_error;
};

The KError object holds an error code and a sub error code to identify the fault.

Here is a link to documentation explaining all of the error and sub error codes:

Callback

If the callback version is used, a std::function is given as a parameter to act as a callback. The header of this std::function includes an Error object containing the error returned by the execution. Since it is a std::function, you can either use a lambda expression or a standard C callback.

Example using lambda

// callback function used in Refresh_callback
auto lambda_fct_callback = [](const Kinova::Api::Error &err, const k_api::BaseCyclic::Feedback data)
{
    // We are printing the data for example purposes
    // avoid this for a real-time loop 

    std::string serialized_data;
    google::protobuf::util::MessageToJsonString(data, &serialized_data);
    std::cout << serialized_data << std::endl;
};

base_cyclic->Refresh_callback(BaseCommand, lambda_fct_callback, 0);

Example using C callback

// callback function used in Refresh_callback
void fct_callback(const k_api::Error &err, const k_api::BaseCyclic::Feedback data)
{
    std::cout << "Callback function results: " << std::endl;
    //react to the fault...
}

void example_function_call()
{
	base_cyclic->Refresh_callback(BaseCommand, fct_callback, 0);
}

Async method

If an async function is used, exceptions must be used to catch any error triggered by the KINOVA KORTEX™ API. The exception is thrown during the execution of the get() function.

Async example

// The function returns a future object, and not a workable object.
std::future<k_api::Base::JointsLimitationsList> limitations_future_async = base->GetAllJointsSpeedHardLimitation_async();

// Waiting for the promise to be completed by the API.
auto timeout_ms = std::chrono::milliseconds(10000);
std::future_status status = limitations_future_async.wait_for(timeout_ms);

if(status != std::future_status::ready)
{
    throw std::runtime_error("Timeout detected while waiting for function\n");
}

// Retrieve the workable object from the future object.
try
{
    auto limitations_async = limitations_future_async.get();
}
catch(k_api::KDetailedException& ex)
{
    // Respond to the fault
}

Special case

This section describes a case that doesn’t follow the standard error management rules documented earlier in this document.

RouterClient

When a RouterClient object is instantiated a callback can be specified for execution when an error occurs.

RouterClient* router = new RouterClient(pTransport, [](KError err){ cout << "callback error" << err.toString(); });