How to transport files between ROS and Android?

asked 2020-12-13 21:36:23 -0500

heweiyan gravatar image

I am an Android developer, and i am new on ROS. My goal is transporting files between ROS and Android. After some test code, i can transport a small PNG image from ROS to Android via ROSBridge. Here is the code:

ROS node code, this code is copy from image_transport/Tutorials/PublishingImages:

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);
  cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
  cv::waitKey(30);
  sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();

  ros::Rate loop_rate(5);
  while (nh.ok()) {
    pub.publish(msg);
    ros::spinOnce();
    loop_rate.sleep();
  }
}

Android code:

// Websocket was connected and the "/camera/image" topic was subscribed before.
public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
    super.onMessage(webSocket, text);

    try {
        JSONObject jsonObj = new JSONObject(text);
        if ("/camera/image".equals(jsonObj.getString("topic"))) {
            decodeImage(jsonObj);
        }
    } catch (JSONException e) {
        e.printStackTrace();
        return;
    }
}

/**
 * Decoding image data from ROSBridge and save to SD card.
 */
private void decodeImage(JSONObject jsonObj) {
    try {
        JSONObject msgJsonObj = jsonObj.getJSONObject("msg");
        int width = msgJsonObj.getInt("width");
        int height = msgJsonObj.getInt("height");
        int step = msgJsonObj.getInt("step");
        String data = msgJsonObj.getString("data");
        byte[] bytes = Base64.decode(data, Base64.DEFAULT);
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int bluePos = y * step + x * 3;
                byte blue = bytes[bluePos];
                byte green = bytes[bluePos + 1];
                byte red = bytes[bluePos + 2];
                bitmap.setPixel(x, y, Color.argb(255, red & 0xFF, green & 0xFF, blue & 0xFF));
            }
        }
        String filePath = getExternalCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".png";
        FileUtil.saveBitmapAsPng(filePath, bitmap);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

The code works fine when the ROS node publish a small PNG image. But when i try to transport a large PNG image, such as a 6816x4480 1.4MB PNG file, the Android websocket occurs OOM problem.
Is there any better ways to transport large files between ROS and Android?

Thanks in advance!

edit retag flag offensive close merge delete

Comments

OOM as in out of memory? Then devide the image in chunks, and encode & send them separately. relevant

crnewton gravatar image crnewton  ( 2022-12-28 09:37:20 -0500 )edit