cancel
Showing results for 
Search instead for 
Did you mean: 

Axis AxsJogIncr command

Axis AxsJogIncr command

David4
New Poster

Hello all,
I have been trying to jog the motors via the sdk. i have the x axis in the status standstill. So if i read the docummentation correctly its now ready to recieve move commands. The problem is that i dont know how i need to declare and implement the axisjogcmd. This is done true the axis commands not the kinematic group. I added the code  below. It gives a error about MotionResult  not being declared. 

David4_0-1728473909467.png

 


 Thanks in advance

#include <functional>
#include <thread>
#include <limits>

 

#include "ctrlx_datalayer_helper.h"
#include "datalayerclient.h"

 

#include <stdio.h>
#include <iostream>
using namespace std;

 

 

static void printStringList(comm::datalayer::Variant& data)
{
  if (data.getType() == comm::datalayer::VariantType::ARRAY_OF_STRING)
  {
    std::cout << "Node List: ";
    const char** strArray = data;
    for (uint32_t i = 0; i < data.getCount(); i++)
    {
      std::cout << strArray[i] << " ";
    }
    std::cout << std::endl;
  }
}
static void printMetadata(comm::datalayer::Variant& data)
{
  if (STATUS_FAILED(data.verifyFlatbuffers(comm::datalayer::VerifyMetadataBuffer)))
  {
    std::cout << "Invalid Flatbuffer: Not a MetadataBuffer";
    return;
  }

 

  auto metadata = comm::datalayer::GetMetadata(data.getData());
  std::cout << metadata->displayName()->c_str() << std::endl;
  std::cout << metadata->displayFormat() << std::endl;
  std::cout << metadata->description()->c_str() << std::endl;
  std::cout << metadata->descriptionUrl()->c_str() << std::endl;

 

  auto operations = metadata->operations();
  std::cout << "AllowedOperations: read=" << operations->read() << " write:" << operations->write() << " create:" << operations->create() << " delete:" << operations->delete_() << std::endl;

 

  auto references = metadata->references();
  for (flatbuffers::uoffset_t i = 0; i < references->size(); i++)
  {
    std::cout << references->Get(i)->type()->c_str() << std::endl;
    std::cout << references->Get(i)->targetAddress()->c_str() << std::endl;
  }
}
DataLayerClient::DataLayerClient(const std::string& ip, const std::string& user, const std::string& password, int sslPort)
  : m_ip(ip)
  , m_user(user)
  , m_password(password)
  , m_sslPort(sslPort)
  , m_client(nullptr)
{}

 

 

bool DataLayerClient::start()
{
  std::cout << "m_datalayer.start(..)" << std::endl;
  m_datalayerSystem.start(false);

 

  m_client = getClient(m_datalayerSystem, m_ip, m_user, m_password, m_sslPort);

 

  return m_client != nullptr && m_client->isConnected();
}

 

 

comm::datalayer::IClient::ResponseCallback DataLayerClient::responseCallback()
{
  // [&]    All needed symbols are provided per reference
  // (...)  Parameter provided by the calling site
  return [&](comm::datalayer::DlResult result, const comm::datalayer::Variant* data)
    {
      m_resultAsync = result;
      if (data != nullptr)
      {
        // data must not be nullptr otherwise the '=' operator crashes
        m_dataAsync = *data;

 

        if (m_dataAsync.getType() == comm::datalayer::VariantType::ARRAY_OF_STRING)
        {
          printStringList(m_dataAsync);
        }
      }

 

      std::cout << "ResponseCallback: " << std::string(result.toString()) << std::endl;
    };
}

 

bool DataLayerClient::waitForResponseCallback(int counter)
{
  for (;;)
  {
    if (counter > 0)
    {
      counter--;
      if (counter <= 0)
      {
        return false;
      }
    }

 

    //sleep(1);

 

    if (m_resultAsync != -1)
    {
      std::cout << "ResponseCallback finished: " << m_resultAsync.toString() << std::endl;
      return true;
    }
  }
}

 

 

void DataLayerClient::ping()
{
  std::cout << "ping" << std::endl;
  m_result = m_client->pingSync();
  std::cout << "m_client->pingSync() " << m_result.toString() << std::endl;

 

  m_resultAsync = -1;
  m_result = m_client->pingAsync(responseCallback());
  waitForResponseCallback(10);
}

 

//"fieldbuses/ethercat/master/instances/ethercatmaster/realtime_data/input/data/ctrlX_DRIVE_XCS_SoE_X/AT.Position_feedback_value_1"
void DataLayerClient::readSync(const std::string& node)
{
  std::string address = node;
  m_result = m_client->readSync(address, &m_data);
   // std::cout << ("readSync() " + address) << endl;
    cout << int32_t(m_data) << endl;
}

 

void DataLayerClient::writeSync(const std::string& node)
{
  auto address = "motion/kin/Kinematics/cmd/group-ena";
  m_result = m_client->writeSync(address, &m_data);
  cout << m_result.toString() << endl;

}

 

 

void DataLayerClient::write()
{
  m_data.setValue(true);
  writeSync("bool8");

 

  m_data.setValue(-0.123456789f);
  writeSync("float32");

 

  m_data.setValue(-0.987654321);
  writeSync("float64");

 

  m_data.setValue((int8_t)-127);
  writeSync("int8");

 

  m_data.setValue((int16_t)-32767);
  writeSync("int16");

 

  m_data.setValue((int32_t)0x80000001);
  writeSync("int32");

 

  m_data.setValue((int64_t)0x8000000000000001);
  writeSync("int64");

 

  m_data.setValue("Changed by cpp ctrlX Data Layer Client");
  writeSync("string");
}

 

