novatel计算odom--GPS坐标与UTM坐标转换

2023-05-16

保证你的novatel的driver是在ros-drivers上的驱动

1 简介


1.1 消息


gps_common定义了两个通用消息,供GPS驱动程序输出:gps_common/GPSFix和gps_common/GPSStatus。

在大多数情况下,这些消息应同时发布,并带有相同的时间戳。

1.2 utm_odometry_node节点


utm_odometry_node将经纬度坐标转换为UTM坐标。

1.3 订阅的话题


fix (sensor_msgs/NavSatFix):GPS测量和状态

1.4 发布的话题


odom (nav_msgs/Odometry):UTM编码的位置

1.5 参数


~rot_covariance (double, default: 99999):指定旋转测量的方差(以米为单位)
~frame_id (string, default: Copy frame_id from fix message): Frame to specify in header of outgoing Odometry message
~child_frame_id (string): Child frame to specify in header of outgoing Odometry message


2 安装


mkdir -p ~/gps_ws/src
cd ~/gps_ws/src
git clone https://github.com/swri-robotics/gps_umd.git
cd ..
catkin_make

报错:

CMake Error at /usr/share/cmake-3.5/Modules/FindPkgConfig.cmake:367 (message):
A required package was not found
Call Stack (most recent call first):
/usr/share/cmake-3.5/Modules/FindPkgConfig.cmake:532 (_pkg_check_modules_internal)
gps_umd/gpsd_client/CMakeLists.txt:15 (pkg_check_modules)

– Configuring incomplete, errors occurred!

解决办法:

sudo apt-get install libgps-dev

最后,重新编译:

catkin_make

3 GPS坐标与UTM坐标的转换

先写这个,个人认为用得比较多。

3.1 GPS坐标转换为UTM坐标

源文件utm_odometry_node.cpp:

/*
 * Translates sensor_msgs/NavSat{Fix,Status} into nav_msgs/Odometry using UTM
 */

#include <ros/ros.h>
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include <sensor_msgs/NavSatStatus.h>
#include <sensor_msgs/NavSatFix.h>
#include <gps_common/conversions.h>
#include <nav_msgs/Odometry.h>

using namespace gps_common;

static ros::Publisher odom_pub;
std::string frame_id, child_frame_id;
double rot_cov;
bool append_zone = false;

void callback(const sensor_msgs::NavSatFixConstPtr& fix) {
  if (fix->status.status == sensor_msgs::NavSatStatus::STATUS_NO_FIX) {
    ROS_DEBUG_THROTTLE(60,"No fix.");
    return;
  }

  if (fix->header.stamp == ros::Time(0)) {
    return;
  }

  double northing, easting;
  std::string zone;

  LLtoUTM(fix->latitude, fix->longitude, northing, easting, zone);

  if (odom_pub) {
    nav_msgs::Odometry odom;
    odom.header.stamp = fix->header.stamp;

    if (frame_id.empty()) {
      if(append_zone) {
        odom.header.frame_id = fix->header.frame_id + "/utm_" + zone;
      } else {
        odom.header.frame_id = fix->header.frame_id;
      }
    } else {
      if(append_zone) {
        odom.header.frame_id = frame_id + "/utm_" + zone;
      } else {
        odom.header.frame_id = frame_id;
      }
    }

    odom.child_frame_id = child_frame_id;

    odom.pose.pose.position.x = easting;
    odom.pose.pose.position.y = northing;
    odom.pose.pose.position.z = fix->altitude;
    
    odom.pose.pose.orientation.x = 0;
    odom.pose.pose.orientation.y = 0;
    odom.pose.pose.orientation.z = 0;
    odom.pose.pose.orientation.w = 1;
    
    // Use ENU covariance to build XYZRPY covariance
    boost::array<double, 36> covariance = {{
      fix->position_covariance[0],
      fix->position_covariance[1],
      fix->position_covariance[2],
      0, 0, 0,
      fix->position_covariance[3],
      fix->position_covariance[4],
      fix->position_covariance[5],
      0, 0, 0,
      fix->position_covariance[6],
      fix->position_covariance[7],
      fix->position_covariance[8],
      0, 0, 0,
      0, 0, 0, rot_cov, 0, 0,
      0, 0, 0, 0, rot_cov, 0,
      0, 0, 0, 0, 0, rot_cov
    }};

    odom.pose.covariance = covariance;

    odom_pub.publish(odom);
  }
}

