ROS与gazebo中常见问题【持续更新中】

ROS中常见问题

【gazebo】

Spawn service failed. Exiting

**将launch文件中.world文件里的sim_time值改为0**
      <sim_time>95 28000000</sim_time>
      <real_time>95 520885217</real_time>
      ⇒ 调整为
      <sim_time>0</sim_time>
      <real_time>0</real_time>

gazebo模型与服务器

本地路径: ~/.gazebo/models
kint@kint:~/.gazebo/models$ pwd
/home/kint/.gazebo/models
kint@kint:~/.gazebo/models$ ls
10cm                                  kinect
16cm                                  kitchen_dining
3_bord                                ksql_airport
3_bord.zip                            ladder_60deg_0rails
ambulance                             ladder_60deg_1rails
apartment                             ladder_60deg_2rails
apollo15_landing_site_1000x1000       ladder_75deg_0rails
arm_part                              ladder_75deg_1rails
arrow_red                             ladder_75deg_2rails
asphalt_plane                         lamp_post
asus_xtion_pro_camera                 law_office
ball_bearing                          LICENSE
baylands                              lunar_tranquillitatis_pit
beer                                  mailbox
bin_4_dropping_task                   manifest.xml.in
blackflys                             marble_1_5cm
bookshelf                             mars_rover
bowl                                  mass_on_rails
box_target_green                      mcmillan_airfield
box_target_red                        metal_peg
breakable_test                        metal_peg_board
brick_box_3x1x3                       monkey_wrench
bumblebee_xb3                         mpl_right_arm
………………………………………………………………………………………………………………………………
house_3                               wooden_board
husky                                 wooden_case
intel_realsense_r200                  wooden_case_metal_peg
iris_with_standoffs                   wooden_case_wooden_peg
iris_with_standoffs_demo              wooden_peg
irobot_hand                           wooden_peg_board
iscas_museum                          yosemite
iss                                   youbot
iss_half                              zephyr_delta_wing
jersey_barrier

1)模型存放网址
http://models.gazebosim.org/
同步到:models.gazebosim.org

   wget -r -R "index\.html*" http://models.gazebosim.org/     
   
   参考: https://answers.ros.org/question/199401/problem-with-indigo-and-gazebo-22/

2)模型github 仓库,直接下载放到本地路径: ~/.gazebo/models下
https://github.com/osrf/gazebo_models
https://gitee.com/slamcn/gazebo_models

  1. 配置说明,服务器连接不上,直接按照12步骤下载成本地离线的,配置中去掉从服务器下载

    调整GAZEBO_MODEL_DATABASE_URI为空, 本地 ~/.gazebo/models 里面
    kint@kint:~/.gazebo/models.gazebosim.org$ cat  /usr/share/gazebo/setup.sh 
    
    export GAZEBO_MASTER_URI=http://localhost:11345
    export GAZEBO_MODEL_DATABASE_URI="" # http://gazebosim.org/models
    export GAZEBO_RESOURCE_PATH=/usr/share/gazebo-9:${GAZEBO_RESOURCE_PATH}
    export GAZEBO_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/gazebo-9/plugins:${GAZEBO_PLUGIN_PATH}
    export GAZEBO_MODEL_PATH=/usr/share/gazebo-9/models:${GAZEBO_MODEL_PATH}
    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins
    export OGRE_RESOURCE_PATH=/usr/lib/x86_64-linux-gnu/OGRE-1.9.0
    
    

gazebo中添加动态障碍物 [actor]

gazebo中添加动态障碍物

gazebo 添加动态障碍物
gazebo添加动态障碍物插件
gazebo中动态障碍物实时pose

docker 中启动gazebo

xhost +local:root
docker run -itd --name=ros2_humble  --net=host --privileged -e DISPLAY=$DISPLAY --gpus all --env="NVIDIA_DRIVER_CAPABILITIES=all"  --volume="$HOME/.Xauthority:/root/.Xauthority:rw"    -v /etc/timezone:/etc/timezone:ro  -v /etc/localtime:/etc/localtime:ro -v /home/robot:/home/robot  -v /home/robot/.gazebo/models:/root/.gazebo/models   -v /tmp/.X11-unix:/tmp/.X11-unix  -v $HOME/.Xauthority:/root/.Xauthority:rw   --device=/dev/bus/usb:/dev/bus/usb   d9aa388a3dea   /bin/bash;;
 
docker run -itd --name=ros2_humble  --net=host --privileged -e DISPLAY=unix$DISPLAY -e GDK_SCALE -e GDK_DPI_SCALE   --volume="$HOME/.Xauthority:/root/.Xauthority:rw"    -v /etc/timezone:/etc/timezone:ro  -v /etc/localtime:/etc/localtime:ro -v /home/robot:/home/robot  -v /home/robot/.gazebo/models:/root/.gazebo/models   -v /tmp/.X11-unix:/tmp/.X11-unix  -v $HOME/.Xauthority:/root/.Xauthority:rw   --device=/dev/bus/usb:/dev/bus/usb   d9aa388a3dea   /bin/bash;;

【ROS】

rosdep install

rosdep install --from-paths src --ignore-src

ROS中多个工作空间同时工作

ref

因为在catkin_make时,会检查编译时的ROS环境并记录下来,保存在work1_ws /devel/_setup_util.py python文件的CMAKE_PREFIX_PATH变量中。
以后在执行这个工作空间的setup.bash脚本时,会使用编译时的状态覆盖ROS_PACKAGE_PATH的值。

