ModalAI Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login
    1. Home
    2. zauberflote1
    3. Posts
    • Profile
    • Following 0
    • Followers 1
    • Topics 5
    • Posts 24
    • Best 3
    • Controversial 0
    • Groups 1

    Posts made by zauberflote1

    • RE: Add thrid party library to voxl-cross

      @remill
      You can also add a FetchContent CMake declaration that will build your library during compilation. Here is an example for yaml-cpp

      include(FetchContent)
      
      # Fetch yaml-cpp from GitHub
      FetchContent_Declare(
        yaml-cpp
        GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
        GIT_TAG yaml-cpp-0.6.3
      )
      
      # Disable yaml-cpp tests
      set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
      set(YAML_BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) #cross 4.0 quits the chat if building static
      FetchContent_MakeAvailable(yaml-cpp)
      # Confirm target exists
      if (TARGET yaml-cpp)
          add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
      endif()
      
      install(FILES
          ${yaml-cpp_BINARY_DIR}/libyaml-cpp.so
          ${yaml-cpp_BINARY_DIR}/libyaml-cpp.so.0.6
          ${yaml-cpp_BINARY_DIR}/libyaml-cpp.so.0.6.3
          DESTINATION ${CMAKE_INSTALL_LIBDIR}
      )
      
      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: Migrating from QVIO to OpenVINS (SDK1.6)

      To clarify, our current platforms are shipped with voxl-open-vins-server as the default VINS solution; however, QVIO is still available (SDK 1.6.2).

      posted in GPS-denied Navigation (VIO)
      zauberflote1Z
      zauberflote1
    • RE: Migrating from QVIO to OpenVINS (SDK1.6)

      @Rowan-Dempster Hi there,
      Glad to hear you are exploring the new voxl-open-vins-server.

      A few things to consider, as you are not using a "ModalAI airframe".

      • OpenVINS follows the classic Kalibr calibration model (both cameras and IMU)
      • Calibration involves IMU intrinsics, Cam Intrinsics, IMU-CAM extrinsics

      From this point, I'll assume you're using a VOXL2 Board. Hence, your IMU intrinsics should be "1:1" to the values reported in here. However, depending on your airframe vibration you may need to tune the noise density and random walk values -- Personally, I would leave this as a final option, as these are a result of extensive calibration routines and have shown to be invariant among our airframes.

      Moreover, you can obtain the camera intrinsics using our voxl-camera-calibration repo. I highly recommend to re-calibrate your cameras, making sure your reprojection error is in the subpixel range.

      Next, we need the extrinsics from each CAM to IMU. Ideally, you may want to run Kalibr or you can use the sync_config flag in /etc/modalai/voxl-open-vins-server.conf as true under the assumption your extrinsics.conf is setup correctly. If you opt to use Kalibr, you will need to update the camchain file and make sure your sync_config flag is set to false.

      Finally, we need to address the most important config file. Tuning this file may be a bit challenging because it revolves around use-case that being said, I would leave as is for the most part, addressing ZUPT params and chi2_multipliers/sigma_px based on simple hand-held tests. Particularly, if the estimator blows up when the drone is sitting still right after a power-cycle -> ZUPT params, and/or if due to heavy dynamic motion MSCKF features are losing track frequently or the platform is drifting slightly -> Bump chi2_multiplier + increase/decrease (case-by-case) sigma_px (SLAM/MSCKF).

      To conclude, I would recommend deactivating the thermal calibration of the IMU for initial testing, as depending on the SDK version and platform, it could increase the perceived noise in the accel. Also, I would attempt 2Cam flights using ION pipes (vio_cams.conf) before jumping to 3Cam, as the 3rd Cam seems to add more noise into estimator if placed in opposite direction to another Cam (e.g., front and rear) and the extrinsics are not "perfectly" tuned.

      PS: We have a converter from voxl-logs to rosbags for seamless integration with Kalibr, feel free to check it out

      PS2: Regarding camera time-synchronization, if your cameras are being driven by an fsync line, you shouldn't have to worry about the sync dt; however, if they are not, you may want to bump the fusion_rate_dt_ms flag (voxl-open-vins-server.conf) to a value that guarantees that every camera has one individual frame. Moreover, if the timestamps are not monotonically increasing or the cameras don't start exposing at the same time -- implying that the 3Cams have non-aligned timestamps, you may need to "hot-fix" your timestamps to get a stable performance. As for the CAM-IMU dt, we use the online calibration inside of our OpenVINS implementation to estimates the value.

      PS3: We currently don't have any external-release report for performance comparison with QVIO, but internally we have seen significant differences in behavior between the two (especially in multi-camera setups and under aggressive motion). In general, OpenVINS gives you more tuning flexibility and multi-camera support, at the cost of being more sensitive to calibration quality.

      posted in GPS-denied Navigation (VIO)
      zauberflote1Z
      zauberflote1
    • RE: QVIO unstable flight. Please help!

      @Daniel-Rincon,
      Please consider updating to the latest SDK release, 1.5.0, if you haven't already. This has our latest VIO public development.

      As Tom mentioned, OV in 1.5.0 can use a binocular+ tracking, i.e., number of cams => 2 without stereo matching. This improves VIO robustness significantly compared to the single cam QVIO. Hence, OV should be preferred.

      Additionally, I would recommend redoing a full calibration of all sensors (IMU, PX4, Cams) and checking if the extrinsics file is correct.

      This should improve your flight performance.

      I hope this clarifies some of your questions

      posted in GPS-denied Navigation (VIO)
      zauberflote1Z
      zauberflote1
    • RE: Open-vins keeps diverging and re-initializing.

      Hello,
      Please refer to the following and see if the problem persists:
      https://forum.modalai.com/topic/4475/voxl-open-vins-server?_=1749222785639

      Thanks,

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server

      @Jetson-Nano
      Could you confirm that you are using the correct camera stream?

      Please run the following:

      voxl-inspect-cams
       voxl-inspect-vins #with openvins running on a separate terminal
      

      Check if you have any error codes or camera feeds that have stalled.

      Finally, double check your vio_cams.conf file to see if you are using the *misp_norm
      camera pipes.
      -- An easy way to do this is to reset your openvins and vio cam configuration files, run the following after backing up your .conf files.

       voxl-configure-cameras 
      voxl-configure-open-vins
      
      

      Then, reboot the platform and attempt to run openvins with the new conf files.

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server

      Hello,
      Regarding the IMU temperature calibration, it is now optional as some platforms may underperform if the calibration is not executed properly, i.e., getting poor measurements at the cold phase. I would recommend removing the IMU temperature calibration file from /data/modalai and double-checking if the behaviour persists.
      Quick question: Which cameras are you using? Did you set your extrinsics file correctly?
      Please make sure you calibrate all the cameras as well.

      Thanks,
      ZBFT

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server

      Hello @Jetson-Nano,

      Would you be able to confirm your SDK version?

      Also, have you attempted to recalibrate the IMU?

      voxl-calibrate-imu
      ``
      https://docs.modalai.com/calibrate-imu/
      
      All the best,
      ZBFT
      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: Problems in resetting voxl-open-vins-server

      @Marco-Spangaro
      From your test case description, there could be a few reasons for an imperfect re-initialization. Please note that monocular VINS has four unobservable directions (position and yaw), so your hand motion could likely affect initialization, especially if you are moving too erratically or performing a degenerate motion that would affect the calibration refinement.

      Note that if the image frames post-reset are not feature-friendly, they could also have a negative impact.

      Regarding the vio_always_on flag, some segments of the voxl-open-vins-server code will only be executed if the drone is armed or the flag is set to true.

      Finally, I noticed that you increased the tracking and publishing frequency. Did you see an increase in robustness from these new parameters? Usually, for general environments, I would suggest leaving these as the default values, as you will likely have a better feature triangulation between keyframes. Additionally, enabling feature refinement can also help.

      posted in GPS-denied Navigation (VIO)
      zauberflote1Z
      zauberflote1
    • RE: Problems in resetting voxl-open-vins-server

      Hello Marco,
      Thanks for your question.

      A few things to consider:
      What is your camera setup -- or is it a ModalAI development drone?

      Note that the default configuration of voxl-open-vins-server does not use dynamic initialization, meaning that if a reset triggers while the platform has some motion above the maximum threshold, OV won't be able to properly re-initialize.
      If you want to test if that is the case, set "init_dyn_use" to true in the voxl-open-vins-server.conf

      To further diagnose the issue, please do the following:

      • Run voxl-open-vins-server from terminal
      voxl-open-vins-server
      
      • Check why the reset was triggered based on the output
      • Analyze the following messages post unsuccessful re-initialization -- usually, motion issues will be characterized by IMU threshold messages
      • If the problem persists, upload your voxl-open-vins-server.conf file
      posted in GPS-denied Navigation (VIO)
      zauberflote1Z
      zauberflote1
    • VOXL-MAPPER WITHOUT VOXL-PORTAL

      Hello ModalAI community,
      Hardware: VOXL2 (Sentinel)

      Recently, I was trying to run a few experiments that required a conservative obstacle avoidance capability. My objective was to send relative position setpoints (drone-centered frame) to voxl-mapper; however, I noticed that the only available package that allows to pipeline setpoints to voxl-mapper is voxl-portal, and the user has to manually on click each individual setpoint on the portal site.

      Note that I am not talking about sending a full trajectory, just a goal setpoint and allow voxl-mapper to find the optimal path to it

      Hence, I developed what is called the mapper-commander package. Of course, implementation details will vary from application to application, but for this base case example, the package allows the user to send a square maneuver -- you can easily modify this as you wish, e.g., figure 8 maneuver.

      How it works?

      • Grab VIO estimates insert them in the ring buffer
      • Add desired relative setpoints to current position in the ring buffer
      • Send control pipe commands to plan, follow and stop following accordingly
      • A separate thread controls the cmdHandler callbacks and sleeps based on the realtime clock
      /**
       * @ Author: zauberflote1
       * @ Create Time: 2024-10-06 23:20:17
       * @ Modified by: zauberflote1
       * @ Modified time: 2024-10-11 19:31:20
       * @ Description:
       * PIPELINE TO VOXL-MAPPER VIA COMMANDS
       */
      
      
      #include "mapper_cmd.hpp"
      
      MapperCmd::MapperCmd() {
          
      
          ch_mapper = pipe_client_get_next_available_channel();
          ch_vio = pipe_client_get_next_available_channel();
      
          pose_buffer = RC_TF_RINGBUF_INITIALIZER;
          rc_tf_ringbuf_alloc(&pose_buffer, 2500);
      
          pipe_client_set_simple_helper_cb(ch_vio, [](int ch, char* data, int bytes, void* context) {
              static_cast<MapperCmd*>(context)->_vio_helper_cb(ch, data, bytes, context);
          }, this);
      
          pipe_client_set_connect_cb(ch_vio, [](int ch, void* context) {
              static_cast<MapperCmd*>(context)->_vio_connect_cb(ch, context);
          }, this);
      
          pipe_client_set_disconnect_cb(ch_vio, [](int ch, void* context) {
              static_cast<MapperCmd*>(context)->_vio_disconnect_cb(ch, context);
          }, this);
      
      
      //SQUARE MISSION ONLY
      //1M SQUARE
          square_mission << 1.0, 0.0, 0.0,
                            0.0, 1.0, 0.0,
                            -1.0, 0.0, 0.0,
                            0.0, -1.0, 0.0;
      
          pts_togo = square_mission.rows();
      }
      
      MapperCmd::~MapperCmd() {
          //CLOSE PIPES --  AND FREE BUFFERS?
          _cmdHandler_terminate_cb();
          pipe_client_close_all();
      }
      
      
      
      int MapperCmd::getRobotPose(rc_tf_t &tf_body_wrt_fixed, int64_t ts){
          static int error_ctr = 0;
      
          int ret = rc_tf_ringbuf_get_tf_at_time(&pose_buffer, ts, &tf_body_wrt_fixed);
          if (ret < 0)
          {
              error_ctr++;
              if(error_ctr>5){
                  //fprintf(stderr, "ERROR fetching tf from tf ringbuffer\n");
                  if (ret == -2){
                      printf("INFO waiting for VIO to start\n");
                      error_ctr = 0;
                  }
                  if (ret == -3){
                      printf("WARNING the requested timestamp was too new, VIO may have stopped\n");
                      error_ctr = 0;
                  }
                  if (ret == -4){
                      printf("WARNING the requested timestamp was too old\n");
                  }
              }
              return -1;
          }
      
          return 0;
      }
      
      int MapperCmd::sendPlanCommand(Eigen::Vector3d goal_vtf) {
      
      
          char command[100];
          //DO NOT STOP FOLLOWING IF THIS IS THE FIRST ITERATION -- MAY CHANGE THIS IN THE FUTURE...
          if (goal_plan){ //CHECK POTENTIAL RACE CONDITION
              snprintf(command, sizeof(command), STOP_FOLLOWING); // STOP_FOLLOWING = "stop_following"
              if (pipe_client_send_control_cmd(ch_mapper, command) == 0) {
                  std::cout << "Sent STOP_FOLLOWING command: " << command << std::endl;
              } else {
                  std::cerr << "Failed to send STOP_FOLLOWING command" << std::endl;
                  return -1;
              }
          }
          usleep(500000); // SLEEP FOR 0.5 SECOND TO GIVE THE SERVER TIME TO PROCESS STOP_FOLLOWING COMMAND
          snprintf(command, sizeof(command), "plan_to:%.2f,%.2f,%.2f", goal_vtf.x(), goal_vtf.y(), goal_vtf.z());
      
          // Send the command to the server using pipe_client_send_control_cmd
          if (pipe_client_send_control_cmd(ch_mapper, command) == 0) {
              std::cout << "Sent PLAN_TO command: " << command << std::endl;
          } else {
              std::cerr << "Failed to send PLAN_TO command" << std::endl;
              return -1;
          }
          usleep(500000); // SLEEP FOR 0.5 SECOND TO GIVE THE SERVER TIME TO PROCESS PLAN_TO COMMAND
          snprintf(command, sizeof(command), FOLLOW_PATH); // FOLLOW_PATH = "follow_path"
          if (pipe_client_send_control_cmd(ch_mapper, command) == 0) { 
              std::cout << "Sent FOLLOW_TO command: " << command << std::endl;
          } else {
              std::cerr << "Failed to send FOLLOW_TO command" << std::endl;
              return -1;
          }
          return 0;
      
      }
      //////////////////////////////////////////////////////////////////////////////////////////////////////////
      //VIO HELPER FUNCTIONS (FROM VOXL-MAPPER)
      void MapperCmd::_vio_helper_cb(__attribute__((unused)) int ch, char *data, int bytes, __attribute__((unused)) void *context){
          // validate data
          int n_packets;
          pose_vel_6dof_t *d = pipe_validate_pose_vel_6dof_t(data, bytes, &n_packets);
      
          // if there was an error OR no packets received, just return;
          if (d == NULL){
              std::cerr << "[VIO] ERROR: Failed to validate pose_vel_6dof_t data" << std::endl;
              return;
          }
          if (n_packets <= 0){
              std::cerr << "[VIO] ERROR: No packets received" << std::endl;
              return;
          }
      
          for (int i = 0; i < n_packets; i++)
          {
              rc_tf_ringbuf_insert_pose(&pose_buffer, d[i]);
          }
          // std::cout << "[VIO] GOT NEW" << std::endl;
          return;
      }
      
      void MapperCmd::_vio_connect_cb(__attribute__((unused)) int ch, __attribute__((unused)) void *context){
          printf("Connected to VIO server\n");
      }
      
      void MapperCmd::_vio_disconnect_cb(__attribute__((unused)) int ch, __attribute__((unused)) void *context){
          printf("Disconnected from VIO server\n");
      }
      //////////////////////////////////////////////////////////////////////////////////////////////////////////
      
      //MAPPERCMD HELPER FUNCTIONS
      void MapperCmd::cmdHandler(){
          //GET CURRENT POSITION
          rc_tf_t tf_body_wrt_fixed = RC_TF_INITIALIZER;
          int ret_cmd = -2;
          if (getRobotPose(tf_body_wrt_fixed, my_time_monotonic_ns()) != 0) {
              return; //EARLY EXIT IF WE FAIL TO GET THE CURRENT POSITION
          }
          Eigen::Vector3d current_pos = Eigen::Vector3d(tf_body_wrt_fixed.d[0][3], tf_body_wrt_fixed.d[1][3], tf_body_wrt_fixed.d[2][3]);
          // std::cout << tf_body_wrt_fixed.d[0][3] << std::endl;
          // std::cout << tf_body_wrt_fixed.d[1][3] << std::endl;
          // std::cout << tf_body_wrt_fixed.d[2][3] << std::endl;
          if (pts_togo == 0){
      
              std::cout << "MISSION COMPLETE" << std::endl;
      
              return;
          }
          Eigen::Vector3d goal_pos = square_mission.row(pts_togo - 1).transpose() + current_pos;
          //START GOAL PLAN, IF WE HAVEN'T ALREADY
          if (!goal_plan){
              //SEND INITIAL GOAL
              ret_cmd = sendPlanCommand(goal_pos);
              if (ret_cmd != 0){
                  std::cerr << "[MAPPER-CMD] Failed to send initial goal" << std::endl;
                  return;
              }
              goal_plan = true; //CHECK POTENTIAL RACE CONDITION IF USING MULTIPLE DRONES
          }
          else{
              if((current_pos - (square_mission.row(pts_togo)).transpose()).norm() < 0.1){
                  //SEND NEW GOAL
                  ret_cmd = sendPlanCommand(goal_pos);
                  if (ret_cmd != 0){
                      std::cerr << "[MAPPER-CMD] Failed to send new goal" << std::endl;
                      return;
                  }   
              } else{
                  // std::cout << "WAITING FOR GOAL" << std::endl;
                  return;
              }
              
          }
          if (pts_togo > 0) { //EXTRA SAFETY CHECK
              pts_togo--;
          }
      
      
      }
      
      void MapperCmd::_cmdHandler_cb() {
          int64_t next_time = 0;
          while (!stop_thread) {
              {
                  std::lock_guard<std::mutex> lock(cmd_mutex);
                  // std::cout << "[CMD HANDLER] Iteration start" << std::endl;
                  cmdHandler();
              }
              // std::cout << "[CMD HANDLER] Sleeping for 20Hz cycle." << std::endl; 
              my_loop_sleep(20.0, &next_time); //20HZ, MIGHT BE TOO FAST OR TOO SLOW...
          }
              // std::cout << "[CMD HANDLER] Thread stopping." << std::endl; 
      }
      void MapperCmd::_cmdHandler_terminate_cb() {
          stop_thread = true;
          if (cmd_thread.joinable()) {
              cmd_thread.join();
          }
      }
      void MapperCmd::initMPA(){
      //MAPPER
          ret_mapper = pipe_client_open(ch_mapper, PLAN_LOCATION, "zbft-mapper-cmd", EN_PIPE_CLIENT_AUTO_RECONNECT, 1024 * 1024 * 64); //NOT SURE ABOUT THE BUFFER SIZE HERE...JUST COPYING FROM VOXL-MAPPER
          if (ret_mapper != 0) {
              std::cerr << "[MAPPER] Failed to open the pipe client." << std::endl;
              return;
          }
          std::cout << "[MAPPER] Pipe client opened successfully." << std::endl;
      //VIO
         ret_vio = pipe_client_open(ch_vio, BODY_WRT_FIXED_POSE_PATH, "zbft-mapper-cmd",
                               EN_PIPE_CLIENT_SIMPLE_HELPER | EN_PIPE_CLIENT_AUTO_RECONNECT,
                               POSE_6DOF_RECOMMENDED_READ_BUF_SIZE);
          if (ret_vio != 0){
              std::cerr << "[VIO] Failed to open the pipe client." << std::endl;
              return;
          }
          std::cout << "[VIO] Pipe client opened successfully." << std::endl;
      //CMD THREAD
          cmd_thread = std::thread(&MapperCmd::_cmdHandler_cb, this);
      }
      
      
      
      

      Observation 1:
      My goal was to not modify the voxl-mapper package, but if you decide that integrating mapper-commander to voxl-mapper is better for you, you can make the ring buffer variable a shared pointer -- this should save some memory allocation/usage cost.

      Observation 2:
      I am not using librc-math library, so I copied the source files needed for ring buffer operations -- similarly to what is done in voxl-mapper, but different than what is done in voxl-vision-hub.

      Observation 3:
      You may not need a ring buffer variable, but for more complex routines it might be interested to store past VIO estimates. If you decide to not use the ring buffer variable, make sure to add the proper mutex to avoid race conditions from the VIO pipe client thread and the command handler thread when dealing with the current pose variable

      Future TODOs (it would be great to hear your insights): 🤠

      • ADD CHECK IF DESIRED SETPOINT WAS ILLEGAL -- maybe elapsed time based?
      • POTENTIALLY SEND STOP_FOLLOWING BEFORE INITIAL POINT -- in case you want to repeat the maneuver without resetting voxl-mapper

      DISCLAIMER:
      Fly offboard at your own discretion and responsibility!

      Full Github repo:
      https://github.com/zauberflote1/zbft-mapper-commander/tree/main
      Please let me know your thoughts!

      As always happy to contribute,
      --ZBFT

      posted in Ask your questions right here! voxl2 voxl-mapper voxl-portal
      zauberflote1Z
      zauberflote1
    • RE: IMX412 Autoexposure Compensation

      @ctitus
      You can set up a custom camera configuration

      #!/bin/bash
      
      ################################################################################
      #
      # This file allows setting of custom camera configurations by defining what
      # sensors are plugged into which port.
      #
      # There is no guarantee that any arbitrary configuration will work. Only the
      # predefined camera configs at https://docs.modalai.com/voxl2-camera-configs/
      # are supported.
      #
      # each slot can be one of the following sensors:
      #
      # pmd-tof
      # pmd-tof-liow2
      # ov7251
      # ov7251-combo
      # ov9782
      # ov9782-combo
      # ar0144
      # ar0144-fsin (for use with m0173 and Starling 2 only)
      # ar0144-fsin-combo (for use with m0173 and Starling 2 only)
      # imx214
      # imx412
      # imx412-fpv (low latency mode)
      # imx678
      #
      #
      # When using a combo mode pair, you must also add a JX_COMBO_MODE field which
      # specifies is the pair is to be set up as either a stereo pair ordered
      # left-right, right-left, or treated as two independent cameras. If you are
      # using a combo-mode flex but only physically connect one of the two cameras
      # then select "single" it does not matter which one you connect.
      #
      # For example:
      # J6_LOWER_COMBO_MODE="left-right"
      # J6_LOWER_COMBO_MODE="right-left"
      # J6_LOWER_COMBO_MODE="independent"
      # J6_LOWER_COMBO_MODE="single"
      #
      # when running "independent" combo mode, also add a NAME2 field for the second cam
      # e.g J6_LOWER_NAME2="tracking_rear"
      #
      # for all sensors except TOF, you can specify a "rotate" flag to
      # rotate the image 180 degrees e.g. J6_LOWER_ROTATE="true" or "false"
      # for stereo pairs (e.g. ov7251 combo or ar0144-slave-strereo) you can specify
      # "rotate-first-only" or "rotate-second-only" to only rotate one, other wise
      # when setting the rotate option to "true" both will be rotated.
      #
      #
      # Once configured, this file should live in /data/modalai/custom_camera-config.txt
      # then run voxl-configure-cameras custom to load it in
      #
      #
      # cp /usr/share/modalai/voxl-camera-server/custom_camera_config.txt /data/modalai/
      #
      # We also suggest changing your /data/modalai/sku.txt file to have a camera
      # config term "CC" such as MRB-D0005-4-V2-CC
      ################################################################################
      
      
      J6_LOWER_SENSOR=""
      J6_LOWER_NAME=""
      J6_LOWER_ROTATE="false"
      
      
      J6_UPPER_SENSOR=""
      J6_UPPER_NAME=""
      J6_UPPER_ROTATE="false"
      
      
      J7_LOWER_SENSOR=""
      J7_LOWER_NAME=""
      J7_LOWER_ROTATE="false"
      
      
      J7_UPPER_SENSOR=""
      J7_UPPER_NAME=""
      J7_UPPER_ROTATE="false"
      
      
      J8_LOWER_SENSOR=""
      J8_LOWER_NAME=""
      J8_LOWER_ROTATE="false"
      
      
      J8_UPPER_SENSOR=""
      J8_UPPER_NAME=""
      J8_UPPER_ROTATE="false"
      
      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: IMX412 Autoexposure Compensation

      That's interesting. I think the modalai exposure package might not be directly compatible with the hires camera then -- I have to test it myself, although I have the IMX 214 not the 412. Additionally, I am pretty sure I was able to use the lme_msv before with the Hires coupled with less aggressive parameters, but I don't recall if I made modifications to the source code -- it's been 5 months since I came across this.
      I'll take a closer look in my modified ModalAI packages directory and will upload any necessary patches for the latest SDK release related packages.

      If you can, please upload your full .conf and sample images in the meantime.

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • Learning how to lock a thread to a CPU core

      Hello,
      If you are developing your own custom pipelines, applications, and modifying existing source code from ModalAI, this may be applicable to you.

      Motivation: Control which CPU core is responsible for a certain thread in your custom application.

      Background: It all started when I was observing the htop behavior. Sometimes the dynamic core allocation, overloads a particular core instead of keeping the effort evenly distributed, potentially causing issues if you have a "real-time" sensitive application. -- Assuming you have already set the priority and scheduler properly...

      Tackling the issue: If you look in the qvio-server source files, you will find that a particular computer vision thread is locked to CPU core 7 -- known to be the fastest VOXL2 core. Then, what if we use the same idea in a custom application (potentially for a different core), would it work? YES.

      How to do it:
      PS1: I rather use ROS over modalpipes, so the full example linked is a for a modified IMU server that controls the driver entirely via ROS, but you can do the same for a modalpipe implementation WLOG.

      Using the heavenly chosen language, C++, and ROS syntax

      void _set_affinity_to_core_7() {
          cpu_set_t cpuset;
          pthread_t thread = pthread_self();
      
          //SET IT UP TO CORE 7
          CPU_ZERO(&cpuset);
      //change this to the core you want
          CPU_SET(7, &cpuset); 
          if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset)) {
              perror("pthread_setaffinity_np");
          }
      
          //CHECK IF IT WAS SET UP
          if (pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset)) {
              perror("pthread_getaffinity_np");
          }
      
          ROS_INFO("IMU read thread is now locked to core: ");
          for (int j = 0; j < CPU_SETSIZE; j++) {
              if (CPU_ISSET(j, &cpuset)) {
                  ROS_INFO(" %d", j);
              }
          }
          ROS_INFO("\n");
      }
      

      In the main() and using boost, define the lambda as follows:

          std::vector<boost::thread> threads;
          for (int i = 0; i < 1; ++i) {
              if (imu_enable[i]) {
                  //IF YOU DONT WANT TO LOCK A SPECIFIC CORE, THEN 
                  // threads.push_back(boost::thread(boost::bind(&readThreadFunc, i)));
      
                  threads.push_back(boost::thread([i]() {
                  _set_affinity_to_core_7();  
                  readThreadFunc(i);
                  }));
      
              }
          }
      

      PS2: Full Example can be found here:
      https://github.com/zauberflote1/voxlSyncVINS/blob/91d74b57cacd78db87c6bd48ac03f14ca36874ab/imu_ros/src/voxl_imu_ros/server/src/node.cpp#L43C32-L43C33

      Final Remarks:
      Only do this if you know what you are doing as you may overload a core by accident.

      All the best,
      ZBFT

      posted in Ask your questions right here! cpu resource-aware threads
      zauberflote1Z
      zauberflote1
    • RE: IMX412 Autoexposure Compensation

      Hello,
      Long time I haven't posted here, but I ran into similar issues before.

      All you need to do is to change the ae_mode field to either off or lme_msv -- I think lme_msv works with hires natively, but double check it using the latest voxl-camera-server. Also note that most IMX hires sensors are rolling shutter, so forcing drastic parameters will cause the line delay effect to be more apparent.

      Pro tip, reducing the picture dimension will reduce the computational effort of the lme_msv

      Below are the fields you should add for lme_msv

      			"ae_mode":	"lme_msv",
      			"ae_desired_msv":	60, ##CHANGE
      			"exposure_min_us":	0, ##CHANGE
      			"exposure_max_us":	1000, ##CHANGE
      			"gain_min":	54, ##CHANGE
      			"gain_max":	8000, ##CHANGE
      			"exposure_soft_min_us":	50, ##CHANGE
      			"ae_filter_alpha":	0.600000023841858, ##CHANGE
      			"ae_ignore_fraction":	0.20000000298023224, ##CHANGE
      			"ae_slope":	0.05000000074505806, ##CHANGE
      			"ae_exposure_period":	1,
      			"ae_gain_period":	1
      

      All the best,
      ZBFT

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server How to Use, Overall Questions, ROS/ROS2 Findings

      @tiralonghipol and community
      Here it is,
      https://github.com/zauberflote1/voxlSyncVINS

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • Math Behind Fusion of FIXED POSE (AprilTag Pose)

      Hello,
      I am curious about the math behind the "fusion" of the fixed pose coming from the apriltags. From what I understood reading pose_filter.c and geometry.c, the filter uses a ring buffer and finds the average of the values buffered as the new correct values of x, y, z, and yaw. Could anyone confirm this?

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server How to Use, Overall Questions, ROS/ROS2 Findings

      @zauberflote1
      Forgot to mention that a way to reduce jitter is also by checking if the interrupt DTA Rdy is true before reading, avoiding reading past info from the registers.
      Sorry for the many messages

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1
    • RE: voxl-open-vins-server How to Use, Overall Questions, ROS/ROS2 Findings

      @Cliff-Wong
      Image Description:
      1)BsicRead Server Using MPA-ROS
      2)Classic Server and MPA-ROS
      3)IMU ROS ~500Hz
      4)IMU ROS ~200Hz

      posted in Ask your questions right here!
      zauberflote1Z
      zauberflote1