int main (int argc, char **argv) {
  ros::init(argc, argv, "utm_odometry_node");
  ros::NodeHandle node;
  ros::NodeHandle priv_node("~");

  priv_node.param<std::string>("frame_id", frame_id, "");
  priv_node.param<std::string>("child_frame_id", child_frame_id, "");
  priv_node.param<double>("rot_covariance", rot_cov, 99999.0);
  priv_node.param<bool>("append_zone", append_zone, false);

  odom_pub = node.advertise<nav_msgs::Odometry>("odom", 10);

  ros::Subscriber fix_sub = node.subscribe("fix", 10, callback);

  ros::spin();
}

坐标转换函数所在的头文件conversion.h:

/* Taken from utexas-art-ros-pkg:art_vehicle/applanix */

/*
 * Conversions between coordinate systems.
 *
 * Includes LatLong<->UTM.
 */

#ifndef _UTM_H
#define _UTM_H

/**  @file

     @brief Universal Transverse Mercator transforms.

     Functions to convert (spherical) latitude and longitude to and
     from (Euclidean) UTM coordinates.

     @author Chuck Gantz- chuck.gantz@globalstar.com

 */

#include <cmath>
#include <cstdio>
#include <cstdlib>

namespace gps_common
{

const double RADIANS_PER_DEGREE = M_PI/180.0;
const double DEGREES_PER_RADIAN = 180.0/M_PI;

// WGS84 Parameters
const double WGS84_A = 6378137.0;		// major axis
const double WGS84_B = 6356752.31424518;	// minor axis
const double WGS84_F = 0.0033528107;		// ellipsoid flattening
const double WGS84_E = 0.0818191908;		// first eccentricity
const double WGS84_EP = 0.0820944379;		// second eccentricity

// UTM Parameters
const double UTM_K0 = 0.9996;			// scale factor
const double UTM_FE = 500000.0;		// false easting
const double UTM_FN_N = 0.0;			// false northing on north hemisphere
const double UTM_FN_S = 10000000.0;		// false northing on south hemisphere
const double UTM_E2 = (WGS84_E*WGS84_E);	// e^2
const double UTM_E4 = (UTM_E2*UTM_E2);		// e^4
const double UTM_E6 = (UTM_E4*UTM_E2);		// e^6
const double UTM_EP2 = (UTM_E2/(1-UTM_E2));	// e'^2

/**
 * Utility function to convert geodetic to UTM position
 *
 * Units in are floating point degrees (sign for east/west)
 *
 * Units out are meters
 */
static inline void UTM(double lat, double lon, double *x, double *y)
{
  // constants
  const static double m0 = (1 - UTM_E2/4 - 3*UTM_E4/64 - 5*UTM_E6/256);
  const static double m1 = -(3*UTM_E2/8 + 3*UTM_E4/32 + 45*UTM_E6/1024);
  const static double m2 = (15*UTM_E4/256 + 45*UTM_E6/1024);
  const static double m3 = -(35*UTM_E6/3072);

  // compute the central meridian
  int cm = ((lon >= 0.0)
	    ? ((int)lon - ((int)lon)%6 + 3)
	    : ((int)lon - ((int)lon)%6 - 3));

  // convert degrees into radians
  double rlat = lat * RADIANS_PER_DEGREE;
  double rlon = lon * RADIANS_PER_DEGREE;
  double rlon0 = cm * RADIANS_PER_DEGREE;

  // compute trigonometric functions
  double slat = sin(rlat);
  double clat = cos(rlat);
  double tlat = tan(rlat);

  // decide the false northing at origin
  double fn = (lat > 0) ? UTM_FN_N : UTM_FN_S;

  double T = tlat * tlat;
  double C = UTM_EP2 * clat * clat;
  double A = (rlon - rlon0) * clat;
  double M = WGS84_A * (m0*rlat + m1*sin(2*rlat)
			+ m2*sin(4*rlat) + m3*sin(6*rlat));
  double V = WGS84_A / sqrt(1 - UTM_E2*slat*slat);

  // compute the easting-northing coordinates
  *x = UTM_FE + UTM_K0 * V * (A + (1-T+C)*pow(A,3)/6
			      + (5-18*T+T*T+72*C-58*UTM_EP2)*pow(A,5)/120);
  *y = fn + UTM_K0 * (M + V * tlat * (A*A/2
				      + (5-T+9*C+4*C*C)*pow(A,4)/24
				      + ((61-58*T+T*T+600*C-330*UTM_EP2)
					 * pow(A,6)/720)));

  return;
}

/**
 * Determine the correct UTM letter designator for the
 * given latitude
 *
 * @returns 'Z' if latitude is outside the UTM limits of 84N to 80S
 *
 * Written by Chuck Gantz- chuck.gantz@globalstar.com
 */
static inline char UTMLetterDesignator(double Lat)
{
	char LetterDesignator;

	if     ((84 >= Lat) && (Lat >= 72))  LetterDesignator = 'X';
	else if ((72 > Lat) && (Lat >= 64))  LetterDesignator = 'W';
	else if ((64 > Lat) && (Lat >= 56))  LetterDesignator = 'V';
	else if ((56 > Lat) && (Lat >= 48))  LetterDesignator = 'U';
	else if ((48 > Lat) && (Lat >= 40))  LetterDesignator = 'T';
	else if ((40 > Lat) && (Lat >= 32))  LetterDesignator = 'S';
	else if ((32 > Lat) && (Lat >= 24))  LetterDesignator = 'R';
	else if ((24 > Lat) && (Lat >= 16))  LetterDesignator = 'Q';
	else if ((16 > Lat) && (Lat >= 8))   LetterDesignator = 'P';
	else if (( 8 > Lat) && (Lat >= 0))   LetterDesignator = 'N';
	else if (( 0 > Lat) && (Lat >= -8))  LetterDesignator = 'M';
	else if ((-8 > Lat) && (Lat >= -16)) LetterDesignator = 'L';
	else if((-16 > Lat) && (Lat >= -24)) LetterDesignator = 'K';
	else if((-24 > Lat) && (Lat >= -32)) LetterDesignator = 'J';
	else if((-32 > Lat) && (Lat >= -40)) LetterDesignator = 'H';
	else if((-40 > Lat) && (Lat >= -48)) LetterDesignator = 'G';
	else if((-48 > Lat) && (Lat >= -56)) LetterDesignator = 'F';
	else if((-56 > Lat) && (Lat >= -64)) LetterDesignator = 'E';
	else if((-64 > Lat) && (Lat >= -72)) LetterDesignator = 'D';
	else if((-72 > Lat) && (Lat >= -80)) LetterDesignator = 'C';
        // 'Z' is an error flag, the Latitude is outside the UTM limits
	else LetterDesignator = 'Z';
	return LetterDesignator;
}

/**
 * Convert lat/long to UTM coords.  Equations from USGS Bulletin 1532
 *
 * East Longitudes are positive, West longitudes are negative.
 * North latitudes are positive, South latitudes are negative
 * Lat and Long are in fractional degrees
 *
 * Written by Chuck Gantz- chuck.gantz@globalstar.com
 */
static inline void LLtoUTM(const double Lat, const double Long,
                           double &UTMNorthing, double &UTMEasting,
                           char* UTMZone)
{
	double a = WGS84_A;
	double eccSquared = UTM_E2;
	double k0 = UTM_K0;

	double LongOrigin;
	double eccPrimeSquared;
	double N, T, C, A, M;

        //Make sure the longitude is between -180.00 .. 179.9
	double LongTemp = (Long+180)-int((Long+180)/360)*360-180;

	double LatRad = Lat*RADIANS_PER_DEGREE;
	double LongRad = LongTemp*RADIANS_PER_DEGREE;
	double LongOriginRad;
	int    ZoneNumber;

	ZoneNumber = int((LongTemp + 180)/6) + 1;

	if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
		ZoneNumber = 32;

        // Special zones for Svalbard
	if( Lat >= 72.0 && Lat < 84.0 )
	{
	  if(      LongTemp >= 0.0  && LongTemp <  9.0 ) ZoneNumber = 31;
	  else if( LongTemp >= 9.0  && LongTemp < 21.0 ) ZoneNumber = 33;
	  else if( LongTemp >= 21.0 && LongTemp < 33.0 ) ZoneNumber = 35;
	  else if( LongTemp >= 33.0 && LongTemp < 42.0 ) ZoneNumber = 37;
	 }
        // +3 puts origin in middle of zone
	LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;
	LongOriginRad = LongOrigin * RADIANS_PER_DEGREE;

	//compute the UTM Zone from the latitude and longitude
	snprintf(UTMZone, 4, "%d%c", ZoneNumber, UTMLetterDesignator(Lat));

	eccPrimeSquared = (eccSquared)/(1-eccSquared);

	N = a/sqrt(1-eccSquared*sin(LatRad)*sin(LatRad));
	T = tan(LatRad)*tan(LatRad);
	C = eccPrimeSquared*cos(LatRad)*cos(LatRad);
	A = cos(LatRad)*(LongRad-LongOriginRad);

	M = a*((1	- eccSquared/4		- 3*eccSquared*eccSquared/64	- 5*eccSquared*eccSquared*eccSquared/256)*LatRad
				- (3*eccSquared/8	+ 3*eccSquared*eccSquared/32	+ 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*LatRad)
									+ (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*LatRad)
									- (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*LatRad));

	UTMEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
					+ (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
					+ 500000.0);

	UTMNorthing = (double)(k0*(M+N*tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
				 + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720)));
	if(Lat < 0)
		UTMNorthing += 10000000.0; //10000000 meter offset for southern hemisphere
}