ros项目编译找不到msg/srv文件产生的头文件

ref
ref_en

一般情况下,如果你的msg/srv文件是一个单独的package的话(假设为A),在依赖A生成的头文件的packageB里面编译对应的cpp文件时,
在add_dependencies的最后添加${catkin_EXPORTED_TARGETS}会包含所有在find_package里面列出的包的_generate_messages_cpp宏用来生成对应的头文件,这样编译应该是没有问题的。
但是当msg/srv和需要其产生头文件的cpp文件在同一个包里面时,第一次编译会报找不到头文件的错,在${catkin_EXPORTED_TARGETS}这个宏之前再加一个current_package_generate_messages_cpp,current_package换成当前的包名即可 

rosdep update time out及失败解决方案

参考rosdep update失败的解决方法
第三种本地化离线方式处理:

1. clone rosdistro 到本地
mkdir -p ~/.ros/rosdep
cd ~/.ros/rosdep
git clone https://github.com/ros/rosdistro

2.  修改 20-default.list 连接为本地下载的rosdistro 里面的对应文件
将文件中的网址https://raw.githubusercontent.com/ros/rosdistro/master修改为下载目录file:///home/xxx/rosdistro
sudo vim /etc/ros/rosdep/sources.list.d/20-default.list 
yaml file:///home/kint/.ros/rosdep/rosdistro/rosdep/osx-homebrew.yaml osx

# generic
yaml file:///home/kint/.ros/rosdep/rosdistro/rosdep/base.yaml
yaml file:///home/kint/.ros/rosdep/rosdistro/rosdep/python.yaml
yaml file:///home/kint/.ros/rosdep/rosdistro/rosdep/ruby.yaml
gbpdistro file:///home/kint/.ros/rosdep/rosdistro/releases/fuerte.yaml fuerte
 

#yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
#yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
#yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
#gbpdistro https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml fuerte
# newer distributions (Groovy, Hydro, ...) must not be listed anymore, they are being fetched from the rosdistro index.yaml instead
3.  修改sources_list.py文件
sudo gedit /usr/lib/python2.7/dist-packages/rosdep2/sources_list.py

#DEFAULT_SOURCES_LIST_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list'
DEFAULT_SOURCES_LIST_URL = 'file:///etc/ros/rosdep/sources.list.d/20-default.list'

4. 修改rep3.py
sudo gedit /usr/lib/python2.7/dist-packages/rosdep2/rep3.py

REP3_TARGETS_URL = 'file:///home/kint/.ros/rosdep/rosdistro/releases/targets.yaml'
#REP3_TARGETS_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/releases/targets.yaml'

5. . 修改_init_.py文件
 sudo gedit /usr/lib/python2.7/dist-packages/rosdistro/__init__.py

DEFAULT_INDEX_URL = 'file:///home/kint/.ros/rosdep/rosdistro/index-v4.yaml'
#DEFAULT_INDEX_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/index-v4.yaml'

6. 重新更新
sudo rosdep init
       如果20-default.list 已经存在,可以先删除,再执行一遍sudo rosdep init
rosdep update

---------正确更新的log
 kint@kint:~/.ros/rosdep$ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit file:///home/kint/.ros/rosdep/rosdistro/rosdep/osx-homebrew.yaml
Hit file:///home/kint/.ros/rosdep/rosdistro/rosdep/base.yaml
Hit file:///home/kint/.ros/rosdep/rosdistro/rosdep/python.yaml
Hit file:///home/kint/.ros/rosdep/rosdistro/rosdep/ruby.yaml
Hit file:///home/kint/.ros/rosdep/rosdistro/releases/fuerte.yaml
Query rosdistro index file:///home/kint/.ros/rosdep/rosdistro/index-v4.yaml
Skip end-of-life distro "ardent"
Skip end-of-life distro "bouncy"
Skip end-of-life distro "crystal"
Skip end-of-life distro "dashing"
Skip end-of-life distro "eloquent"
Add distro "foxy"
Add distro "galactic"
Skip end-of-life distro "groovy"
Add distro "humble"
Skip end-of-life distro "hydro"
Skip end-of-life distro "indigo"
Skip end-of-life distro "jade"
Skip end-of-life distro "kinetic"
Skip end-of-life distro "lunar"
Add distro "melodic"
Add distro "noetic"
Add distro "rolling"
updated cache in /home/kint/.ros/rosdep/sources.cache
-----------------

fatal error: Eigen/Geometry: No such file or directory

ref
创建软链接

cd /usr/include
sudo ln -sf eigen3/Eigen Eigen
sudo ln -sf eigen3/unsupported unsupported

Node Manager

参考:https://github.com/fkie/multimaster_fkie/wiki
Installation via apt
melodic and older: sudo apt install ros-melodic-multimaster-fkie
noetic and newer: sudo apt install ros-noetic-fkie-multimaster (Note: Currently broken, issue here)

Test node_manager

node_manager

在这里插入图片描述

rospy

1. rospy模块导入 Import Python Module From Another Package
解决思路: 导出python执行文件与模块到对应的ROS全局命名空间内的新package中

文件目录:
robot_helper
├── api
│   ├── api.py
│   ├── api2.py
│   ├── my_test_exe
│   └── __init__.py
├── scripts
│   ├── manager.py
├── package.xml
├── CMakeLists.txt
├── setup.py

具体文件内容:
#And inside the api.py, you have some class
class MY_API():
   def __init__(self):

