- спросил Росс. Arduino Publishing custom msg (6 значений float64 и заголовок) и subscribe Vector3Stamped msg от Arduino mega2560 не работают!
Rosserial Arduino custom msg publisher. Я публикую пользовательские msg (6 float64 значения и заголовок) и подписаться Vector3Stamped msg от Arduino mega2560. Но не работает!
Ошибка, которую я получаю, следующая (пользовательский издатель публикует правильно, но обычный подписчик не работает):
Создание подписчика не удалось: требуется более 1 значения для распаковки
Когда у меня есть следующее в Arduino/библиотеки/Rosserial_Arduino_Library/src/ros.h
#elif defined(__AVR_ATmega2560__)
typedef NodeHandle_ <ArduinoHardware, 15, 15, 512, 512> NodeHandle
в то время как ошибка отличается при изменении Arduino/libraries/Rosserial_Arduino_Library/src/ros.h на следующее:
#elif defined(__AVR_ATmega2560__)
typedef NodeHandle_<ArduinoHardware, 15, 15, 512, 512,FlashReadOutBuffer_> NodeHandle;
Ошибка, которую я получаю в этом случае, - это следование (пользовательский издатель не работает, но работает обычный подписчик)
Создание издателя не удалось: требуется более 1 значения для распаковки
Пытался опубликовать перед настройкой, идентификатор темы 115
Мой код arduino выглядит следующим образом:
#include <HardwareSerial.h>
#include <ODriveArduino.h>
#include <Wire.h>
#include <ros.h>
#include <std_msgs/String.h>
#include <geometry_msgs/Vector3Stamped.h>
#include <geometry_msgs/Twist.h>
#include <ros/time.h>
#include <mybot/encoderMsgStamped.h>
#define ROBOT_WIDTH (480) //МИЛЛИМЕТР
#define WHEEL_DIAMETER (165.1) ///МИЛЛИМЕТР
#define WHEEL_CIRC (518.676947108) //окружность КОЛЕСА
#define CPR_ENCODER (90)
HardwareSerial& odrive_serial1 = Serial1;
HardwareSerial& odrive_serial2 = Serial2;
HardwareSerial& odrive_serial3 = Serial3;
//axis0(M0)-слева
//axis1(M1)-справа
ODriveArduino odrive1(odrive_serial1);
ODriveArduino odrive2(odrive_serial2);
ODriveArduino odrive3(odrive_serial3);
// переменные / cmd_vel, которые будут получены для привода с
float demandx;
float demandz;
// таймеры для суб-основного цикла
unsigned long currentMillis;
long previousMillis = 0; // set up timers
float loopTime = 100; //100ms
long forward0;
long forward1;
long turn0;
long turn1;
// переменные положения и скорости считываются из ODrive
long posfl,posfr,posml,posmr,posrl,posrr;
long posfl_old,posfr_old,posml_old,posmr_old,posrl_old,posrr_old;
long posfl_diff,posfr_diff,posml_diff,posmr_diff,posrl_diff,posrr_diff;
float posfl_mm_diff,posfr_mm_diff,posml_mm_diff,posmr_mm_diff,posrl_mm_diff,posrr_mm_diff;
ros::NodeHandle nh;
//функция, которая будет вызываться при получении команды от хоста
void handle_cmd (const geometry_msgs::Twist& cmd_vel) {
demandx = cmd_vel.linear.x;
demandz = cmd_vel.angular.z;
}
ros::Subscriber<geometry_msgs::Twist> cmd_vel("/cmd_vel", handle_cmd); //create a subscriber to ROS topic for velocity commands (will execute "handle_cmd" function when receiving data)
mybot::encoderMsgStamped pos_msg; //create a "pos_msg" ROS message
ros::Publisher pos_pub("encoderPos", &pos_msg); //create a publisher to ROS topic "encoderPos" using the "pos_msg" type
void setup() {
nh.initNode(); //init ROS node
nh.getHardware()->setBaud(115200); //set baud for ROS serial communication
nh.subscribe(cmd_vel); //suscribe to ROS topic for velocity commands
nh.advertise(pos_pub); //prepare to publish speed in ROS topic
odrive_serial1.begin(115200);
odrive_serial2.begin(115200);
odrive_serial3.begin(115200);
odrive1.SetVelocity(0,0);
odrive1.SetVelocity(1,0);
odrive2.SetVelocity(0,0);
odrive2.SetVelocity(1,0);
odrive3.SetVelocity(0,0);
odrive3.SetVelocity(1,0);
odrive1.SetPosition(0,0.0);
odrive1.SetPosition(1,0.0);
odrive2.SetPosition(0,0.0);
odrive2.SetPosition(1,0.0);
odrive3.SetPosition(0,0.0);
odrive3.SetPosition(1,0.0);
Serial.begin(115200);
while (!Serial) ;
}
//_________________________________________________________________________
void loop() {
nh.spinOnce();
currentMillis = millis();
if (currentMillis - previousMillis >= loopTime) { // run a loop every 100ms
previousMillis = currentMillis; // reset the clock to time it
float modifier_lin = 1.03; // scaling factor because the wheels are squashy / there is wheel slip etc.
float modifier_ang = 0.92; // scaling factor because the wheels are squashy / there is wheel slip etc.
forward0 = demandx * 1.927982351202 * modifier_lin ; // convert m/s into counts/s
forward1 = demandx * 1.927982351202 * modifier_lin; // convert m/s into counts/s
turn0 = demandz * 0.46271576428 * modifier_ang; // convert rads/s into counts/s
turn1 = demandz * 0.46271576428 * modifier_ang; // convert rads/s into counts/s
forward1 = forward1*-1; // one motor and encoder is mounted facing the other way
odrive1.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
odrive1.SetVelocity(0, forward1 + turn1);
odrive2.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
odrive2.SetVelocity(0, forward1 + turn1);
odrive3.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
odrive3.SetVelocity(0, forward1 + turn1);
// get positions from ODrive
posfr = odrive3.GetPosition(1) *-1;
posfl = odrive3.GetPosition(0);
posmr = odrive2.GetPosition(1) *-1;
posml = odrive2.GetPosition(0);
posrr = odrive1.GetPosition(1) *-1;
posrl = odrive1.GetPosition(0);
// work out the difference on each loop, and bookmark the old value
posfl_diff = posfl - posfl_old;
posfr_diff = posfr - posfr_old;
posfl_old = posfl;
posfr_old = posfr;
posml_diff = posml - posml_old;
posmr_diff = posmr - posmr_old;
posml_old = posml;
posmr_old = posmr;
posrl_diff = posrl - posrl_old;
posrr_diff = posrr - posrr_old;
posrl_old = posrl;
posrr_old = posrr;
// calc mm from encoder counts
posfl_mm_diff = posfl_diff /0.1735184116;
posfr_mm_diff = posfr_diff /0.1735184116;
posml_mm_diff = posml_diff /0.1735184116;
posmr_mm_diff = posmr_diff /0.1735184116;
posrl_mm_diff = posrl_diff /0.1735184116;
posrr_mm_diff = posrr_diff /0.1735184116;
publishPos();
}
}
void publishPos() {
pos_msg.header.stamp = nh.now(); //timestamp for odometry data
pos_msg.fl = posfl_mm_diff;
pos_msg.ml = posml_mm_diff;
pos_msg.rl = posrl_mm_diff;
pos_msg.fr = posfr_mm_diff;
pos_msg.mr = posmr_mm_diff;
pos_msg.rr = posrr_mm_diff;
pos_pub.publish(&pos_msg);
}
Примечание: С обычной публикацией и подпиской msgs и следующими Arduino/libraries/Rosserial_Arduino_Library/src/ros.h все отлично работает как для публикации, так и для подписки:
#elif defined(__AVR_ATmega2560__)
typedef NodeHandle_<ArduinoHardware, 15, 15, 512, 512,FlashReadOutBuffer_> NodeHandle;
@Mazox, 👍2
Обсуждение0
- Как разделить входящую строку?
- Как использовать SPI на Arduino?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Arduino Due vs Mega 2560
- Как получить уникальный идентификатор для всех плат Arduino?
- Почему я получаю avrdude: stk500v2_ReceiveMessage(): timeout error when uploading to Arduino Mega?
- Тайм-аут связи Arduino Mega с ошибкой программатора
Что на самом деле отвечает за создание сообщения "Создание подписчика не удалось"?, @timemage
напишите простой скетч, который публикует одно фиксированное сообщение, @jsotola
Чего бы это ни стоило, avr-gcc реализует свой тип "двойной" в виде 32-разрядной "плавающей" 32-разрядной точности. Это может быть проблемой для вашего использования
float64
, независимо от того, с какой проблемой вы сталкиваетесь сейчас., @timemage