static inline void LLtoUTM(const double Lat, const double Long,
                           double &UTMNorthing, double &UTMEasting,
                           std::string &UTMZone) {
  char zone_buf[] = {0, 0, 0, 0};

  LLtoUTM(Lat, Long, UTMNorthing, UTMEasting, zone_buf);

  UTMZone = zone_buf;
}

/**
 * Converts UTM coords to lat/long.  Equations from USGS Bulletin 1532
 *
 * East Longitudes are positive, West longitudes are negative.
 * North latitudes are positive, South latitudes are negative
 * Lat and Long are in fractional degrees.
 *
 * Written by Chuck Gantz- chuck.gantz@globalstar.com
 */
static inline void UTMtoLL(const double UTMNorthing, const double UTMEasting,
                           const char* UTMZone, double& Lat,  double& Long )
{
	double k0 = UTM_K0;
	double a = WGS84_A;
	double eccSquared = UTM_E2;
	double eccPrimeSquared;
	double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared));
	double N1, T1, C1, R1, D, M;
	double LongOrigin;
	double mu, phi1Rad;
	double x, y;
	int ZoneNumber;
	char* ZoneLetter;

	x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
	y = UTMNorthing;

	ZoneNumber = strtoul(UTMZone, &ZoneLetter, 10);
	if((*ZoneLetter - 'N') < 0)
	{
		y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
	}

	LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;  //+3 puts origin in middle of zone

	eccPrimeSquared = (eccSquared)/(1-eccSquared);

	M = y / k0;
	mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));

	phi1Rad = mu	+ (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
				+ (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
				+(151*e1*e1*e1/96)*sin(6*mu);

	N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad));
	T1 = tan(phi1Rad)*tan(phi1Rad);
	C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad);
	R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5);
	D = x/(N1*k0);

	Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
					+(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
	Lat = Lat * DEGREES_PER_RADIAN;

	Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
					*D*D*D*D*D/120)/cos(phi1Rad);
	Long = LongOrigin + Long * DEGREES_PER_RADIAN;

}

static inline void UTMtoLL(const double UTMNorthing, const double UTMEasting,
    std::string UTMZone, double& Lat, double& Long) {
  UTMtoLL(UTMNorthing, UTMEasting, UTMZone.c_str(), Lat, Long);
}
} // end namespace UTM

#endif // _UTM_H

 

运行:

rosrun gps_common utm_odometry_node

3.2 UTM坐标转换为GPS坐标

代码在~/gps_ws/src/gps_umd/gps_common/src/utm_odometry_to_navsatfix_node.cpp,这里就不贴了。

注:代码写得标准又易读,值得学习,这也是我在这里贴代码的原因。

 

4 sensor_msgs/NavSatFix与gps_common/GPSFix的转换


sensor_msgs/NavSatFix的内容见:http://docs.ros.org/api/sensor_msgs/html/msg/NavSatFix.html

gps_common/GPSFix的路径为~/tingjiandan/gps_ws/src/gps_umd/gps_common/msg/GPSFix.msg,描述如下:

# A more complete GPS fix to supplement sensor_msgs/NavSatFix.

主函数fix_translator.py:

#!/usr/bin/env python

# Translates from NavSatFix to GPSFix and back

import rospy
from sensor_msgs.msg import NavSatFix
from gps_common.msg import GPSFix
import gps_common.gps_message_converter as converter

navsat_pub = rospy.Publisher('navsat_fix_out', NavSatFix, queue_size=10)
gps_pub = rospy.Publisher('gps_fix_out', GPSFix, queue_size=10)

def navsat_callback(navsat_msg):
    gps_msg = converter.navsatfix_to_gpsfix(navsat_msg)
    gps_pub.publish(gps_msg)

# Translates from GPSFix to NavSatFix.
# As GPSFix can store much more information than NavSatFix, 
# a lot of this additional information might get lost.
def gps_callback(gps_msg):
    navsat_msg = converter.gpsfix_to_navsatfix(gps_msg)
    navsat_pub.publish(navsat_msg)