#And inside the api2.py, you have some class
class MY_API2():
   def __init__(self):
1. 在api文件夹中创建空文件 __init__.py  
2. 创建文件 setup.py
3. 在 CMakeLists.txt 文件中,find_package后加入 catkin_python_setup()
	## Uncomment if the package has a setup.py
	catkin_python_setup()

4. 完成文件setup.py
	from distutils.core import setup
	from catkin_pkg.python_setup import generate_distutils_setup
	
	setup_args = generate_distutils_setup(
	    packages=['my_api'],
		package_dir={'': 'api'}
	)
	setup(**setup_args) 
5. 在 CMakeLists.txt 文件中加入install 
	# catkin_install_python(PROGRAMS api/my_test_exe
	#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
说明setup.py:
1. CMakeLists.txt 文件中catkin_python_setup() 会对应执行 run setup.py.
2.  __init__.py   将文件夹内容暴露给setup.py  
3.  packages=['my_api']  让ROS找到 python  package. 
4. package_dir={'': 'api'}  告诉ROS将对应api文件夹的所有python文件作为全局python环境  


Python文件导入测试: api,api2 对应my_api包中api.py  api2.py文件
from api import MY_API
from api2 import MY_API2

xacro 与 urdf 文件检查

xacro的urdf检查需要先转化为urdf文件

rosrun xacro xacro test.xacro  > test.urdf  # 格式转化
check_urdf racecar.urdf.urdf        #语法检查,输出关系或错误
urdf_to_graphiz racecar.urdf.urdf  # 可视化输出树形结构

rosparam单个string参数划分多个string

借助std::stringstream 是 C++ 中的一个类,提供了一个输入/输出流接口,用于将内存中的字符串缓冲区视为流进行读写操作。它可以用于从字符串中读取输入,或将输出写入到字符串中。

  std::string topics_string;
  // get the topics that we'll subscribe to from the parameter server
  node_handle.param("topics_string", topics_string, std::string(""));
  LOG(INFO)<<"   topics_string: "<<topics_string;

  std::stringstream ss(topics_string);
  std::string source;
  while (ss >> source)
  {
    LOG(INFO)<<"source: "<<source;
  }
    <node pkg="xx" type="xx" name="xx" output="screen">
        <param name="topics_string"   type="string"   value="name1 name2 name3 "/>    
    </node>

I0224 16:57:24.099885 21613 xx.cpp:14]    topics_string: name1 name2 name3
I0224 16:57:24.100028 21613 xx.cpp:20] source: name1
I0224 16:57:24.100047 21613 xx.cpp:20] source: name2
I0224 16:57:24.100056 21613 xx.cpp:20] source: name3

nodelet 常见问题: 命名空间

nodelet说明参照: https://robkin.blog.csdn.net/article/details/52143309

  1. 正常node程序改写成nodelet
    参照nodelet的说明, 注意点:
    CMakeLists.txt:
