赞
踩
本文是边分析边写的,顺便就记录下了分析的思路,并不是按照教材那种思路介绍性的,而是按照程序员分析程序的思路来的。所以读者跟着看有些地方看了意义不大,但是这种程序分析的思路还是可以借鉴的,如果有大神看到了本文,有更好的见解,欢迎指教。
前面的是从APM代码角度看的,后面是从原生码角度看的。这blog写的我自己看了都想吐,翻下去都是代码,就最后一张图人性化一点。
温馨提示:可以从后面点看,程序中有注释。
先从ardupilot/libraries/AP_OpticalFlow/examples/AP_OpticalFlow_test/ AP_OpticalFlow_test.cpp看起
- voidsetup()
- {
- hal.console->println("OpticalFlowlibrary test ver 1.6");
-
- hal.scheduler->delay(1000);
-
- // flowSensor initialization
- optflow.init();
-
- if (!optflow.healthy()) {
- hal.console->print("Failed toinitialise PX4Flow ");
- }
-
- hal.scheduler->delay(1000);只需要看
- }
- voidloop()
- {
- hal.console->println("this onlytests compilation succeeds");
-
- hal.scheduler->delay(5000);
- }
因此optflow.init();再进行判断if (!optflow.healthy()),任务就完成了
跳转到optflow.init();
- voidOpticalFlow::init(void)
- {
- if (backend != NULL) {
- backend->init();
- } else {
- _enabled = 0;
- }
- }
跳转到init();
- classOpticalFlow_backend
- {
- friend class OpticalFlow;
-
- public:
- // constructor
- OpticalFlow_backend(OpticalFlow&_frontend) : frontend(_frontend) {}
-
- // init - initialise sensor
- virtual void init() = 0;
-
- // read latest values from sensor and fillin x,y and totals.
- virtual void update() = 0;
-
- protected:
- // access to frontend
- OpticalFlow &frontend;
-
- // update the frontend
- void _update_frontend(const structOpticalFlow::OpticalFlow_state &state);
-
- // get the flow scaling parameters
- Vector2f _flowScaler(void) const { returnVector2f(frontend._flowScalerX, frontend._flowScalerY); }
-
- // get the yaw angle in radians
- float _yawAngleRad(void) const { returnradians(float(frontend._yawAngle_cd) * 0.01f); }
- };
看到了吧,virtualvoid init() = 0;就是这个虚函数
怎么找到它的实例化呢?
Ctrl+H全局搜索public OpticalFlow_backend
路径是:ardupilot/libraries/AP_OpticalFlow/ AP_OpticalFlow_PX4.h
- 路径是:ardupilot/libraries/AP_OpticalFlow/ AP_OpticalFlow_PX4.h
- class AP_OpticalFlow_PX4 : public OpticalFlow_backend
- {
- public:
- /// constructor
- AP_OpticalFlow_PX4(OpticalFlow &_frontend);
-
- // init - initialise the sensor
- void init();
-
- // update - read latest values from sensor and fill in x,y and totals.
- void update(void);
-
- private:
- int _fd; // file descriptor for sensor
- uint64_t _last_timestamp; // time of last update (used to avoid processing old reports)
- };
- void init();就是实例化,继续搜索AP_OpticalFlow_PX4:: init
void init();就是实例化,继续搜索AP_OpticalFlow_PX4::init
本体就是
- voidAP_OpticalFlow_PX4::init(void)
- {
- _fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);//关于sd卡文件的read
-
- // check for failure to open device
- if (_fd == -1) {
- return;
- }
-
- // change to 10Hz update
- if (ioctl(_fd, SENSORIOCSPOLLRATE, 10) != 0) {
- hal.console->printf("Unable to set flow rate to10Hz\n");
- }
- }
慢慢查看,先看_fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);源码如下
路径是ardupilot/modules/PX4NuttX/nuttx/fs/fs_open.c
- /****************************************************************************
- *Name: open
- *
- *Description:
- * Standard 'open' interface
- *
- ****************************************************************************/
- int open(const char *path, int oflags, ...)
- {
- FARstruct filelist *list;
- FARstruct inode *inode;
- FARconst char *relpath = NULL;
- #if defined(CONFIG_FILE_MODE) ||!defined(CONFIG_DISABLE_MOUNTPOINT)
- mode_t mode = 0666;
- #endif
- int ret;
- int fd;
- /*Get the thread-specific file list */得到具体线程列表
- list = sched_getfiles();
- if(!list)
- {
- ret = EMFILE;
- goto errout;
- }
- #ifdef CONFIG_FILE_MODE
- # ifdef CONFIG_CPP_HAVE_WARNING
- # warning "File creation not implemented"
- # endif
- /*If the file is opened for creation, then get the mode bits */
- if(oflags & (O_WRONLY|O_CREAT) != 0)
- {
- va_list ap;
- va_start(ap, oflags);
- mode = va_arg(ap, mode_t);
- va_end(ap);
- }
- #endif
- /*Get an inode for this file */得到索引节点
- inode = inode_find(path, &relpath);
- if(!inode)
- {
- /* "O_CREAT is not set and the named file does not exist. Or, a
- * directory component in pathname does not exist or is a dangling
- * symbolic link."
- */
- ret = ENOENT;
- goto errout;
- }
- /*Verify that the inode is valid and either a "normal" or amountpoint. We
- *specifically exclude block drivers.
- */
- #ifndef CONFIG_DISABLE_MOUNTPOINT
- if((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) ||!inode->u.i_ops)
- #else
- if(!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
- #endif
- {
- ret = ENXIO;
- goto errout_with_inode;
- }
- /*Make sure that the inode supports the requested access */
- ret= inode_checkflags(inode, oflags);
- if(ret < 0)
- {
- ret = -ret;
- goto errout_with_inode;
- }
- /*Associate the inode with a file structure */
- fd= files_allocate(inode, oflags, 0, 0);
- if(fd < 0)
- {
- ret = EMFILE;
- goto errout_with_inode;
- }
- /*Perform the driver open operation. NOTEthat the open method may be
- *called many times. The driver/mountpointlogic should handled this
- *because it may also be closed that many times.
- */
- ret= OK;
- if(inode->u.i_ops->open)
- {
- #ifndef CONFIG_DISABLE_MOUNTPOINT
- if (INODE_IS_MOUNTPT(inode))
- {
- ret = inode->u.i_mops->open((FAR structfile*)&list->fl_files[fd],
- relpath,oflags, mode);
- }
- else
- #endif
- {
- ret = inode->u.i_ops->open((FAR structfile*)&list->fl_files[fd]);
- }
- }
- if(ret < 0)
- {
- ret = -ret;
- goto errout_with_fd;
- }
- return fd;
- errout_with_fd:
- files_release(fd);
- errout_with_inode:
- inode_release(inode);
- errout:
- set_errno(ret);
- return ERROR;
- }
- 跳转到list = sched_getfiles();
- 路径是ardupilot/modules/PX4NuttX/nuttx/sched/sched_getfiles.c
- /************************************************************************
- *Name: sched_getfiles
- *
- *Description:
- * Return a pointer to the file list for this thread
- *
- *Parameters:
- * None
- *
- *Return Value:
- * Apointer to the errno.
- *
- *Assumptions:
- *
- ************************************************************************/
- #if CONFIG_NFILE_DESCRIPTORS > 0
- FAR struct filelist *sched_getfiles(void)
- {
- FARstruct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
- FARstruct task_group_s *group = rtcb->group;
- /*The group may be NULL under certain conditions. For example, if
- *debug output is attempted from the IDLE thead before the group has
- *been allocated. I have only seen thiscase when memory management
- *debug is enabled.
- */
- if(group)
- {
- return &group->tg_filelist;
- }
- /*Higher level logic must handle the NULL gracefully */
- return NULL;
- }
- #endif /* CONFIG_NFILE_DESCRIPTORS */
- 跳转到inode = inode_find(path, &relpath);
- 路径是ardupilot/modules/PX4NuttX/nuttx/fs/fs_inodefine.c
- /****************************************************************************
- *Name: inode_find
- *
- *Description:
- * Thisis called from the open() logic to get a reference to the inode
- * associated with a path.
- *
- ****************************************************************************/
- //得到一个inode与路径相关的引用
- FAR struct inode *inode_find(FAR const char*path, FAR const char **relpath)
- {
- FARstruct inode *node;
- if(!*path || path[0] != '/')
- {
- return NULL;
- }
- /*Find the node matching the path. Iffound, increment the count of
- *references on the node.
- */
- inode_semtake();
- node = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL,relpath);
- if(node)
- {
- node->i_crefs++;
- }
- inode_semgive();
- return node;
- }
看到不大懂,姑且认为是关于sd卡文件的read
#definePX4FLOW0_DEVICE_PATH "/dev/px4flow0"路径ardupilot/modules/PX4Firmware/src/drivers/drv_px4flow.h
- void AP_OpticalFlow_PX4::init(void)
- {
- _fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
- // check for failure to open device
- if (_fd == -1) {
- return;
- }
- // change to 10Hz update
- if (ioctl(_fd, SENSORIOCSPOLLRATE, 10) != 0) {
- hal.console->printf("Unable to set flow rate to10Hz\n");
- }
- }
继续往下看ioctl(_fd, SENSORIOCSPOLLRATE, 10);这句话的目的是控制光流跟新频率为10Hz
分别看ioctl的输入
_fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);_fd用来判断是否有这个路径并读到了东西
SENSORIOCSPOLLRATE设置传感器读取的时间间隔
路径ardupilot/modules/PX4Firmware/src/drivers/drv_sensor.h
#define SENSORIOCSPOLLRATE _SENSORIOC(0)
#define _SENSORIOC(_n) (_PX4_IOC(_SENSORIOCBASE,_n))
#define _SENSORIOCBASE (0x2000)ardupilot/modules/PX4Firmware/src/drivers/drv_sensor.h
#define _PX4_IOC(x,y) _IOC(x,y) ardupilot/modules/PX4Firmware/src/platforms/px4_defines.h
#define_IOC(type,nr) ((type)|(nr))
也就是说SENSORIOCSPOLLRATE等价于_PX4_IOC(0x2000,0)等价于(0x2000)|(0)
ardupilot/modules/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/fs/ioctl.h
与上面的宏定义相比
#define_PX4FLOWIOCBASE (0x7700)
#define__PX4FLOWIOC(_n) (_IOC(_PX4FLOWIOCBASE,_n))
另外,在ardupilot/modules/PX4Firmware/src/drivers/drv_px4flow.h中找到“px4flow drivers also implement the generic sensordriver interfaces from drv_sensor.h”,表明光流的驱动在通用传感器驱动文件中ardupilot/modules/PX4Firmware/src/drivers/drv_sensor.h
跳转到ioctl(_fd,SENSORIOCSPOLLRATE, 10)
- /****************************************************************************
- *Name: ioctl
- *
- *Description:
- * Perform device specific operations.
- *
- *Parameters:
- * fd File/socket descriptor ofdevice
- * req The ioctl command
- * arg The argument of the ioctlcmd
- *
- *Return:
- * >=0 on success (positive non-zero values are cmd-specific)
- * -1on failure withi errno set properly:
- *
- * EBADF
- * 'fd' is not a valid descriptor.
- * EFAULT
- * 'arg' references an inaccessible memory area.
- * EINVAL
- * 'cmd' or 'arg' is not valid.
- * ENOTTY
- * 'fd' is not associated with a character special device.
- * ENOTTY
- * The specified request does not apply to the kind of object that the
- * descriptor 'fd' references.
- *
- ****************************************************************************/
- int ioctl(int fd, int req, unsigned longarg)
- {
- interr;
- #if CONFIG_NFILE_DESCRIPTORS > 0
- FARstruct filelist *list;
- FARstruct file *this_file;
- FARstruct inode *inode;
- int ret = OK;
- /*Did we get a valid file descriptor? */
- if((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
- #endif
- {
- /* Perform the socket ioctl */
- #if defined(CONFIG_NET) &&CONFIG_NSOCKET_DESCRIPTORS > 0
- if ((unsigned int)fd <(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
- {
- return netdev_ioctl(fd, req, arg);
- }
- else
- #endif
- {
- err = EBADF;
- goto errout;
- }
- }
- #if CONFIG_NFILE_DESCRIPTORS > 0
- /*Get the thread-specific file list */
- list = sched_getfiles();
- if(!list)
- {
- err = EMFILE;
- goto errout;
- }
- /*Is a driver registered? Does it support the ioctl method? */
- this_file = &list->fl_files[fd];
- inode = this_file->f_inode;
- if(inode && inode->u.i_ops && inode->u.i_ops->ioctl)
- {
- /* Yes, then let it perform the ioctl */
- ret = (int)inode->u.i_ops->ioctl(this_file,req, arg);
- if (ret < 0)
- {
- err = -ret;
- goto errout;
- }
- }
- return ret;
- #endif
- errout:
- set_errno(err);
- return ERROR;
- }
这句话是这个函数的核心
/* Yes, then let it perform the ioctl */
ret =(int)inode->u.i_ops->ioctl(this_file, req, arg);
跳转至ardupilot/modules/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/fs/fs.h
int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
无意中跑到ardupilot/libraries/AP_HAL_PX4/GPIO.cpp中,Ctrl+点击ioctl
可以搜索到现在可以总结关于光流的程序有哪些部分了:
ardupilot/libraries/AP_OpticalFlow文件夹
ardupilot/modules/PX4Firmware/src/drivers/drv_px4flow.h
ardupilot/modules/PX4Firmware/src/drivers/px4flow文件夹
顺便再ardupilot/modules/PX4Firmware/src/drivers/px4flow/px4flow.cpp里面找到了
extern "C"__EXPORT int px4flow_main(int argc, char *argv[]);
也就是程序入口,久违的感动
现在有2条思路:一是继续跳转至ioctl实例化,继续看如何执行的;二是顺着main来看,先还是按照老思路example来
- int
- PX4FLOW::ioctl(structfile *filp, int cmd, unsigned long arg)
- {
- switch(cmd) {
- caseSENSORIOCSPOLLRATE: {
- switch(arg) {
- /*switching to manual polling */
- caseSENSOR_POLLRATE_MANUAL:
- stop();
- _measure_ticks= 0;
- returnOK;
- /*external signalling (DRDY) not supported */
- case SENSOR_POLLRATE_EXTERNAL:
- /*zero would be bad */
- case0:
- return-EINVAL;
- /*set default/max polling rate */
- caseSENSOR_POLLRATE_MAX:
- caseSENSOR_POLLRATE_DEFAULT: {
- /*do we need to start internal polling? */
- boolwant_start = (_measure_ticks == 0);
- /*set interval for next measurement to minimum legal value */
- _measure_ticks= USEC2TICK(PX4FLOW_CONVERSION_INTERVAL);
- /*if we need to start the poll state machine, do it */
- if(want_start) {
- start();
- }
- returnOK;
- }
- /*adjust to a legal polling interval in Hz */
- default:{
- /*do we need to start internal polling? */
- boolwant_start = (_measure_ticks == 0);
- /*convert hz to tick interval via microseconds */
- unsignedticks = USEC2TICK(1000000 / arg);
- /*check against maximum rate */
- if(ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
- return-EINVAL;
- }
- /*update interval for next measurement */
- _measure_ticks= ticks;
- /*if we need to start the poll state machine, do it */
- if(want_start) {
- start();
- }
- returnOK;
- }
- }
- }
- caseSENSORIOCGPOLLRATE:
- if(_measure_ticks == 0) {
- returnSENSOR_POLLRATE_MANUAL;
- }
- return(1000 / _measure_ticks);
- caseSENSORIOCSQUEUEDEPTH: {
- /*lower bound is mandatory, upper bound is a sanity check */
- if((arg < 1) || (arg > 100)) {
- return-EINVAL;
- }
- irqstate_t flags = irqsave();
- if(!_reports->resize(arg)) {
- irqrestore(flags);
- return-ENOMEM;
- }
- irqrestore(flags);
- returnOK;
- }
- caseSENSORIOCGQUEUEDEPTH:
- return_reports->size();
- caseSENSORIOCSROTATION:
- _sensor_rotation= (enum Rotation)arg;
- returnOK;
- caseSENSORIOCGROTATION:
- return_sensor_rotation;
- caseSENSORIOCRESET:
- /*XXX implement this */
- return-EINVAL;
- default:
- /*give it to the superclass */
- returnI2C::ioctl(filp, cmd, arg);
- }
- }
这个函数很好理解,根据传入的参数对号入座,传入的是SENSORIOCSPOLLRATE,那么进入
- case SENSORIOCSPOLLRATE: {
- switch(arg) {
- /*switching to manual polling */
- caseSENSOR_POLLRATE_MANUAL:
- stop();
- _measure_ticks= 0;
- returnOK;
- /*external signalling (DRDY) not supported */
- case SENSOR_POLLRATE_EXTERNAL:
- /*zero would be bad */
- case0:
- return-EINVAL;
- /*set default/max polling rate */
- caseSENSOR_POLLRATE_MAX:
- caseSENSOR_POLLRATE_DEFAULT: {
- /*do we need to start internal polling? */
- boolwant_start = (_measure_ticks == 0);
- /*set interval for next measurement to minimum legal value */
- _measure_ticks= USEC2TICK(PX4FLOW_CONVERSION_INTERVAL);
- /*if we need to start the poll state machine, do it */
- if(want_start) {
- start();
- }
- returnOK;
- }
- /*adjust to a legal polling interval in Hz */
- default:{
- /*do we need to start internal polling? */
- boolwant_start = (_measure_ticks == 0);
- /*convert hz to tick interval via microseconds */
- unsignedticks = USEC2TICK(1000000 / arg);
- /*check against maximum rate */
- if(ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
- return-EINVAL;
- }
- /*update interval for next measurement */
- _measure_ticks= ticks;
- /* if we need to start thepoll state machine, do it */
- if(want_start) {
- start();
- }
- returnOK;
- }
Ok,下一个参数是10,那么进入default
看注释能明白default是用来调整合适的间隔
里面需要重点看的是
unsigned ticks =USEC2TICK(1000000 / arg);// 看注释能明白应该是处理时间间隔的
start();//轮询状态机
先看unsigned ticks = USEC2TICK(1000000 / arg);
跳转至ardupilot/modules/PX4Firmware/Build/px4fmu-v2_APM.build/nuttx-export/include/nuttx/clock.h
#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK) /* Rounds */
这里并没有寄存器的相关操作,只是把用户所定的时间进行了一些转换,方便单片机之后定时操作
那么跳转至start();
- void
- PX4FLOW::start()
- {
- /*reset the report ring and state machine *///复位报告环和状态机
- _collect_phase= false;
- _reports->flush();
- /*schedule a cycle to start things *///安排一个周期开始一些事情
- work_queue(HPWORK,&_work, (worker_t)&PX4FLOW::cycle_trampoline, this, 1);
- /*notify about state change */
- structsubsystem_info_s info = {
- true,
- true,
- true,
- subsystem_info_s::SUBSYSTEM_TYPE_OPTICALFLOW
- };
- staticorb_advert_t pub = nullptr;
- if(pub != nullptr) {
- orb_publish(ORB_ID(subsystem_info),pub, &info);
- }else {
- pub= orb_advertise(ORB_ID(subsystem_info), &info);
- }
- }
看函数名字的意思是启动光流
看来最关键的是work_queue(HPWORK, &_work, (worker_t)&PX4FLOW::cycle_trampoline,this, 1)再后面就是发布和公告子系统信息,跳转至work_queue(HPWORK, &_work,(worker_t)&PX4FLOW::cycle_trampoline, this, 1);
- /****************************************************************************
- *Name: work_queue
- *
- *Description:
- * Queue work to be performed at a later time. All queued work will be
- * performed on the worker thread of of execution (not the caller's).
- *
- * Thework structure is allocated by caller, but completely managed by
- * thework queue logic. The caller shouldnever modify the contents of
- * thework queue structure; the caller should not call work_queue()
- * again until either (1) the previous work has been performed and removed
- * fromthe queue, or (2) work_cancel() has been called to cancel the work
- * andremove it from the work queue.
- *
- *Input parameters:
- * qid - The work queue ID (index)
- * work - The work structure toqueue
- * worker - The worker callback to be invoked. The callback will invoked
- * on the worker thread of execution.
- * arg - The argument that will bepassed to the workder callback when
- * int is invoked.
- * delay - Delay (in clock ticks)from the time queue until the worker
- * is invoked. Zero means to perform the work immediately.
- *
- *Returned Value:
- * Zeroon success, a negated errno on failure
- *
- ****************************************************************************/
- 注释翻译:
- 在稍后的时间将要执行的队列的工作。 所有排队工作将在工作线程(不是调用的程序)上进行。
- 工作结构由调用者分配,but,由工作队列逻辑完全管理。调用者不能修改工作队列结构的内容,也不能再次调用work_queue(),除非任务执行完毕或者任务被取消
- 输入参数:
- qid -工作队列的ID
- work -队列的工作结构
- worker -工作线程被执行,worker callback 会被调用
- arg -参数会传递给worker callback
- delay -延时多久再执行这个任务,若为0,则直接执行
- 返回值:
- 0,则成功执行;错误号,则失败
- int work_queue(int qid, FAR struct work_s*work, worker_t worker,
- FAR void *arg, uint32_t delay)
- {
- FARstruct wqueue_s *wqueue = &g_work[qid];
- irqstate_t flags;
- DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS);//应该是调试用的debug
- /* First, initialize the work structure */
- work->worker = worker; /* Work callback */
- work->arg = arg; /* Callback argument */
- work->delay = delay; /* Delay until work performed */
- /*Now, time-tag that entry and put it in the work queue. This must be
- *done with interrupts disabled. Thispermits this function to be called
- *from with task logic or interrupt handlers.
- */
- flags = irqsave();
- work->qtime = clock_systimer(); /* Time work queued */
- dq_addlast((FAR dq_entry_t *)work, &wqueue->q);
- kill(wqueue->pid, SIGWORK); /* Wake up the worker thread */
- irqrestore(flags);
- return OK;
- }
在看一下调用的函数work_queue(HPWORK, &_work,(worker_t)&PX4FLOW::cycle_trampoline, this, 1);
int work_queue(int qid, FAR struct work_s*work, worker_t worker, FAR void *arg, uint32_t delay)
这个应该是比较关键的函数,一点点看
- FAR struct wqueue_s *wqueue =&g_work[qid];
- /* This structure defines the state on onework queue. Thisstructure is
- * used internally by the OS and worker queuelogic and should not be
- * accessed by application logic.
- */
- 注释翻译:
- 这个结构体定义了一个工作队列的状态。这种结构是由系统和worker队列逻辑在内部使用,不应被应用程序逻辑访问。
- struct wqueue_s
- {
- pid_t pid; /* The taskID of the worker thread *///worker线程中的任务ID
- struct dq_queue_s q; /* Thequeue of pending work *///挂起的工作队列
- };
- typedef int16_t pid_t;
- struct dq_queue_s
- {
- FARdq_entry_t *head;//头
- FARdq_entry_t *tail;//尾
- };
也就是说
FARstruct wqueue_s *wqueue = &g_work[qid];
irqstate_t flags;
这2句是声明数据类型
/*First, initialize the work structure *///初始化work结构体
work->worker = worker; /* Work callback */
work->arg = arg; /* Callback argument */
work->delay = delay; /* Delay until work performed */
work的定义struct work_s work;
work_s的定义
- /* Defines one entry in the workqueue. The user only needs thisstructure
- * inorder to declare instances of the work structure. Handling of all
- *fields is performed by the work APIs
- */
- 注释翻译:定义一个工作队列的入口。使用前声明这个结构,再实例化。所有处理都是有API来完成的
- struct work_s
- {
- structdq_entry_s dq; /* Implements a doublylinked list */
- worker_t worker; /* Work callback */
- FARvoid *arg; /* Callback argument*/
- uint32_t qtime; /* Time work queued */
- uint32_t delay; /* Delay until work performed */
- };
- work->worker = worker; /* Work callback */
- work->arg = arg; /* Callback argument */
- work->delay = delay; /* Delay until work performed */
- /* Now, time-tag that entry and put it inthe work queue. This must be
- *done with interrupts disabled. Thispermits this function to be called
- *from with task logic or interrupt handlers.
- */
- 注释翻译:现在,时间标记该条目,并把它的工作队列。这个需要在中断失能的情况下完成。允许这个函数从任务逻辑或中断处理程序调用。
- flags = irqsave();/* Save the current primask state& disable IRQs */保存当前primask的状态,并失能中断
- work->qtime = clock_systimer(); /* Time work queued */
跳转至irqsave();
- static inline irqstate_t irqsave(void)
- {
- #ifdef CONFIG_ARMV7M_USEBASEPRI
- uint8_t basepri = getbasepri();
- setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
- return (irqstate_t)basepri;
- #else
- unsigned short primask;
- /*Return the current value of primask register and set
- *bit 0 of the primask register to disable interrupts
- */
- __asm__ __volatile__
- (
- "\tmrs %0, primask\n"
- "\tcpsid i\n"
- : "=r" (primask)
- :
- : "memory");
- return primask;
- #endif
- }
PRIMASK位:只允许NMI和hard fault异常,其他中断/ 异常都被屏蔽(当前CPU优先级=0)。(stm32的一个中断控制寄存器的位)
跳转至clock_systimer()
/* Access to raw system clock*****************/访问原始系统时钟
/* Direct access to the systemtimer/counter is supported only if (1) the
*system timer counter is available (i.e., we are notconfigured to use
* ahardware periodic timer), and (2) the execution environment has direct
*access to kernel global data
*/
注释翻译:下面2种情况可以直接访问系统时钟/计数器,(1)系统时钟是可得的(这就是说,我们没有配置硬件周期定时),(2)执行环境可以直接访问内核全局数据
extern volatile uint32_t g_system_timer
#define clock_systimer() g_system_timer
这个意思是从其他地方传来内核全局数据g_system_timer赋给work->qtime
关于g_system_timer的地方,只有/****************************************************************************
* Name: clock_timer
*
* Description:
* Thisfunction must be called once every time the real time clock
* interrupt occurs. The interval ofthis clock interrupt must be
* MSEC_PER_TICK
*
****************************************************************************/
void clock_timer(void)
{
/* Increment the per-tick system counter */
}
就是每一次时钟中断g_system_timer++一次,另g_system_timer初始化为0
dq_addlast((FAR dq_entry_t *)work,&wqueue->q);
跳转至dq_addlast()//dq_addlast adds 'node' to the end of 'queue' dq_addlast增加'节点'到'队列'的末端
输入参数就是之前声明的work结构体和wqueue结构体
struct dq_queue_s
{
FAR dq_entry_t *head;
FAR dq_entry_t *tail;
};
kill(wqueue->pid,SIGWORK); /* Wake up theworker thread */唤醒工作进程
跳转至kill()
- /************************************************************************
- * Name: kill
- *
- * Description:
- * Thekill() system call can be used to send any signal to any task.
- *
- * Limitation: Sending of signals to 'process groups' is not
- * supported in NuttX
- *
- * Parameters:
- * pid- The id of the task to receive the signal. The POSIX kill
- * specification encodes process group information as zero and
- * negative pid values. Onlypositive, non-zero values of pid are
- * supported by this implementation.
- * signo - The signal number to send. If signo is zero, no signal is
- * sent, but all error checking is performed.
- *
- * Returned Value:
- * Onsuccess (at least one signal was sent), zero is returned. On
- * error, -1 is returned, and errno is set appropriately:
- *
- * EINVAL An invalid signal was specified.
- * EPERM The process does not havepermission to send the
- * signal to any of the target processes.
- * ESRCH The pid or process groupdoes not exist.
- * ENOSYS Do not support sending signals to process groups.
- *
- * Assumptions:
- *
- ************************************************************************/
- 注释翻译:
- 这个kill()系统调用可用于任何信号发送到任何任务。
- 限制:信号发送到“进程组”在NuttX不支持
- 参数:
- pid -任务的ID用来接收信号。如果pid的值是0或负的,POSIX的kill规范会编码进程组信息
- 只有正的pid才会被执行
- signo -需发送的信号数量。如果signo为0,就是没有信号发送,但是所有错误检查会被执行
- 返回值:
- 0, 成功;-1,发生错误,并且会返回错误码:
- EINVAL 无效的信号指定。
- EPERM 进程没有权限将信号发送到任何目标进程。
- ESRCH PID或进程组不存在。
- ENOSYS 不支持发送的信号来处理组。
- int kill(pid_t pid, int signo)
- {
- #ifdef CONFIG_SCHED_HAVE_PARENT
- FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
- #endif
- siginfo_t info;
- int ret;
- /* We do not support sending signals to process groups */
- if (pid <= 0)
- {
- ret = -ENOSYS;
- goto errout;
- }
- /* Make sure that the signal is valid */
- if (!GOOD_SIGNO(signo))
- {
- ret = -EINVAL;
- goto errout;
- }
- //至此都是保证pid大于0
- /* Keep things stationary through the following */
- sched_lock();
- /* Create the siginfo structure */创建siginfo结构体
- info.si_signo = signo;
- info.si_code = SI_USER;
- info.si_value.sival_ptr = NULL;
- #ifdef CONFIG_SCHED_HAVE_PARENT
- info.si_pid =rtcb->pid;
- info.si_status = OK;
- #endif
- /* Send the signal */
- ret = sig_dispatch(pid, &info);
- sched_unlock();
- if (ret < 0)
- {
- goto errout;
- }
- return OK;
- errout:
- set_errno(-ret);
- return ERROR;
- }
sched_lock();/* Keep thingsstationary through the following */通过这个让事情变得平稳,
sched_unlock();//也就是一个保护作用,里面的内容不让其他程序触碰
重点就是info结构体赋值,赋值的内容就是之前的任务的相关信息,然后就是ret =sig_dispatch(pid,&info);把任务发出去(这一层一层包的- -!)
跳转至sig_dispatch()
- /****************************************************************************
- * Name: sig_dispatch
- *
- * Description:
- * Thisis the front-end for sig_tcbdispatch that should be typically
- * beused to dispatch a signal. If HAVE_GROUP_MEMBERS is defined,
- * thenfunction will follow the group signal delivery algorthrims:
- *
- * Thisfront-end does the following things before calling
- * sig_tcbdispatch.
- *
- * With HAVE_GROUP_MEMBERS defined:
- * -Get the TCB associated with the pid.
- * -If the TCB was found, get the group from the TCB.
- * - If the PID has already exited, lookup thegroup that that was
- * started by this task.
- * -Use the group to pick the TCB to receive the signal
- * -Call sig_tcbdispatch with the TCB
- *
- * With HAVE_GROUP_MEMBERS *not* defined
- * -Get the TCB associated with the pid.
- * -Call sig_tcbdispatch with the TCB
- *
- * Returned Value:
- * Returns 0 (OK) on success or a negated errno value on failure.
- *
- ****************************************************************************/
- 注释翻译:(TCB是线程控制块的意思)
- 这个函数是用作派遣任务
- 如果HAVE_GROUP_MEMBERS被定义了,那么要完成
- 获取与PID相关的TCB
- 如果TCB被发现,请从TCB里获取组
- 如果PID已经退出,查找被此任务开始的组
- 使用组pick TCB来接收信号
- 用TCB来调用sig_tcbdispatch
- 如果HAVE_GROUP_MEMBERS没有被定义,那么
- 获取与PID相关的TCB
- 用TCB来调用sig_tcbdispatch
- int sig_dispatch(pid_t pid, FARsiginfo_t *info)
- {
- #ifdef HAVE_GROUP_MEMBERS
- FAR struct tcb_s *stcb;
- FAR struct task_group_s *group;
- /* Get the TCB associated with the pid */
- stcb = sched_gettcb(pid);//获取一个任务ID,这个函数会返回一个指针指向相应的TCB
- if (stcb)
- {
- /* The task/thread associated with thisPID is still active. Get its
- * task group.
- */
- //与PID相关的任务/线程还是激活的,得到它的任务组
- group = stcb->group;
- }
- else
- {
- /* The task/thread associated with thisPID has exited. In the normal
- * usage model, the PID should correspondto the PID of the task that
- * created the task group. Try looking it up.
- */
- group = group_findbypid(pid);
- }
- /* Didwe locate the group? */
- if (group)
- {
- /* Yes.. call group_signal() to send thesignal to the correct group
- * member.
- */
- return group_signal(group, info);
- }
- else
- {
- return -ESRCH;
- }
- #else
- FAR struct tcb_s *stcb;
- /* Get the TCB associated with the pid */
- stcb = sched_gettcb(pid);
- if (!stcb)
- {
- return -ESRCH;
- }
- return sig_tcbdispatch(stcb, info);
- #endif
- }
ret = sig_dispatch(pid,&info);
快到内核了,东西越来越多,一点点看吧
stcb = sched_gettcb(pid); /* Get the TCB associated with the pid */获取pid相关的TCB
跳转至sched_gettcb()
- /****************************************************************************
- * Name: sched_gettcb
- *
- * Description:
- * Given a task ID, this function will return
- * thea pointer to the corresponding TCB (or NULL if there
- * isno such task ID).
- *
- ****************************************************************************/
- 注释翻译:获取一个任务ID,这个函数会返回一个指针指向相应的TCB
- FAR struct tcb_s*sched_gettcb(pid_t pid)
- {
- FAR struct tcb_s *ret = NULL;
- int hash_ndx;
- /* Verify that the PID is within range */
- if (pid >= 0 )
- {
- /* Get the hash_ndx associated with thepid */
- hash_ndx = PIDHASH(pid);
- /* Verify that the correct TCB was found.*/
- if (pid == g_pidhash[hash_ndx].pid)
- {
- /* Return the TCB associated withthis pid (if any) */
- ret = g_pidhash[hash_ndx].tcb;
- }
- }
- /* Return the TCB. */
- return ret;
- }
- 现在应该到了任务分配层了,应该也算内核了吧,下一层就是物理驱动层
- 细细看来,跳转至hash_ndx =PIDHASH(pid);
-
- group = stcb->group;看看这个group是什么东西
- #ifdef HAVE_TASK_GROUP
- FAR struct task_group_s *group; /* Pointer to shared task group data */
- #endif
- struct task_group_s
- {
- #ifdef HAVE_GROUP_MEMBERS
- struct task_group_s *flink; /* Supports a singly linked list */
- gid_t tg_gid; /* The ID of this task group */
- gid_t tg_pgid; /* The ID of the parent task group */
- #endif
- #if!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SCHED_HAVE_PARENT)
- pid_t tg_task; /* The ID of the task within the group */
- #endif
- uint8_t tg_flags; /* See GROUP_FLAG_* definitions */
- /* Group membership ***********************************************************/
- uint8_t tg_nmembers; /* Number of members in thegroup */
- #ifdef HAVE_GROUP_MEMBERS
- uint8_t tg_mxmembers; /* Number of members inallocation */
- FAR pid_t *tg_members; /* Members of the group */
- #endif
- /* atexit/on_exit support ****************************************************/
- #if defined(CONFIG_SCHED_ATEXIT)&& !defined(CONFIG_SCHED_ONEXIT)
- # ifdefined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
- atexitfunc_t tg_atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
- # else
- atexitfunc_t tg_atexitfunc; /* Called when exit is called. */
- # endif
- #endif
- #ifdef CONFIG_SCHED_ONEXIT
- # ifdefined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1
- onexitfunc_t tg_onexitfunc[CONFIG_SCHED_ONEXIT_MAX];
- FAR void *tg_onexitarg[CONFIG_SCHED_ONEXIT_MAX];
- # else
- onexitfunc_t tg_onexitfunc; /* Called when exit is called. */
- FAR void *tg_onexitarg; /* The argument passed to the function */
- # endif
- #endif
- /* Child exit status **********************************************************/
- #ifdefined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
- FAR struct child_status_s *tg_children; /* Head of a list of childstatus */
- #endif
- /* waitpid support************************************************************/
- /*Simple mechanism used only when there is no support for SIGCHLD */
- #if defined(CONFIG_SCHED_WAITPID)&& !defined(CONFIG_SCHED_HAVE_PARENT)
- sem_t tg_exitsem; /* Support for waitpid */
- int *tg_statloc; /* Location to return exitstatus */
- #endif
- /* Pthreads *******************************************************************/
- #ifndef CONFIG_DISABLE_PTHREAD
- /* Pthreadjoin Info: */
- sem_t tg_joinsem; /* Mutually exclusive access tojoin data */
- FAR struct join_s *tg_joinhead; /* Head of a list of joindata */
- FAR struct join_s *tg_jointail; /* Tail of a list of joindata */
- uint8_t tg_nkeys; /* Number pthread keys allocated */
- #endif
- /* POSIX Signal Control Fields ************************************************/
- #ifndef CONFIG_DISABLE_SIGNALS
- sq_queue_t sigpendingq; /* List of pending signals */
- #endif
- /* Environment variables ******************************************************/
- #ifndef CONFIG_DISABLE_ENVIRON
- size_t tg_envsize; /* Size of environment stringallocation */
- FAR char *tg_envp; /* Allocated environmentstrings */
- #endif
- /* PIC data space and address environments************************************/
- /* Logically the PIC data space belongs here (see struct dspace_s). The
- * current logic needs review: There are differences in the away that the
- * life of the PIC data is managed.
- */
- /* File descriptors ***********************************************************/
- #if CONFIG_NFILE_DESCRIPTORS > 0
- struct filelist tg_filelist; /* Maps file descriptor to file */
- #endif
- /* FILE streams***************************************************************/
- /* In a flat, single-heap build. The stream list is allocated with this
- * structure. But kernel mode witha kernel allocator, it must be separately
- * allocated using a user-space allocator.
- */
- #if CONFIG_NFILE_STREAMS > 0
- #if defined(CONFIG_NUTTX_KERNEL)&& defined(CONFIG_MM_KERNEL_HEAP)
- FAR struct streamlist *tg_streamlist;
- #else
- struct streamlist tg_streamlist; /* Holds C buffered I/O info */
- #endif
- #endif
- /* Sockets ********************************************************************/
- #if CONFIG_NSOCKET_DESCRIPTORS >0
- struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
- #endif
- /* POSIX Named Message Queue Fields *******************************************/
- #ifndef CONFIG_DISABLE_MQUEUE
- sq_queue_t tg_msgdesq; /* List of opened message queues */
- #endif
- };
- 好吧,还以为是个什么结构体呢,好长一段啊!!
这些都是不需要改动的地方,太多太杂了,先放着,重点看光流读取并且如何用于控制的部分,这些部分需要根据实际应用改动。
那么第二条思路开始,去main里面看看
(应该是这样前面看到属于ardupilot/libraries/AP_OpticalFlow文件夹里面的,属于APM的那套,应该有个虚拟层把硬件层抽象了,最后根据具体硬件来选择对应的硬件驱动;接下来要看的属于ardupilot/modules/PX4Firmware/src/drivers/px4flow文件夹里面的,属于PX4原生码)
extern "C" __EXPORT int px4flow_main(int argc, char *argv[]);
- int
- px4flow_main(int argc, char *argv[])
- {
- /*
- * Start/load the driver.
- */
- if (!strcmp(argv[1], "start")) {
- return px4flow::start();
- }
- /*
- * Stop the driver
- */
- if (!strcmp(argv[1], "stop")) {
- px4flow::stop();
- }
- /*
- * Test the driver/device.
- */
- if (!strcmp(argv[1], "test")) {
- px4flow::test();
- }
- /*
- * Reset the driver.
- */
- if (!strcmp(argv[1], "reset")) {
- px4flow::reset();
- }
- /*
- * Print driver information.
- */
- if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
- px4flow::info();
- }
- errx(1, "unrecognized command, try 'start', 'test', 'reset' or 'info'");
- }
跳转至start()
- /**
- * Start the driver.
- */
- int
- start()
- {
- int fd;
-
- /* entry check: */
- if (start_in_progress) {
- warnx("start already in progress");
- return 1;
- }
-
- start_in_progress = true;
-
- if (g_dev != nullptr) {
- start_in_progress = false;
- warnx("already started");
- return 1;
- }
-
- warnx("scanning I2C buses for device..");
-
- int retry_nr = 0;
-
- while (1) {
- const int busses_to_try[] = {
- PX4_I2C_BUS_EXPANSION,
- #ifdef PX4_I2C_BUS_ESC
- PX4_I2C_BUS_ESC,
- #endif
- #ifdef PX4_I2C_BUS_ONBOARD
- PX4_I2C_BUS_ONBOARD,
- #endif
- -1
- };
-
- const int *cur_bus = busses_to_try;
-
- while (*cur_bus != -1) {
- /* create the driver */
- /* warnx("trying bus %d", *cur_bus); */
- g_dev = new PX4FLOW(*cur_bus);
-
- if (g_dev == nullptr) {
- /* this is a fatal error */
- break;
- }
-
- /* init the driver: */
- if (OK == g_dev->init()) {
- /* success! */
- break;
- }
-
- /* destroy it again because it failed. */
- delete g_dev;
- g_dev = nullptr;
-
- /* try next! */
- cur_bus++;
- }
-
- /* check whether we found it: */
- if (*cur_bus != -1) {
-
- /* check for failure: */
- if (g_dev == nullptr) {
- break;
- }
-
- /* set the poll rate to default, starts automatic data collection */
- fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
-
- if (fd < 0) {
- break;
- }
-
- if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MAX) < 0) {
- break;
- }
-
- /* success! */
- start_in_progress = false;
- return 0;
- }
-
- if (retry_nr < START_RETRY_COUNT) {
- /* lets not be too verbose */
- // warnx("PX4FLOW not found on I2C busses. Retrying in %d ms. Giving up in %d retries.", START_RETRY_TIMEOUT, START_RETRY_COUNT - retry_nr);
- usleep(START_RETRY_TIMEOUT * 1000);
- retry_nr++;
-
- } else {
- break;
- }
- }
-
- if (g_dev != nullptr) {
- delete g_dev;
- g_dev = nullptr;
- }
-
- start_in_progress = false;
- return 1;
- }
之后又会深入到底层,暂时先放着
读数据在test()里面
- /**
- * Perform some basic functional tests on the driver;
- * make sure we can collect data from the sensor in polled
- * and automatic modes.
- */
- void
- test()
- {
- struct optical_flow_s report;
- ssize_t sz;
- int ret;
-
- int fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
-
- if (fd < 0) {
- err(1, "%s open failed (try 'px4flow start' if the driver is not running", PX4FLOW0_DEVICE_PATH);
- }
-
-
- /* do a simple demand read */
- sz = read(fd, &report, sizeof(report));
-
- if (sz != sizeof(report)) {
- warnx("immediate read failed");
- }
-
- warnx("single read");
- warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
- warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
- warnx("framecount_integral: %u",
- f_integral.frame_count_since_last_readout);
-
- /* start the sensor polling at 10Hz */
- if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 10)) {
- errx(1, "failed to set 10Hz poll rate");
- }
-
- /* read the sensor 5x and report each value */
- for (unsigned i = 0; i < 10; i++) {
- struct pollfd fds;
-
- /* wait for data to be ready */
- fds.fd = fd;
- fds.events = POLLIN;
- ret = poll(&fds, 1, 2000);
-
- if (ret != 1) {
- errx(1, "timed out waiting for sensor data");
- }
-
- /* now go get it */
- sz = read(fd, &report, sizeof(report));
-
- if (sz != sizeof(report)) {
- err(1, "periodic read failed");
- }
-
- warnx("periodic read %u", i);
-
- warnx("framecount_total: %u", f.frame_count);
- warnx("framecount_integral: %u",
- f_integral.frame_count_since_last_readout);
- warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
- warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
- warnx("gyro_x_rate_integral: %i", f_integral.gyro_x_rate_integral);
- warnx("gyro_y_rate_integral: %i", f_integral.gyro_y_rate_integral);
- warnx("gyro_z_rate_integral: %i", f_integral.gyro_z_rate_integral);
- warnx("integration_timespan [us]: %u", f_integral.integration_timespan);
- warnx("ground_distance: %0.2f m",
- (double) f_integral.ground_distance / 1000);
- warnx("time since last sonar update [us]: %i",
- f_integral.sonar_timestamp);
- warnx("quality integration average : %i", f_integral.qual);
- warnx("quality : %i", f.qual);
-
-
- }
-
- errx(0, "PASS");
- }
看注释能明白sz = read(fd, &report, sizeof(report));是读的操作
ardupilot/modules/PX4Nuttx/nuttx/fs/fs_read.c这个路径应该是系统的路径,已经进了系统吗?系统是什么概念啊?
- ssize_t read(int fd, FAR void *buf, size_t nbytes)
- {
- /* Did we get a valid file descriptor? */
-
- #if CONFIG_NFILE_DESCRIPTORS > 0
- if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
- #endif
- {
- /* No.. If networking is enabled, read() is the same as recv() with
- * the flags parameter set to zero.
- */
-
- #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
- return recv(fd, buf, nbytes, 0);
- #else
- /* No networking... it is a bad descriptor in any event */
-
- set_errno(EBADF);
- return ERROR;
- #endif
- }
-
- /* The descriptor is in a valid range to file descriptor... do the read */
-
- #if CONFIG_NFILE_DESCRIPTORS > 0
- return file_read(fd, buf, nbytes);
- #endif
- }
看注释能明白return file_read(fd, buf, nbytes);是读操作
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
-
- #if CONFIG_NFILE_DESCRIPTORS > 0
- static inline ssize_t file_read(int fd, FAR void *buf, size_t nbytes)
- {
- FAR struct filelist *list;
- int ret = -EBADF;
-
- /* Get the thread-specific file list */
-
- list = sched_getfiles();
- if (!list)
- {
- /* Failed to get the file list */
-
- ret = -EMFILE;
- }
-
- /* Were we given a valid file descriptor? */
-
- else if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
- {
- FAR struct file *this_file = &list->fl_files[fd];
- FAR struct inode *inode = this_file->f_inode;
-
- /* Yes.. Was this file opened for read access? */
-
- if ((this_file->f_oflags & O_RDOK) == 0)
- {
- /* No.. File is not read-able */
-
- ret = -EACCES;
- }
-
- /* Is a driver or mountpoint registered? If so, does it support
- * the read method?
- */
-
- else if (inode && inode->u.i_ops && inode->u.i_ops->read)
- {
- /* Yes.. then let it perform the read. NOTE that for the case
- * of the mountpoint, we depend on the read methods bing
- * identical in signature and position in the operations vtable.
- */
-
- ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes);
- }
- }
-
- /* If an error occurred, set errno and return -1 (ERROR) */
-
- if (ret < 0)
- {
- set_errno(-ret);
- return ERROR;
- }
-
- /* Otherwise, return the number of bytes read */
-
- return ret;
- }
- #endif
跟踪buf可知ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes);是读操作
于是进入了“文件操作”
- struct file_operations
- {
- /* The device driver open method differs from the mountpoint open method */
-
- int (*open)(FAR struct file *filp);
-
- /* The following methods must be identical in signature and position because
- * the struct file_operations and struct mountp_operations are treated like
- * unions.
- */
-
- int (*close)(FAR struct file *filp);
- ssize_t (*read)(FAR struct file *filp, FAR char *buffer, size_t buflen);
- ssize_t (*write)(FAR struct file *filp, FAR const char *buffer, size_t buflen);
- off_t (*seek)(FAR struct file *filp, off_t offset, int whence);
- int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
- #ifndef CONFIG_DISABLE_POLL
- int (*poll)(FAR struct file *filp, struct pollfd *fds, bool setup);
- #endif
-
- /* The two structures need not be common after this point */
- };
怎么继续找下去呢?C++好麻烦啊
看注释This structure is provided by devices when they are registered with the system. It is used to call back to perform device specific operations.
这种结构由设备当它们与系统中注册提供。 它是用来回调来执行设备的特定操作。
就是说首先要注册,再根据具体的设备(控制芯片)选用具体的操作。
ardupilot/modules/PX4Firmware/src/drivers/px4flow.cpp中找到了相应的read函数
- ssize_t
- PX4FLOW::read(struct file *filp, char *buffer, size_t buflen)
- {
- unsigned count = buflen / sizeof(struct optical_flow_s);
- struct optical_flow_s *rbuf = reinterpret_cast<struct optical_flow_s *>(buffer);
- int ret = 0;
-
- /* buffer must be large enough */
- if (count < 1) {
- return -ENOSPC;
- }
-
- /* if automatic measurement is enabled */
- if (_measure_ticks > 0) {
-
- /*
- * While there is space in the caller's buffer, and reports, copy them.
- * Note that we may be pre-empted by the workq thread while we are doing this;
- * we are careful to avoid racing with them.
- */
- while (count--) {
- if (_reports->get(rbuf)) {
- ret += sizeof(*rbuf);
- rbuf++;
- }
- }
-
- /* if there was no data, warn the caller */
- return ret ? ret : -EAGAIN;
- }
-
- /* manual measurement - run one conversion */
- do {
- _reports->flush();
-
- /* trigger a measurement */
- if (OK != measure()) {
- ret = -EIO;
- break;
- }
-
- /* run the collection phase */
- if (OK != collect()) {
- ret = -EIO;
- break;
- }
-
- /* state machine will have generated a report, copy it out */
- if (_reports->get(rbuf)) {
- ret = sizeof(*rbuf);
- }
-
- } while (0);
-
- return ret;
- }
get(rbuf) (read函数中)
- bool
- RingBuffer::get(void *val, size_t val_size)
- {
- if (_tail != _head) {
- unsigned candidate;
- unsigned next;
-
- if ((val_size == 0) || (val_size > _item_size)) {
- val_size = _item_size;
- }
-
- do {
- /* decide which element we think we're going to read */
- candidate = _tail;
-
- /* and what the corresponding next index will be */
- next = _next(candidate);
-
- /* go ahead and read from this index */
- if (val != NULL) {
- memcpy(val, &_buf[candidate * _item_size], val_size);
- }
-
- /* if the tail pointer didn't change, we got our item */
- } while (!__PX4_SBCAP(&_tail, candidate, next));
-
- return true;
-
- } else {
- return false;
- }
- }
字面意思的从缓冲环中得到数据,并存到rbuf中
- int
- PX4FLOW::measure()
- {
- int ret;
-
- /*
- * Send the command to begin a measurement.
- */
- uint8_t cmd = PX4FLOW_REG;
- ret = transfer(&cmd, 1, nullptr, 0);
-
- if (OK != ret) {
- perf_count(_comms_errors);
- DEVICE_DEBUG("i2c::transfer returned %d", ret);
- return ret;
- }
-
- ret = OK;
-
- return ret;
- }
看到 PX4FLOW_REG
- /* PX4FLOW Registers addresses */
- #define PX4FLOW_REG 0x16 ///< Measure Register 22
根据DEVICE_DEBUG("i2c::transfer returned %d", ret);可以得知使用的transfer为i2c::transfer
Ctrl+H全局搜索i2c::transfer
i2c函数很多,综合输入参数和DEVICE_DEBUG("i2c::transfer returned %d", ret);信息,可知上图中的i2c::transfer就是我们要找的函数
- int
- I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
- {
- struct i2c_msg_s msgv[2];
- unsigned msgs;
- int ret;
- unsigned retry_count = 0;
-
- do {
- // DEVICE_DEBUG("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);
-
- msgs = 0;
-
- if (send_len > 0) {
- msgv[msgs].addr = _address;
- msgv[msgs].flags = 0;
- msgv[msgs].buffer = const_cast<uint8_t *>(send);
- msgv[msgs].length = send_len;
- msgs++;
- }
-
- if (recv_len > 0) {
- msgv[msgs].addr = _address;
- msgv[msgs].flags = I2C_M_READ;
- msgv[msgs].buffer = recv;
- msgv[msgs].length = recv_len;
- msgs++;
- }
-
- if (msgs == 0) {
- return -EINVAL;
- }
-
- ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
-
- /* success */
- if (ret == OK) {
- break;
- }
-
- /* if we have already retried once, or we are going to give up, then reset the bus */
- if ((retry_count >= 1) || (retry_count >= _retries)) {
- up_i2creset(_dev);
- }
-
- } while (retry_count++ < _retries);
-
- return ret;
-
- }
struct i2c_msg_s msgv[2];
- struct i2c_msg_s
- {
- uint16_t addr; /* Slave address */
- uint16_t flags; /* See I2C_M_* definitions */
- uint8_t *buffer;
- int length;
- };
ret = I2C_TRANSFER(_dev, &msgv[0], msgs);找I2C_TRANSFER函数
#define I2C_TRANSFER(d,m,c) ((d)->ops->transfer(d,m,c)),找transfer函数
已无能为力了,找不下去了。好吧到此断了,找不到硬件层了,数据还没读回来
继续看collect()
- int
- PX4FLOW::collect()
- {
- int ret = -EIO;
-
- /* read from the sensor */
- uint8_t val[I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE] = { 0 };
-
- perf_begin(_sample_perf);
-
- if (PX4FLOW_REG == 0x00) {
- ret = transfer(nullptr, 0, &val[0], I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE);
- }
-
- if (PX4FLOW_REG == 0x16) {
- ret = transfer(nullptr, 0, &val[0], I2C_INTEGRAL_FRAME_SIZE);
- }
-
- if (ret < 0) {
- DEVICE_DEBUG("error reading from sensor: %d", ret);
- perf_count(_comms_errors);
- perf_end(_sample_perf);
- return ret;
- }
-
- if (PX4FLOW_REG == 0) {
- memcpy(&f, val, I2C_FRAME_SIZE);
- memcpy(&f_integral, &(val[I2C_FRAME_SIZE]), I2C_INTEGRAL_FRAME_SIZE);
- }
-
- if (PX4FLOW_REG == 0x16) {
- memcpy(&f_integral, val, I2C_INTEGRAL_FRAME_SIZE);
- }
-
-
- struct optical_flow_s report;
-
- report.timestamp = hrt_absolute_time();
-
- report.pixel_flow_x_integral = static_cast<float>(f_integral.pixel_flow_x_integral) / 10000.0f;//convert to radians
-
- report.pixel_flow_y_integral = static_cast<float>(f_integral.pixel_flow_y_integral) / 10000.0f;//convert to radians
-
- report.frame_count_since_last_readout = f_integral.frame_count_since_last_readout;
-
- report.ground_distance_m = static_cast<float>(f_integral.ground_distance) / 1000.0f;//convert to meters
-
- report.quality = f_integral.qual; //0:bad ; 255 max quality
-
- report.gyro_x_rate_integral = static_cast<float>(f_integral.gyro_x_rate_integral) / 10000.0f; //convert to radians
-
- report.gyro_y_rate_integral = static_cast<float>(f_integral.gyro_y_rate_integral) / 10000.0f; //convert to radians
-
- report.gyro_z_rate_integral = static_cast<float>(f_integral.gyro_z_rate_integral) / 10000.0f; //convert to radians
-
- report.integration_timespan = f_integral.integration_timespan; //microseconds
-
- report.time_since_last_sonar_update = f_integral.sonar_timestamp;//microseconds
-
- report.gyro_temperature = f_integral.gyro_temperature;//Temperature * 100 in centi-degrees Celsius
-
- report.sensor_id = 0;
-
- /* rotate measurements according to parameter */根据参数测量旋转
- float zeroval = 0.0f;
-
- rotate_3f(_sensor_rotation, report.pixel_flow_x_integral, report.pixel_flow_y_integral, zeroval);
-
- rotate_3f(_sensor_rotation, report.gyro_x_rate_integral, report.gyro_y_rate_integral, report.gyro_z_rate_integral);
-
- if (_px4flow_topic == nullptr) {
- _px4flow_topic = orb_advertise(ORB_ID(optical_flow), &report);
-
- } else {
- /* publish it */
- orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
- }
-
- /* publish to the distance_sensor topic as well */将distance_sensor主题发布出去
- struct distance_sensor_s distance_report;
- distance_report.timestamp = report.timestamp;
- distance_report.min_distance = PX4FLOW_MIN_DISTANCE;
- distance_report.max_distance = PX4FLOW_MAX_DISTANCE;
- distance_report.current_distance = report.ground_distance_m;
- distance_report.covariance = 0.0f;
- distance_report.type = distance_sensor_s::MAV_DISTANCE_SENSOR_ULTRASOUND;
- /* TODO: the ID needs to be properly set */
- distance_report.id = 0;
- distance_report.orientation = 8;
-
- orb_publish(ORB_ID(distance_sensor), _distance_sensor_topic, &distance_report);
-
- /* post a report to the ring */发布到环的报告
- if (_reports->force(&report)) {
- perf_count(_buffer_overflows);
- }
-
- /* notify anyone waiting for data */通知别人等待数据
- poll_notify(POLLIN);
-
- ret = OK;
-
- perf_end(_sample_perf);
- return ret;
- }
注意看
- if (PX4FLOW_REG == 0x00) {
- ret = transfer(nullptr, 0, &val[0], I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE);
- }
-
- if (PX4FLOW_REG == 0x16) {
- ret = transfer(nullptr, 0, &val[0], I2C_INTEGRAL_FRAME_SIZE);
- }
这个是把数据读回
意思就是measure()是写指令操作,collect()是读传回来的数据,有一点奇怪PX4FLOW_REG什么时候会赋值为0x00
memcpy(&f, val, I2C_FRAME_SIZE);
memcpy(&f_integral, &(val[I2C_FRAME_SIZE]), I2C_INTEGRAL_FRAME_SIZE);
这2句是讲读取的数据存到f和f_integral结构体中
- struct i2c_frame f;
- struct i2c_integral_frame f_integral;
- typedef struct i2c_frame {
- uint16_t frame_count;
- int16_t pixel_flow_x_sum;
- int16_t pixel_flow_y_sum;
- int16_t flow_comp_m_x;
- int16_t flow_comp_m_y;
- int16_t qual;
- int16_t gyro_x_rate;
- int16_t gyro_y_rate;
- int16_t gyro_z_rate;
- uint8_t gyro_range;
- uint8_t sonar_timestamp;
- int16_t ground_distance;
- } i2c_frame;
-
- #define I2C_FRAME_SIZE (sizeof(i2c_frame))
-
-
- typedef struct i2c_integral_frame {
- uint16_t frame_count_since_last_readout;
- int16_t pixel_flow_x_integral;
- int16_t pixel_flow_y_integral;
- int16_t gyro_x_rate_integral;
- int16_t gyro_y_rate_integral;
- int16_t gyro_z_rate_integral;
- uint32_t integration_timespan;
- uint32_t sonar_timestamp;
- uint16_t ground_distance;
- int16_t gyro_temperature;
- uint8_t qual;
- } i2c_integral_frame;
接着optical_flow_s report用来存储处理后的数据,之后控制用的数据就是来自这里
再换个地方,看read数据之后如何用于控制的
全局搜索ORB_ID(optical_flow),看哪个地方订阅了光流消息
有2个地方orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);,再根据rc.mc_apps
默认采用的是
姿态估计 Attitude_estimator_q
位置估计 position_estimator_inav位置控制 mc_pos_control
EKF2暂时先不考虑
接下来要看position_estimator_inav _main.cpp(从常识也知道光流是用来获取空间xy方向的位置信息,所以之后肯定是用于位置估计上)
那么先宏观上分析下这个 position_estimator_inav _main.cpp- #include <px4_posix.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <fcntl.h>
- #include <string.h>
- #include <px4_config.h>
- #include <math.h>
- #include <float.h>
- #include <uORB/uORB.h>
- #include <uORB/topics/parameter_update.h>
- #include <uORB/topics/actuator_controls.h>
- #include <uORB/topics/actuator_controls_0.h>
- #include <uORB/topics/actuator_controls_1.h>
- #include <uORB/topics/actuator_controls_2.h>
- #include <uORB/topics/actuator_controls_3.h>
- #include <uORB/topics/actuator_armed.h>
- #include <uORB/topics/sensor_combined.h>
- #include <uORB/topics/vehicle_attitude.h>
- #include <uORB/topics/vehicle_local_position.h>
- #include <uORB/topics/vehicle_global_position.h>
- #include <uORB/topics/vehicle_gps_position.h>
- #include <uORB/topics/vision_position_estimate.h>
- #include <uORB/topics/att_pos_mocap.h>
- #include <uORB/topics/optical_flow.h>
- #include <uORB/topics/distance_sensor.h>
- #include <poll.h>
- #include <systemlib/err.h>
- #include <systemlib/mavlink_log.h>
- #include <geo/geo.h>
- #include <systemlib/systemlib.h>
- #include <drivers/drv_hrt.h>
- #include <platforms/px4_defines.h>
-
- #include <terrain_estimation/terrain_estimator.h>
- #include "position_estimator_inav_params.h"
- #include "inertial_filter.h"
添加了这么多头文件,大概知道会用于控制、传感器融合、位置定位、gps也用上了、光流、惯性导航滤波等
extern "C" __EXPORT int position_estimator_inav_main(int argc, char *argv[]);
开始工作了,进入
main
这里顺便猜想下,每个这样的功能函数或者文件,都有extern "C" __EXPORT int position_estimator_inav_main(int argc, char *argv[]);,是不是在哪个地方直接调用了,所以启动了该项功能,是不是在rcS中呢?估计有个总的流程,分别调用启动这些功能“函数”
- /****************************************************************************
- * main
- ****************************************************************************/
- int position_estimator_inav_thread_main(int argc, char *argv[])
- {
- /**************************类似于初始化或者声明******************************/
- orb_advert_t mavlink_log_pub = nullptr;
-
- float x_est[2] = { 0.0f, 0.0f }; // pos, vel
- float y_est[2] = { 0.0f, 0.0f }; // pos, vel
- float z_est[2] = { 0.0f, 0.0f }; // pos, vel
-
- float est_buf[EST_BUF_SIZE][3][2]; // estimated position buffer
- float R_buf[EST_BUF_SIZE][3][3]; // rotation matrix buffer
- float R_gps[3][3]; // rotation matrix for GPS correction moment
- memset(est_buf, 0, sizeof(est_buf));
- memset(R_buf, 0, sizeof(R_buf));
- memset(R_gps, 0, sizeof(R_gps));
- int buf_ptr = 0;
-
- static const float min_eph_epv = 2.0f; // min EPH/EPV, used for weight calculation
- static const float max_eph_epv = 20.0f; // max EPH/EPV acceptable for estimation
-
- float eph = max_eph_epv;
- float epv = 1.0f;
-
- float eph_flow = 1.0f;
-
- float eph_vision = 0.2f;
- float epv_vision = 0.2f;
-
- float eph_mocap = 0.05f;
- float epv_mocap = 0.05f;
-
- float x_est_prev[2], y_est_prev[2], z_est_prev[2];
- memset(x_est_prev, 0, sizeof(x_est_prev));
- memset(y_est_prev, 0, sizeof(y_est_prev));
- memset(z_est_prev, 0, sizeof(z_est_prev));
-
- int baro_init_cnt = 0;
- int baro_init_num = 200;
- float baro_offset = 0.0f; // baro offset for reference altitude, initialized on start, then adjusted
-
- hrt_abstime accel_timestamp = 0;
- hrt_abstime baro_timestamp = 0;
-
- bool ref_inited = false;
- hrt_abstime ref_init_start = 0;
- const hrt_abstime ref_init_delay = 1000000; // wait for 1s after 3D fix
- struct map_projection_reference_s ref;
- memset(&ref, 0, sizeof(ref));
-
- uint16_t accel_updates = 0;
- uint16_t baro_updates = 0;
- uint16_t gps_updates = 0;
- uint16_t attitude_updates = 0;
- uint16_t flow_updates = 0;
- uint16_t vision_updates = 0;
- uint16_t mocap_updates = 0;
-
- hrt_abstime updates_counter_start = hrt_absolute_time();
- hrt_abstime pub_last = hrt_absolute_time();
-
- hrt_abstime t_prev = 0;
-
- /* store error when sensor updates, but correct on each time step to avoid jumps in estimated value */
- float acc[] = { 0.0f, 0.0f, 0.0f }; // N E D
- float acc_bias[] = { 0.0f, 0.0f, 0.0f }; // body frame
- float corr_baro = 0.0f; // D
- float corr_gps[3][2] = {
- { 0.0f, 0.0f }, // N (pos, vel)
- { 0.0f, 0.0f }, // E (pos, vel)
- { 0.0f, 0.0f }, // D (pos, vel)
- };
- float w_gps_xy = 1.0f;
- float w_gps_z = 1.0f;
-
- float corr_vision[3][2] = {
- { 0.0f, 0.0f }, // N (pos, vel)
- { 0.0f, 0.0f }, // E (pos, vel)
- { 0.0f, 0.0f }, // D (pos, vel)
- };
-
- float corr_mocap[3][1] = {
- { 0.0f }, // N (pos)
- { 0.0f }, // E (pos)
- { 0.0f }, // D (pos)
- };
- const int mocap_heading = 2;
-
- float dist_ground = 0.0f; //variables for lidar altitude estimation
- float corr_lidar = 0.0f;
- float lidar_offset = 0.0f;
- int lidar_offset_count = 0;
- bool lidar_first = true;
- bool use_lidar = false;
- bool use_lidar_prev = false;
-
- float corr_flow[] = { 0.0f, 0.0f }; // N E
- float w_flow = 0.0f;
-
- hrt_abstime lidar_time = 0; // time of last lidar measurement (not filtered)
- hrt_abstime lidar_valid_time = 0; // time of last lidar measurement used for correction (filtered)
-
- int n_flow = 0;
- float gyro_offset_filtered[] = { 0.0f, 0.0f, 0.0f };
- float flow_gyrospeed[] = { 0.0f, 0.0f, 0.0f };
- float flow_gyrospeed_filtered[] = { 0.0f, 0.0f, 0.0f };
- float att_gyrospeed_filtered[] = { 0.0f, 0.0f, 0.0f };
- float yaw_comp[] = { 0.0f, 0.0f };
- hrt_abstime flow_time = 0;
- float flow_min_dist = 0.2f;
-
- bool gps_valid = false; // GPS is valid
- bool lidar_valid = false; // lidar is valid
- bool flow_valid = false; // flow is valid
- bool flow_accurate = false; // flow should be accurate (this flag not updated if flow_valid == false)
- bool vision_valid = false; // vision is valid
- bool mocap_valid = false; // mocap is valid
-
- /* declare and safely initialize all structs */
- struct actuator_controls_s actuator;
- memset(&actuator, 0, sizeof(actuator));
- struct actuator_armed_s armed;
- memset(&armed, 0, sizeof(armed));
- struct sensor_combined_s sensor;
- memset(&sensor, 0, sizeof(sensor));
- struct vehicle_gps_position_s gps;
- memset(&gps, 0, sizeof(gps));
- struct vehicle_attitude_s att;
- memset(&att, 0, sizeof(att));
- struct vehicle_local_position_s local_pos;
- memset(&local_pos, 0, sizeof(local_pos));
- struct optical_flow_s flow;
- memset(&flow, 0, sizeof(flow));
- struct vision_position_estimate_s vision;
- memset(&vision, 0, sizeof(vision));
- struct att_pos_mocap_s mocap;
- memset(&mocap, 0, sizeof(mocap));
- struct vehicle_global_position_s global_pos;
- memset(&global_pos, 0, sizeof(global_pos));
- struct distance_sensor_s lidar;
- memset(&lidar, 0, sizeof(lidar));
- struct vehicle_rates_setpoint_s rates_setpoint;
- memset(&rates_setpoint, 0, sizeof(rates_setpoint));
- /**************************订阅各种信息******************************/
- /* subscribe */
- int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
- int actuator_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
- int armed_sub = orb_subscribe(ORB_ID(actuator_armed));
- int sensor_combined_sub = orb_subscribe(ORB_ID(sensor_combined));
- int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
- int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
- int vehicle_gps_position_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
- int vision_position_estimate_sub = orb_subscribe(ORB_ID(vision_position_estimate));
- int att_pos_mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
- int distance_sensor_sub = orb_subscribe(ORB_ID(distance_sensor));
- int vehicle_rate_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
- /**************************发布位置信息******************************/
- /* advertise */
- orb_advert_t vehicle_local_position_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
- orb_advert_t vehicle_global_position_pub = NULL;
- /**************************类似于初始化params******************************/
- struct position_estimator_inav_params params;
- memset(¶ms, 0, sizeof(params));
- struct position_estimator_inav_param_handles pos_inav_param_handles;
- /* initialize parameter handles */
- inav_parameters_init(&pos_inav_param_handles);
-
- /* first parameters read at start up */
- struct parameter_update_s param_update;
- orb_copy(ORB_ID(parameter_update), parameter_update_sub,
- ¶m_update); /* read from param topic to clear updated flag */
- /* first parameters update */
- inav_parameters_update(&pos_inav_param_handles, ¶ms);
- /**************************sensor_combined******************************/
- px4_pollfd_struct_t fds_init[1] = {};
- fds_init[0].fd = sensor_combined_sub;
- fds_init[0].events = POLLIN;
- 气压计///
- /* wait for initial baro value */
- bool wait_baro = true;
- TerrainEstimator *terrain_estimator = new TerrainEstimator();
-
- thread_running = true;
- hrt_abstime baro_wait_for_sample_time = hrt_absolute_time();
-
- while (wait_baro && !thread_should_exit) {
- int ret = px4_poll(&fds_init[0], 1, 1000);
-
- if (ret < 0) {
- /* poll error */
- mavlink_log_info(&mavlink_log_pub, "[inav] poll error on init");
- } else if (hrt_absolute_time() - baro_wait_for_sample_time > MAX_WAIT_FOR_BARO_SAMPLE) {
- wait_baro = false;
- mavlink_log_info(&mavlink_log_pub, "[inav] timed out waiting for a baro sample");
- }
- else if (ret > 0) {
- if (fds_init[0].revents & POLLIN) {
- orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
-
- if (wait_baro && sensor.baro_timestamp[0] != baro_timestamp) {
- baro_timestamp = sensor.baro_timestamp[0];
- baro_wait_for_sample_time = hrt_absolute_time();
-
- /* mean calculation over several measurements */
- if (baro_init_cnt < baro_init_num) {
- if (PX4_ISFINITE(sensor.baro_alt_meter[0])) {
- baro_offset += sensor.baro_alt_meter[0];
- baro_init_cnt++;
- }
-
- } else {
- wait_baro = false;
- baro_offset /= (float) baro_init_cnt;
- local_pos.z_valid = true;
- local_pos.v_z_valid = true;
- }
- }
- }
-
- } else {
- PX4_WARN("INAV poll timeout");
- }
- }
- /**************************主循环******************************/
- /* main loop */
- px4_pollfd_struct_t fds[1];
- fds[0].fd = vehicle_attitude_sub;
- fds[0].events = POLLIN;
- 判断是否应该退出该线程///
- while (!thread_should_exit) { //这个判断条件经常使用,到处都用过类似的
- int ret = px4_poll(fds, 1, 20); // wait maximal 20 ms = 50 Hz minimum rate
- hrt_abstime t = hrt_absolute_time();
-
- if (ret < 0) {
- /* poll error */
- mavlink_log_info(&mavlink_log_pub, "[inav] poll error on init");
- continue;
-
- } else if (ret > 0) {
- /* act on attitude updates */
-
- /* vehicle attitude */
- orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);//姿态跟新
- attitude_updates++;
-
- bool updated;
-
- /* parameter update */
- orb_check(parameter_update_sub, &updated);
-
- if (updated) {
- struct parameter_update_s update;
- orb_copy(ORB_ID(parameter_update), parameter_update_sub, &update);//parameter跟新
- inav_parameters_update(&pos_inav_param_handles, ¶ms);
- }
-
- /* actuator */
- orb_check(actuator_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_sub, &actuator);//执行器数据跟新(这里并不是pwm)
- }
-
- /* armed */
- orb_check(armed_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);//解锁数据跟新
- }
-
- /* sensor combined */
- orb_check(sensor_combined_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);//传感器融合数据跟新
-
- if (sensor.accelerometer_timestamp[0] != accel_timestamp) {
- if (att.R_valid) {
- /* correct accel bias */
- sensor.accelerometer_m_s2[0] -= acc_bias[0];
- sensor.accelerometer_m_s2[1] -= acc_bias[1];
- sensor.accelerometer_m_s2[2] -= acc_bias[2];
-
- /* transform acceleration vector from body frame to NED frame */
- for (int i = 0; i < 3; i++) {
- acc[i] = 0.0f;
-
- for (int j = 0; j < 3; j++) {
- acc[i] += PX4_R(att.R, i, j) * sensor.accelerometer_m_s2[j];
- }
- }
-
- acc[2] += CONSTANTS_ONE_G;
-
- } else {
- memset(acc, 0, sizeof(acc));
- }
-
- accel_timestamp = sensor.accelerometer_timestamp[0];
- accel_updates++;
- }
-
- if (sensor.baro_timestamp[0] != baro_timestamp) {
- corr_baro = baro_offset - sensor.baro_alt_meter[0] - z_est[0];
- baro_timestamp = sensor.baro_timestamp[0];
- baro_updates++;
- }
- }
-
-
- /* lidar alt estimation */
- orb_check(distance_sensor_sub, &updated);
-
- /* update lidar separately, needed by terrain estimator */
- if (updated) {
- orb_copy(ORB_ID(distance_sensor), distance_sensor_sub, &lidar);//高度数据跟新
- lidar.current_distance += params.lidar_calibration_offset;
- }
-
- if (updated) { //check if altitude estimation for lidar is enabled and new sensor data
-
- if (params.enable_lidar_alt_est && lidar.current_distance > lidar.min_distance && lidar.current_distance < lidar.max_distance
- && (PX4_R(att.R, 2, 2) > 0.7f)) {
-
- if (!use_lidar_prev && use_lidar) {
- lidar_first = true;
- }
-
- use_lidar_prev = use_lidar;
-
- lidar_time = t;
- dist_ground = lidar.current_distance * PX4_R(att.R, 2, 2); //vertical distance
-
- if (lidar_first) {
- lidar_first = false;
- lidar_offset = dist_ground + z_est[0];
- mavlink_log_info(&mavlink_log_pub, "[inav] LIDAR: new ground offset");
- warnx("[inav] LIDAR: new ground offset");
- }
-
- corr_lidar = lidar_offset - dist_ground - z_est[0];
-
- if (fabsf(corr_lidar) > params.lidar_err) { //check for spike
- corr_lidar = 0;
- lidar_valid = false;
- lidar_offset_count++;
-
- if (lidar_offset_count > 3) { //if consecutive bigger/smaller measurements -> new ground offset -> reinit
- lidar_first = true;
- lidar_offset_count = 0;
- }
-
- } else {
- corr_lidar = lidar_offset - dist_ground - z_est[0];
- lidar_valid = true;
- lidar_offset_count = 0;
- lidar_valid_time = t;
- }
- } else {
- lidar_valid = false;
- }
- }
- /**************************************这里就是光流的处理*********************************/
- /* optical flow */
- orb_check(optical_flow_sub, &updated);
-
- if (updated && lidar_valid) {
- orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);//光流数据跟新
-
- flow_time = t;
- float flow_q = flow.quality / 255.0f;
- float dist_bottom = lidar.current_distance;//高度信息
-
- if (dist_bottom > flow_min_dist && flow_q > params.flow_q_min && PX4_R(att.R, 2, 2) > 0.7f) {
- /* distance to surface */
- //float flow_dist = dist_bottom / PX4_R(att.R, 2, 2); //use this if using sonar
- float flow_dist = dist_bottom; //use this if using lidar
-
- /* check if flow if too large for accurate measurements */
- /* calculate estimated velocity in body frame */
- float body_v_est[2] = { 0.0f, 0.0f };
-
- for (int i = 0; i < 2; i++) {
- body_v_est[i] = PX4_R(att.R, 0, i) * x_est[1] + PX4_R(att.R, 1, i) * y_est[1] + PX4_R(att.R, 2, i) * z_est[1];
- }
-
- /* set this flag if flow should be accurate according to current velocity and attitude rate estimate */
- flow_accurate = fabsf(body_v_est[1] / flow_dist - att.rollspeed) < max_flow &&
- fabsf(body_v_est[0] / flow_dist + att.pitchspeed) < max_flow;
-
- /*calculate offset of flow-gyro using already calibrated gyro from autopilot*/
- flow_gyrospeed[0] = flow.gyro_x_rate_integral / (float)flow.integration_timespan * 1000000.0f;
- flow_gyrospeed[1] = flow.gyro_y_rate_integral / (float)flow.integration_timespan * 1000000.0f;
- flow_gyrospeed[2] = flow.gyro_z_rate_integral / (float)flow.integration_timespan * 1000000.0f;
-
- //moving average
- if (n_flow >= 100) {
- gyro_offset_filtered[0] = flow_gyrospeed_filtered[0] - att_gyrospeed_filtered[0];
- gyro_offset_filtered[1] = flow_gyrospeed_filtered[1] - att_gyrospeed_filtered[1];
- gyro_offset_filtered[2] = flow_gyrospeed_filtered[2] - att_gyrospeed_filtered[2];
- n_flow = 0;
- flow_gyrospeed_filtered[0] = 0.0f;
- flow_gyrospeed_filtered[1] = 0.0f;
- flow_gyrospeed_filtered[2] = 0.0f;
- att_gyrospeed_filtered[0] = 0.0f;
- att_gyrospeed_filtered[1] = 0.0f;
- att_gyrospeed_filtered[2] = 0.0f;
-
- } else {
- flow_gyrospeed_filtered[0] = (flow_gyrospeed[0] + n_flow * flow_gyrospeed_filtered[0]) / (n_flow + 1);
- flow_gyrospeed_filtered[1] = (flow_gyrospeed[1] + n_flow * flow_gyrospeed_filtered[1]) / (n_flow + 1);
- flow_gyrospeed_filtered[2] = (flow_gyrospeed[2] + n_flow * flow_gyrospeed_filtered[2]) / (n_flow + 1);
- att_gyrospeed_filtered[0] = (att.pitchspeed + n_flow * att_gyrospeed_filtered[0]) / (n_flow + 1);
- att_gyrospeed_filtered[1] = (att.rollspeed + n_flow * att_gyrospeed_filtered[1]) / (n_flow + 1);
- att_gyrospeed_filtered[2] = (att.yawspeed + n_flow * att_gyrospeed_filtered[2]) / (n_flow + 1);
- n_flow++;
- }
-
-
- /*yaw compensation (flow sensor is not in center of rotation) -> params in QGC*/
- yaw_comp[0] = - params.flow_module_offset_y * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
- yaw_comp[1] = params.flow_module_offset_x * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
-
- /* convert raw flow to angular flow (rad/s) */
- float flow_ang[2];
-
- /* check for vehicle rates setpoint - it below threshold -> dont subtract -> better hover */
- orb_check(vehicle_rate_sp_sub, &updated);
- if (updated)
- orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
-
- double rate_threshold = 0.15f;
-
- if (fabs(rates_setpoint.pitch) < rate_threshold) {
- //warnx("[inav] test ohne comp");
- flow_ang[0] = (flow.pixel_flow_x_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)
- }
- else {
- //warnx("[inav] test mit comp");
- //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
- flow_ang[0] = ((flow.pixel_flow_x_integral - flow.gyro_x_rate_integral) / (float)flow.integration_timespan * 1000000.0f
- + gyro_offset_filtered[0]) * params.flow_k;//for now the flow has to be scaled (to small)
- }
-
- if (fabs(rates_setpoint.roll) < rate_threshold) {
- flow_ang[1] = (flow.pixel_flow_y_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)
- }
- else {
- //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
- flow_ang[1] = ((flow.pixel_flow_y_integral - flow.gyro_y_rate_integral) / (float)flow.integration_timespan * 1000000.0f
- + gyro_offset_filtered[1]) * params.flow_k;//for now the flow has to be scaled (to small)
- }
-
- /* flow measurements vector */
- float flow_m[3];
- if (fabs(rates_setpoint.yaw) < rate_threshold) {
- flow_m[0] = -flow_ang[0] * flow_dist;
- flow_m[1] = -flow_ang[1] * flow_dist;
- } else {
- flow_m[0] = -flow_ang[0] * flow_dist - yaw_comp[0] * params.flow_k;
- flow_m[1] = -flow_ang[1] * flow_dist - yaw_comp[1] * params.flow_k;
- }
- flow_m[2] = z_est[1];
-
- /* velocity in NED */
- float flow_v[2] = { 0.0f, 0.0f };
-
- /* project measurements vector to NED basis, skip Z component */
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 3; j++) {
- flow_v[i] += PX4_R(att.R, i, j) * flow_m[j];
- }
- }
-
- /* velocity correction */
- corr_flow[0] = flow_v[0] - x_est[1];
- corr_flow[1] = flow_v[1] - y_est[1];
- /* adjust correction weight */
- float flow_q_weight = (flow_q - params.flow_q_min) / (1.0f - params.flow_q_min);
- w_flow = PX4_R(att.R, 2, 2) * flow_q_weight / fmaxf(1.0f, flow_dist);
-
-
- /* if flow is not accurate, reduce weight for it */
- // TODO make this more fuzzy
- if (!flow_accurate) {
- w_flow *= 0.05f;
- }
-
- /* under ideal conditions, on 1m distance assume EPH = 10cm */
- eph_flow = 0.1f / w_flow;
-
- flow_valid = true;
-
- } else {
- w_flow = 0.0f;
- flow_valid = false;
- }
-
- flow_updates++;
- }
- /**************************************光流结束*********************************/
- //视觉的处理
- /* check no vision circuit breaker is set */
- if (params.no_vision != CBRK_NO_VISION_KEY) {
- /* vehicle vision position */
- orb_check(vision_position_estimate_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vision_position_estimate), vision_position_estimate_sub, &vision);
-
- static float last_vision_x = 0.0f;
- static float last_vision_y = 0.0f;
- static float last_vision_z = 0.0f;
-
- /* reset position estimate on first vision update */
- if (!vision_valid) {
- x_est[0] = vision.x;
- x_est[1] = vision.vx;
- y_est[0] = vision.y;
- y_est[1] = vision.vy;
-
- /* only reset the z estimate if the z weight parameter is not zero */
- if (params.w_z_vision_p > MIN_VALID_W) {
- z_est[0] = vision.z;
- z_est[1] = vision.vz;
- }
-
- vision_valid = true;
-
- last_vision_x = vision.x;
- last_vision_y = vision.y;
- last_vision_z = vision.z;
-
- warnx("VISION estimate valid");
- mavlink_log_info(&mavlink_log_pub, "[inav] VISION estimate valid");
- }
-
- /* calculate correction for position */
- corr_vision[0][0] = vision.x - x_est[0];
- corr_vision[1][0] = vision.y - y_est[0];
- corr_vision[2][0] = vision.z - z_est[0];
-
- static hrt_abstime last_vision_time = 0;
-
- float vision_dt = (vision.timestamp_boot - last_vision_time) / 1e6f;
- last_vision_time = vision.timestamp_boot;
-
- if (vision_dt > 0.000001f && vision_dt < 0.2f) {
- vision.vx = (vision.x - last_vision_x) / vision_dt;
- vision.vy = (vision.y - last_vision_y) / vision_dt;
- vision.vz = (vision.z - last_vision_z) / vision_dt;
-
- last_vision_x = vision.x;
- last_vision_y = vision.y;
- last_vision_z = vision.z;
-
- /* calculate correction for velocity */
- corr_vision[0][1] = vision.vx - x_est[1];
- corr_vision[1][1] = vision.vy - y_est[1];
- corr_vision[2][1] = vision.vz - z_est[1];
-
- } else {
- /* assume zero motion */
- corr_vision[0][1] = 0.0f - x_est[1];
- corr_vision[1][1] = 0.0f - y_est[1];
- corr_vision[2][1] = 0.0f - z_est[1];
- }
-
- vision_updates++;
- }
- }
- ///mocap数据处理///
- /* vehicle mocap position */
- orb_check(att_pos_mocap_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(att_pos_mocap), att_pos_mocap_sub, &mocap);
-
- if (!params.disable_mocap) {
- /* reset position estimate on first mocap update */
- if (!mocap_valid) {
- x_est[0] = mocap.x;
- y_est[0] = mocap.y;
- z_est[0] = mocap.z;
-
- mocap_valid = true;
-
- warnx("MOCAP data valid");
- mavlink_log_info(&mavlink_log_pub, "[inav] MOCAP data valid");
- }
-
- /* calculate correction for position */
- corr_mocap[0][0] = mocap.x - x_est[0];
- corr_mocap[1][0] = mocap.y - y_est[0];
- corr_mocap[2][0] = mocap.z - z_est[0];
-
- mocap_updates++;
- }
- }
- //GPS数据处理///
- /* vehicle GPS position */
- orb_check(vehicle_gps_position_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);
-
- bool reset_est = false;
-
- /* hysteresis for GPS quality */
- if (gps_valid) {
- if (gps.eph > max_eph_epv || gps.epv > max_eph_epv || gps.fix_type < 3) {
- gps_valid = false;
- mavlink_log_info(&mavlink_log_pub, "[inav] GPS signal lost");
- warnx("[inav] GPS signal lost");
- }
-
- } else {
- if (gps.eph < max_eph_epv * 0.7f && gps.epv < max_eph_epv * 0.7f && gps.fix_type >= 3) {
- gps_valid = true;
- reset_est = true;
- mavlink_log_info(&mavlink_log_pub, "[inav] GPS signal found");
- warnx("[inav] GPS signal found");
- }
- }
-
- if (gps_valid) {
- double lat = gps.lat * 1e-7;
- double lon = gps.lon * 1e-7;
- float alt = gps.alt * 1e-3;
-
- /* initialize reference position if needed */
- if (!ref_inited) {
- if (ref_init_start == 0) {
- ref_init_start = t;
-
- } else if (t > ref_init_start + ref_init_delay) {
- ref_inited = true;
-
- /* set position estimate to (0, 0, 0), use GPS velocity for XY */
- x_est[0] = 0.0f;
- x_est[1] = gps.vel_n_m_s;
- y_est[0] = 0.0f;
- y_est[1] = gps.vel_e_m_s;
-
- local_pos.ref_lat = lat;
- local_pos.ref_lon = lon;
- local_pos.ref_alt = alt + z_est[0];
- local_pos.ref_timestamp = t;
-
- /* initialize projection */
- map_projection_init(&ref, lat, lon);
- // XXX replace this print
- warnx("init ref: lat=%.7f, lon=%.7f, alt=%8.4f", (double)lat, (double)lon, (double)alt);
- mavlink_log_info(&mavlink_log_pub, "[inav] init ref: %.7f, %.7f, %8.4f", (double)lat, (double)lon, (double)alt);
- }
- }
-
- if (ref_inited) {
- /* project GPS lat lon to plane */
- float gps_proj[2];
- map_projection_project(&ref, lat, lon, &(gps_proj[0]), &(gps_proj[1]));
-
- /* reset position estimate when GPS becomes good */
- if (reset_est) {
- x_est[0] = gps_proj[0];
- x_est[1] = gps.vel_n_m_s;
- y_est[0] = gps_proj[1];
- y_est[1] = gps.vel_e_m_s;
- }
-
- /* calculate index of estimated values in buffer */
- int est_i = buf_ptr - 1 - min(EST_BUF_SIZE - 1, max(0, (int)(params.delay_gps * 1000000.0f / PUB_INTERVAL)));
-
- if (est_i < 0) {
- est_i += EST_BUF_SIZE;
- }
-
- /* calculate correction for position */
- corr_gps[0][0] = gps_proj[0] - est_buf[est_i][0][0];
- corr_gps[1][0] = gps_proj[1] - est_buf[est_i][1][0];
- corr_gps[2][0] = local_pos.ref_alt - alt - est_buf[est_i][2][0];
-
- /* calculate correction for velocity */
- if (gps.vel_ned_valid) {
- corr_gps[0][1] = gps.vel_n_m_s - est_buf[est_i][0][1];
- corr_gps[1][1] = gps.vel_e_m_s - est_buf[est_i][1][1];
- corr_gps[2][1] = gps.vel_d_m_s - est_buf[est_i][2][1];
-
- } else {
- corr_gps[0][1] = 0.0f;
- corr_gps[1][1] = 0.0f;
- corr_gps[2][1] = 0.0f;
- }
-
- /* save rotation matrix at this moment */
- memcpy(R_gps, R_buf[est_i], sizeof(R_gps));
-
- w_gps_xy = min_eph_epv / fmaxf(min_eph_epv, gps.eph);
- w_gps_z = min_eph_epv / fmaxf(min_eph_epv, gps.epv);
- }
-
- } else {
- /* no GPS lock */
- memset(corr_gps, 0, sizeof(corr_gps));
- ref_init_start = 0;
- }
-
- gps_updates++;
- }
- }
- ///检查是否timeout//
- /* check for timeout on FLOW topic */
- if ((flow_valid || lidar_valid) && t > (flow_time + flow_topic_timeout)) {
- flow_valid = false;
- warnx("FLOW timeout");
- mavlink_log_info(&mavlink_log_pub, "[inav] FLOW timeout");
- }
-
- /* check for timeout on GPS topic */
- if (gps_valid && (t > (gps.timestamp_position + gps_topic_timeout))) {
- gps_valid = false;
- warnx("GPS timeout");
- mavlink_log_info(&mavlink_log_pub, "[inav] GPS timeout");
- }
-
- /* check for timeout on vision topic */
- if (vision_valid && (t > (vision.timestamp_boot + vision_topic_timeout))) {
- vision_valid = false;
- warnx("VISION timeout");
- mavlink_log_info(&mavlink_log_pub, "[inav] VISION timeout");
- }
-
- /* check for timeout on mocap topic */
- if (mocap_valid && (t > (mocap.timestamp_boot + mocap_topic_timeout))) {
- mocap_valid = false;
- warnx("MOCAP timeout");
- mavlink_log_info(&mavlink_log_pub, "[inav] MOCAP timeout");
- }
-
- /* check for lidar measurement timeout */
- if (lidar_valid && (t > (lidar_time + lidar_timeout))) {
- lidar_valid = false;
- warnx("LIDAR timeout");
- mavlink_log_info(&mavlink_log_pub, "[inav] LIDAR timeout");
- }
-
- float dt = t_prev > 0 ? (t - t_prev) / 1000000.0f : 0.0f;
- dt = fmaxf(fminf(0.02, dt), 0.0002); // constrain dt from 0.2 to 20 ms
- t_prev = t;
-
- /* increase EPH/EPV on each step */
- if (eph < 0.000001f) { //get case where eph is 0 -> would stay 0
- eph = 0.001;
- }
-
- if (eph < max_eph_epv) {
- eph *= 1.0f + dt;
- }
-
- if (epv < 0.000001f) { //get case where epv is 0 -> would stay 0
- epv = 0.001;
- }
-
- if (epv < max_eph_epv) {
- epv += 0.005f * dt; // add 1m to EPV each 200s (baro drift)
- }
- //根据具体情况,将决策赋给标志位//
- /* use GPS if it's valid and reference position initialized */使用全球定位系统,如果它是有效的,并参考位置初始化
- bool use_gps_xy = ref_inited && gps_valid && params.w_xy_gps_p > MIN_VALID_W;
- bool use_gps_z = ref_inited && gps_valid && params.w_z_gps_p > MIN_VALID_W;
- /* use VISION if it's valid and has a valid weight parameter */使用VISION,如果它是有效的,并具有有效的权重参数
- bool use_vision_xy = vision_valid && params.w_xy_vision_p > MIN_VALID_W;
- bool use_vision_z = vision_valid && params.w_z_vision_p > MIN_VALID_W;
- /* use MOCAP if it's valid and has a valid weight parameter */使用MOCAP如果它是有效的,并具有有效的权重参数
- bool use_mocap = mocap_valid && params.w_mocap_p > MIN_VALID_W && params.att_ext_hdg_m == mocap_heading; //check if external heading is mocap
-
- if (params.disable_mocap) { //disable mocap if fake gps is used
- use_mocap = false;
- }
-
- /* use flow if it's valid and (accurate or no GPS available) */
- bool use_flow = flow_valid && (flow_accurate || !use_gps_xy);
-
- /* use LIDAR if it's valid and lidar altitude estimation is enabled */
- use_lidar = lidar_valid && params.enable_lidar_alt_est;
-
- bool can_estimate_xy = (eph < max_eph_epv) || use_gps_xy || use_flow || use_vision_xy || use_mocap;
-
- bool dist_bottom_valid = (t < lidar_valid_time + lidar_valid_timeout);
-
- float w_xy_gps_p = params.w_xy_gps_p * w_gps_xy;
- float w_xy_gps_v = params.w_xy_gps_v * w_gps_xy;
- float w_z_gps_p = params.w_z_gps_p * w_gps_z;
- float w_z_gps_v = params.w_z_gps_v * w_gps_z;
-
- float w_xy_vision_p = params.w_xy_vision_p;
- float w_xy_vision_v = params.w_xy_vision_v;
- float w_z_vision_p = params.w_z_vision_p;
-
- float w_mocap_p = params.w_mocap_p;
- //根据之前的决策,开始校准数据处理///
- /* reduce GPS weight if optical flow is good */
- if (use_flow && flow_accurate) {
- w_xy_gps_p *= params.w_gps_flow;
- w_xy_gps_v *= params.w_gps_flow;
- }
-
- /* baro offset correction */
- if (use_gps_z) {
- float offs_corr = corr_gps[2][0] * w_z_gps_p * dt;
- baro_offset += offs_corr;
- corr_baro += offs_corr;
- }
-
- /* accelerometer bias correction for GPS (use buffered rotation matrix) */
- float accel_bias_corr[3] = { 0.0f, 0.0f, 0.0f };
-
- if (use_gps_xy) {
- accel_bias_corr[0] -= corr_gps[0][0] * w_xy_gps_p * w_xy_gps_p;
- accel_bias_corr[0] -= corr_gps[0][1] * w_xy_gps_v;
- accel_bias_corr[1] -= corr_gps[1][0] * w_xy_gps_p * w_xy_gps_p;
- accel_bias_corr[1] -= corr_gps[1][1] * w_xy_gps_v;
- }
-
- if (use_gps_z) {
- accel_bias_corr[2] -= corr_gps[2][0] * w_z_gps_p * w_z_gps_p;
- accel_bias_corr[2] -= corr_gps[2][1] * w_z_gps_v;
- }
-
- /* transform error vector from NED frame to body frame */
- for (int i = 0; i < 3; i++) {
- float c = 0.0f;
-
- for (int j = 0; j < 3; j++) {
- c += R_gps[j][i] * accel_bias_corr[j];
- }
-
- if (PX4_ISFINITE(c)) {
- acc_bias[i] += c * params.w_acc_bias * dt;
- }
- }
-
- /* accelerometer bias correction for VISION (use buffered rotation matrix) */
- accel_bias_corr[0] = 0.0f;
- accel_bias_corr[1] = 0.0f;
- accel_bias_corr[2] = 0.0f;
-
- if (use_vision_xy) {
- accel_bias_corr[0] -= corr_vision[0][0] * w_xy_vision_p * w_xy_vision_p;
- accel_bias_corr[0] -= corr_vision[0][1] * w_xy_vision_v;
- accel_bias_corr[1] -= corr_vision[1][0] * w_xy_vision_p * w_xy_vision_p;
- accel_bias_corr[1] -= corr_vision[1][1] * w_xy_vision_v;
- }
-
- if (use_vision_z) {
- accel_bias_corr[2] -= corr_vision[2][0] * w_z_vision_p * w_z_vision_p;
- }
-
- /* accelerometer bias correction for MOCAP (use buffered rotation matrix) */
- accel_bias_corr[0] = 0.0f;
- accel_bias_corr[1] = 0.0f;
- accel_bias_corr[2] = 0.0f;
-
- if (use_mocap) {
- accel_bias_corr[0] -= corr_mocap[0][0] * w_mocap_p * w_mocap_p;
- accel_bias_corr[1] -= corr_mocap[1][0] * w_mocap_p * w_mocap_p;
- accel_bias_corr[2] -= corr_mocap[2][0] * w_mocap_p * w_mocap_p;
- }
-
- /* transform error vector from NED frame to body frame */
- for (int i = 0; i < 3; i++) {
- float c = 0.0f;
-
- for (int j = 0; j < 3; j++) {
- c += PX4_R(att.R, j, i) * accel_bias_corr[j];
- }
-
- if (PX4_ISFINITE(c)) {
- acc_bias[i] += c * params.w_acc_bias * dt;
- }
- }
-
- /* accelerometer bias correction for flow and baro (assume that there is no delay) */
- accel_bias_corr[0] = 0.0f;
- accel_bias_corr[1] = 0.0f;
- accel_bias_corr[2] = 0.0f;
-
- if (use_flow) {
- accel_bias_corr[0] -= corr_flow[0] * params.w_xy_flow;
- accel_bias_corr[1] -= corr_flow[1] * params.w_xy_flow;
- }
-
- if (use_lidar) {
- accel_bias_corr[2] -= corr_lidar * params.w_z_lidar * params.w_z_lidar;
- } else {
- accel_bias_corr[2] -= corr_baro * params.w_z_baro * params.w_z_baro;
- }
-
- /* transform error vector from NED frame to body frame */
- for (int i = 0; i < 3; i++) {
- float c = 0.0f;
-
- for (int j = 0; j < 3; j++) {
- c += PX4_R(att.R, j, i) * accel_bias_corr[j];
- }
-
- if (PX4_ISFINITE(c)) {
- acc_bias[i] += c * params.w_acc_bias * dt;
- }
- }
- //滤波处理///
- /* inertial filter prediction for altitude */
- inertial_filter_predict(dt, z_est, acc[2]);
-
- if (!(PX4_ISFINITE(z_est[0]) && PX4_ISFINITE(z_est[1]))) {
- write_debug_log("BAD ESTIMATE AFTER Z PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
- acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
- corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
- memcpy(z_est, z_est_prev, sizeof(z_est));
- }
-
- /* inertial filter correction for altitude */
- if (use_lidar) {
- inertial_filter_correct(corr_lidar, dt, z_est, 0, params.w_z_lidar);
-
- } else {
- inertial_filter_correct(corr_baro, dt, z_est, 0, params.w_z_baro);
- }
-
- if (use_gps_z) {
- epv = fminf(epv, gps.epv);
-
- inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);
- inertial_filter_correct(corr_gps[2][1], dt, z_est, 1, w_z_gps_v);
- }
-
- if (use_vision_z) {
- epv = fminf(epv, epv_vision);
- inertial_filter_correct(corr_vision[2][0], dt, z_est, 0, w_z_vision_p);
- }
-
- if (use_mocap) {
- epv = fminf(epv, epv_mocap);
- inertial_filter_correct(corr_mocap[2][0], dt, z_est, 0, w_mocap_p);
- }
-
- if (!(PX4_ISFINITE(z_est[0]) && PX4_ISFINITE(z_est[1]))) {
- write_debug_log("BAD ESTIMATE AFTER Z CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
- acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
- corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
- memcpy(z_est, z_est_prev, sizeof(z_est));
- memset(corr_gps, 0, sizeof(corr_gps));
- memset(corr_vision, 0, sizeof(corr_vision));
- memset(corr_mocap, 0, sizeof(corr_mocap));
- corr_baro = 0;
-
- } else {
- memcpy(z_est_prev, z_est, sizeof(z_est));
- }
-
- if (can_estimate_xy) {
- /* inertial filter prediction for position */
- inertial_filter_predict(dt, x_est, acc[0]);
- inertial_filter_predict(dt, y_est, acc[1]);
-
- if (!(PX4_ISFINITE(x_est[0]) && PX4_ISFINITE(x_est[1]) && PX4_ISFINITE(y_est[0]) && PX4_ISFINITE(y_est[1]))) {
- write_debug_log("BAD ESTIMATE AFTER PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
- acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
- corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
- memcpy(x_est, x_est_prev, sizeof(x_est));
- memcpy(y_est, y_est_prev, sizeof(y_est));
- }
-
- /* inertial filter correction for position */
- if (use_flow) {
- eph = fminf(eph, eph_flow);
-
- inertial_filter_correct(corr_flow[0], dt, x_est, 1, params.w_xy_flow * w_flow);
- inertial_filter_correct(corr_flow[1], dt, y_est, 1, params.w_xy_flow * w_flow);
- }
-
- if (use_gps_xy) {
- eph = fminf(eph, gps.eph);
-
- inertial_filter_correct(corr_gps[0][0], dt, x_est, 0, w_xy_gps_p);
- inertial_filter_correct(corr_gps[1][0], dt, y_est, 0, w_xy_gps_p);
-
- if (gps.vel_ned_valid && t < gps.timestamp_velocity + gps_topic_timeout) {
- inertial_filter_correct(corr_gps[0][1], dt, x_est, 1, w_xy_gps_v);
- inertial_filter_correct(corr_gps[1][1], dt, y_est, 1, w_xy_gps_v);
- }
- }
-
- if (use_vision_xy) {
- eph = fminf(eph, eph_vision);
-
- inertial_filter_correct(corr_vision[0][0], dt, x_est, 0, w_xy_vision_p);
- inertial_filter_correct(corr_vision[1][0], dt, y_est, 0, w_xy_vision_p);
-
- if (w_xy_vision_v > MIN_VALID_W) {
- inertial_filter_correct(corr_vision[0][1], dt, x_est, 1, w_xy_vision_v);
- inertial_filter_correct(corr_vision[1][1], dt, y_est, 1, w_xy_vision_v);
- }
- }
-
- if (use_mocap) {
- eph = fminf(eph, eph_mocap);
-
- inertial_filter_correct(corr_mocap[0][0], dt, x_est, 0, w_mocap_p);
- inertial_filter_correct(corr_mocap[1][0], dt, y_est, 0, w_mocap_p);
- }
-
- if (!(PX4_ISFINITE(x_est[0]) && PX4_ISFINITE(x_est[1]) && PX4_ISFINITE(y_est[0]) && PX4_ISFINITE(y_est[1]))) {
- write_debug_log("BAD ESTIMATE AFTER CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
- acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
- corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
- memcpy(x_est, x_est_prev, sizeof(x_est));
- memcpy(y_est, y_est_prev, sizeof(y_est));
- memset(corr_gps, 0, sizeof(corr_gps));
- memset(corr_vision, 0, sizeof(corr_vision));
- memset(corr_mocap, 0, sizeof(corr_mocap));
- memset(corr_flow, 0, sizeof(corr_flow));
-
- } else {
- memcpy(x_est_prev, x_est, sizeof(x_est));
- memcpy(y_est_prev, y_est, sizeof(y_est));
- }
-
- } else {
- /* gradually reset xy velocity estimates */
- inertial_filter_correct(-x_est[1], dt, x_est, 1, params.w_xy_res_v);
- inertial_filter_correct(-y_est[1], dt, y_est, 1, params.w_xy_res_v);
- }
- ///运行地形估计//
- /* run terrain estimator */
- terrain_estimator->predict(dt, &att, &sensor, &lidar);
- terrain_estimator->measurement_update(hrt_absolute_time(), &gps, &lidar, &att);
-
- if (inav_verbose_mode) {
- /* print updates rate */
- if (t > updates_counter_start + updates_counter_len) {
- float updates_dt = (t - updates_counter_start) * 0.000001f;
- warnx(
- "updates rate: accelerometer = %.1f/s, baro = %.1f/s, gps = %.1f/s, attitude = %.1f/s, flow = %.1f/s, vision = %.1f/s, mocap = %.1f/s",
- (double)(accel_updates / updates_dt),
- (double)(baro_updates / updates_dt),
- (double)(gps_updates / updates_dt),
- (double)(attitude_updates / updates_dt),
- (double)(flow_updates / updates_dt),
- (double)(vision_updates / updates_dt),
- (double)(mocap_updates / updates_dt));
- updates_counter_start = t;
- accel_updates = 0;
- baro_updates = 0;
- gps_updates = 0;
- attitude_updates = 0;
- flow_updates = 0;
- vision_updates = 0;
- mocap_updates = 0;
- }
- }
-
- if (t > pub_last + PUB_INTERVAL) {
- pub_last = t;
-
- /* push current estimate to buffer */
- est_buf[buf_ptr][0][0] = x_est[0];
- est_buf[buf_ptr][0][1] = x_est[1];
- est_buf[buf_ptr][1][0] = y_est[0];
- est_buf[buf_ptr][1][1] = y_est[1];
- est_buf[buf_ptr][2][0] = z_est[0];
- est_buf[buf_ptr][2][1] = z_est[1];
-
- /* push current rotation matrix to buffer */
- memcpy(R_buf[buf_ptr], att.R, sizeof(att.R));
-
- buf_ptr++;
-
- if (buf_ptr >= EST_BUF_SIZE) {
- buf_ptr = 0;
- }
-
- ///发布位置信息///
- /* publish local position */
- local_pos.xy_valid = can_estimate_xy;
- local_pos.v_xy_valid = can_estimate_xy;
- local_pos.xy_global = local_pos.xy_valid && use_gps_xy;
- local_pos.z_global = local_pos.z_valid && use_gps_z;
- local_pos.x = x_est[0];
- local_pos.vx = x_est[1];
- local_pos.y = y_est[0];
- local_pos.vy = y_est[1];
- local_pos.z = z_est[0];
- local_pos.vz = z_est[1];
- local_pos.yaw = att.yaw;
- local_pos.dist_bottom_valid = dist_bottom_valid;
- local_pos.eph = eph;
- local_pos.epv = epv;
-
- if (local_pos.dist_bottom_valid) {
- local_pos.dist_bottom = dist_ground;
- local_pos.dist_bottom_rate = - z_est[1];
- }
-
- local_pos.timestamp = t;
-
- orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
-
- if (local_pos.xy_global && local_pos.z_global) {
- /* publish global position */
- global_pos.timestamp = t;
- global_pos.time_utc_usec = gps.time_utc_usec;
-
- double est_lat, est_lon;
- map_projection_reproject(&ref, local_pos.x, local_pos.y, &est_lat, &est_lon);
-
- global_pos.lat = est_lat;
- global_pos.lon = est_lon;
- global_pos.alt = local_pos.ref_alt - local_pos.z;
-
- global_pos.vel_n = local_pos.vx;
- global_pos.vel_e = local_pos.vy;
- global_pos.vel_d = local_pos.vz;
-
- global_pos.yaw = local_pos.yaw;
-
- global_pos.eph = eph;
- global_pos.epv = epv;
-
- if (terrain_estimator->is_valid()) {
- global_pos.terrain_alt = global_pos.alt - terrain_estimator->get_distance_to_ground();
- global_pos.terrain_alt_valid = true;
-
- } else {
- global_pos.terrain_alt_valid = false;
- }
-
- global_pos.pressure_alt = sensor.baro_alt_meter[0];
-
- if (vehicle_global_position_pub == NULL) {
- vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
-
- } else {
- orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
- }
- }
- }
- }
- /***************************************大循环结束********************************/
- warnx("stopped");
- mavlink_log_info(&mavlink_log_pub, "[inav] stopped");
- thread_running = false;
- return 0;
- }
这里发布的信息有2个vehicle_local_position和vehicle_global_position
- #ifdef __cplusplus
- struct __EXPORT vehicle_local_position_s {
- #else
- struct vehicle_local_position_s {
- #endif
- uint64_t timestamp;
- bool xy_valid;
- bool z_valid;
- bool v_xy_valid;
- bool v_z_valid;
- float x;
- float y;
- float z;
- float vx;
- float vy;
- float vz;
- float yaw;
- bool xy_global;
- bool z_global;
- uint64_t ref_timestamp;
- double ref_lat;
- double ref_lon;
- float ref_alt;
- float dist_bottom;
- float dist_bottom_rate;
- uint64_t surface_bottom_timestamp;
- bool dist_bottom_valid;
- float eph;
- float epv;
- #ifdef __cplusplus
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT vehicle_global_position_s {
- #else
- struct vehicle_global_position_s {
- #endif
- uint64_t timestamp;
- uint64_t time_utc_usec;
- double lat;
- double lon;
- float alt;
- float vel_n;
- float vel_e;
- float vel_d;
- float yaw;
- float eph;
- float epv;
- float terrain_alt;
- bool terrain_alt_valid;
- bool dead_reckoning;
- float pressure_alt;
- #ifdef __cplusplus
- #endif
- };
其他会用到的数据全部在ardupilot/modules/PX4Firmware/src/modules/uORB/topics文件夹中
- #ifdef __cplusplus
- struct __EXPORT sensor_combined_s {
- #else
- struct sensor_combined_s {
- #endif
- uint64_t timestamp;
- uint64_t gyro_timestamp[3];
- int16_t gyro_raw[9];
- float gyro_rad_s[9];
- uint32_t gyro_priority[3];
- float gyro_integral_rad[9];
- uint64_t gyro_integral_dt[3];
- uint32_t gyro_errcount[3];
- float gyro_temp[3];
- int16_t accelerometer_raw[9];
- float accelerometer_m_s2[9];
- float accelerometer_integral_m_s[9];
- uint64_t accelerometer_integral_dt[3];
- int16_t accelerometer_mode[3];
- float accelerometer_range_m_s2[3];
- uint64_t accelerometer_timestamp[3];
- uint32_t accelerometer_priority[3];
- uint32_t accelerometer_errcount[3];
- float accelerometer_temp[3];
- int16_t magnetometer_raw[9];
- float magnetometer_ga[9];
- int16_t magnetometer_mode[3];
- float magnetometer_range_ga[3];
- float magnetometer_cuttoff_freq_hz[3];
- uint64_t magnetometer_timestamp[3];
- uint32_t magnetometer_priority[3];
- uint32_t magnetometer_errcount[3];
- float magnetometer_temp[3];
- float baro_pres_mbar[3];
- float baro_alt_meter[3];
- float baro_temp_celcius[3];
- uint64_t baro_timestamp[3];
- uint32_t baro_priority[3];
- uint32_t baro_errcount[3];
- float adc_voltage_v[10];
- uint16_t adc_mapping[10];
- float mcu_temp_celcius;
- float differential_pressure_pa[3];
- uint64_t differential_pressure_timestamp[3];
- float differential_pressure_filtered_pa[3];
- uint32_t differential_pressure_priority[3];
- uint32_t differential_pressure_errcount[3];
- #ifdef __cplusplus
- static const int32_t MAGNETOMETER_MODE_NORMAL = 0;
- static const int32_t MAGNETOMETER_MODE_POSITIVE_BIAS = 1;
- static const int32_t MAGNETOMETER_MODE_NEGATIVE_BIAS = 2;
- static const uint32_t SENSOR_PRIO_MIN = 0;
- static const uint32_t SENSOR_PRIO_VERY_LOW = 25;
- static const uint32_t SENSOR_PRIO_LOW = 50;
- static const uint32_t SENSOR_PRIO_DEFAULT = 75;
- static const uint32_t SENSOR_PRIO_HIGH = 100;
- static const uint32_t SENSOR_PRIO_VERY_HIGH = 125;
- static const uint32_t SENSOR_PRIO_MAX = 255;
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT parameter_update_s {
- #else
- struct parameter_update_s {
- #endif
- uint64_t timestamp;
- bool saved;
- #ifdef __cplusplus
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT actuator_controls_s {
- #else
- struct actuator_controls_s {
- #endif
- uint64_t timestamp;
- uint64_t timestamp_sample;
- float control[8];
- #ifdef __cplusplus
- static const uint8_t NUM_ACTUATOR_CONTROLS = 8;
- static const uint8_t NUM_ACTUATOR_CONTROL_GROUPS = 4;
- static const uint8_t INDEX_ROLL = 0;
- static const uint8_t INDEX_PITCH = 1;
- static const uint8_t INDEX_YAW = 2;
- static const uint8_t INDEX_THROTTLE = 3;
- static const uint8_t INDEX_FLAPS = 4;
- static const uint8_t INDEX_SPOILERS = 5;
- static const uint8_t INDEX_AIRBRAKES = 6;
- static const uint8_t INDEX_LANDING_GEAR = 7;
- static const uint8_t GROUP_INDEX_ATTITUDE = 0;
- static const uint8_t GROUP_INDEX_ATTITUDE_ALTERNATE = 1;
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT actuator_armed_s {
- #else
- struct actuator_armed_s {
- #endif
- uint64_t timestamp;
- bool armed;
- bool prearmed;
- bool ready_to_arm;
- bool lockdown;
- bool force_failsafe;
- bool in_esc_calibration_mode;
- #ifdef __cplusplus
- #endif
- #ifdef __cplusplus
- struct __EXPORT vision_position_estimate_s {
- #else
- struct vision_position_estimate_s {
- #endif
- uint32_t id;
- uint64_t timestamp_boot;
- uint64_t timestamp_computer;
- float x;
- float y;
- float z;
- float vx;
- float vy;
- float vz;
- float q[4];
- #ifdef __cplusplus
- #endif
- };
-
- #ifdef __cplusplus
- struct __EXPORT att_pos_mocap_s {
- #else
- struct att_pos_mocap_s {
- #endif
- uint32_t id;
- uint64_t timestamp_boot;
- uint64_t timestamp_computer;
- float q[4];
- float x;
- float y;
- float z;
- #ifdef __cplusplus
- #endif
- };
-
- #ifdef __cplusplus
- struct __EXPORT vehicle_gps_position_s {
- #else
- struct vehicle_gps_position_s {
- #endif
- uint64_t timestamp_position;
- int32_t lat;
- int32_t lon;
- int32_t alt;
- int32_t alt_ellipsoid;
- uint64_t timestamp_variance;
- float s_variance_m_s;
- float c_variance_rad;
- uint8_t fix_type;
- float eph;
- float epv;
- float hdop;
- float vdop;
- int32_t noise_per_ms;
- int32_t jamming_indicator;
- uint64_t timestamp_velocity;
- float vel_m_s;
- float vel_n_m_s;
- float vel_e_m_s;
- float vel_d_m_s;
- float cog_rad;
- bool vel_ned_valid;
- uint64_t timestamp_time;
- uint64_t time_utc_usec;
- uint8_t satellites_used;
- #ifdef __cplusplus
-
- #endif
- };
把光流部分单独拿出来
- /**************************************这里就是光流的处理*********************************/
- /* optical flow */
- orb_check(optical_flow_sub, &updated);
-
- if (updated && lidar_valid) {
- orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);//光流数据跟新
-
- flow_time = t;
- float flow_q = flow.quality / 255.0f;
- float dist_bottom = lidar.current_distance;//高度信息
-
- if (dist_bottom > flow_min_dist && flow_q > params.flow_q_min && PX4_R(att.R, 2, 2) > 0.7f) {
- /* distance to surface */
- //float flow_dist = dist_bottom / PX4_R(att.R, 2, 2); //use this if using sonar
- float flow_dist = dist_bottom; //use this if using lidar
-
- /* check if flow if too large for accurate measurements */检查速度是否太大,影响光流精确测量
- /*****************************计算机架估计的速度*****************************/
- /* calculate estimated velocity in body frame */
- float body_v_est[2] = { 0.0f, 0.0f };
-
- for (int i = 0; i < 2; i++) {
- body_v_est[i] = PX4_R(att.R, 0, i) * x_est[1] + PX4_R(att.R, 1, i) * y_est[1] + PX4_R(att.R, 2, i) * z_est[1];
- }
- /*************设置这个标志,如果光流按照当前速度和姿态率的估计是准确的*************/
- /* set this flag if flow should be accurate according to current velocity and attitude rate estimate */
- flow_accurate = fabsf(body_v_est[1] / flow_dist - att.rollspeed) < max_flow &&
- fabsf(body_v_est[0] / flow_dist + att.pitchspeed) < max_flow;
- /*************利用自动驾驶仪(飞控)已经校准的陀螺仪计算光流用的陀螺仪的偏移*************/
- /*calculate offset of flow-gyro using already calibrated gyro from autopilot*/
- flow_gyrospeed[0] = flow.gyro_x_rate_integral / (float)flow.integration_timespan * 1000000.0f;
- flow_gyrospeed[1] = flow.gyro_y_rate_integral / (float)flow.integration_timespan * 1000000.0f;
- flow_gyrospeed[2] = flow.gyro_z_rate_integral / (float)flow.integration_timespan * 1000000.0f;
-
- //moving average
- if (n_flow >= 100) {
- gyro_offset_filtered[0] = flow_gyrospeed_filtered[0] - att_gyrospeed_filtered[0];
- gyro_offset_filtered[1] = flow_gyrospeed_filtered[1] - att_gyrospeed_filtered[1];
- gyro_offset_filtered[2] = flow_gyrospeed_filtered[2] - att_gyrospeed_filtered[2];
- n_flow = 0;
- flow_gyrospeed_filtered[0] = 0.0f;
- flow_gyrospeed_filtered[1] = 0.0f;
- flow_gyrospeed_filtered[2] = 0.0f;
- att_gyrospeed_filtered[0] = 0.0f;
- att_gyrospeed_filtered[1] = 0.0f;
- att_gyrospeed_filtered[2] = 0.0f;
-
- } else {
- flow_gyrospeed_filtered[0] = (flow_gyrospeed[0] + n_flow * flow_gyrospeed_filtered[0]) / (n_flow + 1);
- flow_gyrospeed_filtered[1] = (flow_gyrospeed[1] + n_flow * flow_gyrospeed_filtered[1]) / (n_flow + 1);
- flow_gyrospeed_filtered[2] = (flow_gyrospeed[2] + n_flow * flow_gyrospeed_filtered[2]) / (n_flow + 1);
- att_gyrospeed_filtered[0] = (att.pitchspeed + n_flow * att_gyrospeed_filtered[0]) / (n_flow + 1);
- att_gyrospeed_filtered[1] = (att.rollspeed + n_flow * att_gyrospeed_filtered[1]) / (n_flow + 1);
- att_gyrospeed_filtered[2] = (att.yawspeed + n_flow * att_gyrospeed_filtered[2]) / (n_flow + 1);
- n_flow++;
- }
-
- /*******************************偏航补偿(光流传感器不处于旋转中心)->参数在QGC中***********************/
- /*yaw compensation (flow sensor is not in center of rotation) -> params in QGC*/
- yaw_comp[0] = - params.flow_module_offset_y * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
- yaw_comp[1] = params.flow_module_offset_x * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
- /***************************将原始流转换成角度流**********************************/
- /* convert raw flow to angular flow (rad/s) */
- float flow_ang[2];
- /***************************检查机体速度设定值->它低于阈值->不减去->更好悬停*********************/
- /* check for vehicle rates setpoint - it below threshold -> dont subtract -> better hover */
- orb_check(vehicle_rate_sp_sub, &updated);
- if (updated)
- orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
-
- double rate_threshold = 0.15f;
-
- if (fabs(rates_setpoint.pitch) < rate_threshold) {
- //warnx("[inav] test ohne comp");
- flow_ang[0] = (flow.pixel_flow_x_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)
- }
- else {
- //warnx("[inav] test mit comp");
- //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
- //计算光流的速度[rad/s]并补偿旋转(和光流的陀螺仪的偏置)
- flow_ang[0] = ((flow.pixel_flow_x_integral - flow.gyro_x_rate_integral) / (float)flow.integration_timespan * 1000000.0f
- + gyro_offset_filtered[0]) * params.flow_k;//for now the flow has to be scaled (to small)
- }
-
- if (fabs(rates_setpoint.roll) < rate_threshold) {
- flow_ang[1] = (flow.pixel_flow_y_integral / (float)flow.integration_timespan * 1000000.0f) * params.flow_k;//for now the flow has to be scaled (to small)
- }
- else {
- //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
- //计算光流的速度[rad/s]并补偿旋转(和光流的陀螺仪的偏置)
- flow_ang[1] = ((flow.pixel_flow_y_integral - flow.gyro_y_rate_integral) / (float)flow.integration_timespan * 1000000.0f
- + gyro_offset_filtered[1]) * params.flow_k;//for now the flow has to be scaled (to small)
- }
- /************************光流测量向量********************************/
- /* flow measurements vector */
- float flow_m[3];
- if (fabs(rates_setpoint.yaw) < rate_threshold) {
- flow_m[0] = -flow_ang[0] * flow_dist;
- flow_m[1] = -flow_ang[1] * flow_dist;
- } else {
- flow_m[0] = -flow_ang[0] * flow_dist - yaw_comp[0] * params.flow_k;
- flow_m[1] = -flow_ang[1] * flow_dist - yaw_comp[1] * params.flow_k;
- }
- flow_m[2] = z_est[1];
-
- /* velocity in NED */NED是北东地,还有一种旋转方式是东北天,都是属于右手系
- float flow_v[2] = { 0.0f, 0.0f };
- /************************基于NED工程测量向量,跳过Z分量*********************/
- /* project measurements vector to NED basis, skip Z component */
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 3; j++) {
- flow_v[i] += PX4_R(att.R, i, j) * flow_m[j];
- }
- }
- /********************向量矫正***********************/
- /* velocity correction */
- corr_flow[0] = flow_v[0] - x_est[1];
- corr_flow[1] = flow_v[1] - y_est[1];
- /********************调整矫正权重***********************/
- /* adjust correction weight */
- float flow_q_weight = (flow_q - params.flow_q_min) / (1.0f - params.flow_q_min);
- w_flow = PX4_R(att.R, 2, 2) * flow_q_weight / fmaxf(1.0f, flow_dist);
-
- /********************如果光流是不准确的,那么减少他的权重***********************/
- /* if flow is not accurate, reduce weight for it */
- // TODO make this more fuzzy
- if (!flow_accurate) {
- w_flow *= 0.05f;
- }
- /**********************在理想条件下,在1m的距离EPH =10厘米****************/
- /* under ideal conditions, on 1m distance assume EPH = 10cm */
- eph_flow = 0.1f / w_flow;
-
- flow_valid = true;
-
- } else {
- w_flow = 0.0f;
- flow_valid = false;
- }
-
- flow_updates++;
- }
- /**************************************光流结束*********************************/
接下来就到了
ardupilot/modules/PX4Firmware/src/modules/mc_pos_control/mc_pos_control_main.cpp
和ardupilot/modules/PX4Firmware/src/modules/vtol_att_control_main.cpp
进行控制
先看mc_pos_control_main.cpp
extern "C" __EXPORT int mc_pos_control_main(int argc, char *argv[]);
- int mc_pos_control_main(int argc, char *argv[])
- {
- if (argc < 2) {
- warnx("usage: mc_pos_control {start|stop|status}");
- return 1;
- }
-
- if (!strcmp(argv[1], "start")) {
-
- if (pos_control::g_control != nullptr) {
- warnx("already running");
- return 1;
- }
-
- pos_control::g_control = new MulticopterPositionControl;
-
- if (pos_control::g_control == nullptr) {
- warnx("alloc failed");
- return 1;
- }
-
- if (OK != pos_control::g_control->start()) {
- delete pos_control::g_control;
- pos_control::g_control = nullptr;
- warnx("start failed");
- return 1;
- }
-
- return 0;
- }
-
- if (!strcmp(argv[1], "stop")) {
- if (pos_control::g_control == nullptr) {
- warnx("not running");
- return 1;
- }
-
- delete pos_control::g_control;
- pos_control::g_control = nullptr;
- return 0;
- }
-
- if (!strcmp(argv[1], "status")) {
- if (pos_control::g_control) {
- warnx("running");
- return 0;
-
- } else {
- warnx("not running");
- return 1;
- }
- }
-
- warnx("unrecognized command");
- return 1;
- }
这个里面就start和status需要看
- int
- MulticopterPositionControl::start()
- {
- ASSERT(_control_task == -1);
-
- /* start the task */
- _control_task = px4_task_spawn_cmd("mc_pos_control",
- SCHED_DEFAULT,
- SCHED_PRIORITY_MAX - 5,
- 1900,
- (px4_main_t)&MulticopterPositionControl::task_main_trampoline,
- nullptr);
-
- if (_control_task < 0) {
- warn("task start failed");
- return -errno;
- }
-
- return OK;
- }
- void
- MulticopterPositionControl::task_main_trampoline(int argc, char *argv[])
- {
- pos_control::g_control->task_main();
- }
- void
- MulticopterPositionControl::task_main()
- {
- /***************************订阅各种信息***********************/
- /*
- * do subscriptions
- */
- _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
- _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
- _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
- _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
- _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
- //这个就是从position_estimator_inav_main.cpp中来的,里面包含光流数据
- _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
- _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
- _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
-
-
- parameters_update(true);//参数跟新
- /*****************初始化关键结构的值,直到第一次定期更新*****************/
- /* initialize values of critical structs until first regular update */
- _arming.armed = false;
- /*****************初始跟新,获取所有传感器的数据和状态数据*****************/
- /* get an initial update for all sensor and status data */
- poll_subscriptions();//具体在下面展开了
-
- bool reset_int_z = true;
- bool reset_int_z_manual = false;
- bool reset_int_xy = true;
- bool reset_yaw_sp = true;
- bool was_armed = false;
-
- hrt_abstime t_prev = 0;
-
- math::Vector<3> thrust_int;
- thrust_int.zero();
-
-
- math::Matrix<3, 3> R;
- R.identity();
-
- /* wakeup source */
- px4_pollfd_struct_t fds[1];
-
- fds[0].fd = _local_pos_sub;
- fds[0].events = POLLIN;
- /***********************大循环***************************/
- while (!_task_should_exit) {
- /* wait for up to 500ms for data */等待500ms来获取数据
- int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 500);
-
- /* timed out - periodic check for _task_should_exit */
- if (pret == 0) {
- continue;
- }
-
- /* this is undesirable but not much we can do */
- if (pret < 0) {
- warn("poll error %d, %d", pret, errno);
- continue;
- }
- //获取所有传感器的数据和状态数据//
- poll_subscriptions();
- ///参数跟新
- parameters_update(false);
-
- hrt_abstime t = hrt_absolute_time();
- float dt = t_prev != 0 ? (t - t_prev) * 0.000001f : 0.0f;//dt是控制周期吗?
- t_prev = t;
-
- // set dt for control blocks
- setDt(dt);
- /判断是否锁定
- if (_control_mode.flag_armed && !was_armed) {
- /* reset setpoints and integrals on arming */
- _reset_pos_sp = true;
- _reset_alt_sp = true;
- _vel_sp_prev.zero();
- reset_int_z = true;
- reset_int_xy = true;
- reset_yaw_sp = true;
- }
- //复位yaw和姿态的设定 为垂直起降 fw模式/
- /* reset yaw and altitude setpoint for VTOL which are in fw mode */
- if (_vehicle_status.is_vtol) {
- if (!_vehicle_status.is_rotary_wing) {
- reset_yaw_sp = true;
- _reset_alt_sp = true;
- }
- }
- 跟新前一时刻锁定的状态///
- //Update previous arming state
- was_armed = _control_mode.flag_armed;
-
- update_ref();//跟新参考点,是不是期望目标?该函数在下面会展开
- 跟新速度导数(加速度) 独立于当前飞行模式///
- /* Update velocity derivative,
- * independent of the current flight mode
- */
- if (_local_pos.timestamp > 0) {
-
- if (PX4_ISFINITE(_local_pos.x) && //ISFINITE是测试数据是否是个有限数的函数
- PX4_ISFINITE(_local_pos.y) &&
- PX4_ISFINITE(_local_pos.z)) {
-
- _pos(0) = _local_pos.x;
- _pos(1) = _local_pos.y;
- _pos(2) = _local_pos.z;
- }
-
- if (PX4_ISFINITE(_local_pos.vx) &&
- PX4_ISFINITE(_local_pos.vy) &&
- PX4_ISFINITE(_local_pos.vz)) {
-
- _vel(0) = _local_pos.vx;
- _vel(1) = _local_pos.vy;
- _vel(2) = _local_pos.vz;
- }
-
- _vel_err_d(0) = _vel_x_deriv.update(-_vel(0));
- _vel_err_d(1) = _vel_y_deriv.update(-_vel(1));
- _vel_err_d(2) = _vel_z_deriv.update(-_vel(2));
- }
- ///复位在非手动模式下的水平垂直位置保持标志位,让位置和姿态不被控制//
- // reset the horizontal and vertical position hold flags for non-manual modes
- // or if position / altitude is not controlled
- if (!_control_mode.flag_control_position_enabled || !_control_mode.flag_control_manual_enabled) {
- _pos_hold_engaged = false;
- }
-
- if (!_control_mode.flag_control_altitude_enabled || !_control_mode.flag_control_manual_enabled) {
- _alt_hold_engaged = false;
- }
- //根据控制模式选择对应的控制函数//
- if (_control_mode.flag_control_altitude_enabled ||
- _control_mode.flag_control_position_enabled ||
- _control_mode.flag_control_climb_rate_enabled ||
- _control_mode.flag_control_velocity_enabled) {
-
- _vel_ff.zero();
- /默认运行位置和姿态控制,在control_*函数中可以失能这种模式而直接在循环中运行速度控制模式/
- /* by default, run position/altitude controller. the control_* functions
- * can disable this and run velocity controllers directly in this cycle */
- _run_pos_control = true;
- _run_alt_control = true;
- /选择控制源/
- /* select control source */
- if (_control_mode.flag_control_manual_enabled) {
- /* manual control */
- control_manual(dt);//手动控制,在下面会展开
- _mode_auto = false;
-
- } else if (_control_mode.flag_control_offboard_enabled) {
- /* offboard control */
- control_offboard(dt);//和control_manual(dt);貌似都是根据具体情况设定期望值
- _mode_auto = false;
-
- } else {
- /* AUTO */
- control_auto(dt);//自动控制
- }
- /********感觉这3个函数功能是实现根据实际复杂情况调整期望值,之后用控制函数一个一个的达到期望值*************/
- /* weather-vane mode for vtol: disable yaw control */风向标模式垂直起降:禁用偏航控制
- if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.disable_mc_yaw_control == true) {
- _att_sp.disable_mc_yaw_control = true;
-
- } else {
- /* reset in case of setpoint updates */
- _att_sp.disable_mc_yaw_control = false;
- }
- /判断///
- if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
- && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_IDLE) {
- /* idle state, don't run controller and set zero thrust */
- //空闲状态,不运行控制,并设置为零推力//
- R.identity();
- memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
- _att_sp.R_valid = true;
-
- _att_sp.roll_body = 0.0f;
- _att_sp.pitch_body = 0.0f;
- _att_sp.yaw_body = _yaw;
- _att_sp.thrust = 0.0f;
-
- _att_sp.timestamp = hrt_absolute_time();
- /发布姿态设定值///
- /* publish attitude setpoint */
- if (_att_sp_pub != nullptr) {
- orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
-
- } else if (_attitude_setpoint_id) {
- _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
- }
- /另一个判断///
- } else if (_control_mode.flag_control_manual_enabled
- && _vehicle_status.condition_landed) {
- /* don't run controller when landed */着陆不要运行控制器
- _reset_pos_sp = true;
- _reset_alt_sp = true;
- _mode_auto = false;
- reset_int_z = true;
- reset_int_xy = true;
-
- R.identity();
- memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
- _att_sp.R_valid = true;
-
- _att_sp.roll_body = 0.0f;
- _att_sp.pitch_body = 0.0f;
- _att_sp.yaw_body = _yaw;
- _att_sp.thrust = 0.0f;
-
- _att_sp.timestamp = hrt_absolute_time();
-
- /* publish attitude setpoint */
- if (_att_sp_pub != nullptr) {
- orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
-
- } else if (_attitude_setpoint_id) {
- _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
- }
- /另一个判断///
- } else {
- /* run position & altitude controllers, if enabled (otherwise use already computed velocity setpoints) */
- if (_run_pos_control) {
- _vel_sp(0) = (_pos_sp(0) - _pos(0)) * _params.pos_p(0);
- _vel_sp(1) = (_pos_sp(1) - _pos(1)) * _params.pos_p(1);
- }
-
- // do not go slower than the follow target velocity when position tracking is active (set to valid)
-
- if(_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_FOLLOW_TARGET &&
- _pos_sp_triplet.current.velocity_valid &&
- _pos_sp_triplet.current.position_valid) {
-
- math::Vector<3> ft_vel(_pos_sp_triplet.current.vx, _pos_sp_triplet.current.vy, 0);
-
- float cos_ratio = (ft_vel*_vel_sp)/(ft_vel.length()*_vel_sp.length());
-
- // only override velocity set points when uav is traveling in same direction as target and vector component
- // is greater than calculated position set point velocity component
-
- if(cos_ratio > 0) {
- ft_vel *= (cos_ratio);
- // min speed a little faster than target vel
- ft_vel += ft_vel.normalized()*1.5f;
- } else {
- ft_vel.zero();
- }
-
- _vel_sp(0) = fabs(ft_vel(0)) > fabs(_vel_sp(0)) ? ft_vel(0) : _vel_sp(0);
- _vel_sp(1) = fabs(ft_vel(1)) > fabs(_vel_sp(1)) ? ft_vel(1) : _vel_sp(1);
-
- // track target using velocity only
-
- } else if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_FOLLOW_TARGET &&
- _pos_sp_triplet.current.velocity_valid) {
-
- _vel_sp(0) = _pos_sp_triplet.current.vx;
- _vel_sp(1) = _pos_sp_triplet.current.vy;
- }
-
- if (_run_alt_control) {
- _vel_sp(2) = (_pos_sp(2) - _pos(2)) * _params.pos_p(2);
- }
-
- /* make sure velocity setpoint is saturated in xy*/
- float vel_norm_xy = sqrtf(_vel_sp(0) * _vel_sp(0) +
- _vel_sp(1) * _vel_sp(1));
-
- if (vel_norm_xy > _params.vel_max(0)) {
- /* note assumes vel_max(0) == vel_max(1) */
- _vel_sp(0) = _vel_sp(0) * _params.vel_max(0) / vel_norm_xy;
- _vel_sp(1) = _vel_sp(1) * _params.vel_max(1) / vel_norm_xy;
- }
-
- /* make sure velocity setpoint is saturated in z*/
- float vel_norm_z = sqrtf(_vel_sp(2) * _vel_sp(2));
-
- if (vel_norm_z > _params.vel_max(2)) {
- _vel_sp(2) = _vel_sp(2) * _params.vel_max(2) / vel_norm_z;
- }
-
- if (!_control_mode.flag_control_position_enabled) {
- _reset_pos_sp = true;
- }
-
- if (!_control_mode.flag_control_altitude_enabled) {
- _reset_alt_sp = true;
- }
-
- if (!_control_mode.flag_control_velocity_enabled) {
- _vel_sp_prev(0) = _vel(0);
- _vel_sp_prev(1) = _vel(1);
- _vel_sp(0) = 0.0f;
- _vel_sp(1) = 0.0f;
- control_vel_enabled_prev = false;
- }
-
- if (!_control_mode.flag_control_climb_rate_enabled) {
- _vel_sp(2) = 0.0f;
- }
-
- /* use constant descend rate when landing, ignore altitude setpoint */
- if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
- && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) {
- _vel_sp(2) = _params.land_speed;
- }
-
- /* special thrust setpoint generation for takeoff from ground */
- if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
- && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF
- && _control_mode.flag_armed) {
-
- // check if we are not already in air.
- // if yes then we don't need a jumped takeoff anymore
- if (!_takeoff_jumped && !_vehicle_status.condition_landed && fabsf(_takeoff_thrust_sp) < FLT_EPSILON) {
- _takeoff_jumped = true;
- }
-
- if (!_takeoff_jumped) {
- // ramp thrust setpoint up
- if (_vel(2) > -(_params.tko_speed / 2.0f)) {
- _takeoff_thrust_sp += 0.5f * dt;
- _vel_sp.zero();
- _vel_prev.zero();
-
- } else {
- // copter has reached our takeoff speed. split the thrust setpoint up
- // into an integral part and into a P part
- thrust_int(2) = _takeoff_thrust_sp - _params.vel_p(2) * fabsf(_vel(2));
- thrust_int(2) = -math::constrain(thrust_int(2), _params.thr_min, _params.thr_max);
- _vel_sp_prev(2) = -_params.tko_speed;
- _takeoff_jumped = true;
- reset_int_z = false;
- }
- }
-
- if (_takeoff_jumped) {
- _vel_sp(2) = -_params.tko_speed;
- }
-
- } else {
- _takeoff_jumped = false;
- _takeoff_thrust_sp = 0.0f;
- }
-
-
-
- // limit total horizontal acceleration
- math::Vector<2> acc_hor;
- acc_hor(0) = (_vel_sp(0) - _vel_sp_prev(0)) / dt;
- acc_hor(1) = (_vel_sp(1) - _vel_sp_prev(1)) / dt;
-
- if (acc_hor.length() > _params.acc_hor_max) {
- acc_hor.normalize();
- acc_hor *= _params.acc_hor_max;
- math::Vector<2> vel_sp_hor_prev(_vel_sp_prev(0), _vel_sp_prev(1));
- math::Vector<2> vel_sp_hor = acc_hor * dt + vel_sp_hor_prev;
- _vel_sp(0) = vel_sp_hor(0);
- _vel_sp(1) = vel_sp_hor(1);
- }
-
- // limit vertical acceleration
- float acc_v = (_vel_sp(2) - _vel_sp_prev(2)) / dt;
-
- if (fabsf(acc_v) > 2 * _params.acc_hor_max) {
- acc_v /= fabsf(acc_v);
- _vel_sp(2) = acc_v * 2 * _params.acc_hor_max * dt + _vel_sp_prev(2);
- }
-
- _vel_sp_prev = _vel_sp;
-
- _global_vel_sp.vx = _vel_sp(0);
- _global_vel_sp.vy = _vel_sp(1);
- _global_vel_sp.vz = _vel_sp(2);
-
- /* publish velocity setpoint */
- if (_global_vel_sp_pub != nullptr) {
- orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
-
- } else {
- _global_vel_sp_pub = orb_advertise(ORB_ID(vehicle_global_velocity_setpoint), &_global_vel_sp);
- }
-
- if (_control_mode.flag_control_climb_rate_enabled || _control_mode.flag_control_velocity_enabled) {
- /* reset integrals if needed */
- if (_control_mode.flag_control_climb_rate_enabled) {
- if (reset_int_z) {
- reset_int_z = false;
- float i = _params.thr_min;
-
- if (reset_int_z_manual) {
- i = _params.thr_hover;
-
- if (i < _params.thr_min) {
- i = _params.thr_min;
-
- } else if (i > _params.thr_max) {
- i = _params.thr_max;
- }
- }
-
- thrust_int(2) = -i;
- }
-
- } else {
- reset_int_z = true;
- }
-
- if (_control_mode.flag_control_velocity_enabled) {
- if (reset_int_xy) {
- reset_int_xy = false;
- thrust_int(0) = 0.0f;
- thrust_int(1) = 0.0f;
- }
-
- } else {
- reset_int_xy = true;
- }
-
- /* velocity error */
- math::Vector<3> vel_err = _vel_sp - _vel;
- 检查是否从非速度模式转到速度控制模式,如果是的话,校正xy的速度设定值以便姿态设定值保持不变/
- // check if we have switched from a non-velocity controlled mode into a velocity controlled mode
- // if yes, then correct xy velocity setpoint such that the attitude setpoint is continuous
- if (!control_vel_enabled_prev && _control_mode.flag_control_velocity_enabled) {
-
- // choose velocity xyz setpoint such that the resulting thrust setpoint has the direction
- // given by the last attitude setpoint
- _vel_sp(0) = _vel(0) + (-PX4_R(_att_sp.R_body, 0, 2) * _att_sp.thrust - thrust_int(0) - _vel_err_d(0) * _params.vel_d(0)) / _params.vel_p(0);
- _vel_sp(1) = _vel(1) + (-PX4_R(_att_sp.R_body, 1, 2) * _att_sp.thrust - thrust_int(1) - _vel_err_d(1) * _params.vel_d(1)) / _params.vel_p(1);
- _vel_sp(2) = _vel(2) + (-PX4_R(_att_sp.R_body, 2, 2) * _att_sp.thrust - thrust_int(2) - _vel_err_d(2) * _params.vel_d(2)) / _params.vel_p(2);
- _vel_sp_prev(0) = _vel_sp(0);
- _vel_sp_prev(1) = _vel_sp(1);
- _vel_sp_prev(2) = _vel_sp(2);
- control_vel_enabled_prev = true;
-
- // compute updated velocity error
- vel_err = _vel_sp - _vel;
- }
-
- /* thrust vector in NED frame */
- math::Vector<3> thrust_sp = vel_err.emult(_params.vel_p) + _vel_err_d.emult(_params.vel_d) + thrust_int;
-
- if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF
- && !_takeoff_jumped && !_control_mode.flag_control_manual_enabled) {
- // for jumped takeoffs use special thrust setpoint calculated above
- thrust_sp.zero();
- thrust_sp(2) = -_takeoff_thrust_sp;
- }
-
- if (!_control_mode.flag_control_velocity_enabled) {
- thrust_sp(0) = 0.0f;
- thrust_sp(1) = 0.0f;
- }
-
- if (!_control_mode.flag_control_climb_rate_enabled) {
- thrust_sp(2) = 0.0f;
- }
-
- /* limit thrust vector and check for saturation */
- bool saturation_xy = false;
- bool saturation_z = false;
-
- /* limit min lift */
- float thr_min = _params.thr_min;
-
- if (!_control_mode.flag_control_velocity_enabled && thr_min < 0.0f) {
- /* don't allow downside thrust direction in manual attitude mode */
- thr_min = 0.0f;
- }
-
- float thrust_abs = thrust_sp.length();
- float tilt_max = _params.tilt_max_air;
- float thr_max = _params.thr_max;
- /* filter vel_z over 1/8sec */
- _vel_z_lp = _vel_z_lp * (1.0f - dt * 8.0f) + dt * 8.0f * _vel(2);
- /* filter vel_z change over 1/8sec */
- float vel_z_change = (_vel(2) - _vel_prev(2)) / dt;
- _acc_z_lp = _acc_z_lp * (1.0f - dt * 8.0f) + dt * 8.0f * vel_z_change;
-
- /* adjust limits for landing mode */调整限制 着陆模式
- if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid &&
- _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) {
- /* limit max tilt and min lift when landing */
- tilt_max = _params.tilt_max_land;
-
- if (thr_min < 0.0f) {
- thr_min = 0.0f;
- }
-
- /* descend stabilized, we're landing */
- if (!_in_landing && !_lnd_reached_ground
- && (float)fabs(_acc_z_lp) < 0.1f
- && _vel_z_lp > 0.5f * _params.land_speed) {
- _in_landing = true;
- }
-
- /* assume ground, cut thrust */
- if (_in_landing
- && _vel_z_lp < 0.1f) {
- thr_max = 0.0f;
- _in_landing = false;
- _lnd_reached_ground = true;
- }
-
- /* once we assumed to have reached the ground always cut the thrust.
- Only free fall detection below can revoke this
- */
- if (!_in_landing && _lnd_reached_ground) {
- thr_max = 0.0f;
- }
-
- /* if we suddenly fall, reset landing logic and remove thrust limit */
- if (_lnd_reached_ground
- /* XXX: magic value, assuming free fall above 4m/s2 acceleration */
- && (_acc_z_lp > 4.0f
- || _vel_z_lp > 2.0f * _params.land_speed)) {
- thr_max = _params.thr_max;
- _in_landing = false;
- _lnd_reached_ground = false;
- }
-
- } else {
- _in_landing = false;
- _lnd_reached_ground = false;
- }
-
- /* limit min lift */
- if (-thrust_sp(2) < thr_min) {
- thrust_sp(2) = -thr_min;
- saturation_z = true;
- }
-
- if (_control_mode.flag_control_velocity_enabled) {
-
- /* limit max tilt */
- if (thr_min >= 0.0f && tilt_max < M_PI_F / 2 - 0.05f) {
- /* absolute horizontal thrust */
- float thrust_sp_xy_len = math::Vector<2>(thrust_sp(0), thrust_sp(1)).length();
-
- if (thrust_sp_xy_len > 0.01f) {
- /* max horizontal thrust for given vertical thrust*/
- float thrust_xy_max = -thrust_sp(2) * tanf(tilt_max);
-
- if (thrust_sp_xy_len > thrust_xy_max) {
- float k = thrust_xy_max / thrust_sp_xy_len;
- thrust_sp(0) *= k;
- thrust_sp(1) *= k;
- saturation_xy = true;
- }
- }
- }
- }
-
- if (_control_mode.flag_control_altitude_enabled) {
- /* thrust compensation for altitude only control modes */推力的补偿 高度控制模式
- float att_comp;
-
- if (_R(2, 2) > TILT_COS_MAX) {
- att_comp = 1.0f / _R(2, 2);
-
- } else if (_R(2, 2) > 0.0f) {
- att_comp = ((1.0f / TILT_COS_MAX - 1.0f) / TILT_COS_MAX) * _R(2, 2) + 1.0f;
- saturation_z = true;
-
- } else {
- att_comp = 1.0f;
- saturation_z = true;
- }
-
- thrust_sp(2) *= att_comp;
- }
- ///限制最大推力///
- /* limit max thrust */
- thrust_abs = thrust_sp.length(); /* recalculate because it might have changed */
-
- if (thrust_abs > thr_max) {
- if (thrust_sp(2) < 0.0f) {
- if (-thrust_sp(2) > thr_max) {
- /* thrust Z component is too large, limit it */
- thrust_sp(0) = 0.0f;
- thrust_sp(1) = 0.0f;
- thrust_sp(2) = -thr_max;
- saturation_xy = true;
- saturation_z = true;
-
- } else {
- /* preserve thrust Z component and lower XY, keeping altitude is more important than position */
- float thrust_xy_max = sqrtf(thr_max * thr_max - thrust_sp(2) * thrust_sp(2));
- float thrust_xy_abs = math::Vector<2>(thrust_sp(0), thrust_sp(1)).length();
- float k = thrust_xy_max / thrust_xy_abs;
- thrust_sp(0) *= k;
- thrust_sp(1) *= k;
- saturation_xy = true;
- }
-
- } else {
- /* Z component is negative, going down, simply limit thrust vector */
- float k = thr_max / thrust_abs;
- thrust_sp *= k;
- saturation_xy = true;
- saturation_z = true;
- }
-
- thrust_abs = thr_max;
- }
- ///跟新积分//
- /* update integrals */
- if (_control_mode.flag_control_velocity_enabled && !saturation_xy) {
- thrust_int(0) += vel_err(0) * _params.vel_i(0) * dt;
- thrust_int(1) += vel_err(1) * _params.vel_i(1) * dt;
- }
-
- if (_control_mode.flag_control_climb_rate_enabled && !saturation_z) {
- thrust_int(2) += vel_err(2) * _params.vel_i(2) * dt;
-
- /* protection against flipping on ground when landing */
- if (thrust_int(2) > 0.0f) {
- thrust_int(2) = 0.0f;
- }
- }
- /根据推力矢量计算的姿态设定值//
- /* calculate attitude setpoint from thrust vector */
- if (_control_mode.flag_control_velocity_enabled) {
- /* desired body_z axis = -normalize(thrust_vector) */
- math::Vector<3> body_x;
- math::Vector<3> body_y;
- math::Vector<3> body_z;
-
- if (thrust_abs > SIGMA) {
- body_z = -thrust_sp / thrust_abs;
-
- } else {
- /* no thrust, set Z axis to safe value */
- body_z.zero();
- body_z(2) = 1.0f;
- }
-
- /* vector of desired yaw direction in XY plane, rotated by PI/2 */
- math::Vector<3> y_C(-sinf(_att_sp.yaw_body), cosf(_att_sp.yaw_body), 0.0f);
-
- if (fabsf(body_z(2)) > SIGMA) {
- /* desired body_x axis, orthogonal to body_z */
- body_x = y_C % body_z;
-
- /* keep nose to front while inverted upside down */
- if (body_z(2) < 0.0f) {
- body_x = -body_x;
- }
-
- body_x.normalize();
-
- } else {
- /* desired thrust is in XY plane, set X downside to construct correct matrix,
- * but yaw component will not be used actually */
- body_x.zero();
- body_x(2) = 1.0f;
- }
-
- /* desired body_y axis */
- body_y = body_z % body_x;
-
- /* fill rotation matrix */
- for (int i = 0; i < 3; i++) {
- R(i, 0) = body_x(i);
- R(i, 1) = body_y(i);
- R(i, 2) = body_z(i);
- }
- 复制旋转矩阵到姿态设定值主题中
- /* copy rotation matrix to attitude setpoint topic */
- memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
- _att_sp.R_valid = true;
- /复制四元数设定值到姿态设定值主题中///
- /* copy quaternion setpoint to attitude setpoint topic */
- math::Quaternion q_sp;
- q_sp.from_dcm(R);
- memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
- //计算欧拉角,只记录,不得用于控制//
- /* calculate euler angles, for logging only, must not be used for control */
- math::Vector<3> euler = R.to_euler();
- _att_sp.roll_body = euler(0);
- _att_sp.pitch_body = euler(1);
- /* yaw already used to construct rot matrix, but actual rotation matrix can have different yaw near singularity */
- /偏航已经用于构建rot矩阵,但实际旋转矩阵可以有奇点附近的不同偏航///
- } else if (!_control_mode.flag_control_manual_enabled) {
- /没有位置控制的自主高度控制(故障安全降落),强制水平姿态,不改变yaw///
- /* autonomous altitude control without position control (failsafe landing),
- * force level attitude, don't change yaw */
- R.from_euler(0.0f, 0.0f, _att_sp.yaw_body);
- 复制旋转矩阵到姿态设定值主题中
- /* copy rotation matrix to attitude setpoint topic */
- memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
- _att_sp.R_valid = true;
- /复制四元数设定值到姿态设定值主题中///
- /* copy quaternion setpoint to attitude setpoint topic */
- math::Quaternion q_sp;
- q_sp.from_dcm(R);
- memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
-
- _att_sp.roll_body = 0.0f;
- _att_sp.pitch_body = 0.0f;
- }
-
- _att_sp.thrust = thrust_abs;
-
- /* save thrust setpoint for logging */保存推理设定值在logging里
- _local_pos_sp.acc_x = thrust_sp(0) * ONE_G;
- _local_pos_sp.acc_y = thrust_sp(1) * ONE_G;
- _local_pos_sp.acc_z = thrust_sp(2) * ONE_G;
-
- _att_sp.timestamp = hrt_absolute_time();
-
-
- } else {
- reset_int_z = true;
- }
- }
-
- /* fill local position, velocity and thrust setpoint */
- _local_pos_sp.timestamp = hrt_absolute_time();
- _local_pos_sp.x = _pos_sp(0);
- _local_pos_sp.y = _pos_sp(1);
- _local_pos_sp.z = _pos_sp(2);
- _local_pos_sp.yaw = _att_sp.yaw_body;
- _local_pos_sp.vx = _vel_sp(0);
- _local_pos_sp.vy = _vel_sp(1);
- _local_pos_sp.vz = _vel_sp(2);
- 发布当地位置设定值
- /***************这个应该是这段程序处理的最后结果********************/
- /* publish local position setpoint */
- if (_local_pos_sp_pub != nullptr) {
- orb_publish(ORB_ID(vehicle_local_position_setpoint), _local_pos_sp_pub, &_local_pos_sp);
-
- } else {
- _local_pos_sp_pub = orb_advertise(ORB_ID(vehicle_local_position_setpoint), &_local_pos_sp);
- }
-
- } else {位置控制模式失能,那么复位设定值
- /* position controller disabled, reset setpoints */
- _reset_alt_sp = true;
- _reset_pos_sp = true;
- _mode_auto = false;
- reset_int_z = true;
- reset_int_xy = true;
- control_vel_enabled_prev = false;
-
- /* store last velocity in case a mode switch to position control occurs */
- _vel_sp_prev = _vel;
- }
- //从手动控制中产生姿态设定值//
- /* generate attitude setpoint from manual controls */
- if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_attitude_enabled) {
-
- /* reset yaw setpoint to current position if needed */
- if (reset_yaw_sp) {
- reset_yaw_sp = false;
- _att_sp.yaw_body = _yaw;
- }
- //在地上时,不动偏航方向/
- /* do not move yaw while sitting on the ground */
- else if (!_vehicle_status.condition_landed &&
- !(!_control_mode.flag_control_altitude_enabled && _manual.z < 0.1f)) {
-
- /* we want to know the real constraint, and global overrides manual */
- const float yaw_rate_max = (_params.man_yaw_max < _params.global_yaw_max) ? _params.man_yaw_max :
- _params.global_yaw_max;
- const float yaw_offset_max = yaw_rate_max / _params.mc_att_yaw_p;
-
- _att_sp.yaw_sp_move_rate = _manual.r * yaw_rate_max;
- float yaw_target = _wrap_pi(_att_sp.yaw_body + _att_sp.yaw_sp_move_rate * dt);
- float yaw_offs = _wrap_pi(yaw_target - _yaw);
- 如果对于系统跟踪,yaw偏移变得过大,那么停止其转移
- // If the yaw offset became too big for the system to track stop
- // shifting it
-
- // XXX this needs inspection - probably requires a clamp, not an if
- if (fabsf(yaw_offs) < yaw_offset_max) {
- _att_sp.yaw_body = yaw_target;
- }
- }
- //直接控制侧倾和俯仰,如果协助速度控制器没有被激活
- /* control roll and pitch directly if we no aiding velocity controller is active */
- if (!_control_mode.flag_control_velocity_enabled) {
- _att_sp.roll_body = _manual.y * _params.man_roll_max;
- _att_sp.pitch_body = -_manual.x * _params.man_pitch_max;
- }
- //控制油门直接,如果没有爬升率控制器被激活/
- /* control throttle directly if no climb rate controller is active */
- if (!_control_mode.flag_control_climb_rate_enabled) {
- float thr_val = throttle_curve(_manual.z, _params.thr_hover);
- _att_sp.thrust = math::min(thr_val, _manual_thr_max.get());
-
- /* enforce minimum throttle if not landed */
- if (!_vehicle_status.condition_landed) {
- _att_sp.thrust = math::max(_att_sp.thrust, _manual_thr_min.get());
- }
- }
-
- math::Matrix<3, 3> R_sp;
- //构建姿态设定值的旋转矩阵///
- /* construct attitude setpoint rotation matrix */
- R_sp.from_euler(_att_sp.roll_body, _att_sp.pitch_body, _att_sp.yaw_body);
- memcpy(&_att_sp.R_body[0], R_sp.data, sizeof(_att_sp.R_body));
- 为所有非姿态飞行模式 复位加速度设定值/
- /* reset the acceleration set point for all non-attitude flight modes */
- if (!(_control_mode.flag_control_offboard_enabled &&
- !(_control_mode.flag_control_position_enabled ||
- _control_mode.flag_control_velocity_enabled))) {
-
- _thrust_sp_prev = R_sp * math::Vector<3>(0, 0, -_att_sp.thrust);
- }
- /将四元数设定值复制到姿态设定值的主题中/
- /* copy quaternion setpoint to attitude setpoint topic */
- math::Quaternion q_sp;
- q_sp.from_dcm(R_sp);
- memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
- _att_sp.timestamp = hrt_absolute_time();
-
- } else {
- reset_yaw_sp = true;
- }
-
- /* update previous velocity for velocity controller D part */
- _vel_prev = _vel;
- /发布设定值//
- /* publish attitude setpoint
- * Do not publish if offboard is enabled but position/velocity control is disabled,
- * in this case the attitude setpoint is published by the mavlink app. Also do not publish
- * if the vehicle is a VTOL and it's just doing a transition (the VTOL attitude control module will generate
- * attitude setpoints for the transition).
- */
- if (!(_control_mode.flag_control_offboard_enabled &&
- !(_control_mode.flag_control_position_enabled ||
- _control_mode.flag_control_velocity_enabled))) {
-
- if (_att_sp_pub != nullptr) {
- orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
-
- } else if (_attitude_setpoint_id) {
- _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
- }
- }
- /手动油门控制后,将高度控制器积分(悬停油门)复位到手动油门///
- /* reset altitude controller integral (hovering throttle) to manual throttle after manual throttle control */
- reset_int_z_manual = _control_mode.flag_armed && _control_mode.flag_control_manual_enabled
- && !_control_mode.flag_control_climb_rate_enabled;
- }
-
- mavlink_log_info(&_mavlink_log_pub, "[mpc] stopped");
-
- _control_task = -1;
- }
这些设定值的确定是不是就是控制策略的体现?
- void
- MulticopterPositionControl::poll_subscriptions()
- {
- bool updated;
- /**********************机体状态跟新**************************/
- orb_check(_vehicle_status_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
-
- /* set correct uORB ID, depending on if vehicle is VTOL or not */
- if (!_attitude_setpoint_id) {
- if (_vehicle_status.is_vtol) {
- _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
-
- } else {
- _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
- }
- }
- }
- /**********************控制状态跟新**************************/
- orb_check(_ctrl_state_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
-
- /* get current rotation matrix and euler angles from control state quaternions */
- math::Quaternion q_att(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
- _R = q_att.to_dcm();
- math::Vector<3> euler_angles;
- euler_angles = _R.to_euler();
- _yaw = euler_angles(2);
- }
- /**********************setpoint状态跟新**************************/
- orb_check(_att_sp_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
- }
-
- orb_check(_control_mode_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode);
- }
- /**********************手动控制状态跟新**************************/
- orb_check(_manual_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(manual_control_setpoint), _manual_sub, &_manual);
- }
- /**********************解锁状态跟新**************************/
- orb_check(_arming_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(actuator_armed), _arming_sub, &_arming);
- }
- /**********************位置跟新**************************/
- orb_check(_local_pos_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
- }
- }
- void
- MulticopterPositionControl::update_ref()
- {
- if (_local_pos.ref_timestamp != _ref_timestamp) {
- double lat_sp, lon_sp;//维度设定、经度设定
- float alt_sp = 0.0f;//姿态设定
-
- if (_ref_timestamp != 0) {
- /*************在整体框架下计算当前位置设定值***************/
- /* calculate current position setpoint in global frame */
- map_projection_reproject(&_ref_pos, _pos_sp(0), _pos_sp(1), &lat_sp, &lon_sp);
- alt_sp = _ref_alt - _pos_sp(2);
- }
- /*************跟新投影参考*********************/
- /* update local projection reference */
- map_projection_init(&_ref_pos, _local_pos.ref_lat, _local_pos.ref_lon);
- _ref_alt = _local_pos.ref_alt;
-
- if (_ref_timestamp != 0) {
- /*********************设置新的位置设定值*******************/
- /* reproject position setpoint to new reference */
- map_projection_project(&_ref_pos, lat_sp, lon_sp, &_pos_sp.data[0], &_pos_sp.data[1]);
- _pos_sp(2) = -(alt_sp - _ref_alt);
- }
-
- _ref_timestamp = _local_pos.ref_timestamp;
- }
- }
- void
- MulticopterPositionControl::control_manual(float dt)
- {
- math::Vector<3> req_vel_sp; // X,Y in local frame and Z in global (D), in [-1,1] normalized range
- req_vel_sp.zero();
-
- if (_control_mode.flag_control_altitude_enabled) {
- /* set vertical velocity setpoint with throttle stick */用油门棒设置垂直速度
- req_vel_sp(2) = -scale_control(_manual.z - 0.5f, 0.5f, _params.alt_ctl_dz, _params.alt_ctl_dy); // D
- }
-
- if (_control_mode.flag_control_position_enabled) {
- /* set horizontal velocity setpoint with roll/pitch stick */用roll/pitch棒设置水平速度
- req_vel_sp(0) = _manual.x;
- req_vel_sp(1) = _manual.y;
- }
-
- if (_control_mode.flag_control_altitude_enabled) {
- /* reset alt setpoint to current altitude if needed */复位姿态设定值
- reset_alt_sp();
- }
-
- if (_control_mode.flag_control_position_enabled) {
- /* reset position setpoint to current position if needed */复位位置设定值
- reset_pos_sp();
- }
-
- /* limit velocity setpoint */限制速度设定值
- float req_vel_sp_norm = req_vel_sp.length();
-
- if (req_vel_sp_norm > 1.0f) {
- req_vel_sp /= req_vel_sp_norm;//相当于是向量除以它的模值
- }
- ///_req_vel_sp的范围是0到1,围绕yaw旋转
- /* _req_vel_sp scaled to 0..1, scale it to max speed and rotate around yaw */
- math::Matrix<3, 3> R_yaw_sp;
- R_yaw_sp.from_euler(0.0f, 0.0f, _att_sp.yaw_body);
- math::Vector<3> req_vel_sp_scaled = R_yaw_sp * req_vel_sp.emult(
- _params.vel_cruise); // in NED and scaled to actual velocity在NED旋转方式下缩放到实际速度
- /用户辅助模式:用户控制速度,但是,如果速度足够小,相应的轴的位置就会保持
- /*
- * assisted velocity mode: user controls velocity, but if velocity is small enough, position
- * hold is activated for the corresponding axis
- */
-
- /* horizontal axes */水平轴
- if (_control_mode.flag_control_position_enabled) {
- /* check for pos. hold */检测位置的保持状态
- if (fabsf(req_vel_sp(0)) < _params.hold_xy_dz && fabsf(req_vel_sp(1)) < _params.hold_xy_dz) {
- if (!_pos_hold_engaged) {
- if (_params.hold_max_xy < FLT_EPSILON || (fabsf(_vel(0)) < _params.hold_max_xy
- && fabsf(_vel(1)) < _params.hold_max_xy)) {
- _pos_hold_engaged = true;
-
- } else {
- _pos_hold_engaged = false;
- }
- }
-
- } else {
- _pos_hold_engaged = false;
- }
-
- /* set requested velocity setpoint */设置所需的速度设定值
- if (!_pos_hold_engaged) {
- _pos_sp(0) = _pos(0);
- _pos_sp(1) = _pos(1);
- //速度设定值会被利用,位置设定值不会被用/
- _run_pos_control = false; /* request velocity setpoint to be used, instead of position setpoint */
- _vel_sp(0) = req_vel_sp_scaled(0);
- _vel_sp(1) = req_vel_sp_scaled(1);
- }
- }
-
- /* vertical axis */垂直轴
- if (_control_mode.flag_control_altitude_enabled) {
- /* check for pos. hold */
- if (fabsf(req_vel_sp(2)) < FLT_EPSILON) {
- if (!_alt_hold_engaged) {
- if (_params.hold_max_z < FLT_EPSILON || fabsf(_vel(2)) < _params.hold_max_z) {
- _alt_hold_engaged = true;
-
- } else {
- _alt_hold_engaged = false;
- }
- }
-
- } else {
- _alt_hold_engaged = false;
- }
-
- /* set requested velocity setpoint */
- if (!_alt_hold_engaged) {
- _run_alt_control = false; /* request velocity setpoint to be used, instead of altitude setpoint */
- _vel_sp(2) = req_vel_sp_scaled(2);
- _pos_sp(2) = _pos(2);
- }
- }
- }
- #ifdef __cplusplus
- struct __EXPORT position_setpoint_triplet_s {
- #else
- struct position_setpoint_triplet_s {
- #endif
- struct position_setpoint_s previous;
- struct position_setpoint_s current;
- struct position_setpoint_s next;
- uint8_t nav_state;
- #ifdef __cplusplus
- #endif
- };
整个MulticopterPositionControl::task_main()的输出应该是
- orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
- orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
- orb_publish(ORB_ID(vehicle_local_position_setpoint), _local_pos_sp_pub, &_local_pos_sp);
其中orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);是在main的最下面,应该这个是最后处理的结果
但是全局搜索ORB_ID(vehicle_local_position_setpoint)- if (!_attitude_setpoint_id) {
- if (_vehicle_status.is_vtol) {
- _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
-
- } else {
- _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
- }
- }
再看看
- void
- MulticopterPositionControl::task_main()
- {
-
- /*
- * do subscriptions
- */
- _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
- _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
- _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
- _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
- _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
- _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
- _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
- _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
全局搜索vehicle_attitude_setpoint
- if (!_attitude_setpoint_id) {
- if (_vehicle_status.is_vtol) {
- _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
-
- } else {
- _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
- }
- }
//ardupilot/modules/PX4Firmware/src/modules/mc_att_control/mc_att_control_main.cpp
- void
- MulticopterAttitudeControl::vehicle_attitude_setpoint_poll()
- {
- /* check if there is a new setpoint */
- bool updated;
- orb_check(_v_att_sp_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
- }
- }
突然发现//ardupilot/modules/PX4Firmware/src/modules/vtol_att_control//vtol_att_control_main.cpp中也有orb_copy(ORB_ID(vehicle_attitude_setpoint)
- void
- VtolAttitudeControl::vehicle_attitude_setpoint_poll()
- {
- /* check if there is a new setpoint */
- bool updated;
- orb_check(_v_att_sp_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
- }
- }
- void
- VtolAttitudeControl::mc_virtual_att_sp_poll()
- {
- bool updated;
-
- orb_check(_mc_virtual_att_sp_sub, &updated);
-
- if (updated) {
- orb_copy(ORB_ID(mc_virtual_attitude_setpoint), _mc_virtual_att_sp_sub , &_mc_virtual_att_sp);
- }
-
- }
- void VtolAttitudeControl::publish_att_sp()
- {
- if (_v_att_sp_pub != nullptr) {
- /* publish the attitude setpoint */
- orb_publish(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_pub, &_v_att_sp);
-
- } else {
- /* advertise and publish */
- _v_att_sp_pub = orb_advertise(ORB_ID(vehicle_attitude_setpoint), &_v_att_sp);
- }
- }
好奇葩啊,//ardupilot/modules/PX4Firmware/src/modules/vtol_att_control//vtol_att_control_main.cppextern "C" __EXPORT int mc_att_control_main(int argc, char *argv[]);
- int mc_att_control_main(int argc, char *argv[])
- {
- if (argc < 2) {
- warnx("usage: mc_att_control {start|stop|status}");
- return 1;
- }
-
- if (!strcmp(argv[1], "start")) {
-
- if (mc_att_control::g_control != nullptr) {
- warnx("already running");
- return 1;
- }
-
- mc_att_control::g_control = new MulticopterAttitudeControl;
-
- if (mc_att_control::g_control == nullptr) {
- warnx("alloc failed");
- return 1;
- }
-
- if (OK != mc_att_control::g_control->start()) {
- delete mc_att_control::g_control;
- mc_att_control::g_control = nullptr;
- warnx("start failed");
- return 1;
- }
-
- return 0;
- }
-
- if (!strcmp(argv[1], "stop")) {
- if (mc_att_control::g_control == nullptr) {
- warnx("not running");
- return 1;
- }
-
- delete mc_att_control::g_control;
- mc_att_control::g_control = nullptr;
- return 0;
- }
-
- if (!strcmp(argv[1], "status")) {
- if (mc_att_control::g_control) {
- warnx("running");
- return 0;
-
- } else {
- warnx("not running");
- return 1;
- }
- }
-
- warnx("unrecognized command");
- return 1;
- }
这里MulticopterAttitudeControl
*g_control;*g_control是最大的一个类的实例
- /* fetch initial parameter values */
- parameters_update();
里面好多参数,不知道是不是上位机配置的参数,就是说是不是把上位机的各种关于飞行的参数存到了sd卡中,在通过这个函数跟新到程序中用于飞行器的控制??
- int
- MulticopterAttitudeControl::start()
- {
- ASSERT(_control_task == -1);
-
- /* start the task */
- _control_task = px4_task_spawn_cmd("mc_att_control",
- SCHED_DEFAULT,
- SCHED_PRIORITY_MAX - 5,
- 1500,
- (px4_main_t)&MulticopterAttitudeControl::task_main_trampoline,
- nullptr);
-
- if (_control_task < 0) {
- warn("task start failed");
- return -errno;
- }
-
- return OK;
- }
- void
- MulticopterAttitudeControl::task_main_trampoline(int argc, char *argv[])
- {
- mc_att_control::g_control->task_main();
- }
- void
- MulticopterAttitudeControl::task_main()
- {
- /**************************订阅各种信息**************************/
- /*
- * do subscriptions
- */
- _v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- _v_rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
- _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
- _v_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _manual_control_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
- _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
- _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
- _motor_limits_sub = orb_subscribe(ORB_ID(multirotor_motor_limits));
- /**************************初始化各种参数**************************/
- /* initialize parameters cache */
- parameters_update();
- /**************************启动机体姿态原函数**************************/
- /* wakeup source: vehicle attitude */
- px4_pollfd_struct_t fds[1];
-
- fds[0].fd = _ctrl_state_sub;
- fds[0].events = POLLIN;
- /**************************大循环**************************/
- while (!_task_should_exit) {
- /等待100ms 为了获取数据/
- /* wait for up to 100ms for data */
- int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 100);
-
- /* timed out - periodic check for _task_should_exit */
- if (pret == 0) {
- continue;
- }
-
- /* this is undesirable but not much we can do - might want to flag unhappy status */
- if (pret < 0) {
- warn("mc att ctrl: poll error %d, %d", pret, errno);
- /* sleep a bit before next try */
- usleep(100000);
- continue;
- }
-
- perf_begin(_loop_perf);
- ///运行姿态变化控制器//
- /* run controller on attitude changes */
- if (fds[0].revents & POLLIN) {
- static uint64_t last_run = 0;
- float dt = (hrt_absolute_time() - last_run) / 1000000.0f;
- last_run = hrt_absolute_time();
- /防止dt太小或太大 2ms<dt<20ms
- /* guard against too small (< 2ms) and too large (> 20ms) dt's */
- if (dt < 0.002f) {
- dt = 0.002f;
-
- } else if (dt > 0.02f) {
- dt = 0.02f;
- }
-
- /* copy attitude and control state topics */
- orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
-
- /* check for updates in other topics */
- parameter_update_poll();
- vehicle_control_mode_poll();
- arming_status_poll();
- vehicle_manual_poll();
- vehicle_status_poll();
- vehicle_motor_limits_poll();
- 若xy轴的设定值大于阈值,那么不运行姿态控制/
- /* Check if we are in rattitude mode and the pilot is above the threshold on pitch
- * or roll (yaw can rotate 360 in normal att control). If both are true don't
- * even bother running the attitude controllers */
- if (_vehicle_status.main_state == vehicle_status_s::MAIN_STATE_RATTITUDE) {
- if (fabsf(_manual_control_sp.y) > _params.rattitude_thres ||
- fabsf(_manual_control_sp.x) > _params.rattitude_thres) {
- _v_control_mode.flag_control_attitude_enabled = false;
- }
- }
- /姿态控制使能
- if (_v_control_mode.flag_control_attitude_enabled) {
-
- if (_ts_opt_recovery == nullptr) {
- // the tailsitter recovery instance has not been created, thus, the vehicle
- // is not a tailsitter, do normal attitude control
- control_attitude(dt);
-
- } else {
- vehicle_attitude_setpoint_poll();
- _thrust_sp = _v_att_sp.thrust;
- math::Quaternion q(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
- math::Quaternion q_sp(&_v_att_sp.q_d[0]);
- _ts_opt_recovery->setAttGains(_params.att_p, _params.yaw_ff);
- _ts_opt_recovery->calcOptimalRates(q, q_sp, _v_att_sp.yaw_sp_move_rate, _rates_sp);
-
- /* limit rates */
- for (int i = 0; i < 3; i++) {
- _rates_sp(i) = math::constrain(_rates_sp(i), -_params.mc_rate_max(i), _params.mc_rate_max(i));
- }
- }
-
- /* publish attitude rates setpoint */
- _v_rates_sp.roll = _rates_sp(0);
- _v_rates_sp.pitch = _rates_sp(1);
- _v_rates_sp.yaw = _rates_sp(2);
- _v_rates_sp.thrust = _thrust_sp;
- _v_rates_sp.timestamp = hrt_absolute_time();
-
- if (_v_rates_sp_pub != nullptr) {
- orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
-
- } else if (_rates_sp_id) {
- _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
- }
-
- //}
-
- } else {
- /手动控制使能//
- /* attitude controller disabled, poll rates setpoint topic */
- if (_v_control_mode.flag_control_manual_enabled) {
- ///特技模式/
- /* manual rates control - ACRO mode */
- _rates_sp = math::Vector<3>(_manual_control_sp.y, -_manual_control_sp.x,
- _manual_control_sp.r).emult(_params.acro_rate_max);
- _thrust_sp = math::min(_manual_control_sp.z, MANUAL_THROTTLE_MAX_MULTICOPTER);
- /发布角速度设定值
- /* publish attitude rates setpoint */
- _v_rates_sp.roll = _rates_sp(0);
- _v_rates_sp.pitch = _rates_sp(1);
- _v_rates_sp.yaw = _rates_sp(2);
- _v_rates_sp.thrust = _thrust_sp;
- _v_rates_sp.timestamp = hrt_absolute_time();
-
- if (_v_rates_sp_pub != nullptr) {
- orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
-
- } else if (_rates_sp_id) {
- _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
- }
-
- }
- //非特技模式//
- else {
- //速度设定值来自于vehicle_rates_setpoint//
- //vehicle_rates_setpoint来自于哪里??///
- /* attitude controller disabled, poll rates setpoint topic */
- vehicle_rates_setpoint_poll();
- _rates_sp(0) = _v_rates_sp.roll;
- _rates_sp(1) = _v_rates_sp.pitch;
- _rates_sp(2) = _v_rates_sp.yaw;
- _thrust_sp = _v_rates_sp.thrust;
- }
- }
- ///速度控制/
- if (_v_control_mode.flag_control_rates_enabled) {
- //角速度控制
- control_attitude_rates(dt);
- //发布执行器控制///
- //这个就是pwm吗??
- /* publish actuator controls */
- _actuators.control[0] = (PX4_ISFINITE(_att_control(0))) ? _att_control(0) : 0.0f;
- _actuators.control[1] = (PX4_ISFINITE(_att_control(1))) ? _att_control(1) : 0.0f;
- _actuators.control[2] = (PX4_ISFINITE(_att_control(2))) ? _att_control(2) : 0.0f;
- _actuators.control[3] = (PX4_ISFINITE(_thrust_sp)) ? _thrust_sp : 0.0f;
- _actuators.timestamp = hrt_absolute_time();
- _actuators.timestamp_sample = _ctrl_state.timestamp;
-
- _controller_status.roll_rate_integ = _rates_int(0);
- _controller_status.pitch_rate_integ = _rates_int(1);
- _controller_status.yaw_rate_integ = _rates_int(2);
- _controller_status.timestamp = hrt_absolute_time();
-
- if (!_actuators_0_circuit_breaker_enabled) {
- if (_actuators_0_pub != nullptr) {
-
- orb_publish(_actuators_id, _actuators_0_pub, &_actuators);
- perf_end(_controller_latency_perf);
-
- } else if (_actuators_id) {
- _actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
- }
-
- }
-
- /* publish controller status */
- if (_controller_status_pub != nullptr) {
- orb_publish(ORB_ID(mc_att_ctrl_status), _controller_status_pub, &_controller_status);
-
- } else {
- _controller_status_pub = orb_advertise(ORB_ID(mc_att_ctrl_status), &_controller_status);
- }
- }
- }
-
- perf_end(_loop_perf);
- }
-
- _control_task = -1;
- return;
- }
看看这3段控制程序的输入输出,大概能猜想他们的运行逻辑并不是并列的,很有可能_v_control_mode.flag_control_rates_enabled跟在_v_control_mode.flag_control_attitude_enabled之后,这样就形成了常用的外环角度(也就是这里的姿态)内环角速度(姿态速度)的控制结构,这个还需要细看里面的输入输出和标志位如何赋值控制运行逻辑。
- /**
- * Attitude controller.
- * Input: 'vehicle_attitude_setpoint' topics (depending on mode)
- * Output: '_rates_sp' vector, '_thrust_sp'
- */
- /*************************注意看注释!!********************/
- /***********输入是'vehicle_attitude_setpoint'主题***********/
- /************输出是角速度设定值向量和油门设定值*************/
- void
- MulticopterAttitudeControl::control_attitude(float dt)
- {
- vehicle_attitude_setpoint_poll();//获取'vehicle_attitude_setpoint'主题
-
- _thrust_sp = _v_att_sp.thrust;
- //构建姿态设定值的旋转矩阵就是vehicle_attitude_setpoint_poll()获取的//
- /* construct attitude setpoint rotation matrix */
- math::Matrix<3, 3> R_sp;
- R_sp.set(_v_att_sp.R_body);//这里做的事只是把订阅_v_att_sp复制到一个新的地方
- /**** void set(const float *d) {
- **** memcpy(data, d, sizeof(data));
- **** }
- ****/
- //定义一个控制状态的四元数和相应的方向余弦矩阵(dcm)/
- /* get current rotation matrix from control state quaternions */
- math::Quaternion q_att(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
- math::Matrix<3, 3> R = q_att.to_dcm();
- /输入就准备好了,就是姿态设定值,并转变成能用的形式四元数和dcm///
- /* all input data is ready, run controller itself */
-
- /* try to move thrust vector shortest way, because yaw response is slower than roll/pitch */
- math::Vector<3> R_z(R(0, 2), R(1, 2), R(2, 2));//控制状态的z轴
- math::Vector<3> R_sp_z(R_sp(0, 2), R_sp(1, 2), R_sp(2, 2));//设定姿态的z轴
-
- /* axis and sin(angle) of desired rotation */轴与角的理想旋转
- math::Vector<3> e_R = R.transposed() * (R_z % R_sp_z);//transposed()换位函数,%是求叉积的意思
- /*** ardupilot/modules/PX4Firmware/src/lib/matrix/matrix/Matrix.hpp
- *** Matrix<Type, N, M> transpose() const
- *** {
- *** Matrix<Type, N, M> res;
- *** const Matrix<Type, M, N> &self = *this;
- ***
- *** for (size_t i = 0; i < M; i++) {
- *** for (size_t j = 0; j < N; j++) {
- *** res(j, i) = self(i, j);
- *** }
- *** }
- ***
- *** return res;
- *** }
- ***/
- /* calculate angle error */计算角的误差
- float e_R_z_sin = e_R.length();
- float e_R_z_cos = R_z * R_sp_z;
- //计算姿态角度误差(姿态误差),一个数学知识背景:由公式a×b=︱a︱︱b︱sinθ,a•b=︱a︱︱b︱cosθ
- //这里的R_z和R_sp_z都是单位向量,模值为1,因此误差向量e_R(a×b叉积就是误差)的模就是sinθ,点积就是cosθ。
- /*** ardupilot/modules/PX4Firmware/src/lib/mathlib/math/Vector.hpp
- *** float length() const {
- *** float res = 0.0f;
- ***
- *** for (unsigned int i = 0; i < N; i++)
- *** res += data[i] * data[i];
- ***
- *** return sqrtf(res);
- *** }
- ***/
- /* calculate weight for yaw control */计算yaw控制的权重
- float yaw_w = R_sp(2, 2) * R_sp(2, 2);//姿态设定值矩阵的第三行第三列元素的平方
-
- /* calculate rotation matrix after roll/pitch only rotation */
- math::Matrix<3, 3> R_rp;
-
- if (e_R_z_sin > 0.0f) {
- /* get axis-angle representation */
- float e_R_z_angle = atan2f(e_R_z_sin, e_R_z_cos);//得到z轴的误差角度
- math::Vector<3> e_R_z_axis = e_R / e_R_z_sin;
- /*** R.transposed() * (R_z % R_sp_z)
- *** -----------------------------------
- *** ||R.transposed() * (R_z % R_sp_z)||
- ***/
- /***********这些式子的数据具体怎么算的可以看得出来,具体含义应该与理论知识有关吧**********/
- e_R = e_R_z_axis * e_R_z_angle;
-
- /* cross product matrix for e_R_axis */
- math::Matrix<3, 3> e_R_cp;
- e_R_cp.zero();
- e_R_cp(0, 1) = -e_R_z_axis(2);
- e_R_cp(0, 2) = e_R_z_axis(1);
- e_R_cp(1, 0) = e_R_z_axis(2);
- e_R_cp(1, 2) = -e_R_z_axis(0);
- e_R_cp(2, 0) = -e_R_z_axis(1);
- e_R_cp(2, 1) = e_R_z_axis(0);
-
- /* rotation matrix for roll/pitch only rotation */
- R_rp = R * (_I + e_R_cp * e_R_z_sin + e_R_cp * e_R_cp * (1.0f - e_R_z_cos));
-
- } else {
- /* zero roll/pitch rotation */
- R_rp = R;
- }
-
- /* R_rp and R_sp has the same Z axis, calculate yaw error */
- math::Vector<3> R_sp_x(R_sp(0, 0), R_sp(1, 0), R_sp(2, 0));
- math::Vector<3> R_rp_x(R_rp(0, 0), R_rp(1, 0), R_rp(2, 0));
- e_R(2) = atan2f((R_rp_x % R_sp_x) * R_sp_z, R_rp_x * R_sp_x) * yaw_w;
-
- if (e_R_z_cos < 0.0f) {
- /* for large thrust vector rotations use another rotation method:
- * calculate angle and axis for R -> R_sp rotation directly */
- math::Quaternion q;
- q.from_dcm(R.transposed() * R_sp);
- math::Vector<3> e_R_d = q.imag();
- e_R_d.normalize();
- e_R_d *= 2.0f * atan2f(e_R_d.length(), q(0));
-
- /* use fusion of Z axis based rotation and direct rotation */
- float direct_w = e_R_z_cos * e_R_z_cos * yaw_w;//计算权重
- e_R = e_R * (1.0f - direct_w) + e_R_d * direct_w;
- }
- ///计算角速度设定值 也是矩阵表达的1*3矩阵///
- /* calculate angular rates setpoint */
- _rates_sp = _params.att_p.emult(e_R);
-
- /* limit rates */限制角速度大小
- for (int i = 0; i < 3; i++) {
- if (_v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
- _rates_sp(i) = math::constrain(_rates_sp(i), -_params.auto_rate_max(i), _params.auto_rate_max(i));
- } else {
- _rates_sp(i) = math::constrain(_rates_sp(i), -_params.mc_rate_max(i), _params.mc_rate_max(i));
- }
- }
- //风向标模式,抑制yaw角速度(风向标模式是定航向的意思吗??)///
- //yaw控制失能、速度模式使能、非手动模式/
- /* weather-vane mode, dampen yaw rate */
- if (_v_att_sp.disable_mc_yaw_control == true && _v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
- float wv_yaw_rate_max = _params.auto_rate_max(2) * _params.vtol_wv_yaw_rate_scale;
- _rates_sp(2) = math::constrain(_rates_sp(2), -wv_yaw_rate_max, wv_yaw_rate_max);
- // prevent integrator winding up in weathervane mode
- _rates_int(2) = 0.0f;
- }
- ///反馈角速度设定值(2) 矩阵中第三个元素/
- /* feed forward yaw setpoint rate */
- _rates_sp(2) += _v_att_sp.yaw_sp_move_rate * yaw_w * _params.yaw_ff;
- ///风向标模式,减小yaw角速度///
- /* weather-vane mode, scale down yaw rate */
- if (_v_att_sp.disable_mc_yaw_control == true && _v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
- float wv_yaw_rate_max = _params.auto_rate_max(2) * _params.vtol_wv_yaw_rate_scale;
- _rates_sp(2) = math::constrain(_rates_sp(2), -wv_yaw_rate_max, wv_yaw_rate_max);
- // prevent integrator winding up in weathervane mode
- _rates_int(2) = 0.0f;
- }
-
- }
- /*
- * Attitude rates controller.
- * Input: '_rates_sp' vector, '_thrust_sp'
- * Output: '_att_control' vector
- */
- /*************************注意看注释!!********************/
- /************输入是角速度设定值向量、油门设定值*************/
- /**************************姿态控制值***********************/
- void
- MulticopterAttitudeControl::control_attitude_rates(float dt)
- {
- /* reset integral if disarmed */如果锁定,则复位角速度积分
- if (!_armed.armed || !_vehicle_status.is_rotary_wing) {
- _rates_int.zero();
- }
- //当前机体角速度设定值//
- /由此可知_ctrl_state表示的传感器测得的机体状态
- //_ctrl_state来源应该是ardupilot/modules/PX4Firmware/src/modules/attitude_estimator_q/attitude_estimator_q.main.cpp//
- /* current body angular rates */
- math::Vector<3> rates;
- rates(0) = _ctrl_state.roll_rate;
- rates(1) = _ctrl_state.pitch_rate;
- rates(2) = _ctrl_state.yaw_rate;
- 角速度误差=角速度设定值-机体角速度///
- /* angular rates error */
- math::Vector<3> rates_err = _rates_sp - rates;
- /_att_control的三个量分别为pitch、roll、yaw方向的pwm值
- /*** _att_control的三个量就是下面的Roll、pitch、yaw
- *** Motor1=(int)(COMD.THR + Roll - pitch + yaw);
- *** Motor2=(int)(COMD.THR + Roll + pitch - yaw);
- *** Motor3=(int)(COMD.THR - Roll + pitch + yaw);
- *** Motor4=(int)(COMD.THR - Roll - pitch - yaw);
- ***/
- _att_control = _params.rate_p.emult(rates_err) + _params.rate_d.emult(_rates_prev - rates) / dt + _rates_int +
- _params.rate_ff.emult(_rates_sp - _rates_sp_prev) / dt;
- _rates_sp_prev = _rates_sp;
- _rates_prev = rates;
- //注意这里用的算法pwm=P*error+D*(角速度_last-角速度_now)/dt+角速度积分+(角速度设定值_now-角速度设定值_last)/dt
- /*** Matrix<Type, M, N> emult(const Matrix<Type, M, N> &other) const
- *** {
- *** Matrix<Type, M, N> res;
- *** const Matrix<Type, M, N> &self = *this;
- ***
- *** for (size_t i = 0; i < M; i++) {
- *** for (size_t j = 0; j < N; j++) {
- *** res(i , j) = self(i, j)*other(i, j);
- *** }
- *** }
- ***
- *** return res;
- *** }
- ***/
- /* update integral only if not saturated on low limit and if motor commands are not saturated */
- /下面是积分的计算,注意积分饱和问题
- if (_thrust_sp > MIN_TAKEOFF_THRUST && !_motor_limits.lower_limit && !_motor_limits.upper_limit) {
- for (int i = 0; i < 3; i++) {
- if (fabsf(_att_control(i)) < _thrust_sp) {
- float rate_i = _rates_int(i) + _params.rate_i(i) * rates_err(i) * dt;
-
- if (PX4_ISFINITE(rate_i) && rate_i > -RATES_I_LIMIT && rate_i < RATES_I_LIMIT &&
- _att_control(i) > -RATES_I_LIMIT && _att_control(i) < RATES_I_LIMIT) {
- _rates_int(i) = rate_i;
- }
- }
- }
- }
- }
- <pre name="code" class="cpp"> ardupilot/modules/PX4Firmware/src/modules/position_estimator_inav/position_estimator_inav_main.cpp
- int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
- int actuator_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
- int armed_sub = orb_subscribe(ORB_ID(actuator_armed));
- int sensor_combined_sub = orb_subscribe(ORB_ID(sensor_combined));
- int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
- int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
- int vehicle_gps_position_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
- int vision_position_estimate_sub = orb_subscribe(ORB_ID(vision_position_estimate));
- int att_pos_mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
- int distance_sensor_sub = orb_subscribe(ORB_ID(distance_sensor));
- int vehicle_rate_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
-
- orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
- orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);
- orb_copy(ORB_ID(parameter_update), parameter_update_sub, &update);
- orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_sub, &actuator);//actuator_controls_0
- orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);
- orb_copy(ORB_ID(distance_sensor), distance_sensor_sub, &lidar);
- orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);
- orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
- orb_copy(ORB_ID(vision_position_estimate), vision_position_estimate_sub, &vision);
- orb_copy(ORB_ID(att_pos_mocap), att_pos_mocap_sub, &mocap);
- orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);
-
- orb_advert_t vehicle_local_position_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
- orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
- vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
- orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
-
-
-
- ardupilot/modules/PX4Firmware/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp
- _sensors_sub = orb_subscribe(ORB_ID(sensor_combined));
- _vision_sub = orb_subscribe(ORB_ID(vision_position_estimate));
- _mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
- _airspeed_sub = orb_subscribe(ORB_ID(airspeed));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
-
- orb_copy(ORB_ID(sensor_combined), _sensors_sub, &sensors)
- orb_copy(ORB_ID(vision_position_estimate), _vision_sub, &_vision);
- orb_copy(ORB_ID(att_pos_mocap), _mocap_sub, &_mocap);
- orb_copy(ORB_ID(airspeed), _airspeed_sub, &_airspeed);
- orb_copy(ORB_ID(vehicle_global_position), _global_pos_sub, &_gpos);
- orb_copy(ORB_ID(att_pos_mocap), _mocap_sub, &_mocap);
-
- orb_publish_auto(ORB_ID(vehicle_attitude), &_att_pub, &att, &att_inst, ORB_PRIO_HIGH);
- orb_publish_auto(ORB_ID(control_state), &_ctrl_state_pub, &ctrl_state, &ctrl_inst, ORB_PRIO_HIGH);
- orb_publish_auto(ORB_ID(estimator_status), &_est_state_pub, &est, &est_inst, ORB_PRIO_HIGH);
-
-
-
- ardupilot/modules/PX4Firmware/src/modules/mc_pos_control/mc_pos_control_main.cpp
- _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
- _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
- _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
- _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
- _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
- _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
- _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
- _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
-
- orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
- orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
- orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
- orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode);
- orb_copy(ORB_ID(manual_control_setpoint), _manual_sub, &_manual);
- orb_copy(ORB_ID(actuator_armed), _arming_sub, &_arming);
- orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
- orb_copy(ORB_ID(position_setpoint_triplet), _pos_sp_triplet_sub, &_pos_sp_triplet);
-
-
- orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
- _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
- if (!_attitude_setpoint_id) {
- if (_vehicle_status.is_vtol) {
- _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
-
- } else {
- _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
- }
- }
- orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
- _global_vel_sp_pub = orb_advertise(ORB_ID(vehicle_global_velocity_setpoint), &_global_vel_sp);
-
-
-
- ardupilot/modules/PX4Firmware/src/modules/mc_att_control/mc_att_control_main.cpp
- _v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- _v_rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
- _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
- _v_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
- _params_sub = orb_subscribe(ORB_ID(parameter_update));
- _manual_control_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
- _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
- _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
- _motor_limits_sub = orb_subscribe(ORB_ID(multirotor_motor_limits));
-
- orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
- orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
- orb_copy(ORB_ID(parameter_update), _params_sub, ¶m_update);
- orb_copy(ORB_ID(vehicle_control_mode), _v_control_mode_sub, &_v_control_mode);
- orb_copy(ORB_ID(actuator_armed), _armed_sub, &_armed);
- orb_copy(ORB_ID(manual_control_setpoint), _manual_control_sp_sub, &_manual_control_sp);
- orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
- if (!_rates_sp_id) {
- if (_vehicle_status.is_vtol) {
- _rates_sp_id = ORB_ID(mc_virtual_rates_setpoint);
- _actuators_id = ORB_ID(actuator_controls_virtual_mc);
-
- } else {
- _rates_sp_id = ORB_ID(vehicle_rates_setpoint);
- _actuators_id = ORB_ID(actuator_controls_0);
- }
- }
- }
- orb_copy(ORB_ID(multirotor_motor_limits), _motor_limits_sub, &_motor_limits);
- orb_copy(ORB_ID(vehicle_rates_setpoint), _v_rates_sp_sub, &_v_rates_sp);
-
- orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
- _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
- orb_publish(_actuators_id, _actuators_0_pub, &_actuators);
- _actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
- orb_publish(ORB_ID(mc_att_ctrl_status), _controller_status_pub, &_controller_status);
- _controller_status_pub = orb_advertise(ORB_ID(mc_att_ctrl_status), &_controller_status);
- #ifdef __cplusplus
- struct __EXPORT vehicle_local_position_s {
- #else
- struct vehicle_local_position_s {
- #endif
- uint64_t timestamp;
- bool xy_valid;
- bool z_valid;
- bool v_xy_valid;
- bool v_z_valid;
- float x;
- float y;
- float z;
- float vx;
- float vy;
- float vz;
- float yaw;
- bool xy_global;
- bool z_global;
- uint64_t ref_timestamp;
- double ref_lat;
- double ref_lon;
- float ref_alt;
- float dist_bottom;
- float dist_bottom_rate;
- uint64_t surface_bottom_timestamp;
- bool dist_bottom_valid;
- float eph;
- float epv;
- #ifdef __cplusplus
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT vehicle_global_position_s {
- #else
- struct vehicle_global_position_s {
- #endif
- uint64_t timestamp;
- uint64_t time_utc_usec;
- double lat;
- double lon;
- float alt;
- float vel_n;
- float vel_e;
- float vel_d;
- float yaw;
- float eph;
- float epv;
- float terrain_alt;
- bool terrain_alt_valid;
- bool dead_reckoning;
- float pressure_alt;
- #ifdef __cplusplus
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT vehicle_attitude_s {
- #else
- struct vehicle_attitude_s {
- #endif
- uint64_t timestamp;
- float roll;
- float pitch;
- float yaw;
- float rollspeed;
- float pitchspeed;
- float yawspeed;
- float rollacc;
- float pitchacc;
- float yawacc;
- float rate_vibration;
- float accel_vibration;
- float mag_vibration;
- float rate_offsets[3];
- float R[9];
- float q[4];
- float g_comp[3];
- bool R_valid;
- bool q_valid;
- #ifdef __cplusplus
-
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT control_state_s {
- #else
- struct control_state_s {
- #endif
- uint64_t timestamp;
- float x_acc;
- float y_acc;
- float z_acc;
- float x_vel;
- float y_vel;
- float z_vel;
- float x_pos;
- float y_pos;
- float z_pos;
- float airspeed;
- bool airspeed_valid;
- float vel_variance[3];
- float pos_variance[3];
- float q[4];
- float roll_rate;
- float pitch_rate;
- float yaw_rate;
- float horz_acc_mag;
- #ifdef __cplusplus
-
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT vehicle_attitude_setpoint_s {
- #else
- struct vehicle_attitude_setpoint_s {
- #endif
- uint64_t timestamp;
- float roll_body;
- float pitch_body;
- float yaw_body;
- float yaw_sp_move_rate;
- float R_body[9];
- bool R_valid;
- float q_d[4];
- bool q_d_valid;
- float q_e[4];
- bool q_e_valid;
- float thrust;
- bool roll_reset_integral;
- bool pitch_reset_integral;
- bool yaw_reset_integral;
- bool fw_control_yaw;
- bool disable_mc_yaw_control;
- bool apply_flaps;
- #ifdef __cplusplus
-
- #endif
- };
-
- #ifdef __cplusplus
- struct __EXPORT vehicle_rates_setpoint_s {
- #else
- struct vehicle_rates_setpoint_s {
- #endif
- uint64_t timestamp;
- float roll;
- float pitch;
- float yaw;
- float thrust;
- #ifdef __cplusplus
-
- #endif
- };
- #ifdef __cplusplus
- struct __EXPORT actuator_controls_0_s {
- #else
- struct actuator_controls_0_s {
- #endif
- uint64_t timestamp;
- uint64_t timestamp_sample;
- float control[8];
- #ifdef __cplusplus
- static const uint8_t NUM_ACTUATOR_CONTROLS = 8;
- static const uint8_t NUM_ACTUATOR_CONTROL_GROUPS = 4;
-
- #endif
- };
这是用到的结构体
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。