if __name__ == '__main__':
    rospy.init_node('fix_translator', anonymous=True)
    navsat_sub = rospy.Subscriber("navsat_fix_in", NavSatFix, navsat_callback)
    gps_sub = rospy.Subscriber("gps_fix_in", GPSFix, gps_callback)
    rospy.spin()



消息转换函数gps_message_converter.py:

from sensor_msgs.msg import NavSatFix
from sensor_msgs.msg import NavSatStatus
from gps_common.msg import GPSFix
from gps_common.msg import GPSStatus

def navsatfix_to_gpsfix(navsat_msg):
    # Convert sensor_msgs/NavSatFix messages to gps_common/GPSFix messages
    gpsfix_msg = GPSFix()
    gpsfix_msg.header = navsat_msg.header
    gpsfix_msg.status.status = navsat_msg.status.status

    gpsfix_msg.status.motion_source = GPSStatus.SOURCE_NONE
    gpsfix_msg.status.orientation_source = GPSStatus.SOURCE_NONE
    gpsfix_msg.status.position_source = GPSStatus.SOURCE_NONE
    if ((navsat_msg.status.service & NavSatStatus.SERVICE_GPS) or
            (navsat_msg.status.service & NavSatStatus.SERVICE_GLONASS) or
            (navsat_msg.status.service & NavSatStatus.SERVICE_GALILEO)):
        gpsfix_msg.status.motion_source = \
            gpsfix_msg.status.motion_source | GPSStatus.SOURCE_GPS
        gpsfix_msg.status.orientation_source = \
            gpsfix_msg.status.orientation_source | GPSStatus.SOURCE_GPS
        gpsfix_msg.status.position_source = \
            gpsfix_msg.status.position_source | GPSStatus.SOURCE_GPS

    if navsat_msg.status.service & NavSatStatus.SERVICE_COMPASS:
        gpsfix_msg.status.orientation_source = \
            gpsfix_msg.status.orientation_source | GPSStatus.SOURCE_MAGNETIC

    gpsfix_msg.latitude = navsat_msg.latitude
    gpsfix_msg.longitude = navsat_msg.longitude
    gpsfix_msg.altitude = navsat_msg.altitude
    gpsfix_msg.position_covariance = navsat_msg.position_covariance
    gpsfix_msg.position_covariance_type = navsat_msg.position_covariance_type

    return gpsfix_msg

def gpsfix_to_navsatfix(gpsfix_msg):
    # Convert gps_common/GPSFix messages to sensor_msgs/NavSatFix messages
    navsat_msg = NavSatFix()
    navsat_msg.header = gpsfix_msg.header

    # Caution: GPSFix has defined some additional status constants, which are
    # not defined in NavSatFix.
    navsat_msg.status.status = gpsfix_msg.status.status

    navsat_msg.status.service = 0
    if gpsfix_msg.status.position_source & GPSStatus.SOURCE_GPS:
        navsat_msg.status.service = \
            navsat_msg.status.service | NavSatStatus.SERVICE_GPS
    if gpsfix_msg.status.orientation_source & GPSStatus.SOURCE_MAGNETIC:
        navsat_msg.status.service = \
            navsat_msg.status.service | NavSatStatus.SERVICE_COMPASS

    navsat_msg.latitude = gpsfix_msg.latitude
    navsat_msg.longitude = gpsfix_msg.longitude
    navsat_msg.altitude = gpsfix_msg.altitude
    navsat_msg.position_covariance = gpsfix_msg.position_covariance
    navsat_msg.position_covariance_type = gpsfix_msg.position_covariance_type

    return navsat_msg


launch文件fix_translator.launch:

<launch>

<!--
    fix_translator translates to and from NatSatFix 
    and GPSFix messages.

    If you want to translate from NavSatFix to GPSFix,
    you have to modify the first two remap lines.
   
    If you want to translate from GPSFix to NavSatFix,
    you have to uncomment and modify the last two remap 
    lines.

    Only adjust topic names after "to=" in each remap line.
-->

  <node name="fix_translator" pkg="gps_common" type="fix_translator">
    <!-- Translate from NavSatFix to GPSFix //-->
      <remap from="/navsat_fix_in"  to="/fix"/>       
      <remap from="/gps_fix_out"    to="/gps_fix"/>

    <!-- Translate from GPSFix to NavSatFix //-->
     <!--
       <remap from="/gps_fix_in"     to="/YOUR_GPSFIX_TOPIC"/>   
       <remap from="/navsat_fix_out" to="/YOUR_NAVSATFIX_TOPIC"/>   
     //-->
  </node>

