ModalAI Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login
    1. Home
    2. Connor Fuhrman
    • Profile
    • Following 0
    • Followers 0
    • Topics 0
    • Posts 4
    • Best 0
    • Controversial 0
    • Groups 0

    Connor Fuhrman

    @Connor Fuhrman

    0
    Reputation
    6
    Profile views
    4
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Connor Fuhrman Unfollow Follow

    Latest posts made by Connor Fuhrman

    • RE: Problem with bitrate and omx encoder

      @Alex-Kushleyev I've got this working using a custom ModalAI pipe sending an RGB image (I tried YUV because I thought that was the expected input but looking through the source code I saw the vixl-streamer could accept RGB as well).

      I am unfortunately only successful with a 480p image and nothing at a higher resolution. I do not get any error messages writing to the pipe with a larger image size and I don't see the voxl-streamer receive an initial frame. Do you have thoughts as to why I'm not seeing any output from voxl-streamer and not getting an error when writing to the pipe?

      I've attached the logs from my application and from running /usr/bin/voxl-streamer -v 0.

      My configuration file is

      {
          "input-pipe": "ros_to_voxl_streamer",
          "bitrate":	10000000,
          "decimator": 1,
          "port": 8900,
          "rotation":	0
      }
      

      The logs from the voxl-streamer can be found here for 480p images and here for 720p images. The logs from my application can be found here for the 480p image output and here for the 720p image output.

      When I write to the pipe my function is

        bool image_pipe::write_frame(cv::Mat frame_bgr)
        {
          namespace time = std::chrono;
      
          log_verbose(fmt::format("Input frame has size [width={}, height={}]",
      			    frame_bgr.size().width,
      			    frame_bgr.size().height));
          
          static auto first_frame = true;
          static std::size_t num_frame_write_errors = 0;
          static constexpr std::size_t num_acceptable_frame_write_errors = 10;
      
          // Resize the image to the output size specified
          cv::resize(frame_bgr, frame_bgr, img_size);
      
          log_verbose(fmt::format("Resized input frame to size [width={}, height={}]",
      			    frame_bgr.size().width,
      			    frame_bgr.size().height));
      
          cv::Mat frame_rgb;
          cv::cvtColor(frame_bgr, frame_rgb, cv::COLOR_BGR2RGB);
      
          // If this is the first frame we've sent then configure the
          // camera metadata
          if (first_frame)
          {
            camera_mdata.height = static_cast<std::int16_t>(img_size.height);
            camera_mdata.width = static_cast<std::int16_t>(img_size.width);
            camera_mdata.size_bytes = static_cast<std::int32_t>(frame_rgb.total()) *
      	static_cast<std::int32_t>(frame_rgb.elemSize());
            camera_mdata.stride = static_cast<std::int32_t>(frame_rgb.step[0]);
      
            log_info(fmt::format("First frame written to image_pipe object. Metadata:\n{}",
      			   describe_camera_pipe_metadata()));
      
            first_frame = false;
          }
      
          camera_mdata.timestamp_ns = time::duration_cast<time::nanoseconds>(
            time::steady_clock::now().time_since_epoch()).count();
      
          log_verbose(fmt::format("Sending image through pipe with metadata\n{}",
      			    describe_camera_pipe_metadata()));
      
          const auto* frame_data = reinterpret_cast<const void*>(frame_rgb.data);
          const auto ret = pipe_server_write_camera_frame(0, camera_mdata, frame_data);
      
          if (ret != 0)
          {
            if (num_frame_write_errors++ == num_acceptable_frame_write_errors)
            {
      	throw std::runtime_error("Maximum number of consequtive frame write errors reached");
            }
            log_warning(fmt::format("Was not able to write a frame to the pipe. There are {} more error(s) left before failure",
      			      num_acceptable_frame_write_errors - num_frame_write_errors));
            return false;
          }
      
          num_frame_write_errors = 0;
      
          if (++camera_mdata.frame_id % 100 == 0)
          {
            log_verbose(fmt::format("Camera metadata:\n{}",
      			      describe_camera_pipe_metadata()));
          }
      
          return true;
        }
      

      Note that the calls to log_ functions are what generates the above-linked log files.

      and the construction of the pipe occurs here:

        static inline pipe_info_t make_pipe_info(const std::string_view pipe_name)
        {
          pipe_info_t info; // = PIPE_INFO_INITIALIZER;
          std::strcpy(info.name, pipe_name.data());
          std::strcpy(info.type, "camera_image_metadata_t");
          std::strcpy(info.server_name, "ros-voxl-streamer");
      
          info.size_bytes = 2 * MODAL_PIPE_DEFAULT_PIPE_SIZE;
      
          return info;
        }
        
        image_pipe::image_pipe(std::string pipe_name, cv::Size _img_size)
          : voxl_pipe_info(make_pipe_info(pipe_name)),
            img_size(_img_size)
        { 
          // Configure the camera_mdata member
          camera_mdata.magic_number = CAMERA_MAGIC_NUMBER;
          camera_mdata.exposure_ns = -1;
          camera_mdata.gain = -1;
          camera_mdata.format = IMAGE_FORMAT_RGB; // IMAGE_FORMAT_YUV420;
          camera_mdata.frame_id = 0;
          camera_mdata.framerate = 5;
      
          const auto ret = pipe_server_create(0, voxl_pipe_info, 0);
          if (ret != 0)
          {
            throw std::runtime_error("Cannot create pipe");
          }
        }
      
      posted in VOXL-CAM
      Connor FuhrmanC
      Connor Fuhrman
    • RE: Problem with bitrate and omx encoder

      @Alex-Kushleyev thank you for the quick reply! My application requires the ability to encode an arbitrary image frame not necessarily directly from a camera stream. Can you please comment on the feasibility of using the modal-pipes library to provide frame data to the video-server (or maybe the proper module is the voxl-streamer?)? I've used this solution in the past to provide data to the Tensorflow Lite server so I'm hoping the same approach can be taken here.

      From this file on ModalAI's gitlab it looks like I can configure the voxl-streamer to accept a raw image frame in YUV colorspace? I can then make the pipe contain arbitrary image data, no?

      posted in VOXL-CAM
      Connor FuhrmanC
      Connor Fuhrman
    • RE: Problem with bitrate and omx encoder

      I'm experiencing similar issues with the omxh264enc showing grainy video. Using identical gstreamer pipelines except for swapping x264enc and omxh264 elements I see clear video with SW-only encoding but grainy with OpenMAX element. Any updates on the omxh264enc gstreamer element?

      posted in VOXL-CAM
      Connor FuhrmanC
      Connor Fuhrman
    • RE: m500 ROS 2 Support

      Bryce - were you successful in running ROS2 on the VOXL? I'm working with a Docker container built from the official ROS2 Foxy container that just adds a simple proof-of-concept package for our use case and ran into some issues actually running a container from my image.

      The container itself runs fine but my ROS2 launch script won't execute. My issues, I believe, surround the pseudoterminal interface on the VOXL's Linux build. ROS2 launch is using the pty Python package and pty.openpty() looks for BSD-style pseudoterminals and I assume the onboard Linux kernel was compiled with the option to disable that depreciated interface (someone please chime in and correct me if I'm wrong). I'm currently wrestling the Docker image to work correctly on the VOXL Flight board.

      Am thinking about trying to run Singularity/Apptainer on the VOXL since it's computerization but focused on integration rather than isolation because I think my issues are Docker-related. Not sure if anyone has tried Singularity or not...

      posted in ROS
      Connor FuhrmanC
      Connor Fuhrman