find_package:  pluginlib   nodelet 
catkin_package(
  INCLUDE_DIRS include
  LIBRARIES berxel_camera_nodelet
  CATKIN_DEPENDS  pluginlib nodelet 
)
# add xml file
install(FILES berxel_nodelets.xml
        DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
install(TARGETS ${PROJECT_NAME} berxel_camera_nodelet
        ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
        LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
        RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

package.xml

  <build_depend>nodelet</build_depend>
  <build_depend>pluginlib</build_depend>  
  
  <exec_depend>nodelet</exec_depend>
  <exec_depend>pluginlib</exec_depend>  
  
  <export>
    <nodelet plugin="${prefix}/berxel_nodelets.xml"/>
  </export>
  

berxel_nodelets.xml

<library path="lib/libberxel_camera_nodelet">
  <class name="CameraNodelet" type="CameraNodelet" base_class_type="nodelet::Nodelet">
    <description>
      Astra camera driver nodelet.
    </description>
  </class>
</library>

cpp文件

#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include "BerxelHawkCamera.h"

class CameraNodelet : public nodelet::Nodelet {
public:
  CameraNodelet() : running_(false) {}
  ~CameraNodelet();

private:
  virtual void onInit();
  volatile bool running_;
  boost::shared_ptr<BerxelHawkCamera> driver_;
};

CameraNodelet::~CameraNodelet() {
  if (running_) {
    std::cout<<"~CameraNodelet"<<std::endl;
  }
}

void CameraNodelet::onInit() {
  ros::NodeHandle nh(getNodeHandle());
  ros::NodeHandle priv_nh(getPrivateNodeHandle());
  driver_.reset(new BerxelHawkCamera(nh, priv_nh));
  driver_->initBerxelCamera();
}


// Register this plugin with pluginlib.
// parameters are: class type, base class type
PLUGINLIB_EXPORT_CLASS(CameraNodelet, nodelet::Nodelet)
  1. 找不到nodelet插件,请检查1里面相关的设置.
    rospack plugins --attrib=plugin nodelet
    berxel_camera ~/xx_ws/install/share/berxel_camera/berxel_nodelets.xml

  2. node节点与命名空间的关系
    n2(“~”) 对应manager的空间; getPrivateNodeHandle()对应节点CameraFilterLeft的空间;
    nh 与 getNodeHandle() 也存在一定的差异.
    建议具体实现类的node_handle都以nodelet中获取的getPrivateNodeHandle()和getNodeHandle()创建并传下去。

launch文件中:
    <node pkg="nodelet" type="nodelet" name="berxel_left_camera_manager"  args="manager" output="screen"/>
    <node pkg="nodelet" type="nodelet" name="CameraFilterLeft" args="load CameraFilterNodelet berxel_left_camera_manager" output="screen"、>

分清楚这个几个命名空间的对应:

void CameraFilterNodelet::onInit() {
  ros::NodeHandle nh(getNodeHandle());
  ros::NodeHandle priv_nh(getPrivateNodeHandle());
  ros::NodeHandle node = this->getPrivateNodeHandle();
  std::cout<<"==>>>>>>>>CameraFilterNodeletonInit1: nh: "<<nh.getNamespace()<<std::endl;   
  std::cout<<"==>>>>>>>>CameraFilterNodeletonInit1: priv_nh: "<<priv_nh.getNamespace()<<std::endl;      
  std::cout<<"==>>>>>>>>CameraFilterNodeletonInit1: node: "<<node.getNamespace()<<std::endl;  

  ros::NodeHandle n1;
  ros::NodeHandle n2("~");
  std::cout<<"==>>>>>>>>CameraFilterNodeletonInit1: n1: "<<n1.getNamespace()<<std::endl;   
  std::cout<<"==>>>>>>>>CameraFilterNodeletonInit1: n2: "<<n2.getNamespace()<<std::endl;  

  cam_filter_.reset(new CameraFilter(nh, priv_nh));
  running_ = true;
}

=======输出:
==>>>>>>>>CameraFilterNodeletonInit1: nh: 
==>>>>>>>>CameraFilterNodeletonInit1: priv_nh: /CameraFilterLeft
==>>>>>>>>CameraFilterNodeletonInit1: node: /CameraFilterLeft
==>>>>>>>>CameraFilterNodeletonInit1: n1: /
==>>>>>>>>CameraFilterNodeletonInit1: n2: /berxel_left_camera_manager
==>>>>>>>>CameraFilter: n1: /
==>>>>>>>>CameraFilter: n2: /berxel_left_camera_manager
  1. nodelet节点与dynamic_reconfigure命名空间的关系
    其实也是3对应的命名空间问题,记得将nh传入, 不然默认是(“~”)
    dsrv_ = new dynamic_reconfigure::Server<depth_camera::calib_paramConfig>(private_nh_);

cv_bridge与opencv版本冲突

问题:

编译正常,有warning, 运行时部分函数报错
/usr/bin/ld: warning: libopencv_imgproc.so.3.4, needed by /usr/local/lib/libopencv_highgui.so.3.4.18, may conflict with libopencv_imgproc.so.3.2

OpenCV Error: Bad argument (Unknown interpolation method) in resize, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/imgwarp.cpp, line 3367
terminate called after throwing an instance of 'cv::Exception'
  what():  /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/imgwarp.cpp:3367: error: (-5) Unknown interpolation method in function resize
  

解决方式:
ref
修改cv_bridge指定的opencv版本。修改指定的include与libs

sudo gedit /opt/ros/melodic/share/cv_bridge/cmake/cv_bridgeConfig.cmake

#if(NOT "include;/usr/include;/usr/include/opencv " STREQUAL " ")
if(NOT "include;/usr/local/include/opencv;/usr/local/include/opencv2 " STREQUAL " ")
  set(cv_bridge_INCLUDE_DIRS "")
  #set(_include_dirs "include;/usr/include;/usr/include/opencv")
  set(_include_dirs "include;/usr/local/lib;/usr/local/include/opencv;/usr/local/include/opencv2;/usr/local/include;/usr/include")



#set(libraries "cv_bridge;/usr/lib/x86_64-linux-gnu/libopencv_core.so.3.2.0;/usr/lib/x86_64-linux-gnu/libopencv_imgproc.so.3.2.0;/usr/lib/x86_64-linux-gnu/libopencv_imgcodecs.so.3.2.0")
set(libraries "cv_bridge;/usr/local/lib/libopencv_core.so.3.4.18;/usr/local/lib/libopencv_imgproc.so.3.4.18;/usr/local/lib/libopencv_imgcodecs.so.3.4.18")


[cartographer] absl R_X86_64_PC32 -fPIC

编译cartographer_rviz遇到问题
[100%] Linking CXX shared library /home/firefly/RenBot_ws/devel/lib/libcartographer_rviz.so
/usr/bin/ld: /usr/local/lib/libabsl_synchronization.a(mutex.cc.o): relocation R_X86_64_PC32 against symbol `_ZNSt11this_thread5yieldEv' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

参考:relocation R_X86_64_PC32 against symbol can not be used when making a shared object; recompile with -fPIC
编译cartographer_rviz出现libabsl_synchronization.a库错误

在安装abseil的cmakelist.txt文件中加入, 重新编译安装abseil库就可以了

set(CMAKE_BUILD_TYPE "Release")
SET( CMAKE_CXX_FLAGS "-std=c++11 -O3")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC")
RUN cd ~/carto_libs/abseil-cpp && \
   mkdir -p build  && \
   cd build  && \
   cmake ..  -DCXX11=ON && \
   make -j16 && \
   make install  >> ../install.info && \
   echo "Finish ceres"

stowing bar would cause conflicts:

WARNING! stowing bar would cause conflicts:
  * existing target is neither a link nor a directory: foo
All operations aborted.
 sudo stow  --adopt  absl
 

终端kill所有的ros节点与rosmater

rosnode kill -a && pkill rosmaster

stdbuf + script 终端后台追加运行脚本并保存终端执行的全部log

roscore_pid=-1
stdbuf -oL -eL script -a -f -c "roscore"   /tmp/roscore.log &
roscore_pid=$!

if [ $roscore_pid -gt 0 ]; then
    wait $roscore_pid
fi

stdbuf 是一个用于调整另一个程序缓冲区的命令行工具。-oL -eL 参数表示将输出(stdout)和错误输出(stderr)设置为行缓冲模式(每行立即刷新缓冲区,而不是等待缓冲区满)。

script 命令用于将终端会话记录到文件中。-a 参数表示追加输出到文件,而不是覆盖文件。-f 参数表示将输出立即刷新到文件。-c 参数后跟要执行的命令。

因此,stdbuf -oL -eL script -a -f -c “” 的意义是:

1. 使用行缓冲模式执行命令 <command>,即每行立即刷新 stdout 和 stderr 缓冲区。
2. 使用 script 命令将 <command> 的输出记录到文件中。
3. 输出将追加到文件中,而不是覆盖文件。
4. 输出将立即刷新到文件中。

这个命令组合通常用于在执行过程中实时捕获和记录命令的输出,而不是在命令完成后将输出写入文件。这在需要实时监控日志文件的场景中非常有用。

使用ROS rosbag工具进行过滤(filter)操作[过滤话题,重映射,tf剪枝]

使用ROS rosbag工具进行过滤(filter)操作[过滤话题,重映射,tf剪枝]

[cartographer][升级Sphinx] exception: cannot import name ‘contextfunction’ from ‘jinja2’

Extension error:
Could not import extension sphinx.builders.latex (exception: cannot import name 'contextfunction' from 'jinja2' (/home/robot/.local/lib/python3.8/site-packages/jinja2/__init__.py))
pip3 install --upgrade Sphinx 
>>> import sphinx as sphinx
>>> sphinx.__version__
'1.8.5'

升级后
>>> import sphinx as sphinx
>>> sphinx.__version__
'7.0.0'

ignore 忽略包编译

在不想被编译的package路径下新建一个文件名为CATKIN_IGNORE的文件

ROS指定单独编译与恢复整体编译

单独包编译:
catkin_make -DCATKIN_WHITELIST_PACKAGES="具体的package"

取消指定单独包编译
catkin_make -DCATKIN_WHITELIST_PACKAGES=""

【ROS2】

rosidl_cmake/cmake/rosidl_generate_interfaces.cmake:240 (list)

工作空间路径有中文

【apt]】

1. dpkg: error processing package install-info

sudo mv /var/lib/dpkg/info/install-info.postinst /var/lib/dpkg/info/install-info.postinst.bad

ref

【git】

1. git 状态栏中文可视化,配置

git config --global core.quotepath false

2. github --> xxxcsdner

xxxcsdner
https://raw.hellogithub.com/

【ubuntu】

1. apt update can not resolve the sources -> dns

Failed to fetch http://mirrors.ustc.edu.cn/ubuntu-ports/dists/xenial/InRelease Could not resolve ‘mirrors.ustc.edu.cn’

查看/etc/apt/sources.list 源文件,网页测试是否可以打开对应网址

 $ cat /etc/apt/sources.list  (ubuntu rk3399环境)
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-backports main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-proposed main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-backports main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-proposed main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe

如果可以打开,基本是dns问题导致终端无法解析

sudo vim /etc/resolv.conf
------------------------------
nameserver 127.0.1.1
#这里用的是阿里云的DNS服务器
nameserver 223.5.5.5
nameserver 223.6.6.6

2. udev 中video端口映射

video usb hub Using multiple cameras
usb hub参考

#ls /dev/video*
/dev/video0  /dev/video1
 
$ udevadm info --query=all --attribute-walk --name=/dev/video0
 
  looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/video4linux/video0':
    KERNEL=="video0"
    SUBSYSTEM=="video4linux"
    DRIVER==""
    ATTR{dev_debug}=="0"
    ATTR{index}=="0"
    ATTR{name}=="Integrated Camera: Integrated C"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0':
    KERNELS=="1-8:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="uvcvideo"
....
  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-8':
    KERNELS=="1-8"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
....
  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
....
  looking at parent device '/devices/pci0000:00/0000:00:14.0':
    KERNELS=="0000:00:14.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="xhci_hcd"
 ....
    ATTRS{subsystem_device}=="0x2279"
    ATTRS{subsystem_vendor}=="0x17aa"
    ATTRS{vendor}=="0x8086"
 

创建 video_usb.rules文件

KERNEL=="video*", KERNELS=="5-1.2", MODE:="0777",SYMLINK+="video_m"
KERNEL=="video*", KERNELS=="5-1.3", MODE:="0777",SYMLINK+="video_r"
KERNEL=="video*", KERNELS=="5-1.4", MODE:="0777",SYMLINK+="video_l"
sudo cp video_usb.rules /etc/udev/rules.d
sudo udevadm control --reload-rules

查看设备序列号:

kint@kint:~$ lsusb -t
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
    |__ Port 3: Dev 2, If 0, Class=Hub, Driver=hub/4p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
    |__ Port 3: Dev 12, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 4: Dev 15, If 1, Class=Video, Driver=uvcvideo, 480M
        |__ Port 4: Dev 15, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 2: Dev 13, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 2: Dev 13, If 1, Class=Video, Driver=uvcvideo, 480M
        |__ Port 3: Dev 14, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 3: Dev 14, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 4: Dev 11, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 4: Dev 11, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 8: Dev 3, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 8: Dev 3, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 9: Dev 4, If 0, Class=Vendor Specific Class, Driver=, 12M

bus001 Port 3.( Port 2, Port 3, Port 4)

kint@kint:/sys/bus/usb/devices/1-3/1-3.2$ cat /sys/bus/usb/devices/1-3/1-3.2/serial 
HK100HA21P100043

3. lib库文件信息查看

3.1. 查看静态库属于哪种架构: x86 arm AArch64

$ readelf -h libceres.a 

$ readelf -h libceres.a  | grep Machine
>>>  Machine:                           AArch64

$ readelf -h libceres.a  | grep -e libceres.a -e Machine:
File: libceres.a(schur_eliminator_4_4_4.cc.o)
  Machine:                           AArch64

$  ar -x libceres.a  (解压静态库)

3.2. 查看动态库信息

file xxx
ldd xxx

$ file libceres.a 
libceres.a: current ar archive

$ file libceres.so
libceres.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=ab60dba2cdc5175e1aa4f7442b8a3a19cf069a98, stripped

$ ldd libceres.so 
	linux-vdso.so.1 (0x0000007f8710c000)
	libglog.so.0 => /usr/lib/aarch64-linux-gnu/libglog.so.0 (0x0000007f86e30000)
	libspqr.so.2 => /usr/lib/aarch64-linux-gnu/libspqr.so.2 (0x0000007f86dfb000)
	libcholmod.so.3 => /usr/lib/aarch64-linux-gnu/libcholmod.so.3 (0x0000007f86d3d000)
	liblapack.so.3 => /usr/lib/aarch64-linux-gnu/liblapack.so.3 (0x0000007f8683a000)
	libf77blas.so.3 => /usr/lib/aarch64-linux-gnu/libf77blas.so.3 (0x0000007f8680f000)
	libcxsparse.so.3 => /usr/lib/aarch64-linux-gnu/libcxsparse.so.3 (0x0000007f867d6000)
	libgomp.so.1 => /usr/lib/aarch64-linux-gnu/libgomp.so.1 (0x0000007f86799000)
	libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007f8676d000)
	libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007f865d9000)
	libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007f86520000)
	libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007f864fc000)
	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007f863a3000)
	/lib/ld-linux-aarch64.so.1 (0x0000007f870e0000)
	libgflags.so.2.2 => /usr/lib/aarch64-linux-gnu/libgflags.so.2.2 (0x0000007f86372000)
	libsuitesparseconfig.so.5 => /usr/lib/aarch64-linux-gnu/libsuitesparseconfig.so.5 (0x0000007f8635e000)
	libblas.so.3 => /usr/lib/aarch64-linux-gnu/libblas.so.3 (0x0000007f860ef000)
	libamd.so.2 => /usr/lib/aarch64-linux-gnu/libamd.so.2 (0x0000007f860d7000)
	libcolamd.so.2 => /usr/lib/aarch64-linux-gnu/libcolamd.so.2 (0x0000007f860c0000)
	libccolamd.so.2 => /usr/lib/aarch64-linux-gnu/libccolamd.so.2 (0x0000007f860a7000)
	libcamd.so.2 => /usr/lib/aarch64-linux-gnu/libcamd.so.2 (0x0000007f8608f000)
	libmetis.so.5 => /usr/lib/aarch64-linux-gnu/libmetis.so.5 (0x0000007f86022000)
	libgfortran.so.4 => /usr/lib/aarch64-linux-gnu/libgfortran.so.4 (0x0000007f85f1f000)
	libatlas.so.3 => /usr/lib/aarch64-linux-gnu/libatlas.so.3 (0x0000007f85cde000)

3.3 arm环境找/usr/lib/x86_64-linux-gnu/libglog.so

make[2]: *** No rule to make target '/usr/lib/x86_64-linux-gnu/libglog.so', needed by 'xx_ws/devel/lib/liblasercamcal.so'.  Stop.

重装glog 都没有解决问题, 对比之前的cmake文件,findpackage(glog)源码编译都是正常的, 现在只是多了ceres库,
怀疑是ceres静态库编译带入的。 重新源码编译并安装ceres库恢复正常

4. c++实现wifi连接

参考: xiaoqiang_qrcode_wifi_exec 通过二维码连接wifi功能

            std::stringstream ss;
            ss << "nmcli device wifi connect " << ssid << " password " << password;
            std::string res = exec(ss.str().c_str());
            if (res.find("successfully activated") != std::string::npos)
            {
                qrNotify.data = "连接wifi成功";
                audioPub.publish(qrNotify);
                ROS_INFO_STREAM("连接wifi成功");
                auto ipList = ListIpAddresses();
                if (ipList.size() != 0)
                {
                    qrNotify.data = "当前机器人ip为 " + ipList[0] + "\n";
                    audioPub.publish(qrNotify);
                    ROS_INFO_STREAM("当前机器人ip为 " << ipList[0] << std::endl);
                    Sleep(5000);
                }
            }
            else
            {
                qrNotify.data = "连接wifi失败";
                ROS_INFO_STREAM("连接wifi失败");
                audioPub.publish(qrNotify);
            }
            
std::string exec(const char *cmd)
{
    std::array<char, 128> buffer;
    std::string result;
    std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
    if (!pipe)
    {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
    {
        result += buffer.data();
    }
    return result;
}

5. pcl kdtree_flann 出错 param_radius_

/usr/include/pcl-1.8/pcl/kdtree/kdtree_flann.h:233:29: error: field ‘param_radius_’ has incomplete type ‘flann::SearchParams’
       ::flann::SearchParams param_radius_; 

sudo vim /usr/include/pcl-1.8/pcl/kdtree/kdtree_flann.h
修改:
::flann::SearchParams param_k_; 改为 ::flann::SearchParams *param_k_;
::flann::SearchParams param_radius_;改为 ::flann::SearchParams *param_radius_;

5. error while loading shared libraries: libg2o_core.so: cannot open shared object file

sudo vim  /etc/ld.so.conf
添加路径:/usr/local/lib
sudo ldconfig
--------------------
或者
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

/etc/ld.so.conf 文件是一个系统级别的配置文件,用于指定动态链接器(ld.so)在运行时查找共享库文件的搜索路径。当程序在运行时需要加载共享库时,动态链接器使用该文件中列出的路径来搜索并加载相应的库文件。
每行路径都代表一个要搜索的目录,可以列出多个路径。路径可以是绝对路径,也可以是相对于当前文件系统根目录的相对路径。

当你需要安装新的共享库文件时,可以将该库文件所在的路径添加到 /etc/ld.so.conf 文件中。然后,使用 sudo ldconfig 命令来刷新动态链接器的缓存,以使其能够找到新添加的库文件。

ldconfig 命令是一个用于配置动态链接器的工具。它会读取 /etc/ld.so.conf 文件中列出的路径,并在运行时更新动态链接器的缓存,使其包含最新的库文件信息。这样,当程序需要加载共享库时,动态链接器就能够快速找到并加载所需的库文件。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib 这个命令是用来设置环境变量 LD_LIBRARY_PATH 的值。当程序在运行时需要加载共享库时,动态链接器会根据 LD_LIBRARY_PATH 的值来搜索共享库文件的路径。

具体来说,这个命令将当前的 LD_LIBRARY_PATH 值与 /usr/local/lib 目录拼接起来,并将结果重新赋值给 LD_LIBRARY_PATH。这样做的目的是将 /usr/local/lib 目录添加到动态链接器的搜索路径中。

与此相关,/etc/ld.so.conf 文件起到了类似的作用。它列出了动态链接器在运行时搜索共享库文件的路径。当系统启动时,动态链接器会读取 /etc/ld.so.conf 文件中列出的路径,并将这些路径作为默认的库文件搜索路径。然而,有时候我们可能希望指定额外的库文件路径,而不仅仅依赖于 /etc/ld.so.conf 中的路径。这时,可以使用 LD_LIBRARY_PATH 环境变量来设置附加的库文件路径。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib 这个命令就是将 /usr/local/lib 目录添加到 LD_LIBRARY_PATH 中。这样设置后, 动态链接器会在搜索共享库文件时先查找 LD_LIBRARY_PATH 中指定的路径,然后再查找 /etc/ld.so.conf 中的路径。

总结:
1 )/etc/ld.so.conf 文件用于指定动态链接器在运行时搜索共享库文件的路径。文件列出了动态链接器默认的库文件搜索路径
2) sudo ldconfig 命令用于刷新动态链接器的缓存,以使其能够找到新添加的库文件。
3) 通过编辑 /etc/ld.so.conf 文件并运行 sudo ldconfig 命令,可以管理系统中的共享库文件路径。
4) export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib 命令用来设置 LD_LIBRARY_PATH 环境变量,将 /usr/local/lib 目录添加到动态链接器的库文件搜索路径中。
5) LD_LIBRARY_PATH 环境变量可以用来指定额外的库文件路径,优先级高于 /etc/ld.so.conf 中的路径。

【c++】

1. Backward-cpp 定位问题track 小工具

github
[参考] (https://zhuanlan.zhihu.com/p/397148839)

  1. 安装第三方库:
sudo apt-get install libdw-dev
  1. 拷贝库文件
wget https://raw.githubusercontent.com/bombela/backward-cpp/master/backward.hpp
sudo mv backward.hpp /usr/include

3) CMakeLists中添加link

target_link_libraries(dw_test   dw )

  1. demo cpp
#include<stdio.h>
#include<stdlib.h>
#define BACKWARD_HAS_DW 1
#include "backward.hpp"

namespace backward{
    backward::SignalHandling sh;
}

int main(){
    char *c = "hello world";
    c[1] = 'H';
}

2. execlp c++中代码运行shell指令

int execlp(const char *file, const char *arg, ...);
"file" 是要执行的程序文件的名称,"arg" 是传递给新进程的参数。

#include <unistd.h>
#include <iostream>

int main() {
 if (fork() == 0) {
   execlp("ls", "ls", "-l", NULL);
 } else {
   std::cout << "Parent process" << std::endl;
 }
 return 0;
}

int main(int argc, char **argv)
{
	ros::init(argc,argv,"sub_spec");
	ros::NodeHandle n;
	execlp("rostopic", "rostopic", "echo", "/IMU_data",NULL);
	ros::spin();
}
cmake_minimum_required(VERSION 3.0)
project(ExeclpExample)

add_executable(ExeclpExample main.cpp)

3. std::stringstream

std::stringstream 是 C++ 中的一个类,提供了一个输入/输出流接口,用于将内存中的字符串缓冲区视为流进行读写操作。它可以用于从字符串中读取输入,或将输出写入到字符串中。

在提供的代码中,std::stringstream 被用来根据空格将存储在 topics_string 中的字符串分割为单个单词或标记。这是通过使用 >> 运算符实现的,该运算符从流中读取输入并返回流对象本身。

  std::stringstream ss(topics_string);
  std::string source;
  while (ss >> source)
  {
    LOG(INFO)<<"source: "<<source;
  }

4. glog

条件记录
		我们可以使用LOG_IF()来到达有条件的输出日志的目的;
        LOG_IF(INFO, i > 15) << "i > 15"; //当i > 15时,记录Log;
 
周期记录
		通过LOG_EVERY_N()实现周期性的输出日志,意思解释说,LOG_EVERY_N()执行n次才输出一次Log;
        LOG_EVERY_N(INFO, 3) << "i: " << i; //每隔3次输出一次信息;
        
条件加周期记录
		通过LOG_IF_EVERY_N实现,当满足条件之后,每隔n次输出Log;
		LOG_IF_EVERY_N(INFO, i > 10, 3) << "i > 10, i: " << i; //当i > 10之后,每隔3次输出一次信息;
 
限制Log输出次数
		通过LOG_FIRST_N()实现,只输出前n次信息;
 		LOG_FIRST_N(INFO, 4) << "i: " << i; // 输出前4次Log

支持调试模式
		调试模式的宏仅在调试模式下有效,在非调试模式编译时为空。
		在宏前面加D就支持了调试模式;
		DLOG(), DLOG_IF(), DLOG_EVERY_N(), …

【cv】

1. opencv mat的构建

构造函数继续举例(Mat对象创建)

cv::Mat im_m(map->info.width, map->info.height, CV_8UC1, cv::Scalar(0));

Mat M(3, 3, CV_8UC3, Scalar(0, 0, 255));  //scale要和通道数目一致
cout << "M:" << endl << M << endl;
Mat a = (Mat_<float>(2,2)<<1,2,3,4);
float b[4]={5,6,7,8};
Mat c = Mat(2,2,CV_32F,b).clone();
memcpy(a.data,b,sizeof(float)*4);
memcpy(b,a.data,sizeof(float)*4); 

opencv Mat与Vector、Mat与数组、Vector与数组之间互转 详解

	cv::Mat im_m = cv::Mat(map->data).clone();//将vector变成单列的mat,这里需要clone(),因为这里的赋值操作是浅拷贝
	cv::Mat dest = im_m.reshape(1, map->info.height);

	uchar arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } };
	cv::Mat srcData(4, 3, CV_8UC1, arr);
	
	Mat dest= (cv::Mat_<float>(2, 1) << 0.4404, 0.3111);

	vector<uchar> array;
	if (dest.isContinuous())
	{
	    array.assign(dest.datastart, dest.dataend);//重新分配vector
	}
	
	uchar cbuf[height][width];
	cv::Mat img(height, width, CV_8UC1, cbuf);

	uchar **array = new uchar*[mat.rows];
	for (int i=0; i<mat.rows; ++i)
	    array[i] = new uchar[mat.cols];
	 
	for (int i = 0; i < mat.rows; ++i)
	    array[i] = mat.ptr<uchar>(i);

	uchar arr[] = { 1, 1,1 ,2 ,2 ,1 ,2 ,1  };  
	vector<uchar> vec(arr, arr + sizeof(arr) / sizeof(uchar));
	
	uchar*buffer = new uchar[vec.size()];
	if (!vec.empty())
	{
	    memcpy(buffer, &vec[0], vec.size() * sizeof(uchar));
	}

【docker】

1. gui环境: ubuntu 18.04 + melodic 环境下运行docker[ubuntu22.04 + humble]

docker 映射运行

docker run -it --net=host --privileged --env="DISPLAY"  --env="QT_X11_NO_MITSHM=1"   -e PYTHONBUFFERED=1  -v /etc/timezone:/etc/timezone:ro  -v /etc/localtime:/etc/localtime:ro -v  /home/xx/ros2/docker_humble_ws:/root/docker_humble_ws:rw  -v /tmp/.X11-unix:/tmp/.X11-unix:rw  -v $HOME/.Xauthority:/root/.Xauthority:ro   --device=/dev/bus/usb:/dev/bus/usb   091a8ef51d0a   /bin/bash

docker中输入gazebo,加载gui会出现问题

# 问题:No protocol specified
 xhost +local:root

xhost 是一个用于管理 X 服务器访问控制列表(ACL)的实用程序。xhost 命令允许您添加或删除主机名或用户名称以允许或拒绝他们访问您的 X 服务器。X 服务器是基于 Unix 和 Linux 系统上的图形显示系统的关键组件。

xhost +local:root 命令允许本地 root 用户访问您的 X 服务器。这对于某些需要图形显示的应用程序(例如,通过 sudo 运行的图形应用程序)可能是必要的。

 xhost +local:root  命令的详细解释:
	xhost:调用 xhost 命令
	+:表示允许访问
	local:root:表示本地 root 用户

需要注意的是,允许 root 用户访问 X 服务器可能会导致安全风险。在完成需要 root 访问权限的操作后,建议禁止 root 用户访问 X 服务器,使用以下命令:

xhost -local:root

这将禁止本地 root 用户访问您的 X 服务器。

猜你喜欢

转载自blog.csdn.net/zyh821351004/article/details/122244597
今日推荐