</launch>


注释写得很详细,就不翻译了。

运行:

roslaunch gps_common fix_translator.launch


注:ROS支持Python,这个项目同时使用了C++和Python,值得学习一下哦。

5 参考


[1] Github: http://wiki.ros.org/gps_common
[2] ROS wiki: http://wiki.ros.org/gps_common
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

novatel计算odom--GPS坐标与UTM坐标转换 的相关文章

  • 我的2011之—混迹于中等城市的.net程序员

    眼瞅着走过了2011年 xff0c 过了这一年我就奔三了 2011年完成了几件大事 xff1a 生了儿子 xff0c 买了房子 按说这生活的本质在逐步体现 xff0c 小日子也算凑合吧 可是怎么确无法高兴起来 到底是为什么呢 xff1f 说
  • 树莓派3B+踩坑记录:一、安装Ubuntu Mate

    树莓派3B 43 踩坑记录 xff1a 一 安装Ubuntu Mate 2020 07 27 05 44 15 来源 互联网 分类 xff1a 相关文章 树莓派3B 43 踩坑记录 xff1a 一 安装Ubuntu Mate 树莓派 xff
  • 1. 从0开始学ARM-安装Keil MDK uVision集成开发环境

    关于ARM的一些基本概念 xff0c 大家可以参考我之前的文章 xff1a 到底什么是Cortex ARMv8 arm架构 ARM指令集 soc xff1f 一文帮你梳理基础概念 科普 二 安装Keil MDK uVision集成开发环境
  • Linux信号量(3)-内核信号量

    概念 Linux内核的信号量在概念和原理上和用户态的System V的IPC机制信号量是相同的 xff0c 不过他绝不可能在内核之外使用 xff0c 因此他和System V的IPC机制信号量毫不相干 如果有一个任务想要获得已经被占用的信号
  • 二维码识别的原理

    二维码的特征定位和信息识别 背景介绍 视觉的方法可以用来估计位置和姿态 最容易想到的是在目标上布置多个容易识别的特征 xff0c 这样使用opencv相机标定和 相机畸变矫正 轮廓提取 solvepnp来获取目标相对于相机的位姿 在实际使用
  • Linux iptables命令详解

    iptables 是 Linux 防火墙系统的重要组成部分 xff0c iptables 的主要功能是实现对网络数据包进出设备及转发的控制 当数据包需要进入设备 从设备中流出或者由该设备转发 路由时 xff0c 都可以使用 iptables
  • 一座5g基站造价多少?

    想知道5G基站的大致价格 xff0c 我们可以通过中国移动2020年5G设备采购方案简单计算得出 xff1a 本次采购5G基站数量为23 2万个 xff0c 采购总额为亿元 xff0c 折合每个5G基站的成本在16万元左右 相当于4G基站价
  • 华为交换机查看端口相关信息常用命令,排查故障法宝,转发收藏

    一 查看接口状态 1 显示接口的运行状态和相关信息 display interface Ethernet brief 查看以太网端口的简要信息 xff0c 物理端口是否连通 xff0c 端口是否是全双工 xff0c 带宽是多少 xff0c
  • 从0学Linux驱动第一期视频已经录制完毕,资料全部奉送

    历时4个多月 xff0c 第一期Linux驱动视频录制完毕 xff0c 一共32期 xff0c 现在全部同步到了B站 如果你觉得视频对你有用 xff0c 建议大家多多点赞 xff0c 投投免费硬币 xff0c 算是对我辛苦的劳动的认可 视频
  • 千年虫”是什么东西?一个在计算机诞生之初,遗留下的巨大BUG

    说起来 xff0c 现在社会科技中 xff0c 除了真正学过计算机专业的人 xff0c 大部分人对于 千年虫 这个称号都有些陌生 xff0c 甚至有些人连听都没听过 xff0c 不知道的网友听到 虫 这个字可能还会脑补出一大堆不明生物的样子
  • 小灵通为什么会退市?

    价廉物美的 小灵通 退市最主要的原因 xff0c 其一是因为 小灵通 本身月租太便宜 xff0c 让别的移动运营商无钱可挣 xff1b 其二则是中国电信自己的CDMA网络也发展起来了 xff0c 小灵通 让自己无钱可挣 所以 小灵通 必须退
  • Camera | 4.瑞芯微平台MIPI摄像头应用程序编写

    前面3篇我们讲解了camera的基础概念 xff0c MIPI协议 xff0c CSI2 xff0c 常用命令等 xff0c 本文带领大家入门 xff0c 如何用c语言编写应用程序来操作摄像头 Linux下摄像头驱动都是基于v4l2架构 x
  • Camera | 9.如何让camera支持闪光灯?-基于rk3568

    一 闪光灯基本原理 工作模式 Camera flash led分flash和torch两种模式 flash xff1a 拍照时上光灯瞬间亮一下 xff0c 电流比较大 xff0c 目前是1000mA xff0c 最大电流不能超过led最大承
  • 我的新书上架了!

    talk is cheap xff0c show you my book xff01 新书 从0开始学ARM 终于在各大平台上架了 xff01 xff01 一 关于本书 1 本书主要内容 ARM体系架构是目前市面上的主流处理器体系架构 xf
  • 签名预售活动圆满结束!各位敬等快递,第一个付款的兄弟来领取大礼!

    我的新书经过千难万险终于上架 xff0c 为了感谢众多老铁的支持 xff0c 所以上周日搞了签名预售的活动 xff0c 挂了300本 xff0c 一上线很快就被大家买光了 xff0c 留言需要单独写一些话的老铁 xff0c 我也都尽量满足了
  • Android P(Android 9)出现Detected problems with API compatibility问题解决

    安卓系统升级到Android P后打开应用出现Detected problems with API compatibility问题 xff0c 如下图 通过查询发现是 Android P 后谷歌限制了开发者调用非官方公开API 方法或接口
  • eclipse + GDB + JLink 搭建MCU调试环境

    安装Java环境 1 进入Java官网 http www oracle com technetwork java javase downloads index html 2 下载安装包 如果是先要安装Java开发环境 xff0c 就安装JD
  • Jeston TX2 使用cmake 运行测试realsense D435i相关代码(C++)

    Jeston TX2 使用cmake 运行测试realsense D435i相关代码 xff08 C 43 43 xff09 前言 xff1a 我这些天作毕设的TX2上面的Jetpack包是4 3的 然后我又自己用JetPack4 6 1包
  • C++ 服务器通过Tcp传输图片 到 QT客户端显示

    C 43 43 服务器通过Tcp传输图片 到 QT客户端显示 简单的方法通过流数据传输图片 xff0c 并且在QT上面显示出来这里贴出核心代码 xff0c 供大家参考 xff1a 先附上资源源码 xff1a Qt客户端和C 43 43 服务
  • Docker 安装部署

    目录 Docker 安装部署 一 Docker 安装 二 设置镜像加速 三 网络优化 开启路由转发的作用 四 总结 docker server端配置文件建议配置 Docker 安装部署 一 Docker 安装 开源社区 xff1a dcok