void DataLayerClient::createSync(const std::string& node)
{
  std::string address = node;
  m_client->removeSync(address); // First remove - may be node exists
  m_result = m_client->createSync(address, &m_data);
  cout << m_result.toString() << endl;
}

 

 

 

void DataLayerClient::stop()
{

  delete m_client;
  m_client = nullptr;
}

 

 

int main() {
  // builds object
    DataLayerClient test;

 

  // starts tcp
    test.start();

 

  //payload definition

 

 

 

    int p;
  // ping ctrl x core
    test.ping();

  //set power to true
  test.m_data.setValue(true);
  test.createSync("motion/axs/X/cmd/power");

 

  // this is the command responsible for jog the x axis
  virtual MotionResult axsPosCmd(const cmd::DataLayerClient::CmdSourceInfo & sourceInfo, const char* x, cmd::axs::AxsCmdType AXS_CMD_POS_ABS, double 400, const cmd::DynamicLimitsT & dynLim, bool true, uint64_t & cmdID) const = 0;

    for ( p = 0; p < 100; p++) {
       //cout << p << endl;

        //read out x encoder 100 times
     test.readSync("fieldbuses/ethercat/master/instances/ethercatmaster/realtime_data/input/data/ctrlX_DRIVE_XCS_SoE_X/AT.Position_feedback_value_1");

 

       


}  //set power to false
  //test.m_data.setValue(false);
  //test.createSync("motion/axs/X/cmd/power");
  //test.stop();
}

 

 

 


With kinde regards,

David

5 REPLIES 5

nickH
Community Moderator
Community Moderator

Hi David, 

The command you posted here is from the Bundle-Interface of the Motion App. This command can only be used if you build your own RT-Bundle with our RT-SDK. Learn more about how to access the RT-SDK here: FAQ for SDK for ctrlX AUTOMATION

But to be able to command the axis, its not necessary to use the RT-SDK. You can just use another interface of the Motion App. For example the Data Layer interface or the Script interface. See the Motion App Application Manual for more information regarding the interfaces. What kind of application do you want to achieve? There are use cases for every interface of the motion app. 

If you want to use the same command via the Data Layer interface for example, you can do a "create" with a DL-Client to the path "motion/axs/<axs_name>/cmd/pos-rel" or "/pos-abs" or "pos-add". This you can also try out via the Data Layer web interface: 

nickH_0-1728477600628.png

 

See also the Motion App Manual on this command.

Best regards, 

Nick

Hi Nick,
Thanks for the fast response. We are trying to operate the ctrl x core via are own windows application we tried before with the create function to the exact same path. Once we send the payload that was specefied in the documentation we got the error code DL_type_mismatch what i could find in the documentation, that this has to do with sending a wrong datatype. But its not specified what datatype it needs to be or maybe its somthing with the syntac? It only specified what needs to be in the payload in the documentation.
https://docs.automation.boschrexroth.com/doc/28483558/axsjogincr-incremental-axis-jogging/latest/en/ 

David4_0-1728543870882.png

Best regards,
David

 

nickH
Community Moderator
Community Moderator

Hi David, 

you have two Options: 

1. Use the Data Layer functions and create a complex FlatBuffer Data Type

2. Or use a REST Client and do a post. Here you have to send the payload like you can see in the Docu. 

Best regards, 

Nick

Hello Nick,
Thanks for the reply.

I just had a meeting with our contact person from Bosch rexroth. She was able to do it via python with the create, problem that she did it in python. That offcourse has different syntac and is managed while c++ isnt. My specific qeustion is how do i send this payload via the sdk i assume thats the flatbuffer data type. and if so do you have an example.

nickH
Community Moderator
Community Moderator

Hi David, 

I made a little test and succeded. 

To create a flatbuffer data type you need to use the genearted-header files, which got created out of the FlatBuffer-schema (.fbs). 

You can check, I think depending on the SDK Version you are using the _generated.h files of the motion-app data types are allready in the SDK (under the path /include). If they are not there then you can also generate them out of the .fbs files with the help of the flatc (flatbuffer compiler). 

Here is how I have done it for the two flatbuffers I need for the pos-abs command:

nickH_1-1729008553429.png

 

If you include these headers in your .cpp you can use the "Create..."-functions like this: 

// Synchronous create of a ctrlX Data Layer of the motion app to command the Axis "Axis_1" -----------------------------------------------------------
    auto DataLayerAddress = "motion/axs/Axis_1/cmd/pos-abs";
    comm::datalayer::Variant myCmdPositionData;

    //create the flatbuffer data type with the help of the generated header
    flatbuffers::FlatBufferBuilder builder;
    auto limits = motion::core::fbtypes::CreateDynamicLimits(builder,1.0,1.0,1.0,0.0,0.0);
    auto cmdData = motion::core::fbtypes::CreateAxsCmdPosData(builder,10.0,true,limits,motion::core::fbtypes::CmdPosAbsDir_SHORTEST_WAY);
    builder.Finish(cmdData);
    myCmdPositionData.shareFlatbuffers(builder);

    std::cout << "INFO create " << DataLayerAddress << " synchronously..." << std::endl;
    auto result = dataLayerClient->createSync(DataLayerAddress, &myCmdPositionData);
    if (result != DL_OK)
    {
      std::cout << "WARN create " << DataLayerAddress << " failed with: " << result.toString() << std::endl;
    }
    else
    {
      std::cout << "Create to " << DataLayerAddress << " succeded: "<< result.toString()<< std::endl;
    }

 

Best regards, 

Nick

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist