0

I create ROS services that pass the IMU sensors values from the Server to Client. Im able to build the package but some how the Client values are all zeros.

So I would like to create IMU ROS services. I have a Server(in my case is a microcontroller ESC32) that can obtain IMU reading and should pass to the Client (in my case is Raspberry PI 4B) the IMU data when requested for further processing.So I just need to pass the raw IMU data. This is my .srv file

float64 x_orient_in
float64 y_orient_in
float64 z_orient_in
float64 w_orient_in
float64 x_veloc_in
float64 y_veloc_in
float64 z_veloc_in
float64 x_accel_in
float64 y_accel_in
float64 z_accel_in
---
float64 x_orient_out
float64 y_orient_out
float64 z_orient_out
float64 w_orient_out
float64 x_veloc_out
float64 y_veloc_out
float64 z_veloc_out
float64 x_accel_out
float64 y_accel_out
float64 z_accel_out
bool success

then my Server cpp node

#include "ros/ros.h"
#include <sensor_msgs/Imu.h>
#include "ros_services/ImuValue.h"


bool get_val(ros_services::ImuValue::Request  &req, ros_services::ImuValue::Response &res)
{
    
    ROS_INFO("sending back response");

    res.current_x_orientation = get_orientation_x(); 
   
    
}


void imuCallback(const  sensor_msgs::Imu::ConstPtr& msg)
{
  
     double current_x_orientation;
     current_x_orientation= msg->orientation.x;
    
}



int main(int argc, char **argv)
{
  ros::init(argc, argv, "imu_status_server");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("imu_data", 1000, imuCallback);

  ros::ServiceServer service = n.advertiseService("imu_status_server", get_val);
  ROS_INFO("Starting server...");
  ros::spin();

  return 0;
}

then my client mode

#include "ros/ros.h"
#include "ros_services/ImuValue.h"
#include <cstdlib>

int main(int argc, char **argv)
{
        ros::init(argc,argv,"imu_client_node");
        ros::NodeHandle n;
    ros::ServiceClient client = n.serviceClient<ros_services::ImuValue>("imu_status_server");
    ros_services::ImuValue srv;
    client.call(srv);
    std::cout << "Got orient x: " << srv.response.x_orient_out << std::endl;
    std::cout << "Got orient y: " << srv.response.y_orient_out << std::endl;
    std::cout << "Got orient z: " << srv.response.z_orient_out << std::endl;
    std::cout << "Got orient w: " << srv.response.w_orient_out << std::endl;
    std::cout << "Got veloc x: " << srv.response.x_veloc_out << std::endl;
    std::cout << "Got veloc y: " << srv.response.y_veloc_out << std::endl;
    std::cout << "Got veloc z: " << srv.response.z_veloc_out << std::endl;
    std::cout << "Got accel x: " << srv.response.x_accel_out << std::endl;
    std::cout << "Got accel y: " << srv.response.y_accel_out << std::endl;
    std::cout << "Got accel z: " << srv.response.z_accel_out << std::endl;

  return 0;
}

And the IMU topic is

header: 
  seq: 93931
  stamp: 
    secs: 1919
    nsecs: 264000000
  frame_id: "thrbot/imu_link"
orientation: 
  x: 0.011051219171
  y: 0.0185614347587
  z: 0.271966050405
  w: -0.962064348743
orientation_covariance: [0.0001, 0.0, 0.0, 0.0, 0.0001, 0.0, 0.0, 0.0, 0.0001]
angular_velocity: 
  x: 0.000226259345086
  y: 0.0135818332253
  z: -0.0254669231582
angular_velocity_covariance: [1.1519236000000001e-07, 0.0, 0.0, 0.0, 1.1519236000000001e-07, 0.0, 0.0, 0.0, 1.1519236000000001e-07]
linear_acceleration: 
  x: 0.40810519334
  y: -0.109897852778
  z: 9.79053552816
linear_acceleration_covariance: [1.6e-05, 0.0, 0.0, 0.0, 1.6e-05, 0.0, 0.0, 0.0, 1.6e-05]

Any help?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Bob9710
  • 205
  • 3
  • 15

1 Answers1

0

The server is just returning the values of req which in the above code is a default service message passed in from main(). You need to cache the IMU values when them come in on a topic(in the server code). Then when the service is called it needs to pulled from the last IMU value. Your server needs to include something like this:

void imu_callback(const sensor_msgs::Imu::ConstPtr& msg)
{
    current_x_orientation = msg->orientation.x; //Variable declared somewhere in a scope the service can see
    //Save other needed fields here
}

In your service assign each response field to its respective values saved in the callback.

BTables
  • 4,413
  • 2
  • 11
  • 30
  • ok. I modified the server node in the question according your suggestion . Now i got only two errors. error: ‘ros_services::ImuValue::Response {aka struct ros_services::ImuValueResponse_ >}’ has no member named ‘current_x_orientation’ res.current_x_orientation = get_orientation_x(); ^~~~~~~~~~~~~~~~~~~~~ /home/bojan/uuv_simulator_ws/src/ros_services/src/ImuServer.cpp:11:33: error: ‘get_orientation_x’ was not declared in this scope res.current_x_orientation = get_orientation_x(); – Bob9710 Sep 13 '21 at 18:12
  • You don't have a field in your `srv` file for `current_x_orientation`, you call it `x_orient_out`. You also need to actually declare the message `get_orientation_x()` – BTables Sep 13 '21 at 18:28
  • ok clear about current_x_orientation. But how to declare the message get_orientation_x()? – Bob9710 Sep 14 '21 at 06:35
  • That's a function, not a message. You just write it like a normal function and have it return the cached values inside my example of `imu_callback`. You could also just assign the values directly. – BTables Sep 14 '21 at 12:46
  • and how to declare current_x_orientation Variable in a scope the service can see? – Bob9710 Sep 14 '21 at 13:06
  • In this case not using a class it just needs to be a global variable. Declare it above the function. – BTables Sep 14 '21 at 13:08
  • I will open a new question as I would like to use ROS Services every time I control the tele operated robot by pressing the joystick . Thats should be a new question right? – Bob9710 Sep 14 '21 at 13:33
  • Glad it helped. Yes, I think it'd be a new question. – BTables Sep 14 '21 at 13:34