随机推荐

  • 学习笔记:SLAM_因子图优化

    SLAM 因子图优化 Factor graoh 模型 概率模型到因子图模型 定义一个简单的机器人问题 xff08 SLAM xff09 假设有一个机器人在往前运动 xff0c 运动过程中能观测到两个路标点 xff0c 定义了三个时间 xff
  • [NVIDIA]-2 从零入手 Jetson Xavier NX 内核编译、源码编译流程

    NVIDIA 从零入手 Jetson Xavier NX 内核编译 源码编译流程 注明 xff1a 感谢网友提醒 xff0c 我当时买的时候nx套件还没开售 xff0c 因为核心板兼容b01 xff0c 先买了核心板和b01的板子合在一起用
  • [NVIDIA]-1 入手Jetson Xavier NX 刷机+开机配置+系统烧录+Bring up

    NVIDIA 入手 Jetson Xavier NX 刷机 43 开机配置 43 系统烧录 43 Bring up 注明 xff1a 感谢网友提醒 xff0c 我当时买的时候nx套件还没开售 xff0c 因为核心板兼容b01 xff0c 先
  • RTOS解读一

    什么是RTOS 维基百科定义 实时操作系统 Real Time Operating System RTOS xff0c 通常读作 34 R toss 34 xff0c 指的是专为实时应用而设计的多任务操作系统 其应用场合包括嵌入式系统 可编
  • switch-case使用方法

    switch case 语句判断一个变量与一系列值中某个值是否相等 xff0c 每个值称为一个分支 switch case 语句语法格式如下 xff1a switch语句应用举例1 xff1a public class VariableTe
  • Linux单片机串口通信总结

    这是一个目录 Linux与单片机串口通信运行ROS串口发送节点后异常中断栈溢出问题catkin make报错 xff1a 函数未定义的引用ERROR L107 ADDRESS SPACE OVERFLOW串口实验总结程序组织串口调试 Lin
  • Apache Options指令详解

    前言 xff1a Options指令是Apache配置文件中一个比较常见也比较重要的指令 xff0c Options指令可以在Apache服务器核心配置 server config 虚拟主机配置 virtual host 特定目录配置 di
  • 欠驱动机械臂运动学仿真

    这是个目录 三轴机械臂建模及运动学仿真各仿真项目的个人理解三轴机械臂 xff08 欠驱动 xff09 分析难点更改RTB中逆解求解源码求解析解数值求解工作空间筛选 实用的解析解法总结 三轴机械臂建模及运动学仿真 在开始具体的机械结构及驱动结
  • postman安装使用教程(标贝科技)

    postman安装使用教程 文章目录 postman安装使用教程前言一 postman安装二 postman使用 前言 postman是Chrome浏览器的插件 xff0c 是一款功能强大的网页调试工具 xff08 接口调试神器 xff09
  • 流媒体推流原理

    我们知道一个完整的直播过程 xff0c 包括采集 处理 编码 封包 推流 传输 转码 分发 解码 播放等 xff0c 这一过程所采用的技术 xff0c 我们也称之为 流媒体技术 其中推流是指使用推流工具等内容抓取软件把直播内容传输到服务器的
  • 机器学习必知必会10大算法!

    Datawhale干货 作者 xff1a Fahim ul Haq xff0c 编译 xff1a InfoQ 现在 xff0c 机器学习有很多算法 如此多的算法 xff0c 可能对于初学者来说 xff0c 是相当不堪重负的 今天 xff0c
  • C语言结构体及链表定义

    最近在看 大话数据结构 xff0c 一边看书一边跑一下书中的案例 xff0c 加深下理解 书中的案例都是C写的 xff0c 顺便熟悉下C语言 此处第三章线性表链式存储 xff1a 在用代码描述单链表之前 xff0c 我们需要定义一个结构体来
  • 【ROS教程 005】ROS可视化

    在ROS系统中它可以通过一些通用工具轻松绘制标量数据图 xff0c 它要求对每一个标量字段数据分别绘制成二维曲线 xff08 1 xff09 用rxplot画出时间趋势曲线 在ROS系统中 xff0c 标量数据可以根据消息中提供的时间戳作为
  • C/C++/Windows/VC/MFC/Unix/Linux编程书籍推荐

    C C 43 43 编程书籍 C Primer Plus C 43 43 Primer C 43 43 Primer Plus C和指针 C陷阱与缺陷 C专家编程 C 43 43 沉思录 C语言深度剖析 Effective C 43 43
  • 使用CPM管理CMake C++工程中的外部依赖库

    严正声明 xff1a 本文系作者davidhopper原创 xff0c 未经许可 xff0c 不得转载 众所周知 xff0c 对于外部依赖库的管理是CMake C 43 43 工程中一个令人头疼的问题 人们一直希望能有一个工具来自动配置CM
  • 字典和集合2:高效性和可哈希

    目录 1 字典和集合的高效性 2 散列表操作 2 1 散列表的写入 2 2 散列表的查找 2 3 散列表的缺点 3 可哈希 1 字典和集合的高效性 许多时候 xff0c 将列表改为字典或集合后 xff0c 执行效率将会有巨大的飞跃 xff0
  • 卡尔曼滤波(Kalman filter)公式推导详细版

    卡尔曼滤波 xff08 Kalman filter xff09 公式推导详细版 记得很早的时候 xff0c 我曾经手工推导过卡尔曼滤波 xff0c 但是之前的已经大多记不起来了 今天帮着老师整理PPT的时候 xff0c 老师让我补充完相应的
  • 4g dtu透传模块

    4g dtu透传模块 xff0c 是一款支持双向透明传输的产品 xff0c 用户使用无需关心复杂的协议 xff0c 产品为双向透传 xff0c 只需要简单配置即可 同时产品为4G全网通 xff0c 支持国内全部运营商网络 xff0c 通讯模
  • PCB设计学习笔记(一)原理图界面

    一 画原理图库 多个引脚可以ctrl 43 c一个引脚后 xff0c 编辑 gt 设置粘贴阵列 xff0c 一次性复制出来多个引脚 二 原理图界面 生成原理图库 xff1a 在一个现成的原理图界面可以直接将现有的原理图内的原件生成一个原理图
  • novatel计算odom--GPS坐标与UTM坐标转换

    保证你的novatel的driver是在ros drivers上的驱动 1 简介 1 1 消息 gps common定义了两个通用消息 xff0c 供GPS驱动程序输出 xff1a gps common GPSFix和gps common