casting — правильная типизация байтов для записи в дескриптор последовательного порта в переполнении стека

Фон

Я делаю порт кода Arduino в C ++ и у меня возникают проблемы с данными, отправляемыми в виде unsigned char. Мне нужно отправить 8-байтовый пакет без знака, состоящий из:

Byte 1 - Header - 0xFF
Byte 2 - Right Joy Vertical - value between -100 to 100 shifted up by 128
Byte 3 - Right Joy Horizontal - value between -100 to 100 shifted up by 128
Byte 4 - Left Joy Vertical - value between -100 to 100 shifted up by 128
Byte 5 - Right Joy Horizontal - value between -100 to 100 shifted up by 128
Byte 6 - Button Values - 8 bit byte where each bit is mapped to a button
Byte 7 - Extended Inst. - "0" not needed
Byte 8 - Checksum

У кода arduino был код, написанный как:

Serial.write((unsigned char)right_V);
Serial.write((unsigned char)buttons);

Это явно не так просто в C ++.

Проблемы:

1) Как правильно настроить тип для отправки 8 байтов неподписанного символа с помощью моей функции sp-> write ()?

2) Какие модификаторы printf я использую для отображения данных в виде беззнаковых байтов в HEX?

Разъяснение кода

btn является структурой, состоящей из значений джойстика двойной точности

cmd[] массив без знака размера 8

sp->write(const char * data, int length) является оберткой для функции записи fstream Я включил определение на всякий случай.

ROS_INFO это оболочка для printf для вывода на консоль ROS

КОД

// *****************************************************************************
// Create the Commander unsigned char packet as per the Arbotix Commander specifications
int PhantomXROS::arbotixCmdPackage(cont_value btn)
{

int d_cmd=0;
unsigned char st_code;

std::stringstream ss;
ss << std::hex << "0xFF";
ss >> st_code;

//Mapping joystick values to the servo values of the robot arm
int right_V=this->map(btn.rightV, -1, 1, -100, 100)+128;
int right_H=this->map(btn.rightH, -1, 1, -100, 100)+128;
int left_V=this->map(btn.leftV, -1, 1, -100, 100)+128;
int left_H=this->map(btn.leftH, -1, 1, -100, 100)+128;//Bytes 1-5 Convert integers to bytes
this->cmd[0] = (unsigned char)st_code;
this->cmd[1] = (unsigned char)right_V;
this->cmd[2] = (unsigned char)right_H;
this->cmd[3] = (unsigned char)left_V;
this->cmd[4] = (unsigned char)left_H;

//Byte 6 - Assign a button ON/OFF to its corresponding bit
d_cmd += (btn.R1 > 0) ? 1 : 0;
d_cmd += (btn.R2 > 0) ? 2 : 0;
d_cmd += (btn.R3 > 0) ? 4 : 0;
d_cmd += (btn.L4 > 0) ? 8 : 0;
d_cmd += (btn.L5 > 0) ? 16 : 0;
d_cmd += (btn.L6 > 0) ? 32 : 0;
d_cmd += (btn.RT > 0) ? 64 : 0;
d_cmd += (btn.LT > 0) ? 128 : 0;
this->cmd[5] = (unsigned char)d_cmd;

//Byte 7 - Extended instruction - none, therefore 0
this->cmd[6] = (unsigned char)0;

//Byte 8 - Checksum
this->cmd[7] = (unsigned char)((255 - (right_V+right_H+left_V+left_H+d_cmd)%256));

//Reinterpret the cmd byte array to an 8 char string
std::string buf(reinterpret_cast<const char*>(cmd), 8);

//write to the arbotix serial handle
try{
sp_->write(buf.c_str(),buf.size());

}
catch(cereal::Exception& e){
ROS_INFO("Could not write to Arbotix:");
ROS_BREAK();
return(-1);
}//Output data to the ROS console
if(this->timer > 500)
{ROS_INFO("Arbotix Cmd right_v has written: %d", right_V);
ROS_INFO("Arbotix Cmd right_h has written: %d", right_H);
ROS_INFO("Arbotix Cmd left_v has written: %d", left_V);
ROS_INFO("Arbotix Cmd left_h has written: %d", left_H);
ROS_INFO("Arbotix Cmd d_cmd has written: %d", d_cmd);
ROS_INFO("String command: %s",buf.c_str());

this->timer = 0;

}return 0;}

Ниже приведен код записи

int cereal::CerealPort::write(const char * data, int length)
00146 {
00147         int len = length==-1 ? strlen(data) : length;
00148
00149         // IO is currently non-blocking. This is what we want for the more cerealon read case.
00150         int origflags = fcntl(fd_, F_GETFL, 0);
00151         fcntl(fd_, F_SETFL, origflags & ~O_NONBLOCK); // TODO: @todo can we make this all work in non-blocking?
00152         int retval = ::write(fd_, data, len);
00153         fcntl(fd_, F_SETFL, origflags | O_NONBLOCK);
00154
00155         if(retval == len) return retval;
00156         else CEREAL_EXCEPT(cereal::Exception, "write failed");
00157 }

0

Решение

Ваше приведение типов правильное, но с использованием std:string здесь не нужно Вы можете использовать cmd буфер прямо в вашем вызове sp_->write()

//write to the arbotix serial handle
try
{
sp_->write(reinterpret_cast<const char*>(cmd), 8);
}
catch(cereal::Exception& e){
ROS_INFO("Could not write to Arbotix:");
ROS_BREAK();
return(-1);
}

Для печати данных в шестнадцатеричном формате вы можете использовать %02x или же %02X спецификаторы формата вроде так

ROS_INFO("Arbotix Cmd right_v has written: %02X", right_V);

Это говорит printf функция (используется ROS_INFO) распечатать как минимум две шестнадцатеричные цифры и добавить нулевой символ, если выводится менее двух цифр.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]