当前位置:   article > 正文

pixhawk 光流--位置估计--姿态估计--位置控制--姿态控制_motorspeed = map(abs(tiltangle), 0, 90, 0, 500);

motorspeed = map(abs(tiltangle), 0, 90, 0, 500);

本文是边分析边写的,顺便就记录下了分析的思路,并不是按照教材那种思路介绍性的,而是按照程序员分析程序的思路来的。所以读者跟着看有些地方看了意义不大,但是这种程序分析的思路还是可以借鉴的,如果有大神看到了本文,有更好的见解,欢迎指教。

前面的是从APM代码角度看的,后面是从原生码角度看的。这blog写的我自己看了都想吐,翻下去都是代码,就最后一张图人性化一点。

温馨提示:可以从后面点看,程序中有注释。

先从ardupilot/libraries/AP_OpticalFlow/examples/AP_OpticalFlow_test/ AP_OpticalFlow_test.cpp看起

  1. voidsetup()
  2. {
  3. hal.console->println("OpticalFlowlibrary test ver 1.6");
  4. hal.scheduler->delay(1000);
  5. // flowSensor initialization
  6. optflow.init();
  7. if (!optflow.healthy()) {
  8. hal.console->print("Failed toinitialise PX4Flow ");
  9. }
  10. hal.scheduler->delay(1000);只需要看
  11. }
  12. voidloop()
  13. {
  14. hal.console->println("this onlytests compilation succeeds");
  15. hal.scheduler->delay(5000);
  16. }

因此optflow.init();再进行判断if (!optflow.healthy()),任务就完成了

跳转到optflow.init();

  1. voidOpticalFlow::init(void)
  2. {
  3. if (backend != NULL) {
  4. backend->init();
  5. } else {
  6. _enabled = 0;
  7. }
  8. }

跳转到init();

  1. classOpticalFlow_backend
  2. {
  3. friend class OpticalFlow;
  4. public:
  5. // constructor
  6. OpticalFlow_backend(OpticalFlow&_frontend) : frontend(_frontend) {}
  7. // init - initialise sensor
  8. virtual void init() = 0;
  9. // read latest values from sensor and fillin x,y and totals.
  10. virtual void update() = 0;
  11. protected:
  12. // access to frontend
  13. OpticalFlow &frontend;
  14. // update the frontend
  15. void _update_frontend(const structOpticalFlow::OpticalFlow_state &state);
  16. // get the flow scaling parameters
  17. Vector2f _flowScaler(void) const { returnVector2f(frontend._flowScalerX, frontend._flowScalerY); }
  18. // get the yaw angle in radians
  19. float _yawAngleRad(void) const { returnradians(float(frontend._yawAngle_cd) * 0.01f); }
  20. };

看到了吧,virtualvoid init() = 0;就是这个虚函数

怎么找到它的实例化呢?

Ctrl+H全局搜索public OpticalFlow_backend


路径是:ardupilot/libraries/AP_OpticalFlow/ AP_OpticalFlow_PX4.h

  1. 路径是:ardupilot/libraries/AP_OpticalFlow/ AP_OpticalFlow_PX4.h
  2. class AP_OpticalFlow_PX4 : public OpticalFlow_backend
  3. {
  4. public:
  5. /// constructor
  6. AP_OpticalFlow_PX4(OpticalFlow &_frontend);
  7. // init - initialise the sensor
  8. void init();
  9. // update - read latest values from sensor and fill in x,y and totals.
  10. void update(void);
  11. private:
  12. int _fd; // file descriptor for sensor
  13. uint64_t _last_timestamp; // time of last update (used to avoid processing old reports)
  14. };
  15. void init();就是实例化,继续搜索AP_OpticalFlow_PX4:: init

void init();就是实例化,继续搜索AP_OpticalFlow_PX4::init


本体就是

  1. voidAP_OpticalFlow_PX4::init(void)
  2. {
  3. _fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);//关于sd卡文件的read
  4. // check for failure to open device
  5. if (_fd == -1) {
  6. return;
  7. }
  8. // change to 10Hz update
  9. if (ioctl(_fd, SENSORIOCSPOLLRATE, 10) != 0) {
  10. hal.console->printf("Unable to set flow rate to10Hz\n");
  11. }
  12. }

慢慢查看,先看_fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);源码如下

路径是ardupilot/modules/PX4NuttX/nuttx/fs/fs_open.c

  1. /****************************************************************************
  2. *Name: open
  3. *
  4. *Description:
  5. * Standard 'open' interface
  6. *
  7. ****************************************************************************/
  8. int open(const char *path, int oflags, ...)
  9. {
  10. FARstruct filelist *list;
  11. FARstruct inode *inode;
  12. FARconst char *relpath = NULL;
  13. #if defined(CONFIG_FILE_MODE) ||!defined(CONFIG_DISABLE_MOUNTPOINT)
  14. mode_t mode = 0666;
  15. #endif
  16. int ret;
  17. int fd;
  18. /*Get the thread-specific file list */得到具体线程列表
  19. list = sched_getfiles();
  20. if(!list)
  21. {
  22. ret = EMFILE;
  23. goto errout;
  24. }
  25. #ifdef CONFIG_FILE_MODE
  26. # ifdef CONFIG_CPP_HAVE_WARNING
  27. # warning "File creation not implemented"
  28. # endif
  29. /*If the file is opened for creation, then get the mode bits */
  30. if(oflags & (O_WRONLY|O_CREAT) != 0)
  31. {
  32. va_list ap;
  33. va_start(ap, oflags);
  34. mode = va_arg(ap, mode_t);
  35. va_end(ap);
  36. }
  37. #endif
  38. /*Get an inode for this file */得到索引节点
  39. inode = inode_find(path, &relpath);
  40. if(!inode)
  41. {
  42. /* "O_CREAT is not set and the named file does not exist. Or, a
  43. * directory component in pathname does not exist or is a dangling
  44. * symbolic link."
  45. */
  46. ret = ENOENT;
  47. goto errout;
  48. }
  49. /*Verify that the inode is valid and either a "normal" or amountpoint. We
  50. *specifically exclude block drivers.
  51. */
  52. #ifndef CONFIG_DISABLE_MOUNTPOINT
  53. if((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) ||!inode->u.i_ops)
  54. #else
  55. if(!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
  56. #endif
  57. {
  58. ret = ENXIO;
  59. goto errout_with_inode;
  60. }
  61. /*Make sure that the inode supports the requested access */
  62. ret= inode_checkflags(inode, oflags);
  63. if(ret < 0)
  64. {
  65. ret = -ret;
  66. goto errout_with_inode;
  67. }
  68. /*Associate the inode with a file structure */
  69. fd= files_allocate(inode, oflags, 0, 0);
  70. if(fd < 0)
  71. {
  72. ret = EMFILE;
  73. goto errout_with_inode;
  74. }
  75. /*Perform the driver open operation. NOTEthat the open method may be
  76. *called many times. The driver/mountpointlogic should handled this
  77. *because it may also be closed that many times.
  78. */
  79. ret= OK;
  80. if(inode->u.i_ops->open)
  81. {
  82. #ifndef CONFIG_DISABLE_MOUNTPOINT
  83. if (INODE_IS_MOUNTPT(inode))
  84. {
  85. ret = inode->u.i_mops->open((FAR structfile*)&list->fl_files[fd],
  86. relpath,oflags, mode);
  87. }
  88. else
  89. #endif
  90. {
  91. ret = inode->u.i_ops->open((FAR structfile*)&list->fl_files[fd]);
  92. }
  93. }
  94. if(ret < 0)
  95. {
  96. ret = -ret;
  97. goto errout_with_fd;
  98. }
  99. return fd;
  100. errout_with_fd:
  101. files_release(fd);
  102. errout_with_inode:
  103. inode_release(inode);
  104. errout:
  105. set_errno(ret);
  106. return ERROR;
  107. }
  108. 跳转到list = sched_getfiles();
  109. 路径是ardupilot/modules/PX4NuttX/nuttx/sched/sched_getfiles.c
  110. /************************************************************************
  111. *Name: sched_getfiles
  112. *
  113. *Description:
  114. * Return a pointer to the file list for this thread
  115. *
  116. *Parameters:
  117. * None
  118. *
  119. *Return Value:
  120. * Apointer to the errno.
  121. *
  122. *Assumptions:
  123. *
  124. ************************************************************************/
  125. #if CONFIG_NFILE_DESCRIPTORS > 0
  126. FAR struct filelist *sched_getfiles(void)
  127. {
  128. FARstruct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  129. FARstruct task_group_s *group = rtcb->group;
  130. /*The group may be NULL under certain conditions. For example, if
  131. *debug output is attempted from the IDLE thead before the group has
  132. *been allocated. I have only seen thiscase when memory management
  133. *debug is enabled.
  134. */
  135. if(group)
  136. {
  137. return &group->tg_filelist;
  138. }
  139. /*Higher level logic must handle the NULL gracefully */
  140. return NULL;
  141. }
  142. #endif /* CONFIG_NFILE_DESCRIPTORS */
  143. 跳转到inode = inode_find(path, &relpath);
  144. 路径是ardupilot/modules/PX4NuttX/nuttx/fs/fs_inodefine.c
  145. /****************************************************************************
  146. *Name: inode_find
  147. *
  148. *Description:
  149. * Thisis called from the open() logic to get a reference to the inode
  150. * associated with a path.
  151. *
  152. ****************************************************************************/
  153. //得到一个inode与路径相关的引用
  154. FAR struct inode *inode_find(FAR const char*path, FAR const char **relpath)
  155. {
  156. FARstruct inode *node;
  157. if(!*path || path[0] != '/')
  158. {
  159. return NULL;
  160. }
  161. /*Find the node matching the path. Iffound, increment the count of
  162. *references on the node.
  163. */
  164. inode_semtake();
  165. node = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL,relpath);
  166. if(node)
  167. {
  168. node->i_crefs++;
  169. }
  170. inode_semgive();
  171. return node;
  172. }

看到不大懂,姑且认为是关于sd卡文件的read

#definePX4FLOW0_DEVICE_PATH "/dev/px4flow0"路径ardupilot/modules/PX4Firmware/src/drivers/drv_px4flow.h

  1. void AP_OpticalFlow_PX4::init(void)
  2. {
  3. _fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
  4. // check for failure to open device
  5. if (_fd == -1) {
  6. return;
  7. }
  8. // change to 10Hz update
  9. if (ioctl(_fd, SENSORIOCSPOLLRATE, 10) != 0) {
  10. hal.console->printf("Unable to set flow rate to10Hz\n");
  11. }
  12. }

继续往下看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)

  1. /****************************************************************************
  2. *Name: ioctl
  3. *
  4. *Description:
  5. * Perform device specific operations.
  6. *
  7. *Parameters:
  8. * fd File/socket descriptor ofdevice
  9. * req The ioctl command
  10. * arg The argument of the ioctlcmd
  11. *
  12. *Return:
  13. * >=0 on success (positive non-zero values are cmd-specific)
  14. * -1on failure withi errno set properly:
  15. *
  16. * EBADF
  17. * 'fd' is not a valid descriptor.
  18. * EFAULT
  19. * 'arg' references an inaccessible memory area.
  20. * EINVAL
  21. * 'cmd' or 'arg' is not valid.
  22. * ENOTTY
  23. * 'fd' is not associated with a character special device.
  24. * ENOTTY
  25. * The specified request does not apply to the kind of object that the
  26. * descriptor 'fd' references.
  27. *
  28. ****************************************************************************/
  29. int ioctl(int fd, int req, unsigned longarg)
  30. {
  31. interr;
  32. #if CONFIG_NFILE_DESCRIPTORS > 0
  33. FARstruct filelist *list;
  34. FARstruct file *this_file;
  35. FARstruct inode *inode;
  36. int ret = OK;
  37. /*Did we get a valid file descriptor? */
  38. if((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
  39. #endif
  40. {
  41. /* Perform the socket ioctl */
  42. #if defined(CONFIG_NET) &&CONFIG_NSOCKET_DESCRIPTORS > 0
  43. if ((unsigned int)fd <(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
  44. {
  45. return netdev_ioctl(fd, req, arg);
  46. }
  47. else
  48. #endif
  49. {
  50. err = EBADF;
  51. goto errout;
  52. }
  53. }
  54. #if CONFIG_NFILE_DESCRIPTORS > 0
  55. /*Get the thread-specific file list */
  56. list = sched_getfiles();
  57. if(!list)
  58. {
  59. err = EMFILE;
  60. goto errout;
  61. }
  62. /*Is a driver registered? Does it support the ioctl method? */
  63. this_file = &list->fl_files[fd];
  64. inode = this_file->f_inode;
  65. if(inode && inode->u.i_ops && inode->u.i_ops->ioctl)
  66. {
  67. /* Yes, then let it perform the ioctl */
  68. ret = (int)inode->u.i_ops->ioctl(this_file,req, arg);
  69. if (ret < 0)
  70. {
  71. err = -ret;
  72. goto errout;
  73. }
  74. }
  75. return ret;
  76. #endif
  77. errout:
  78. set_errno(err);
  79. return ERROR;
  80. }

这句话是这个函数的核心

/* 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

  1. int
  2. PX4FLOW::ioctl(structfile *filp, int cmd, unsigned long arg)
  3. {
  4. switch(cmd) {
  5. caseSENSORIOCSPOLLRATE: {
  6. switch(arg) {
  7. /*switching to manual polling */
  8. caseSENSOR_POLLRATE_MANUAL:
  9. stop();
  10. _measure_ticks= 0;
  11. returnOK;
  12. /*external signalling (DRDY) not supported */
  13. case SENSOR_POLLRATE_EXTERNAL:
  14. /*zero would be bad */
  15. case0:
  16. return-EINVAL;
  17. /*set default/max polling rate */
  18. caseSENSOR_POLLRATE_MAX:
  19. caseSENSOR_POLLRATE_DEFAULT: {
  20. /*do we need to start internal polling? */
  21. boolwant_start = (_measure_ticks == 0);
  22. /*set interval for next measurement to minimum legal value */
  23. _measure_ticks= USEC2TICK(PX4FLOW_CONVERSION_INTERVAL);
  24. /*if we need to start the poll state machine, do it */
  25. if(want_start) {
  26. start();
  27. }
  28. returnOK;
  29. }
  30. /*adjust to a legal polling interval in Hz */
  31. default:{
  32. /*do we need to start internal polling? */
  33. boolwant_start = (_measure_ticks == 0);
  34. /*convert hz to tick interval via microseconds */
  35. unsignedticks = USEC2TICK(1000000 / arg);
  36. /*check against maximum rate */
  37. if(ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
  38. return-EINVAL;
  39. }
  40. /*update interval for next measurement */
  41. _measure_ticks= ticks;
  42. /*if we need to start the poll state machine, do it */
  43. if(want_start) {
  44. start();
  45. }
  46. returnOK;
  47. }
  48. }
  49. }
  50. caseSENSORIOCGPOLLRATE:
  51. if(_measure_ticks == 0) {
  52. returnSENSOR_POLLRATE_MANUAL;
  53. }
  54. return(1000 / _measure_ticks);
  55. caseSENSORIOCSQUEUEDEPTH: {
  56. /*lower bound is mandatory, upper bound is a sanity check */
  57. if((arg < 1) || (arg > 100)) {
  58. return-EINVAL;
  59. }
  60. irqstate_t flags = irqsave();
  61. if(!_reports->resize(arg)) {
  62. irqrestore(flags);
  63. return-ENOMEM;
  64. }
  65. irqrestore(flags);
  66. returnOK;
  67. }
  68. caseSENSORIOCGQUEUEDEPTH:
  69. return_reports->size();
  70. caseSENSORIOCSROTATION:
  71. _sensor_rotation= (enum Rotation)arg;
  72. returnOK;
  73. caseSENSORIOCGROTATION:
  74. return_sensor_rotation;
  75. caseSENSORIOCRESET:
  76. /*XXX implement this */
  77. return-EINVAL;
  78. default:
  79. /*give it to the superclass */
  80. returnI2C::ioctl(filp, cmd, arg);
  81. }
  82. }

这个函数很好理解,根据传入的参数对号入座,传入的是SENSORIOCSPOLLRATE,那么进入

  1. case SENSORIOCSPOLLRATE: {
  2. switch(arg) {
  3. /*switching to manual polling */
  4. caseSENSOR_POLLRATE_MANUAL:
  5. stop();
  6. _measure_ticks= 0;
  7. returnOK;
  8. /*external signalling (DRDY) not supported */
  9. case SENSOR_POLLRATE_EXTERNAL:
  10. /*zero would be bad */
  11. case0:
  12. return-EINVAL;
  13. /*set default/max polling rate */
  14. caseSENSOR_POLLRATE_MAX:
  15. caseSENSOR_POLLRATE_DEFAULT: {
  16. /*do we need to start internal polling? */
  17. boolwant_start = (_measure_ticks == 0);
  18. /*set interval for next measurement to minimum legal value */
  19. _measure_ticks= USEC2TICK(PX4FLOW_CONVERSION_INTERVAL);
  20. /*if we need to start the poll state machine, do it */
  21. if(want_start) {
  22. start();
  23. }
  24. returnOK;
  25. }
  26. /*adjust to a legal polling interval in Hz */
  27. default:{
  28. /*do we need to start internal polling? */
  29. boolwant_start = (_measure_ticks == 0);
  30. /*convert hz to tick interval via microseconds */
  31. unsignedticks = USEC2TICK(1000000 / arg);
  32. /*check against maximum rate */
  33. if(ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
  34. return-EINVAL;
  35. }
  36. /*update interval for next measurement */
  37. _measure_ticks= ticks;
  38. /* if we need to start thepoll state machine, do it */
  39. if(want_start) {
  40. start();
  41. }
  42. returnOK;
  43. }

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();

  1. void
  2. PX4FLOW::start()
  3. {
  4. /*reset the report ring and state machine *///复位报告环和状态机
  5. _collect_phase= false;
  6. _reports->flush();
  7. /*schedule a cycle to start things *///安排一个周期开始一些事情
  8. work_queue(HPWORK,&_work, (worker_t)&PX4FLOW::cycle_trampoline, this, 1);
  9. /*notify about state change */
  10. structsubsystem_info_s info = {
  11. true,
  12. true,
  13. true,
  14. subsystem_info_s::SUBSYSTEM_TYPE_OPTICALFLOW
  15. };
  16. staticorb_advert_t pub = nullptr;
  17. if(pub != nullptr) {
  18. orb_publish(ORB_ID(subsystem_info),pub, &info);
  19. }else {
  20. pub= orb_advertise(ORB_ID(subsystem_info), &info);
  21. }
  22. }

看函数名字的意思是启动光流

看来最关键的是work_queue(HPWORK, &_work, (worker_t)&PX4FLOW::cycle_trampoline,this, 1)再后面就是发布和公告子系统信息,跳转至work_queue(HPWORK, &_work,(worker_t)&PX4FLOW::cycle_trampoline, this, 1);


  1. /****************************************************************************
  2. *Name: work_queue
  3. *
  4. *Description:
  5. * Queue work to be performed at a later time. All queued work will be
  6. * performed on the worker thread of of execution (not the caller's).
  7. *
  8. * Thework structure is allocated by caller, but completely managed by
  9. * thework queue logic. The caller shouldnever modify the contents of
  10. * thework queue structure; the caller should not call work_queue()
  11. * again until either (1) the previous work has been performed and removed
  12. * fromthe queue, or (2) work_cancel() has been called to cancel the work
  13. * andremove it from the work queue.
  14. *
  15. *Input parameters:
  16. * qid - The work queue ID (index)
  17. * work - The work structure toqueue
  18. * worker - The worker callback to be invoked. The callback will invoked
  19. * on the worker thread of execution.
  20. * arg - The argument that will bepassed to the workder callback when
  21. * int is invoked.
  22. * delay - Delay (in clock ticks)from the time queue until the worker
  23. * is invoked. Zero means to perform the work immediately.
  24. *
  25. *Returned Value:
  26. * Zeroon success, a negated errno on failure
  27. *
  28. ****************************************************************************/
  29. 注释翻译:
  30. 在稍后的时间将要执行的队列的工作。 所有排队工作将在工作线程(不是调用的程序)上进行。
  31. 工作结构由调用者分配,but,由工作队列逻辑完全管理。调用者不能修改工作队列结构的内容,也不能再次调用work_queue(),除非任务执行完毕或者任务被取消
  32. 输入参数:
  33. qid -工作队列的ID
  34. work -队列的工作结构
  35. worker -工作线程被执行,worker callback 会被调用
  36. arg -参数会传递给worker callback
  37. delay -延时多久再执行这个任务,若为0,则直接执行
  38. 返回值:
  39. 0,则成功执行;错误号,则失败
  40. int work_queue(int qid, FAR struct work_s*work, worker_t worker,
  41. FAR void *arg, uint32_t delay)
  42. {
  43. FARstruct wqueue_s *wqueue = &g_work[qid];
  44. irqstate_t flags;
  45. DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS);//应该是调试用的debug
  46. /* First, initialize the work structure */
  47. work->worker = worker; /* Work callback */
  48. work->arg = arg; /* Callback argument */
  49. work->delay = delay; /* Delay until work performed */
  50. /*Now, time-tag that entry and put it in the work queue. This must be
  51. *done with interrupts disabled. Thispermits this function to be called
  52. *from with task logic or interrupt handlers.
  53. */
  54. flags = irqsave();
  55. work->qtime = clock_systimer(); /* Time work queued */
  56. dq_addlast((FAR dq_entry_t *)work, &wqueue->q);
  57. kill(wqueue->pid, SIGWORK); /* Wake up the worker thread */
  58. irqrestore(flags);
  59. return OK;
  60. }

在看一下调用的函数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)

这个应该是比较关键的函数,一点点看

  1. FAR struct wqueue_s *wqueue =&g_work[qid];
  2. /* This structure defines the state on onework queue. Thisstructure is
  3. * used internally by the OS and worker queuelogic and should not be
  4. * accessed by application logic.
  5. */
  6. 注释翻译:
  7. 这个结构体定义了一个工作队列的状态。这种结构是由系统和worker队列逻辑在内部使用,不应被应用程序逻辑访问。
  8. struct wqueue_s
  9. {
  10. pid_t pid; /* The taskID of the worker thread *///worker线程中的任务ID
  11. struct dq_queue_s q; /* Thequeue of pending work *///挂起的工作队列
  12. };
  13. typedef int16_t pid_t;
  14. struct dq_queue_s
  15. {
  16. FARdq_entry_t *head;//头
  17. FARdq_entry_t *tail;//尾
  18. };

也就是说

  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的定义

  1. /* Defines one entry in the workqueue. The user only needs thisstructure
  2. * inorder to declare instances of the work structure. Handling of all
  3. *fields is performed by the work APIs
  4. */
  5. 注释翻译:定义一个工作队列的入口。使用前声明这个结构,再实例化。所有处理都是有API来完成的
  6. struct work_s
  7. {
  8. structdq_entry_s dq; /* Implements a doublylinked list */
  9. worker_t worker; /* Work callback */
  10. FARvoid *arg; /* Callback argument*/
  11. uint32_t qtime; /* Time work queued */
  12. uint32_t delay; /* Delay until work performed */
  13. };
  14. work->worker = worker; /* Work callback */
  15. work->arg = arg; /* Callback argument */
  16. work->delay = delay; /* Delay until work performed */
  17. /* Now, time-tag that entry and put it inthe work queue. This must be
  18. *done with interrupts disabled. Thispermits this function to be called
  19. *from with task logic or interrupt handlers.
  20. */
  21. 注释翻译:现在,时间标记该条目,并把它的工作队列。这个需要在中断失能的情况下完成。允许这个函数从任务逻辑或中断处理程序调用。
  22. flags = irqsave();/* Save the current primask state& disable IRQs */保存当前primask的状态,并失能中断
  23. work->qtime = clock_systimer(); /* Time work queued */

跳转至irqsave();

  1. static inline irqstate_t irqsave(void)
  2. {
  3. #ifdef CONFIG_ARMV7M_USEBASEPRI
  4. uint8_t basepri = getbasepri();
  5. setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
  6. return (irqstate_t)basepri;
  7. #else
  8. unsigned short primask;
  9. /*Return the current value of primask register and set
  10. *bit 0 of the primask register to disable interrupts
  11. */
  12. __asm__ __volatile__
  13. (
  14. "\tmrs %0, primask\n"
  15. "\tcpsid i\n"
  16. : "=r" (primask)
  17. :
  18. : "memory");
  19. return primask;
  20. #endif
  21. }

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++一次,另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()

  1. /************************************************************************
  2. * Name: kill
  3. *
  4. * Description:
  5. * Thekill() system call can be used to send any signal to any task.
  6. *
  7. * Limitation: Sending of signals to 'process groups' is not
  8. * supported in NuttX
  9. *
  10. * Parameters:
  11. * pid- The id of the task to receive the signal. The POSIX kill
  12. * specification encodes process group information as zero and
  13. * negative pid values. Onlypositive, non-zero values of pid are
  14. * supported by this implementation.
  15. * signo - The signal number to send. If signo is zero, no signal is
  16. * sent, but all error checking is performed.
  17. *
  18. * Returned Value:
  19. * Onsuccess (at least one signal was sent), zero is returned. On
  20. * error, -1 is returned, and errno is set appropriately:
  21. *
  22. * EINVAL An invalid signal was specified.
  23. * EPERM The process does not havepermission to send the
  24. * signal to any of the target processes.
  25. * ESRCH The pid or process groupdoes not exist.
  26. * ENOSYS Do not support sending signals to process groups.
  27. *
  28. * Assumptions:
  29. *
  30. ************************************************************************/
  31. 注释翻译:
  32. 这个kill()系统调用可用于任何信号发送到任何任务。
  33. 限制:信号发送到“进程组”在NuttX不支持
  34. 参数:
  35. pid -任务的ID用来接收信号。如果pid的值是0或负的,POSIX的kill规范会编码进程组信息
  36. 只有正的pid才会被执行
  37. signo -需发送的信号数量。如果signo为0,就是没有信号发送,但是所有错误检查会被执行
  38. 返回值:
  39. 0, 成功;-1,发生错误,并且会返回错误码:
  40. EINVAL 无效的信号指定。
  41. EPERM 进程没有权限将信号发送到任何目标进程。
  42. ESRCH PID或进程组不存在。
  43. ENOSYS 不支持发送的信号来处理组。
  44. int kill(pid_t pid, int signo)
  45. {
  46. #ifdef CONFIG_SCHED_HAVE_PARENT
  47. FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
  48. #endif
  49. siginfo_t info;
  50. int ret;
  51. /* We do not support sending signals to process groups */
  52. if (pid <= 0)
  53. {
  54. ret = -ENOSYS;
  55. goto errout;
  56. }
  57. /* Make sure that the signal is valid */
  58. if (!GOOD_SIGNO(signo))
  59. {
  60. ret = -EINVAL;
  61. goto errout;
  62. }
  63. //至此都是保证pid大于0
  64. /* Keep things stationary through the following */
  65. sched_lock();
  66. /* Create the siginfo structure */创建siginfo结构体
  67. info.si_signo = signo;
  68. info.si_code = SI_USER;
  69. info.si_value.sival_ptr = NULL;
  70. #ifdef CONFIG_SCHED_HAVE_PARENT
  71. info.si_pid =rtcb->pid;
  72. info.si_status = OK;
  73. #endif
  74. /* Send the signal */
  75. ret = sig_dispatch(pid, &info);
  76. sched_unlock();
  77. if (ret < 0)
  78. {
  79. goto errout;
  80. }
  81. return OK;
  82. errout:
  83. set_errno(-ret);
  84. return ERROR;
  85. }

sched_lock();/* Keep thingsstationary through the following */通过这个让事情变得平稳,

sched_unlock();//也就是一个保护作用,里面的内容不让其他程序触碰

重点就是info结构体赋值,赋值的内容就是之前的任务的相关信息,然后就是ret =sig_dispatch(pid,&info);把任务发出去(这一层一层包的- -!)

跳转至sig_dispatch()

  1. /****************************************************************************
  2. * Name: sig_dispatch
  3. *
  4. * Description:
  5. * Thisis the front-end for sig_tcbdispatch that should be typically
  6. * beused to dispatch a signal. If HAVE_GROUP_MEMBERS is defined,
  7. * thenfunction will follow the group signal delivery algorthrims:
  8. *
  9. * Thisfront-end does the following things before calling
  10. * sig_tcbdispatch.
  11. *
  12. * With HAVE_GROUP_MEMBERS defined:
  13. * -Get the TCB associated with the pid.
  14. * -If the TCB was found, get the group from the TCB.
  15. * - If the PID has already exited, lookup thegroup that that was
  16. * started by this task.
  17. * -Use the group to pick the TCB to receive the signal
  18. * -Call sig_tcbdispatch with the TCB
  19. *
  20. * With HAVE_GROUP_MEMBERS *not* defined
  21. * -Get the TCB associated with the pid.
  22. * -Call sig_tcbdispatch with the TCB
  23. *
  24. * Returned Value:
  25. * Returns 0 (OK) on success or a negated errno value on failure.
  26. *
  27. ****************************************************************************/
  28. 注释翻译:(TCB是线程控制块的意思)
  29. 这个函数是用作派遣任务
  30. 如果HAVE_GROUP_MEMBERS被定义了,那么要完成
  31. 获取与PID相关的TCB
  32. 如果TCB被发现,请从TCB里获取组
  33. 如果PID已经退出,查找被此任务开始的组
  34. 使用组pick TCB来接收信号
  35. 用TCB来调用sig_tcbdispatch
  36. 如果HAVE_GROUP_MEMBERS没有被定义,那么
  37. 获取与PID相关的TCB
  38. 用TCB来调用sig_tcbdispatch
  39. int sig_dispatch(pid_t pid, FARsiginfo_t *info)
  40. {
  41. #ifdef HAVE_GROUP_MEMBERS
  42. FAR struct tcb_s *stcb;
  43. FAR struct task_group_s *group;
  44. /* Get the TCB associated with the pid */
  45. stcb = sched_gettcb(pid);//获取一个任务ID,这个函数会返回一个指针指向相应的TCB
  46. if (stcb)
  47. {
  48. /* The task/thread associated with thisPID is still active. Get its
  49. * task group.
  50. */
  51. //与PID相关的任务/线程还是激活的,得到它的任务组
  52. group = stcb->group;
  53. }
  54. else
  55. {
  56. /* The task/thread associated with thisPID has exited. In the normal
  57. * usage model, the PID should correspondto the PID of the task that
  58. * created the task group. Try looking it up.
  59. */
  60. group = group_findbypid(pid);
  61. }
  62. /* Didwe locate the group? */
  63. if (group)
  64. {
  65. /* Yes.. call group_signal() to send thesignal to the correct group
  66. * member.
  67. */
  68. return group_signal(group, info);
  69. }
  70. else
  71. {
  72. return -ESRCH;
  73. }
  74. #else
  75. FAR struct tcb_s *stcb;
  76. /* Get the TCB associated with the pid */
  77. stcb = sched_gettcb(pid);
  78. if (!stcb)
  79. {
  80. return -ESRCH;
  81. }
  82. return sig_tcbdispatch(stcb, info);
  83. #endif
  84. }

ret = sig_dispatch(pid,&info);

快到内核了,东西越来越多,一点点看吧

stcb = sched_gettcb(pid); /* Get the TCB associated with the pid */获取pid相关的TCB

跳转至sched_gettcb()

  1. /****************************************************************************
  2. * Name: sched_gettcb
  3. *
  4. * Description:
  5. * Given a task ID, this function will return
  6. * thea pointer to the corresponding TCB (or NULL if there
  7. * isno such task ID).
  8. *
  9. ****************************************************************************/
  10. 注释翻译:获取一个任务ID,这个函数会返回一个指针指向相应的TCB
  11. FAR struct tcb_s*sched_gettcb(pid_t pid)
  12. {
  13. FAR struct tcb_s *ret = NULL;
  14. int hash_ndx;
  15. /* Verify that the PID is within range */
  16. if (pid >= 0 )
  17. {
  18. /* Get the hash_ndx associated with thepid */
  19. hash_ndx = PIDHASH(pid);
  20. /* Verify that the correct TCB was found.*/
  21. if (pid == g_pidhash[hash_ndx].pid)
  22. {
  23. /* Return the TCB associated withthis pid (if any) */
  24. ret = g_pidhash[hash_ndx].tcb;
  25. }
  26. }
  27. /* Return the TCB. */
  28. return ret;
  29. }
  30. 现在应该到了任务分配层了,应该也算内核了吧,下一层就是物理驱动层
  31. 细细看来,跳转至hash_ndx =PIDHASH(pid);
  32. group = stcb->group;看看这个group是什么东西
  33. #ifdef HAVE_TASK_GROUP
  34. FAR struct task_group_s *group; /* Pointer to shared task group data */
  35. #endif
  36. struct task_group_s
  37. {
  38. #ifdef HAVE_GROUP_MEMBERS
  39. struct task_group_s *flink; /* Supports a singly linked list */
  40. gid_t tg_gid; /* The ID of this task group */
  41. gid_t tg_pgid; /* The ID of the parent task group */
  42. #endif
  43. #if!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SCHED_HAVE_PARENT)
  44. pid_t tg_task; /* The ID of the task within the group */
  45. #endif
  46. uint8_t tg_flags; /* See GROUP_FLAG_* definitions */
  47. /* Group membership ***********************************************************/
  48. uint8_t tg_nmembers; /* Number of members in thegroup */
  49. #ifdef HAVE_GROUP_MEMBERS
  50. uint8_t tg_mxmembers; /* Number of members inallocation */
  51. FAR pid_t *tg_members; /* Members of the group */
  52. #endif
  53. /* atexit/on_exit support ****************************************************/
  54. #if defined(CONFIG_SCHED_ATEXIT)&& !defined(CONFIG_SCHED_ONEXIT)
  55. # ifdefined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
  56. atexitfunc_t tg_atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
  57. # else
  58. atexitfunc_t tg_atexitfunc; /* Called when exit is called. */
  59. # endif
  60. #endif
  61. #ifdef CONFIG_SCHED_ONEXIT
  62. # ifdefined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1
  63. onexitfunc_t tg_onexitfunc[CONFIG_SCHED_ONEXIT_MAX];
  64. FAR void *tg_onexitarg[CONFIG_SCHED_ONEXIT_MAX];
  65. # else
  66. onexitfunc_t tg_onexitfunc; /* Called when exit is called. */
  67. FAR void *tg_onexitarg; /* The argument passed to the function */
  68. # endif
  69. #endif
  70. /* Child exit status **********************************************************/
  71. #ifdefined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
  72. FAR struct child_status_s *tg_children; /* Head of a list of childstatus */
  73. #endif
  74. /* waitpid support************************************************************/
  75. /*Simple mechanism used only when there is no support for SIGCHLD */
  76. #if defined(CONFIG_SCHED_WAITPID)&& !defined(CONFIG_SCHED_HAVE_PARENT)
  77. sem_t tg_exitsem; /* Support for waitpid */
  78. int *tg_statloc; /* Location to return exitstatus */
  79. #endif
  80. /* Pthreads *******************************************************************/
  81. #ifndef CONFIG_DISABLE_PTHREAD
  82. /* Pthreadjoin Info: */
  83. sem_t tg_joinsem; /* Mutually exclusive access tojoin data */
  84. FAR struct join_s *tg_joinhead; /* Head of a list of joindata */
  85. FAR struct join_s *tg_jointail; /* Tail of a list of joindata */
  86. uint8_t tg_nkeys; /* Number pthread keys allocated */
  87. #endif
  88. /* POSIX Signal Control Fields ************************************************/
  89. #ifndef CONFIG_DISABLE_SIGNALS
  90. sq_queue_t sigpendingq; /* List of pending signals */
  91. #endif
  92. /* Environment variables ******************************************************/
  93. #ifndef CONFIG_DISABLE_ENVIRON
  94. size_t tg_envsize; /* Size of environment stringallocation */
  95. FAR char *tg_envp; /* Allocated environmentstrings */
  96. #endif
  97. /* PIC data space and address environments************************************/
  98. /* Logically the PIC data space belongs here (see struct dspace_s). The
  99. * current logic needs review: There are differences in the away that the
  100. * life of the PIC data is managed.
  101. */
  102. /* File descriptors ***********************************************************/
  103. #if CONFIG_NFILE_DESCRIPTORS > 0
  104. struct filelist tg_filelist; /* Maps file descriptor to file */
  105. #endif
  106. /* FILE streams***************************************************************/
  107. /* In a flat, single-heap build. The stream list is allocated with this
  108. * structure. But kernel mode witha kernel allocator, it must be separately
  109. * allocated using a user-space allocator.
  110. */
  111. #if CONFIG_NFILE_STREAMS > 0
  112. #if defined(CONFIG_NUTTX_KERNEL)&& defined(CONFIG_MM_KERNEL_HEAP)
  113. FAR struct streamlist *tg_streamlist;
  114. #else
  115. struct streamlist tg_streamlist; /* Holds C buffered I/O info */
  116. #endif
  117. #endif
  118. /* Sockets ********************************************************************/
  119. #if CONFIG_NSOCKET_DESCRIPTORS >0
  120. struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
  121. #endif
  122. /* POSIX Named Message Queue Fields *******************************************/
  123. #ifndef CONFIG_DISABLE_MQUEUE
  124. sq_queue_t tg_msgdesq; /* List of opened message queues */
  125. #endif
  126. };
  127. 好吧,还以为是个什么结构体呢,好长一段啊!!

这些都是不需要改动的地方,太多太杂了,先放着,重点看光流读取并且如何用于控制的部分,这些部分需要根据实际应用改动。

那么第二条思路开始,去main里面看看

(应该是这样前面看到属于ardupilot/libraries/AP_OpticalFlow文件夹里面的,属于APM的那套,应该有个虚拟层把硬件层抽象了,最后根据具体硬件来选择对应的硬件驱动;接下来要看的属于ardupilot/modules/PX4Firmware/src/drivers/px4flow文件夹里面的,属于PX4原生码)

extern "C" __EXPORT int px4flow_main(int argc, char *argv[]);

  1. int
  2. px4flow_main(int argc, char *argv[])
  3. {
  4. /*
  5. * Start/load the driver.
  6. */
  7. if (!strcmp(argv[1], "start")) {
  8. return px4flow::start();
  9. }
  10. /*
  11. * Stop the driver
  12. */
  13. if (!strcmp(argv[1], "stop")) {
  14. px4flow::stop();
  15. }
  16. /*
  17. * Test the driver/device.
  18. */
  19. if (!strcmp(argv[1], "test")) {
  20. px4flow::test();
  21. }
  22. /*
  23. * Reset the driver.
  24. */
  25. if (!strcmp(argv[1], "reset")) {
  26. px4flow::reset();
  27. }
  28. /*
  29. * Print driver information.
  30. */
  31. if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
  32. px4flow::info();
  33. }
  34. errx(1, "unrecognized command, try 'start', 'test', 'reset' or 'info'");
  35. }
跳转至start()

  1. /**
  2. * Start the driver.
  3. */
  4. int
  5. start()
  6. {
  7. int fd;
  8. /* entry check: */
  9. if (start_in_progress) {
  10. warnx("start already in progress");
  11. return 1;
  12. }
  13. start_in_progress = true;
  14. if (g_dev != nullptr) {
  15. start_in_progress = false;
  16. warnx("already started");
  17. return 1;
  18. }
  19. warnx("scanning I2C buses for device..");
  20. int retry_nr = 0;
  21. while (1) {
  22. const int busses_to_try[] = {
  23. PX4_I2C_BUS_EXPANSION,
  24. #ifdef PX4_I2C_BUS_ESC
  25. PX4_I2C_BUS_ESC,
  26. #endif
  27. #ifdef PX4_I2C_BUS_ONBOARD
  28. PX4_I2C_BUS_ONBOARD,
  29. #endif
  30. -1
  31. };
  32. const int *cur_bus = busses_to_try;
  33. while (*cur_bus != -1) {
  34. /* create the driver */
  35. /* warnx("trying bus %d", *cur_bus); */
  36. g_dev = new PX4FLOW(*cur_bus);
  37. if (g_dev == nullptr) {
  38. /* this is a fatal error */
  39. break;
  40. }
  41. /* init the driver: */
  42. if (OK == g_dev->init()) {
  43. /* success! */
  44. break;
  45. }
  46. /* destroy it again because it failed. */
  47. delete g_dev;
  48. g_dev = nullptr;
  49. /* try next! */
  50. cur_bus++;
  51. }
  52. /* check whether we found it: */
  53. if (*cur_bus != -1) {
  54. /* check for failure: */
  55. if (g_dev == nullptr) {
  56. break;
  57. }
  58. /* set the poll rate to default, starts automatic data collection */
  59. fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
  60. if (fd < 0) {
  61. break;
  62. }
  63. if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MAX) < 0) {
  64. break;
  65. }
  66. /* success! */
  67. start_in_progress = false;
  68. return 0;
  69. }
  70. if (retry_nr < START_RETRY_COUNT) {
  71. /* lets not be too verbose */
  72. // warnx("PX4FLOW not found on I2C busses. Retrying in %d ms. Giving up in %d retries.", START_RETRY_TIMEOUT, START_RETRY_COUNT - retry_nr);
  73. usleep(START_RETRY_TIMEOUT * 1000);
  74. retry_nr++;
  75. } else {
  76. break;
  77. }
  78. }
  79. if (g_dev != nullptr) {
  80. delete g_dev;
  81. g_dev = nullptr;
  82. }
  83. start_in_progress = false;
  84. return 1;
  85. }

之后又会深入到底层,暂时先放着

读数据在test()里面

  1. /**
  2. * Perform some basic functional tests on the driver;
  3. * make sure we can collect data from the sensor in polled
  4. * and automatic modes.
  5. */
  6. void
  7. test()
  8. {
  9. struct optical_flow_s report;
  10. ssize_t sz;
  11. int ret;
  12. int fd = open(PX4FLOW0_DEVICE_PATH, O_RDONLY);
  13. if (fd < 0) {
  14. err(1, "%s open failed (try 'px4flow start' if the driver is not running", PX4FLOW0_DEVICE_PATH);
  15. }
  16. /* do a simple demand read */
  17. sz = read(fd, &report, sizeof(report));
  18. if (sz != sizeof(report)) {
  19. warnx("immediate read failed");
  20. }
  21. warnx("single read");
  22. warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
  23. warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
  24. warnx("framecount_integral: %u",
  25. f_integral.frame_count_since_last_readout);
  26. /* start the sensor polling at 10Hz */
  27. if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 10)) {
  28. errx(1, "failed to set 10Hz poll rate");
  29. }
  30. /* read the sensor 5x and report each value */
  31. for (unsigned i = 0; i < 10; i++) {
  32. struct pollfd fds;
  33. /* wait for data to be ready */
  34. fds.fd = fd;
  35. fds.events = POLLIN;
  36. ret = poll(&fds, 1, 2000);
  37. if (ret != 1) {
  38. errx(1, "timed out waiting for sensor data");
  39. }
  40. /* now go get it */
  41. sz = read(fd, &report, sizeof(report));
  42. if (sz != sizeof(report)) {
  43. err(1, "periodic read failed");
  44. }
  45. warnx("periodic read %u", i);
  46. warnx("framecount_total: %u", f.frame_count);
  47. warnx("framecount_integral: %u",
  48. f_integral.frame_count_since_last_readout);
  49. warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
  50. warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
  51. warnx("gyro_x_rate_integral: %i", f_integral.gyro_x_rate_integral);
  52. warnx("gyro_y_rate_integral: %i", f_integral.gyro_y_rate_integral);
  53. warnx("gyro_z_rate_integral: %i", f_integral.gyro_z_rate_integral);
  54. warnx("integration_timespan [us]: %u", f_integral.integration_timespan);
  55. warnx("ground_distance: %0.2f m",
  56. (double) f_integral.ground_distance / 1000);
  57. warnx("time since last sonar update [us]: %i",
  58. f_integral.sonar_timestamp);
  59. warnx("quality integration average : %i", f_integral.qual);
  60. warnx("quality : %i", f.qual);
  61. }
  62. errx(0, "PASS");
  63. }
看注释能明白sz = read(fd, &report, sizeof(report));是读的操作

ardupilot/modules/PX4Nuttx/nuttx/fs/fs_read.c这个路径应该是系统的路径,已经进了系统吗?系统是什么概念啊?

  1. ssize_t read(int fd, FAR void *buf, size_t nbytes)
  2. {
  3. /* Did we get a valid file descriptor? */
  4. #if CONFIG_NFILE_DESCRIPTORS > 0
  5. if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
  6. #endif
  7. {
  8. /* No.. If networking is enabled, read() is the same as recv() with
  9. * the flags parameter set to zero.
  10. */
  11. #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
  12. return recv(fd, buf, nbytes, 0);
  13. #else
  14. /* No networking... it is a bad descriptor in any event */
  15. set_errno(EBADF);
  16. return ERROR;
  17. #endif
  18. }
  19. /* The descriptor is in a valid range to file descriptor... do the read */
  20. #if CONFIG_NFILE_DESCRIPTORS > 0
  21. return file_read(fd, buf, nbytes);
  22. #endif
  23. }
看注释能明白return file_read(fd, buf, nbytes);是读操作

  1. /****************************************************************************
  2. * Private Functions
  3. ****************************************************************************/
  4. #if CONFIG_NFILE_DESCRIPTORS > 0
  5. static inline ssize_t file_read(int fd, FAR void *buf, size_t nbytes)
  6. {
  7. FAR struct filelist *list;
  8. int ret = -EBADF;
  9. /* Get the thread-specific file list */
  10. list = sched_getfiles();
  11. if (!list)
  12. {
  13. /* Failed to get the file list */
  14. ret = -EMFILE;
  15. }
  16. /* Were we given a valid file descriptor? */
  17. else if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
  18. {
  19. FAR struct file *this_file = &list->fl_files[fd];
  20. FAR struct inode *inode = this_file->f_inode;
  21. /* Yes.. Was this file opened for read access? */
  22. if ((this_file->f_oflags & O_RDOK) == 0)
  23. {
  24. /* No.. File is not read-able */
  25. ret = -EACCES;
  26. }
  27. /* Is a driver or mountpoint registered? If so, does it support
  28. * the read method?
  29. */
  30. else if (inode && inode->u.i_ops && inode->u.i_ops->read)
  31. {
  32. /* Yes.. then let it perform the read. NOTE that for the case
  33. * of the mountpoint, we depend on the read methods bing
  34. * identical in signature and position in the operations vtable.
  35. */
  36. ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes);
  37. }
  38. }
  39. /* If an error occurred, set errno and return -1 (ERROR) */
  40. if (ret < 0)
  41. {
  42. set_errno(-ret);
  43. return ERROR;
  44. }
  45. /* Otherwise, return the number of bytes read */
  46. return ret;
  47. }
  48. #endif
跟踪buf可知ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes);是读操作

于是进入了“文件操作”

  1. struct file_operations
  2. {
  3. /* The device driver open method differs from the mountpoint open method */
  4. int (*open)(FAR struct file *filp);
  5. /* The following methods must be identical in signature and position because
  6. * the struct file_operations and struct mountp_operations are treated like
  7. * unions.
  8. */
  9. int (*close)(FAR struct file *filp);
  10. ssize_t (*read)(FAR struct file *filp, FAR char *buffer, size_t buflen);
  11. ssize_t (*write)(FAR struct file *filp, FAR const char *buffer, size_t buflen);
  12. off_t (*seek)(FAR struct file *filp, off_t offset, int whence);
  13. int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
  14. #ifndef CONFIG_DISABLE_POLL
  15. int (*poll)(FAR struct file *filp, struct pollfd *fds, bool setup);
  16. #endif
  17. /* The two structures need not be common after this point */
  18. };
怎么继续找下去呢?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函数

  1. ssize_t
  2. PX4FLOW::read(struct file *filp, char *buffer, size_t buflen)
  3. {
  4. unsigned count = buflen / sizeof(struct optical_flow_s);
  5. struct optical_flow_s *rbuf = reinterpret_cast<struct optical_flow_s *>(buffer);
  6. int ret = 0;
  7. /* buffer must be large enough */
  8. if (count < 1) {
  9. return -ENOSPC;
  10. }
  11. /* if automatic measurement is enabled */
  12. if (_measure_ticks > 0) {
  13. /*
  14. * While there is space in the caller's buffer, and reports, copy them.
  15. * Note that we may be pre-empted by the workq thread while we are doing this;
  16. * we are careful to avoid racing with them.
  17. */
  18. while (count--) {
  19. if (_reports->get(rbuf)) {
  20. ret += sizeof(*rbuf);
  21. rbuf++;
  22. }
  23. }
  24. /* if there was no data, warn the caller */
  25. return ret ? ret : -EAGAIN;
  26. }
  27. /* manual measurement - run one conversion */
  28. do {
  29. _reports->flush();
  30. /* trigger a measurement */
  31. if (OK != measure()) {
  32. ret = -EIO;
  33. break;
  34. }
  35. /* run the collection phase */
  36. if (OK != collect()) {
  37. ret = -EIO;
  38. break;
  39. }
  40. /* state machine will have generated a report, copy it out */
  41. if (_reports->get(rbuf)) {
  42. ret = sizeof(*rbuf);
  43. }
  44. } while (0);
  45. return ret;
  46. }
get(rbuf)  (read函数中)

  1. bool
  2. RingBuffer::get(void *val, size_t val_size)
  3. {
  4. if (_tail != _head) {
  5. unsigned candidate;
  6. unsigned next;
  7. if ((val_size == 0) || (val_size > _item_size)) {
  8. val_size = _item_size;
  9. }
  10. do {
  11. /* decide which element we think we're going to read */
  12. candidate = _tail;
  13. /* and what the corresponding next index will be */
  14. next = _next(candidate);
  15. /* go ahead and read from this index */
  16. if (val != NULL) {
  17. memcpy(val, &_buf[candidate * _item_size], val_size);
  18. }
  19. /* if the tail pointer didn't change, we got our item */
  20. } while (!__PX4_SBCAP(&_tail, candidate, next));
  21. return true;
  22. } else {
  23. return false;
  24. }
  25. }
字面意思的从缓冲环中得到数据,并存到rbuf中
继续看 measure()collect()(read函数中)
  1. int
  2. PX4FLOW::measure()
  3. {
  4. int ret;
  5. /*
  6. * Send the command to begin a measurement.
  7. */
  8. uint8_t cmd = PX4FLOW_REG;
  9. ret = transfer(&cmd, 1, nullptr, 0);
  10. if (OK != ret) {
  11. perf_count(_comms_errors);
  12. DEVICE_DEBUG("i2c::transfer returned %d", ret);
  13. return ret;
  14. }
  15. ret = OK;
  16. return ret;
  17. }
看到 PX4FLOW_REG
  1. /* PX4FLOW Registers addresses */
  2. #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就是我们要找的函数

  1. int
  2. I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
  3. {
  4. struct i2c_msg_s msgv[2];
  5. unsigned msgs;
  6. int ret;
  7. unsigned retry_count = 0;
  8. do {
  9. // DEVICE_DEBUG("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);
  10. msgs = 0;
  11. if (send_len > 0) {
  12. msgv[msgs].addr = _address;
  13. msgv[msgs].flags = 0;
  14. msgv[msgs].buffer = const_cast<uint8_t *>(send);
  15. msgv[msgs].length = send_len;
  16. msgs++;
  17. }
  18. if (recv_len > 0) {
  19. msgv[msgs].addr = _address;
  20. msgv[msgs].flags = I2C_M_READ;
  21. msgv[msgs].buffer = recv;
  22. msgv[msgs].length = recv_len;
  23. msgs++;
  24. }
  25. if (msgs == 0) {
  26. return -EINVAL;
  27. }
  28. ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
  29. /* success */
  30. if (ret == OK) {
  31. break;
  32. }
  33. /* if we have already retried once, or we are going to give up, then reset the bus */
  34. if ((retry_count >= 1) || (retry_count >= _retries)) {
  35. up_i2creset(_dev);
  36. }
  37. } while (retry_count++ < _retries);
  38. return ret;
  39. }

struct i2c_msg_s msgv[2];

  1. struct i2c_msg_s
  2. {
  3. uint16_t addr; /* Slave address */
  4. uint16_t flags; /* See I2C_M_* definitions */
  5. uint8_t *buffer;
  6. int length;
  7. };
ret = I2C_TRANSFER(_dev, &msgv[0], msgs);找I2C_TRANSFER函数

#define I2C_TRANSFER(d,m,c) ((d)->ops->transfer(d,m,c)),找transfer函数

已无能为力了,找不下去了。好吧到此断了,找不到硬件层了,数据还没读回来

继续看collect()

  1. int
  2. PX4FLOW::collect()
  3. {
  4. int ret = -EIO;
  5. /* read from the sensor */
  6. uint8_t val[I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE] = { 0 };
  7. perf_begin(_sample_perf);
  8. if (PX4FLOW_REG == 0x00) {
  9. ret = transfer(nullptr, 0, &val[0], I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE);
  10. }
  11. if (PX4FLOW_REG == 0x16) {
  12. ret = transfer(nullptr, 0, &val[0], I2C_INTEGRAL_FRAME_SIZE);
  13. }
  14. if (ret < 0) {
  15. DEVICE_DEBUG("error reading from sensor: %d", ret);
  16. perf_count(_comms_errors);
  17. perf_end(_sample_perf);
  18. return ret;
  19. }
  20. if (PX4FLOW_REG == 0) {
  21. memcpy(&f, val, I2C_FRAME_SIZE);
  22. memcpy(&f_integral, &(val[I2C_FRAME_SIZE]), I2C_INTEGRAL_FRAME_SIZE);
  23. }
  24. if (PX4FLOW_REG == 0x16) {
  25. memcpy(&f_integral, val, I2C_INTEGRAL_FRAME_SIZE);
  26. }
  27. struct optical_flow_s report;
  28. report.timestamp = hrt_absolute_time();
  29. report.pixel_flow_x_integral = static_cast<float>(f_integral.pixel_flow_x_integral) / 10000.0f;//convert to radians
  30. report.pixel_flow_y_integral = static_cast<float>(f_integral.pixel_flow_y_integral) / 10000.0f;//convert to radians
  31. report.frame_count_since_last_readout = f_integral.frame_count_since_last_readout;
  32. report.ground_distance_m = static_cast<float>(f_integral.ground_distance) / 1000.0f;//convert to meters
  33. report.quality = f_integral.qual; //0:bad ; 255 max quality
  34. report.gyro_x_rate_integral = static_cast<float>(f_integral.gyro_x_rate_integral) / 10000.0f; //convert to radians
  35. report.gyro_y_rate_integral = static_cast<float>(f_integral.gyro_y_rate_integral) / 10000.0f; //convert to radians
  36. report.gyro_z_rate_integral = static_cast<float>(f_integral.gyro_z_rate_integral) / 10000.0f; //convert to radians
  37. report.integration_timespan = f_integral.integration_timespan; //microseconds
  38. report.time_since_last_sonar_update = f_integral.sonar_timestamp;//microseconds
  39. report.gyro_temperature = f_integral.gyro_temperature;//Temperature * 100 in centi-degrees Celsius
  40. report.sensor_id = 0;
  41. /* rotate measurements according to parameter */根据参数测量旋转
  42. float zeroval = 0.0f;
  43. rotate_3f(_sensor_rotation, report.pixel_flow_x_integral, report.pixel_flow_y_integral, zeroval);
  44. rotate_3f(_sensor_rotation, report.gyro_x_rate_integral, report.gyro_y_rate_integral, report.gyro_z_rate_integral);
  45. if (_px4flow_topic == nullptr) {
  46. _px4flow_topic = orb_advertise(ORB_ID(optical_flow), &report);
  47. } else {
  48. /* publish it */
  49. orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
  50. }
  51. /* publish to the distance_sensor topic as well */将distance_sensor主题发布出去
  52. struct distance_sensor_s distance_report;
  53. distance_report.timestamp = report.timestamp;
  54. distance_report.min_distance = PX4FLOW_MIN_DISTANCE;
  55. distance_report.max_distance = PX4FLOW_MAX_DISTANCE;
  56. distance_report.current_distance = report.ground_distance_m;
  57. distance_report.covariance = 0.0f;
  58. distance_report.type = distance_sensor_s::MAV_DISTANCE_SENSOR_ULTRASOUND;
  59. /* TODO: the ID needs to be properly set */
  60. distance_report.id = 0;
  61. distance_report.orientation = 8;
  62. orb_publish(ORB_ID(distance_sensor), _distance_sensor_topic, &distance_report);
  63. /* post a report to the ring */发布到环的报告
  64. if (_reports->force(&report)) {
  65. perf_count(_buffer_overflows);
  66. }
  67. /* notify anyone waiting for data */通知别人等待数据
  68. poll_notify(POLLIN);
  69. ret = OK;
  70. perf_end(_sample_perf);
  71. return ret;
  72. }

注意看

  1. if (PX4FLOW_REG == 0x00) {
  2. ret = transfer(nullptr, 0, &val[0], I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE);
  3. }
  4. if (PX4FLOW_REG == 0x16) {
  5. ret = transfer(nullptr, 0, &val[0], I2C_INTEGRAL_FRAME_SIZE);
  6. }

这个是把数据读回

意思就是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结构体中

  1. struct i2c_frame f;
  2. struct i2c_integral_frame f_integral;
  3. typedef struct i2c_frame {
  4. uint16_t frame_count;
  5. int16_t pixel_flow_x_sum;
  6. int16_t pixel_flow_y_sum;
  7. int16_t flow_comp_m_x;
  8. int16_t flow_comp_m_y;
  9. int16_t qual;
  10. int16_t gyro_x_rate;
  11. int16_t gyro_y_rate;
  12. int16_t gyro_z_rate;
  13. uint8_t gyro_range;
  14. uint8_t sonar_timestamp;
  15. int16_t ground_distance;
  16. } i2c_frame;
  17. #define I2C_FRAME_SIZE (sizeof(i2c_frame))
  18. typedef struct i2c_integral_frame {
  19. uint16_t frame_count_since_last_readout;
  20. int16_t pixel_flow_x_integral;
  21. int16_t pixel_flow_y_integral;
  22. int16_t gyro_x_rate_integral;
  23. int16_t gyro_y_rate_integral;
  24. int16_t gyro_z_rate_integral;
  25. uint32_t integration_timespan;
  26. uint32_t sonar_timestamp;
  27. uint16_t ground_distance;
  28. int16_t gyro_temperature;
  29. uint8_t qual;
  30. } 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_att_control  

位置控制 mc_pos_control  

EKF2暂时先不考虑

接下来要看position_estimator_inav _main.cpp(从常识也知道光流是用来获取空间xy方向的位置信息,所以之后肯定是用于位置估计上)

那么先宏观上分析下这个 position_estimator_inav _main.cpp

  1. #include <px4_posix.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stdbool.h>
  6. #include <fcntl.h>
  7. #include <string.h>
  8. #include <px4_config.h>
  9. #include <math.h>
  10. #include <float.h>
  11. #include <uORB/uORB.h>
  12. #include <uORB/topics/parameter_update.h>
  13. #include <uORB/topics/actuator_controls.h>
  14. #include <uORB/topics/actuator_controls_0.h>
  15. #include <uORB/topics/actuator_controls_1.h>
  16. #include <uORB/topics/actuator_controls_2.h>
  17. #include <uORB/topics/actuator_controls_3.h>
  18. #include <uORB/topics/actuator_armed.h>
  19. #include <uORB/topics/sensor_combined.h>
  20. #include <uORB/topics/vehicle_attitude.h>
  21. #include <uORB/topics/vehicle_local_position.h>
  22. #include <uORB/topics/vehicle_global_position.h>
  23. #include <uORB/topics/vehicle_gps_position.h>
  24. #include <uORB/topics/vision_position_estimate.h>
  25. #include <uORB/topics/att_pos_mocap.h>
  26. #include <uORB/topics/optical_flow.h>
  27. #include <uORB/topics/distance_sensor.h>
  28. #include <poll.h>
  29. #include <systemlib/err.h>
  30. #include <systemlib/mavlink_log.h>
  31. #include <geo/geo.h>
  32. #include <systemlib/systemlib.h>
  33. #include <drivers/drv_hrt.h>
  34. #include <platforms/px4_defines.h>
  35. #include <terrain_estimation/terrain_estimator.h>
  36. #include "position_estimator_inav_params.h"
  37. #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中呢?估计有个总的流程,分别调用启动这些功能“函数”

  1. /****************************************************************************
  2. * main
  3. ****************************************************************************/
  4. int position_estimator_inav_thread_main(int argc, char *argv[])
  5. {
  6. /**************************类似于初始化或者声明******************************/
  7. orb_advert_t mavlink_log_pub = nullptr;
  8. float x_est[2] = { 0.0f, 0.0f }; // pos, vel
  9. float y_est[2] = { 0.0f, 0.0f }; // pos, vel
  10. float z_est[2] = { 0.0f, 0.0f }; // pos, vel
  11. float est_buf[EST_BUF_SIZE][3][2]; // estimated position buffer
  12. float R_buf[EST_BUF_SIZE][3][3]; // rotation matrix buffer
  13. float R_gps[3][3]; // rotation matrix for GPS correction moment
  14. memset(est_buf, 0, sizeof(est_buf));
  15. memset(R_buf, 0, sizeof(R_buf));
  16. memset(R_gps, 0, sizeof(R_gps));
  17. int buf_ptr = 0;
  18. static const float min_eph_epv = 2.0f; // min EPH/EPV, used for weight calculation
  19. static const float max_eph_epv = 20.0f; // max EPH/EPV acceptable for estimation
  20. float eph = max_eph_epv;
  21. float epv = 1.0f;
  22. float eph_flow = 1.0f;
  23. float eph_vision = 0.2f;
  24. float epv_vision = 0.2f;
  25. float eph_mocap = 0.05f;
  26. float epv_mocap = 0.05f;
  27. float x_est_prev[2], y_est_prev[2], z_est_prev[2];
  28. memset(x_est_prev, 0, sizeof(x_est_prev));
  29. memset(y_est_prev, 0, sizeof(y_est_prev));
  30. memset(z_est_prev, 0, sizeof(z_est_prev));
  31. int baro_init_cnt = 0;
  32. int baro_init_num = 200;
  33. float baro_offset = 0.0f; // baro offset for reference altitude, initialized on start, then adjusted
  34. hrt_abstime accel_timestamp = 0;
  35. hrt_abstime baro_timestamp = 0;
  36. bool ref_inited = false;
  37. hrt_abstime ref_init_start = 0;
  38. const hrt_abstime ref_init_delay = 1000000; // wait for 1s after 3D fix
  39. struct map_projection_reference_s ref;
  40. memset(&ref, 0, sizeof(ref));
  41. uint16_t accel_updates = 0;
  42. uint16_t baro_updates = 0;
  43. uint16_t gps_updates = 0;
  44. uint16_t attitude_updates = 0;
  45. uint16_t flow_updates = 0;
  46. uint16_t vision_updates = 0;
  47. uint16_t mocap_updates = 0;
  48. hrt_abstime updates_counter_start = hrt_absolute_time();
  49. hrt_abstime pub_last = hrt_absolute_time();
  50. hrt_abstime t_prev = 0;
  51. /* store error when sensor updates, but correct on each time step to avoid jumps in estimated value */
  52. float acc[] = { 0.0f, 0.0f, 0.0f }; // N E D
  53. float acc_bias[] = { 0.0f, 0.0f, 0.0f }; // body frame
  54. float corr_baro = 0.0f; // D
  55. float corr_gps[3][2] = {
  56. { 0.0f, 0.0f }, // N (pos, vel)
  57. { 0.0f, 0.0f }, // E (pos, vel)
  58. { 0.0f, 0.0f }, // D (pos, vel)
  59. };
  60. float w_gps_xy = 1.0f;
  61. float w_gps_z = 1.0f;
  62. float corr_vision[3][2] = {
  63. { 0.0f, 0.0f }, // N (pos, vel)
  64. { 0.0f, 0.0f }, // E (pos, vel)
  65. { 0.0f, 0.0f }, // D (pos, vel)
  66. };
  67. float corr_mocap[3][1] = {
  68. { 0.0f }, // N (pos)
  69. { 0.0f }, // E (pos)
  70. { 0.0f }, // D (pos)
  71. };
  72. const int mocap_heading = 2;
  73. float dist_ground = 0.0f; //variables for lidar altitude estimation
  74. float corr_lidar = 0.0f;
  75. float lidar_offset = 0.0f;
  76. int lidar_offset_count = 0;
  77. bool lidar_first = true;
  78. bool use_lidar = false;
  79. bool use_lidar_prev = false;
  80. float corr_flow[] = { 0.0f, 0.0f }; // N E
  81. float w_flow = 0.0f;
  82. hrt_abstime lidar_time = 0; // time of last lidar measurement (not filtered)
  83. hrt_abstime lidar_valid_time = 0; // time of last lidar measurement used for correction (filtered)
  84. int n_flow = 0;
  85. float gyro_offset_filtered[] = { 0.0f, 0.0f, 0.0f };
  86. float flow_gyrospeed[] = { 0.0f, 0.0f, 0.0f };
  87. float flow_gyrospeed_filtered[] = { 0.0f, 0.0f, 0.0f };
  88. float att_gyrospeed_filtered[] = { 0.0f, 0.0f, 0.0f };
  89. float yaw_comp[] = { 0.0f, 0.0f };
  90. hrt_abstime flow_time = 0;
  91. float flow_min_dist = 0.2f;
  92. bool gps_valid = false; // GPS is valid
  93. bool lidar_valid = false; // lidar is valid
  94. bool flow_valid = false; // flow is valid
  95. bool flow_accurate = false; // flow should be accurate (this flag not updated if flow_valid == false)
  96. bool vision_valid = false; // vision is valid
  97. bool mocap_valid = false; // mocap is valid
  98. /* declare and safely initialize all structs */
  99. struct actuator_controls_s actuator;
  100. memset(&actuator, 0, sizeof(actuator));
  101. struct actuator_armed_s armed;
  102. memset(&armed, 0, sizeof(armed));
  103. struct sensor_combined_s sensor;
  104. memset(&sensor, 0, sizeof(sensor));
  105. struct vehicle_gps_position_s gps;
  106. memset(&gps, 0, sizeof(gps));
  107. struct vehicle_attitude_s att;
  108. memset(&att, 0, sizeof(att));
  109. struct vehicle_local_position_s local_pos;
  110. memset(&local_pos, 0, sizeof(local_pos));
  111. struct optical_flow_s flow;
  112. memset(&flow, 0, sizeof(flow));
  113. struct vision_position_estimate_s vision;
  114. memset(&vision, 0, sizeof(vision));
  115. struct att_pos_mocap_s mocap;
  116. memset(&mocap, 0, sizeof(mocap));
  117. struct vehicle_global_position_s global_pos;
  118. memset(&global_pos, 0, sizeof(global_pos));
  119. struct distance_sensor_s lidar;
  120. memset(&lidar, 0, sizeof(lidar));
  121. struct vehicle_rates_setpoint_s rates_setpoint;
  122. memset(&rates_setpoint, 0, sizeof(rates_setpoint));
  123. /**************************订阅各种信息******************************/
  124. /* subscribe */
  125. int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
  126. int actuator_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
  127. int armed_sub = orb_subscribe(ORB_ID(actuator_armed));
  128. int sensor_combined_sub = orb_subscribe(ORB_ID(sensor_combined));
  129. int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
  130. int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
  131. int vehicle_gps_position_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
  132. int vision_position_estimate_sub = orb_subscribe(ORB_ID(vision_position_estimate));
  133. int att_pos_mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
  134. int distance_sensor_sub = orb_subscribe(ORB_ID(distance_sensor));
  135. int vehicle_rate_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
  136. /**************************发布位置信息******************************/
  137. /* advertise */
  138. orb_advert_t vehicle_local_position_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
  139. orb_advert_t vehicle_global_position_pub = NULL;
  140. /**************************类似于初始化params******************************/
  141. struct position_estimator_inav_params params;
  142. memset(¶ms, 0, sizeof(params));
  143. struct position_estimator_inav_param_handles pos_inav_param_handles;
  144. /* initialize parameter handles */
  145. inav_parameters_init(&pos_inav_param_handles);
  146. /* first parameters read at start up */
  147. struct parameter_update_s param_update;
  148. orb_copy(ORB_ID(parameter_update), parameter_update_sub,
  149. ¶m_update); /* read from param topic to clear updated flag */
  150. /* first parameters update */
  151. inav_parameters_update(&pos_inav_param_handles, ¶ms);
  152. /**************************sensor_combined******************************/
  153. px4_pollfd_struct_t fds_init[1] = {};
  154. fds_init[0].fd = sensor_combined_sub;
  155. fds_init[0].events = POLLIN;
  156. 气压计///
  157. /* wait for initial baro value */
  158. bool wait_baro = true;
  159. TerrainEstimator *terrain_estimator = new TerrainEstimator();
  160. thread_running = true;
  161. hrt_abstime baro_wait_for_sample_time = hrt_absolute_time();
  162. while (wait_baro && !thread_should_exit) {
  163. int ret = px4_poll(&fds_init[0], 1, 1000);
  164. if (ret < 0) {
  165. /* poll error */
  166. mavlink_log_info(&mavlink_log_pub, "[inav] poll error on init");
  167. } else if (hrt_absolute_time() - baro_wait_for_sample_time > MAX_WAIT_FOR_BARO_SAMPLE) {
  168. wait_baro = false;
  169. mavlink_log_info(&mavlink_log_pub, "[inav] timed out waiting for a baro sample");
  170. }
  171. else if (ret > 0) {
  172. if (fds_init[0].revents & POLLIN) {
  173. orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
  174. if (wait_baro && sensor.baro_timestamp[0] != baro_timestamp) {
  175. baro_timestamp = sensor.baro_timestamp[0];
  176. baro_wait_for_sample_time = hrt_absolute_time();
  177. /* mean calculation over several measurements */
  178. if (baro_init_cnt < baro_init_num) {
  179. if (PX4_ISFINITE(sensor.baro_alt_meter[0])) {
  180. baro_offset += sensor.baro_alt_meter[0];
  181. baro_init_cnt++;
  182. }
  183. } else {
  184. wait_baro = false;
  185. baro_offset /= (float) baro_init_cnt;
  186. local_pos.z_valid = true;
  187. local_pos.v_z_valid = true;
  188. }
  189. }
  190. }
  191. } else {
  192. PX4_WARN("INAV poll timeout");
  193. }
  194. }
  195. /**************************主循环******************************/
  196. /* main loop */
  197. px4_pollfd_struct_t fds[1];
  198. fds[0].fd = vehicle_attitude_sub;
  199. fds[0].events = POLLIN;
  200. 判断是否应该退出该线程///
  201. while (!thread_should_exit) { //这个判断条件经常使用,到处都用过类似的
  202. int ret = px4_poll(fds, 1, 20); // wait maximal 20 ms = 50 Hz minimum rate
  203. hrt_abstime t = hrt_absolute_time();
  204. if (ret < 0) {
  205. /* poll error */
  206. mavlink_log_info(&mavlink_log_pub, "[inav] poll error on init");
  207. continue;
  208. } else if (ret > 0) {
  209. /* act on attitude updates */
  210. /* vehicle attitude */
  211. orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);//姿态跟新
  212. attitude_updates++;
  213. bool updated;
  214. /* parameter update */
  215. orb_check(parameter_update_sub, &updated);
  216. if (updated) {
  217. struct parameter_update_s update;
  218. orb_copy(ORB_ID(parameter_update), parameter_update_sub, &update);//parameter跟新
  219. inav_parameters_update(&pos_inav_param_handles, ¶ms);
  220. }
  221. /* actuator */
  222. orb_check(actuator_sub, &updated);
  223. if (updated) {
  224. orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_sub, &actuator);//执行器数据跟新(这里并不是pwm)
  225. }
  226. /* armed */
  227. orb_check(armed_sub, &updated);
  228. if (updated) {
  229. orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);//解锁数据跟新
  230. }
  231. /* sensor combined */
  232. orb_check(sensor_combined_sub, &updated);
  233. if (updated) {
  234. orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);//传感器融合数据跟新
  235. if (sensor.accelerometer_timestamp[0] != accel_timestamp) {
  236. if (att.R_valid) {
  237. /* correct accel bias */
  238. sensor.accelerometer_m_s2[0] -= acc_bias[0];
  239. sensor.accelerometer_m_s2[1] -= acc_bias[1];
  240. sensor.accelerometer_m_s2[2] -= acc_bias[2];
  241. /* transform acceleration vector from body frame to NED frame */
  242. for (int i = 0; i < 3; i++) {
  243. acc[i] = 0.0f;
  244. for (int j = 0; j < 3; j++) {
  245. acc[i] += PX4_R(att.R, i, j) * sensor.accelerometer_m_s2[j];
  246. }
  247. }
  248. acc[2] += CONSTANTS_ONE_G;
  249. } else {
  250. memset(acc, 0, sizeof(acc));
  251. }
  252. accel_timestamp = sensor.accelerometer_timestamp[0];
  253. accel_updates++;
  254. }
  255. if (sensor.baro_timestamp[0] != baro_timestamp) {
  256. corr_baro = baro_offset - sensor.baro_alt_meter[0] - z_est[0];
  257. baro_timestamp = sensor.baro_timestamp[0];
  258. baro_updates++;
  259. }
  260. }
  261. /* lidar alt estimation */
  262. orb_check(distance_sensor_sub, &updated);
  263. /* update lidar separately, needed by terrain estimator */
  264. if (updated) {
  265. orb_copy(ORB_ID(distance_sensor), distance_sensor_sub, &lidar);//高度数据跟新
  266. lidar.current_distance += params.lidar_calibration_offset;
  267. }
  268. if (updated) { //check if altitude estimation for lidar is enabled and new sensor data
  269. if (params.enable_lidar_alt_est && lidar.current_distance > lidar.min_distance && lidar.current_distance < lidar.max_distance
  270. && (PX4_R(att.R, 2, 2) > 0.7f)) {
  271. if (!use_lidar_prev && use_lidar) {
  272. lidar_first = true;
  273. }
  274. use_lidar_prev = use_lidar;
  275. lidar_time = t;
  276. dist_ground = lidar.current_distance * PX4_R(att.R, 2, 2); //vertical distance
  277. if (lidar_first) {
  278. lidar_first = false;
  279. lidar_offset = dist_ground + z_est[0];
  280. mavlink_log_info(&mavlink_log_pub, "[inav] LIDAR: new ground offset");
  281. warnx("[inav] LIDAR: new ground offset");
  282. }
  283. corr_lidar = lidar_offset - dist_ground - z_est[0];
  284. if (fabsf(corr_lidar) > params.lidar_err) { //check for spike
  285. corr_lidar = 0;
  286. lidar_valid = false;
  287. lidar_offset_count++;
  288. if (lidar_offset_count > 3) { //if consecutive bigger/smaller measurements -> new ground offset -> reinit
  289. lidar_first = true;
  290. lidar_offset_count = 0;
  291. }
  292. } else {
  293. corr_lidar = lidar_offset - dist_ground - z_est[0];
  294. lidar_valid = true;
  295. lidar_offset_count = 0;
  296. lidar_valid_time = t;
  297. }
  298. } else {
  299. lidar_valid = false;
  300. }
  301. }
  302. /**************************************这里就是光流的处理*********************************/
  303. /* optical flow */
  304. orb_check(optical_flow_sub, &updated);
  305. if (updated && lidar_valid) {
  306. orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);//光流数据跟新
  307. flow_time = t;
  308. float flow_q = flow.quality / 255.0f;
  309. float dist_bottom = lidar.current_distance;//高度信息
  310. if (dist_bottom > flow_min_dist && flow_q > params.flow_q_min && PX4_R(att.R, 2, 2) > 0.7f) {
  311. /* distance to surface */
  312. //float flow_dist = dist_bottom / PX4_R(att.R, 2, 2); //use this if using sonar
  313. float flow_dist = dist_bottom; //use this if using lidar
  314. /* check if flow if too large for accurate measurements */
  315. /* calculate estimated velocity in body frame */
  316. float body_v_est[2] = { 0.0f, 0.0f };
  317. for (int i = 0; i < 2; i++) {
  318. 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];
  319. }
  320. /* set this flag if flow should be accurate according to current velocity and attitude rate estimate */
  321. flow_accurate = fabsf(body_v_est[1] / flow_dist - att.rollspeed) < max_flow &&
  322. fabsf(body_v_est[0] / flow_dist + att.pitchspeed) < max_flow;
  323. /*calculate offset of flow-gyro using already calibrated gyro from autopilot*/
  324. flow_gyrospeed[0] = flow.gyro_x_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  325. flow_gyrospeed[1] = flow.gyro_y_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  326. flow_gyrospeed[2] = flow.gyro_z_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  327. //moving average
  328. if (n_flow >= 100) {
  329. gyro_offset_filtered[0] = flow_gyrospeed_filtered[0] - att_gyrospeed_filtered[0];
  330. gyro_offset_filtered[1] = flow_gyrospeed_filtered[1] - att_gyrospeed_filtered[1];
  331. gyro_offset_filtered[2] = flow_gyrospeed_filtered[2] - att_gyrospeed_filtered[2];
  332. n_flow = 0;
  333. flow_gyrospeed_filtered[0] = 0.0f;
  334. flow_gyrospeed_filtered[1] = 0.0f;
  335. flow_gyrospeed_filtered[2] = 0.0f;
  336. att_gyrospeed_filtered[0] = 0.0f;
  337. att_gyrospeed_filtered[1] = 0.0f;
  338. att_gyrospeed_filtered[2] = 0.0f;
  339. } else {
  340. flow_gyrospeed_filtered[0] = (flow_gyrospeed[0] + n_flow * flow_gyrospeed_filtered[0]) / (n_flow + 1);
  341. flow_gyrospeed_filtered[1] = (flow_gyrospeed[1] + n_flow * flow_gyrospeed_filtered[1]) / (n_flow + 1);
  342. flow_gyrospeed_filtered[2] = (flow_gyrospeed[2] + n_flow * flow_gyrospeed_filtered[2]) / (n_flow + 1);
  343. att_gyrospeed_filtered[0] = (att.pitchspeed + n_flow * att_gyrospeed_filtered[0]) / (n_flow + 1);
  344. att_gyrospeed_filtered[1] = (att.rollspeed + n_flow * att_gyrospeed_filtered[1]) / (n_flow + 1);
  345. att_gyrospeed_filtered[2] = (att.yawspeed + n_flow * att_gyrospeed_filtered[2]) / (n_flow + 1);
  346. n_flow++;
  347. }
  348. /*yaw compensation (flow sensor is not in center of rotation) -> params in QGC*/
  349. yaw_comp[0] = - params.flow_module_offset_y * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
  350. yaw_comp[1] = params.flow_module_offset_x * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
  351. /* convert raw flow to angular flow (rad/s) */
  352. float flow_ang[2];
  353. /* check for vehicle rates setpoint - it below threshold -> dont subtract -> better hover */
  354. orb_check(vehicle_rate_sp_sub, &updated);
  355. if (updated)
  356. orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
  357. double rate_threshold = 0.15f;
  358. if (fabs(rates_setpoint.pitch) < rate_threshold) {
  359. //warnx("[inav] test ohne comp");
  360. 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)
  361. }
  362. else {
  363. //warnx("[inav] test mit comp");
  364. //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
  365. flow_ang[0] = ((flow.pixel_flow_x_integral - flow.gyro_x_rate_integral) / (float)flow.integration_timespan * 1000000.0f
  366. + gyro_offset_filtered[0]) * params.flow_k;//for now the flow has to be scaled (to small)
  367. }
  368. if (fabs(rates_setpoint.roll) < rate_threshold) {
  369. 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)
  370. }
  371. else {
  372. //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
  373. flow_ang[1] = ((flow.pixel_flow_y_integral - flow.gyro_y_rate_integral) / (float)flow.integration_timespan * 1000000.0f
  374. + gyro_offset_filtered[1]) * params.flow_k;//for now the flow has to be scaled (to small)
  375. }
  376. /* flow measurements vector */
  377. float flow_m[3];
  378. if (fabs(rates_setpoint.yaw) < rate_threshold) {
  379. flow_m[0] = -flow_ang[0] * flow_dist;
  380. flow_m[1] = -flow_ang[1] * flow_dist;
  381. } else {
  382. flow_m[0] = -flow_ang[0] * flow_dist - yaw_comp[0] * params.flow_k;
  383. flow_m[1] = -flow_ang[1] * flow_dist - yaw_comp[1] * params.flow_k;
  384. }
  385. flow_m[2] = z_est[1];
  386. /* velocity in NED */
  387. float flow_v[2] = { 0.0f, 0.0f };
  388. /* project measurements vector to NED basis, skip Z component */
  389. for (int i = 0; i < 2; i++) {
  390. for (int j = 0; j < 3; j++) {
  391. flow_v[i] += PX4_R(att.R, i, j) * flow_m[j];
  392. }
  393. }
  394. /* velocity correction */
  395. corr_flow[0] = flow_v[0] - x_est[1];
  396. corr_flow[1] = flow_v[1] - y_est[1];
  397. /* adjust correction weight */
  398. float flow_q_weight = (flow_q - params.flow_q_min) / (1.0f - params.flow_q_min);
  399. w_flow = PX4_R(att.R, 2, 2) * flow_q_weight / fmaxf(1.0f, flow_dist);
  400. /* if flow is not accurate, reduce weight for it */
  401. // TODO make this more fuzzy
  402. if (!flow_accurate) {
  403. w_flow *= 0.05f;
  404. }
  405. /* under ideal conditions, on 1m distance assume EPH = 10cm */
  406. eph_flow = 0.1f / w_flow;
  407. flow_valid = true;
  408. } else {
  409. w_flow = 0.0f;
  410. flow_valid = false;
  411. }
  412. flow_updates++;
  413. }
  414. /**************************************光流结束*********************************/
  415. //视觉的处理
  416. /* check no vision circuit breaker is set */
  417. if (params.no_vision != CBRK_NO_VISION_KEY) {
  418. /* vehicle vision position */
  419. orb_check(vision_position_estimate_sub, &updated);
  420. if (updated) {
  421. orb_copy(ORB_ID(vision_position_estimate), vision_position_estimate_sub, &vision);
  422. static float last_vision_x = 0.0f;
  423. static float last_vision_y = 0.0f;
  424. static float last_vision_z = 0.0f;
  425. /* reset position estimate on first vision update */
  426. if (!vision_valid) {
  427. x_est[0] = vision.x;
  428. x_est[1] = vision.vx;
  429. y_est[0] = vision.y;
  430. y_est[1] = vision.vy;
  431. /* only reset the z estimate if the z weight parameter is not zero */
  432. if (params.w_z_vision_p > MIN_VALID_W) {
  433. z_est[0] = vision.z;
  434. z_est[1] = vision.vz;
  435. }
  436. vision_valid = true;
  437. last_vision_x = vision.x;
  438. last_vision_y = vision.y;
  439. last_vision_z = vision.z;
  440. warnx("VISION estimate valid");
  441. mavlink_log_info(&mavlink_log_pub, "[inav] VISION estimate valid");
  442. }
  443. /* calculate correction for position */
  444. corr_vision[0][0] = vision.x - x_est[0];
  445. corr_vision[1][0] = vision.y - y_est[0];
  446. corr_vision[2][0] = vision.z - z_est[0];
  447. static hrt_abstime last_vision_time = 0;
  448. float vision_dt = (vision.timestamp_boot - last_vision_time) / 1e6f;
  449. last_vision_time = vision.timestamp_boot;
  450. if (vision_dt > 0.000001f && vision_dt < 0.2f) {
  451. vision.vx = (vision.x - last_vision_x) / vision_dt;
  452. vision.vy = (vision.y - last_vision_y) / vision_dt;
  453. vision.vz = (vision.z - last_vision_z) / vision_dt;
  454. last_vision_x = vision.x;
  455. last_vision_y = vision.y;
  456. last_vision_z = vision.z;
  457. /* calculate correction for velocity */
  458. corr_vision[0][1] = vision.vx - x_est[1];
  459. corr_vision[1][1] = vision.vy - y_est[1];
  460. corr_vision[2][1] = vision.vz - z_est[1];
  461. } else {
  462. /* assume zero motion */
  463. corr_vision[0][1] = 0.0f - x_est[1];
  464. corr_vision[1][1] = 0.0f - y_est[1];
  465. corr_vision[2][1] = 0.0f - z_est[1];
  466. }
  467. vision_updates++;
  468. }
  469. }
  470. ///mocap数据处理///
  471. /* vehicle mocap position */
  472. orb_check(att_pos_mocap_sub, &updated);
  473. if (updated) {
  474. orb_copy(ORB_ID(att_pos_mocap), att_pos_mocap_sub, &mocap);
  475. if (!params.disable_mocap) {
  476. /* reset position estimate on first mocap update */
  477. if (!mocap_valid) {
  478. x_est[0] = mocap.x;
  479. y_est[0] = mocap.y;
  480. z_est[0] = mocap.z;
  481. mocap_valid = true;
  482. warnx("MOCAP data valid");
  483. mavlink_log_info(&mavlink_log_pub, "[inav] MOCAP data valid");
  484. }
  485. /* calculate correction for position */
  486. corr_mocap[0][0] = mocap.x - x_est[0];
  487. corr_mocap[1][0] = mocap.y - y_est[0];
  488. corr_mocap[2][0] = mocap.z - z_est[0];
  489. mocap_updates++;
  490. }
  491. }
  492. //GPS数据处理///
  493. /* vehicle GPS position */
  494. orb_check(vehicle_gps_position_sub, &updated);
  495. if (updated) {
  496. orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);
  497. bool reset_est = false;
  498. /* hysteresis for GPS quality */
  499. if (gps_valid) {
  500. if (gps.eph > max_eph_epv || gps.epv > max_eph_epv || gps.fix_type < 3) {
  501. gps_valid = false;
  502. mavlink_log_info(&mavlink_log_pub, "[inav] GPS signal lost");
  503. warnx("[inav] GPS signal lost");
  504. }
  505. } else {
  506. if (gps.eph < max_eph_epv * 0.7f && gps.epv < max_eph_epv * 0.7f && gps.fix_type >= 3) {
  507. gps_valid = true;
  508. reset_est = true;
  509. mavlink_log_info(&mavlink_log_pub, "[inav] GPS signal found");
  510. warnx("[inav] GPS signal found");
  511. }
  512. }
  513. if (gps_valid) {
  514. double lat = gps.lat * 1e-7;
  515. double lon = gps.lon * 1e-7;
  516. float alt = gps.alt * 1e-3;
  517. /* initialize reference position if needed */
  518. if (!ref_inited) {
  519. if (ref_init_start == 0) {
  520. ref_init_start = t;
  521. } else if (t > ref_init_start + ref_init_delay) {
  522. ref_inited = true;
  523. /* set position estimate to (0, 0, 0), use GPS velocity for XY */
  524. x_est[0] = 0.0f;
  525. x_est[1] = gps.vel_n_m_s;
  526. y_est[0] = 0.0f;
  527. y_est[1] = gps.vel_e_m_s;
  528. local_pos.ref_lat = lat;
  529. local_pos.ref_lon = lon;
  530. local_pos.ref_alt = alt + z_est[0];
  531. local_pos.ref_timestamp = t;
  532. /* initialize projection */
  533. map_projection_init(&ref, lat, lon);
  534. // XXX replace this print
  535. warnx("init ref: lat=%.7f, lon=%.7f, alt=%8.4f", (double)lat, (double)lon, (double)alt);
  536. mavlink_log_info(&mavlink_log_pub, "[inav] init ref: %.7f, %.7f, %8.4f", (double)lat, (double)lon, (double)alt);
  537. }
  538. }
  539. if (ref_inited) {
  540. /* project GPS lat lon to plane */
  541. float gps_proj[2];
  542. map_projection_project(&ref, lat, lon, &(gps_proj[0]), &(gps_proj[1]));
  543. /* reset position estimate when GPS becomes good */
  544. if (reset_est) {
  545. x_est[0] = gps_proj[0];
  546. x_est[1] = gps.vel_n_m_s;
  547. y_est[0] = gps_proj[1];
  548. y_est[1] = gps.vel_e_m_s;
  549. }
  550. /* calculate index of estimated values in buffer */
  551. int est_i = buf_ptr - 1 - min(EST_BUF_SIZE - 1, max(0, (int)(params.delay_gps * 1000000.0f / PUB_INTERVAL)));
  552. if (est_i < 0) {
  553. est_i += EST_BUF_SIZE;
  554. }
  555. /* calculate correction for position */
  556. corr_gps[0][0] = gps_proj[0] - est_buf[est_i][0][0];
  557. corr_gps[1][0] = gps_proj[1] - est_buf[est_i][1][0];
  558. corr_gps[2][0] = local_pos.ref_alt - alt - est_buf[est_i][2][0];
  559. /* calculate correction for velocity */
  560. if (gps.vel_ned_valid) {
  561. corr_gps[0][1] = gps.vel_n_m_s - est_buf[est_i][0][1];
  562. corr_gps[1][1] = gps.vel_e_m_s - est_buf[est_i][1][1];
  563. corr_gps[2][1] = gps.vel_d_m_s - est_buf[est_i][2][1];
  564. } else {
  565. corr_gps[0][1] = 0.0f;
  566. corr_gps[1][1] = 0.0f;
  567. corr_gps[2][1] = 0.0f;
  568. }
  569. /* save rotation matrix at this moment */
  570. memcpy(R_gps, R_buf[est_i], sizeof(R_gps));
  571. w_gps_xy = min_eph_epv / fmaxf(min_eph_epv, gps.eph);
  572. w_gps_z = min_eph_epv / fmaxf(min_eph_epv, gps.epv);
  573. }
  574. } else {
  575. /* no GPS lock */
  576. memset(corr_gps, 0, sizeof(corr_gps));
  577. ref_init_start = 0;
  578. }
  579. gps_updates++;
  580. }
  581. }
  582. ///检查是否timeout//
  583. /* check for timeout on FLOW topic */
  584. if ((flow_valid || lidar_valid) && t > (flow_time + flow_topic_timeout)) {
  585. flow_valid = false;
  586. warnx("FLOW timeout");
  587. mavlink_log_info(&mavlink_log_pub, "[inav] FLOW timeout");
  588. }
  589. /* check for timeout on GPS topic */
  590. if (gps_valid && (t > (gps.timestamp_position + gps_topic_timeout))) {
  591. gps_valid = false;
  592. warnx("GPS timeout");
  593. mavlink_log_info(&mavlink_log_pub, "[inav] GPS timeout");
  594. }
  595. /* check for timeout on vision topic */
  596. if (vision_valid && (t > (vision.timestamp_boot + vision_topic_timeout))) {
  597. vision_valid = false;
  598. warnx("VISION timeout");
  599. mavlink_log_info(&mavlink_log_pub, "[inav] VISION timeout");
  600. }
  601. /* check for timeout on mocap topic */
  602. if (mocap_valid && (t > (mocap.timestamp_boot + mocap_topic_timeout))) {
  603. mocap_valid = false;
  604. warnx("MOCAP timeout");
  605. mavlink_log_info(&mavlink_log_pub, "[inav] MOCAP timeout");
  606. }
  607. /* check for lidar measurement timeout */
  608. if (lidar_valid && (t > (lidar_time + lidar_timeout))) {
  609. lidar_valid = false;
  610. warnx("LIDAR timeout");
  611. mavlink_log_info(&mavlink_log_pub, "[inav] LIDAR timeout");
  612. }
  613. float dt = t_prev > 0 ? (t - t_prev) / 1000000.0f : 0.0f;
  614. dt = fmaxf(fminf(0.02, dt), 0.0002); // constrain dt from 0.2 to 20 ms
  615. t_prev = t;
  616. /* increase EPH/EPV on each step */
  617. if (eph < 0.000001f) { //get case where eph is 0 -> would stay 0
  618. eph = 0.001;
  619. }
  620. if (eph < max_eph_epv) {
  621. eph *= 1.0f + dt;
  622. }
  623. if (epv < 0.000001f) { //get case where epv is 0 -> would stay 0
  624. epv = 0.001;
  625. }
  626. if (epv < max_eph_epv) {
  627. epv += 0.005f * dt; // add 1m to EPV each 200s (baro drift)
  628. }
  629. //根据具体情况,将决策赋给标志位//
  630. /* use GPS if it's valid and reference position initialized */使用全球定位系统,如果它是有效的,并参考位置初始化
  631. bool use_gps_xy = ref_inited && gps_valid && params.w_xy_gps_p > MIN_VALID_W;
  632. bool use_gps_z = ref_inited && gps_valid && params.w_z_gps_p > MIN_VALID_W;
  633. /* use VISION if it's valid and has a valid weight parameter */使用VISION,如果它是有效的,并具有有效的权重参数
  634. bool use_vision_xy = vision_valid && params.w_xy_vision_p > MIN_VALID_W;
  635. bool use_vision_z = vision_valid && params.w_z_vision_p > MIN_VALID_W;
  636. /* use MOCAP if it's valid and has a valid weight parameter */使用MOCAP如果它是有效的,并具有有效的权重参数
  637. 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
  638. if (params.disable_mocap) { //disable mocap if fake gps is used
  639. use_mocap = false;
  640. }
  641. /* use flow if it's valid and (accurate or no GPS available) */
  642. bool use_flow = flow_valid && (flow_accurate || !use_gps_xy);
  643. /* use LIDAR if it's valid and lidar altitude estimation is enabled */
  644. use_lidar = lidar_valid && params.enable_lidar_alt_est;
  645. bool can_estimate_xy = (eph < max_eph_epv) || use_gps_xy || use_flow || use_vision_xy || use_mocap;
  646. bool dist_bottom_valid = (t < lidar_valid_time + lidar_valid_timeout);
  647. float w_xy_gps_p = params.w_xy_gps_p * w_gps_xy;
  648. float w_xy_gps_v = params.w_xy_gps_v * w_gps_xy;
  649. float w_z_gps_p = params.w_z_gps_p * w_gps_z;
  650. float w_z_gps_v = params.w_z_gps_v * w_gps_z;
  651. float w_xy_vision_p = params.w_xy_vision_p;
  652. float w_xy_vision_v = params.w_xy_vision_v;
  653. float w_z_vision_p = params.w_z_vision_p;
  654. float w_mocap_p = params.w_mocap_p;
  655. //根据之前的决策,开始校准数据处理///
  656. /* reduce GPS weight if optical flow is good */
  657. if (use_flow && flow_accurate) {
  658. w_xy_gps_p *= params.w_gps_flow;
  659. w_xy_gps_v *= params.w_gps_flow;
  660. }
  661. /* baro offset correction */
  662. if (use_gps_z) {
  663. float offs_corr = corr_gps[2][0] * w_z_gps_p * dt;
  664. baro_offset += offs_corr;
  665. corr_baro += offs_corr;
  666. }
  667. /* accelerometer bias correction for GPS (use buffered rotation matrix) */
  668. float accel_bias_corr[3] = { 0.0f, 0.0f, 0.0f };
  669. if (use_gps_xy) {
  670. accel_bias_corr[0] -= corr_gps[0][0] * w_xy_gps_p * w_xy_gps_p;
  671. accel_bias_corr[0] -= corr_gps[0][1] * w_xy_gps_v;
  672. accel_bias_corr[1] -= corr_gps[1][0] * w_xy_gps_p * w_xy_gps_p;
  673. accel_bias_corr[1] -= corr_gps[1][1] * w_xy_gps_v;
  674. }
  675. if (use_gps_z) {
  676. accel_bias_corr[2] -= corr_gps[2][0] * w_z_gps_p * w_z_gps_p;
  677. accel_bias_corr[2] -= corr_gps[2][1] * w_z_gps_v;
  678. }
  679. /* transform error vector from NED frame to body frame */
  680. for (int i = 0; i < 3; i++) {
  681. float c = 0.0f;
  682. for (int j = 0; j < 3; j++) {
  683. c += R_gps[j][i] * accel_bias_corr[j];
  684. }
  685. if (PX4_ISFINITE(c)) {
  686. acc_bias[i] += c * params.w_acc_bias * dt;
  687. }
  688. }
  689. /* accelerometer bias correction for VISION (use buffered rotation matrix) */
  690. accel_bias_corr[0] = 0.0f;
  691. accel_bias_corr[1] = 0.0f;
  692. accel_bias_corr[2] = 0.0f;
  693. if (use_vision_xy) {
  694. accel_bias_corr[0] -= corr_vision[0][0] * w_xy_vision_p * w_xy_vision_p;
  695. accel_bias_corr[0] -= corr_vision[0][1] * w_xy_vision_v;
  696. accel_bias_corr[1] -= corr_vision[1][0] * w_xy_vision_p * w_xy_vision_p;
  697. accel_bias_corr[1] -= corr_vision[1][1] * w_xy_vision_v;
  698. }
  699. if (use_vision_z) {
  700. accel_bias_corr[2] -= corr_vision[2][0] * w_z_vision_p * w_z_vision_p;
  701. }
  702. /* accelerometer bias correction for MOCAP (use buffered rotation matrix) */
  703. accel_bias_corr[0] = 0.0f;
  704. accel_bias_corr[1] = 0.0f;
  705. accel_bias_corr[2] = 0.0f;
  706. if (use_mocap) {
  707. accel_bias_corr[0] -= corr_mocap[0][0] * w_mocap_p * w_mocap_p;
  708. accel_bias_corr[1] -= corr_mocap[1][0] * w_mocap_p * w_mocap_p;
  709. accel_bias_corr[2] -= corr_mocap[2][0] * w_mocap_p * w_mocap_p;
  710. }
  711. /* transform error vector from NED frame to body frame */
  712. for (int i = 0; i < 3; i++) {
  713. float c = 0.0f;
  714. for (int j = 0; j < 3; j++) {
  715. c += PX4_R(att.R, j, i) * accel_bias_corr[j];
  716. }
  717. if (PX4_ISFINITE(c)) {
  718. acc_bias[i] += c * params.w_acc_bias * dt;
  719. }
  720. }
  721. /* accelerometer bias correction for flow and baro (assume that there is no delay) */
  722. accel_bias_corr[0] = 0.0f;
  723. accel_bias_corr[1] = 0.0f;
  724. accel_bias_corr[2] = 0.0f;
  725. if (use_flow) {
  726. accel_bias_corr[0] -= corr_flow[0] * params.w_xy_flow;
  727. accel_bias_corr[1] -= corr_flow[1] * params.w_xy_flow;
  728. }
  729. if (use_lidar) {
  730. accel_bias_corr[2] -= corr_lidar * params.w_z_lidar * params.w_z_lidar;
  731. } else {
  732. accel_bias_corr[2] -= corr_baro * params.w_z_baro * params.w_z_baro;
  733. }
  734. /* transform error vector from NED frame to body frame */
  735. for (int i = 0; i < 3; i++) {
  736. float c = 0.0f;
  737. for (int j = 0; j < 3; j++) {
  738. c += PX4_R(att.R, j, i) * accel_bias_corr[j];
  739. }
  740. if (PX4_ISFINITE(c)) {
  741. acc_bias[i] += c * params.w_acc_bias * dt;
  742. }
  743. }
  744. //滤波处理///
  745. /* inertial filter prediction for altitude */
  746. inertial_filter_predict(dt, z_est, acc[2]);
  747. if (!(PX4_ISFINITE(z_est[0]) && PX4_ISFINITE(z_est[1]))) {
  748. write_debug_log("BAD ESTIMATE AFTER Z PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
  749. acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
  750. corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
  751. memcpy(z_est, z_est_prev, sizeof(z_est));
  752. }
  753. /* inertial filter correction for altitude */
  754. if (use_lidar) {
  755. inertial_filter_correct(corr_lidar, dt, z_est, 0, params.w_z_lidar);
  756. } else {
  757. inertial_filter_correct(corr_baro, dt, z_est, 0, params.w_z_baro);
  758. }
  759. if (use_gps_z) {
  760. epv = fminf(epv, gps.epv);
  761. inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);
  762. inertial_filter_correct(corr_gps[2][1], dt, z_est, 1, w_z_gps_v);
  763. }
  764. if (use_vision_z) {
  765. epv = fminf(epv, epv_vision);
  766. inertial_filter_correct(corr_vision[2][0], dt, z_est, 0, w_z_vision_p);
  767. }
  768. if (use_mocap) {
  769. epv = fminf(epv, epv_mocap);
  770. inertial_filter_correct(corr_mocap[2][0], dt, z_est, 0, w_mocap_p);
  771. }
  772. if (!(PX4_ISFINITE(z_est[0]) && PX4_ISFINITE(z_est[1]))) {
  773. write_debug_log("BAD ESTIMATE AFTER Z CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
  774. acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
  775. corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
  776. memcpy(z_est, z_est_prev, sizeof(z_est));
  777. memset(corr_gps, 0, sizeof(corr_gps));
  778. memset(corr_vision, 0, sizeof(corr_vision));
  779. memset(corr_mocap, 0, sizeof(corr_mocap));
  780. corr_baro = 0;
  781. } else {
  782. memcpy(z_est_prev, z_est, sizeof(z_est));
  783. }
  784. if (can_estimate_xy) {
  785. /* inertial filter prediction for position */
  786. inertial_filter_predict(dt, x_est, acc[0]);
  787. inertial_filter_predict(dt, y_est, acc[1]);
  788. if (!(PX4_ISFINITE(x_est[0]) && PX4_ISFINITE(x_est[1]) && PX4_ISFINITE(y_est[0]) && PX4_ISFINITE(y_est[1]))) {
  789. write_debug_log("BAD ESTIMATE AFTER PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
  790. acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
  791. corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
  792. memcpy(x_est, x_est_prev, sizeof(x_est));
  793. memcpy(y_est, y_est_prev, sizeof(y_est));
  794. }
  795. /* inertial filter correction for position */
  796. if (use_flow) {
  797. eph = fminf(eph, eph_flow);
  798. inertial_filter_correct(corr_flow[0], dt, x_est, 1, params.w_xy_flow * w_flow);
  799. inertial_filter_correct(corr_flow[1], dt, y_est, 1, params.w_xy_flow * w_flow);
  800. }
  801. if (use_gps_xy) {
  802. eph = fminf(eph, gps.eph);
  803. inertial_filter_correct(corr_gps[0][0], dt, x_est, 0, w_xy_gps_p);
  804. inertial_filter_correct(corr_gps[1][0], dt, y_est, 0, w_xy_gps_p);
  805. if (gps.vel_ned_valid && t < gps.timestamp_velocity + gps_topic_timeout) {
  806. inertial_filter_correct(corr_gps[0][1], dt, x_est, 1, w_xy_gps_v);
  807. inertial_filter_correct(corr_gps[1][1], dt, y_est, 1, w_xy_gps_v);
  808. }
  809. }
  810. if (use_vision_xy) {
  811. eph = fminf(eph, eph_vision);
  812. inertial_filter_correct(corr_vision[0][0], dt, x_est, 0, w_xy_vision_p);
  813. inertial_filter_correct(corr_vision[1][0], dt, y_est, 0, w_xy_vision_p);
  814. if (w_xy_vision_v > MIN_VALID_W) {
  815. inertial_filter_correct(corr_vision[0][1], dt, x_est, 1, w_xy_vision_v);
  816. inertial_filter_correct(corr_vision[1][1], dt, y_est, 1, w_xy_vision_v);
  817. }
  818. }
  819. if (use_mocap) {
  820. eph = fminf(eph, eph_mocap);
  821. inertial_filter_correct(corr_mocap[0][0], dt, x_est, 0, w_mocap_p);
  822. inertial_filter_correct(corr_mocap[1][0], dt, y_est, 0, w_mocap_p);
  823. }
  824. if (!(PX4_ISFINITE(x_est[0]) && PX4_ISFINITE(x_est[1]) && PX4_ISFINITE(y_est[0]) && PX4_ISFINITE(y_est[1]))) {
  825. write_debug_log("BAD ESTIMATE AFTER CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev,
  826. acc, corr_gps, w_xy_gps_p, w_xy_gps_v, corr_mocap, w_mocap_p,
  827. corr_vision, w_xy_vision_p, w_z_vision_p, w_xy_vision_v);
  828. memcpy(x_est, x_est_prev, sizeof(x_est));
  829. memcpy(y_est, y_est_prev, sizeof(y_est));
  830. memset(corr_gps, 0, sizeof(corr_gps));
  831. memset(corr_vision, 0, sizeof(corr_vision));
  832. memset(corr_mocap, 0, sizeof(corr_mocap));
  833. memset(corr_flow, 0, sizeof(corr_flow));
  834. } else {
  835. memcpy(x_est_prev, x_est, sizeof(x_est));
  836. memcpy(y_est_prev, y_est, sizeof(y_est));
  837. }
  838. } else {
  839. /* gradually reset xy velocity estimates */
  840. inertial_filter_correct(-x_est[1], dt, x_est, 1, params.w_xy_res_v);
  841. inertial_filter_correct(-y_est[1], dt, y_est, 1, params.w_xy_res_v);
  842. }
  843. ///运行地形估计//
  844. /* run terrain estimator */
  845. terrain_estimator->predict(dt, &att, &sensor, &lidar);
  846. terrain_estimator->measurement_update(hrt_absolute_time(), &gps, &lidar, &att);
  847. if (inav_verbose_mode) {
  848. /* print updates rate */
  849. if (t > updates_counter_start + updates_counter_len) {
  850. float updates_dt = (t - updates_counter_start) * 0.000001f;
  851. warnx(
  852. "updates rate: accelerometer = %.1f/s, baro = %.1f/s, gps = %.1f/s, attitude = %.1f/s, flow = %.1f/s, vision = %.1f/s, mocap = %.1f/s",
  853. (double)(accel_updates / updates_dt),
  854. (double)(baro_updates / updates_dt),
  855. (double)(gps_updates / updates_dt),
  856. (double)(attitude_updates / updates_dt),
  857. (double)(flow_updates / updates_dt),
  858. (double)(vision_updates / updates_dt),
  859. (double)(mocap_updates / updates_dt));
  860. updates_counter_start = t;
  861. accel_updates = 0;
  862. baro_updates = 0;
  863. gps_updates = 0;
  864. attitude_updates = 0;
  865. flow_updates = 0;
  866. vision_updates = 0;
  867. mocap_updates = 0;
  868. }
  869. }
  870. if (t > pub_last + PUB_INTERVAL) {
  871. pub_last = t;
  872. /* push current estimate to buffer */
  873. est_buf[buf_ptr][0][0] = x_est[0];
  874. est_buf[buf_ptr][0][1] = x_est[1];
  875. est_buf[buf_ptr][1][0] = y_est[0];
  876. est_buf[buf_ptr][1][1] = y_est[1];
  877. est_buf[buf_ptr][2][0] = z_est[0];
  878. est_buf[buf_ptr][2][1] = z_est[1];
  879. /* push current rotation matrix to buffer */
  880. memcpy(R_buf[buf_ptr], att.R, sizeof(att.R));
  881. buf_ptr++;
  882. if (buf_ptr >= EST_BUF_SIZE) {
  883. buf_ptr = 0;
  884. }
  885. ///发布位置信息///
  886. /* publish local position */
  887. local_pos.xy_valid = can_estimate_xy;
  888. local_pos.v_xy_valid = can_estimate_xy;
  889. local_pos.xy_global = local_pos.xy_valid && use_gps_xy;
  890. local_pos.z_global = local_pos.z_valid && use_gps_z;
  891. local_pos.x = x_est[0];
  892. local_pos.vx = x_est[1];
  893. local_pos.y = y_est[0];
  894. local_pos.vy = y_est[1];
  895. local_pos.z = z_est[0];
  896. local_pos.vz = z_est[1];
  897. local_pos.yaw = att.yaw;
  898. local_pos.dist_bottom_valid = dist_bottom_valid;
  899. local_pos.eph = eph;
  900. local_pos.epv = epv;
  901. if (local_pos.dist_bottom_valid) {
  902. local_pos.dist_bottom = dist_ground;
  903. local_pos.dist_bottom_rate = - z_est[1];
  904. }
  905. local_pos.timestamp = t;
  906. orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
  907. if (local_pos.xy_global && local_pos.z_global) {
  908. /* publish global position */
  909. global_pos.timestamp = t;
  910. global_pos.time_utc_usec = gps.time_utc_usec;
  911. double est_lat, est_lon;
  912. map_projection_reproject(&ref, local_pos.x, local_pos.y, &est_lat, &est_lon);
  913. global_pos.lat = est_lat;
  914. global_pos.lon = est_lon;
  915. global_pos.alt = local_pos.ref_alt - local_pos.z;
  916. global_pos.vel_n = local_pos.vx;
  917. global_pos.vel_e = local_pos.vy;
  918. global_pos.vel_d = local_pos.vz;
  919. global_pos.yaw = local_pos.yaw;
  920. global_pos.eph = eph;
  921. global_pos.epv = epv;
  922. if (terrain_estimator->is_valid()) {
  923. global_pos.terrain_alt = global_pos.alt - terrain_estimator->get_distance_to_ground();
  924. global_pos.terrain_alt_valid = true;
  925. } else {
  926. global_pos.terrain_alt_valid = false;
  927. }
  928. global_pos.pressure_alt = sensor.baro_alt_meter[0];
  929. if (vehicle_global_position_pub == NULL) {
  930. vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
  931. } else {
  932. orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
  933. }
  934. }
  935. }
  936. }
  937. /***************************************大循环结束********************************/
  938. warnx("stopped");
  939. mavlink_log_info(&mavlink_log_pub, "[inav] stopped");
  940. thread_running = false;
  941. return 0;
  942. }

这里发布的信息有2个vehicle_local_position和vehicle_global_position

  1. #ifdef __cplusplus
  2. struct __EXPORT vehicle_local_position_s {
  3. #else
  4. struct vehicle_local_position_s {
  5. #endif
  6. uint64_t timestamp;
  7. bool xy_valid;
  8. bool z_valid;
  9. bool v_xy_valid;
  10. bool v_z_valid;
  11. float x;
  12. float y;
  13. float z;
  14. float vx;
  15. float vy;
  16. float vz;
  17. float yaw;
  18. bool xy_global;
  19. bool z_global;
  20. uint64_t ref_timestamp;
  21. double ref_lat;
  22. double ref_lon;
  23. float ref_alt;
  24. float dist_bottom;
  25. float dist_bottom_rate;
  26. uint64_t surface_bottom_timestamp;
  27. bool dist_bottom_valid;
  28. float eph;
  29. float epv;
  30. #ifdef __cplusplus
  31. #endif
  32. };
  1. #ifdef __cplusplus
  2. struct __EXPORT vehicle_global_position_s {
  3. #else
  4. struct vehicle_global_position_s {
  5. #endif
  6. uint64_t timestamp;
  7. uint64_t time_utc_usec;
  8. double lat;
  9. double lon;
  10. float alt;
  11. float vel_n;
  12. float vel_e;
  13. float vel_d;
  14. float yaw;
  15. float eph;
  16. float epv;
  17. float terrain_alt;
  18. bool terrain_alt_valid;
  19. bool dead_reckoning;
  20. float pressure_alt;
  21. #ifdef __cplusplus
  22. #endif
  23. };

其他会用到的数据全部在ardupilot/modules/PX4Firmware/src/modules/uORB/topics文件夹中

  1. #ifdef __cplusplus
  2. struct __EXPORT sensor_combined_s {
  3. #else
  4. struct sensor_combined_s {
  5. #endif
  6. uint64_t timestamp;
  7. uint64_t gyro_timestamp[3];
  8. int16_t gyro_raw[9];
  9. float gyro_rad_s[9];
  10. uint32_t gyro_priority[3];
  11. float gyro_integral_rad[9];
  12. uint64_t gyro_integral_dt[3];
  13. uint32_t gyro_errcount[3];
  14. float gyro_temp[3];
  15. int16_t accelerometer_raw[9];
  16. float accelerometer_m_s2[9];
  17. float accelerometer_integral_m_s[9];
  18. uint64_t accelerometer_integral_dt[3];
  19. int16_t accelerometer_mode[3];
  20. float accelerometer_range_m_s2[3];
  21. uint64_t accelerometer_timestamp[3];
  22. uint32_t accelerometer_priority[3];
  23. uint32_t accelerometer_errcount[3];
  24. float accelerometer_temp[3];
  25. int16_t magnetometer_raw[9];
  26. float magnetometer_ga[9];
  27. int16_t magnetometer_mode[3];
  28. float magnetometer_range_ga[3];
  29. float magnetometer_cuttoff_freq_hz[3];
  30. uint64_t magnetometer_timestamp[3];
  31. uint32_t magnetometer_priority[3];
  32. uint32_t magnetometer_errcount[3];
  33. float magnetometer_temp[3];
  34. float baro_pres_mbar[3];
  35. float baro_alt_meter[3];
  36. float baro_temp_celcius[3];
  37. uint64_t baro_timestamp[3];
  38. uint32_t baro_priority[3];
  39. uint32_t baro_errcount[3];
  40. float adc_voltage_v[10];
  41. uint16_t adc_mapping[10];
  42. float mcu_temp_celcius;
  43. float differential_pressure_pa[3];
  44. uint64_t differential_pressure_timestamp[3];
  45. float differential_pressure_filtered_pa[3];
  46. uint32_t differential_pressure_priority[3];
  47. uint32_t differential_pressure_errcount[3];
  48. #ifdef __cplusplus
  49. static const int32_t MAGNETOMETER_MODE_NORMAL = 0;
  50. static const int32_t MAGNETOMETER_MODE_POSITIVE_BIAS = 1;
  51. static const int32_t MAGNETOMETER_MODE_NEGATIVE_BIAS = 2;
  52. static const uint32_t SENSOR_PRIO_MIN = 0;
  53. static const uint32_t SENSOR_PRIO_VERY_LOW = 25;
  54. static const uint32_t SENSOR_PRIO_LOW = 50;
  55. static const uint32_t SENSOR_PRIO_DEFAULT = 75;
  56. static const uint32_t SENSOR_PRIO_HIGH = 100;
  57. static const uint32_t SENSOR_PRIO_VERY_HIGH = 125;
  58. static const uint32_t SENSOR_PRIO_MAX = 255;
  59. #endif
  60. };
  61. #ifdef __cplusplus
  62. struct __EXPORT parameter_update_s {
  63. #else
  64. struct parameter_update_s {
  65. #endif
  66. uint64_t timestamp;
  67. bool saved;
  68. #ifdef __cplusplus
  69. #endif
  70. };
  71. #ifdef __cplusplus
  72. struct __EXPORT actuator_controls_s {
  73. #else
  74. struct actuator_controls_s {
  75. #endif
  76. uint64_t timestamp;
  77. uint64_t timestamp_sample;
  78. float control[8];
  79. #ifdef __cplusplus
  80. static const uint8_t NUM_ACTUATOR_CONTROLS = 8;
  81. static const uint8_t NUM_ACTUATOR_CONTROL_GROUPS = 4;
  82. static const uint8_t INDEX_ROLL = 0;
  83. static const uint8_t INDEX_PITCH = 1;
  84. static const uint8_t INDEX_YAW = 2;
  85. static const uint8_t INDEX_THROTTLE = 3;
  86. static const uint8_t INDEX_FLAPS = 4;
  87. static const uint8_t INDEX_SPOILERS = 5;
  88. static const uint8_t INDEX_AIRBRAKES = 6;
  89. static const uint8_t INDEX_LANDING_GEAR = 7;
  90. static const uint8_t GROUP_INDEX_ATTITUDE = 0;
  91. static const uint8_t GROUP_INDEX_ATTITUDE_ALTERNATE = 1;
  92. #endif
  93. };
  94. #ifdef __cplusplus
  95. struct __EXPORT actuator_armed_s {
  96. #else
  97. struct actuator_armed_s {
  98. #endif
  99. uint64_t timestamp;
  100. bool armed;
  101. bool prearmed;
  102. bool ready_to_arm;
  103. bool lockdown;
  104. bool force_failsafe;
  105. bool in_esc_calibration_mode;
  106. #ifdef __cplusplus
  107. #endif
  108. #ifdef __cplusplus
  109. struct __EXPORT vision_position_estimate_s {
  110. #else
  111. struct vision_position_estimate_s {
  112. #endif
  113. uint32_t id;
  114. uint64_t timestamp_boot;
  115. uint64_t timestamp_computer;
  116. float x;
  117. float y;
  118. float z;
  119. float vx;
  120. float vy;
  121. float vz;
  122. float q[4];
  123. #ifdef __cplusplus
  124. #endif
  125. };
  126. #ifdef __cplusplus
  127. struct __EXPORT att_pos_mocap_s {
  128. #else
  129. struct att_pos_mocap_s {
  130. #endif
  131. uint32_t id;
  132. uint64_t timestamp_boot;
  133. uint64_t timestamp_computer;
  134. float q[4];
  135. float x;
  136. float y;
  137. float z;
  138. #ifdef __cplusplus
  139. #endif
  140. };
  141. #ifdef __cplusplus
  142. struct __EXPORT vehicle_gps_position_s {
  143. #else
  144. struct vehicle_gps_position_s {
  145. #endif
  146. uint64_t timestamp_position;
  147. int32_t lat;
  148. int32_t lon;
  149. int32_t alt;
  150. int32_t alt_ellipsoid;
  151. uint64_t timestamp_variance;
  152. float s_variance_m_s;
  153. float c_variance_rad;
  154. uint8_t fix_type;
  155. float eph;
  156. float epv;
  157. float hdop;
  158. float vdop;
  159. int32_t noise_per_ms;
  160. int32_t jamming_indicator;
  161. uint64_t timestamp_velocity;
  162. float vel_m_s;
  163. float vel_n_m_s;
  164. float vel_e_m_s;
  165. float vel_d_m_s;
  166. float cog_rad;
  167. bool vel_ned_valid;
  168. uint64_t timestamp_time;
  169. uint64_t time_utc_usec;
  170. uint8_t satellites_used;
  171. #ifdef __cplusplus
  172. #endif
  173. };

把光流部分单独拿出来

  1. /**************************************这里就是光流的处理*********************************/
  2. /* optical flow */
  3. orb_check(optical_flow_sub, &updated);
  4. if (updated && lidar_valid) {
  5. orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);//光流数据跟新
  6. flow_time = t;
  7. float flow_q = flow.quality / 255.0f;
  8. float dist_bottom = lidar.current_distance;//高度信息
  9. if (dist_bottom > flow_min_dist && flow_q > params.flow_q_min && PX4_R(att.R, 2, 2) > 0.7f) {
  10. /* distance to surface */
  11. //float flow_dist = dist_bottom / PX4_R(att.R, 2, 2); //use this if using sonar
  12. float flow_dist = dist_bottom; //use this if using lidar
  13. /* check if flow if too large for accurate measurements */检查速度是否太大,影响光流精确测量
  14. /*****************************计算机架估计的速度*****************************/
  15. /* calculate estimated velocity in body frame */
  16. float body_v_est[2] = { 0.0f, 0.0f };
  17. for (int i = 0; i < 2; i++) {
  18. 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];
  19. }
  20. /*************设置这个标志,如果光流按照当前速度和姿态率的估计是准确的*************/
  21. /* set this flag if flow should be accurate according to current velocity and attitude rate estimate */
  22. flow_accurate = fabsf(body_v_est[1] / flow_dist - att.rollspeed) < max_flow &&
  23. fabsf(body_v_est[0] / flow_dist + att.pitchspeed) < max_flow;
  24. /*************利用自动驾驶仪(飞控)已经校准的陀螺仪计算光流用的陀螺仪的偏移*************/
  25. /*calculate offset of flow-gyro using already calibrated gyro from autopilot*/
  26. flow_gyrospeed[0] = flow.gyro_x_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  27. flow_gyrospeed[1] = flow.gyro_y_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  28. flow_gyrospeed[2] = flow.gyro_z_rate_integral / (float)flow.integration_timespan * 1000000.0f;
  29. //moving average
  30. if (n_flow >= 100) {
  31. gyro_offset_filtered[0] = flow_gyrospeed_filtered[0] - att_gyrospeed_filtered[0];
  32. gyro_offset_filtered[1] = flow_gyrospeed_filtered[1] - att_gyrospeed_filtered[1];
  33. gyro_offset_filtered[2] = flow_gyrospeed_filtered[2] - att_gyrospeed_filtered[2];
  34. n_flow = 0;
  35. flow_gyrospeed_filtered[0] = 0.0f;
  36. flow_gyrospeed_filtered[1] = 0.0f;
  37. flow_gyrospeed_filtered[2] = 0.0f;
  38. att_gyrospeed_filtered[0] = 0.0f;
  39. att_gyrospeed_filtered[1] = 0.0f;
  40. att_gyrospeed_filtered[2] = 0.0f;
  41. } else {
  42. flow_gyrospeed_filtered[0] = (flow_gyrospeed[0] + n_flow * flow_gyrospeed_filtered[0]) / (n_flow + 1);
  43. flow_gyrospeed_filtered[1] = (flow_gyrospeed[1] + n_flow * flow_gyrospeed_filtered[1]) / (n_flow + 1);
  44. flow_gyrospeed_filtered[2] = (flow_gyrospeed[2] + n_flow * flow_gyrospeed_filtered[2]) / (n_flow + 1);
  45. att_gyrospeed_filtered[0] = (att.pitchspeed + n_flow * att_gyrospeed_filtered[0]) / (n_flow + 1);
  46. att_gyrospeed_filtered[1] = (att.rollspeed + n_flow * att_gyrospeed_filtered[1]) / (n_flow + 1);
  47. att_gyrospeed_filtered[2] = (att.yawspeed + n_flow * att_gyrospeed_filtered[2]) / (n_flow + 1);
  48. n_flow++;
  49. }
  50. /*******************************偏航补偿(光流传感器不处于旋转中心)->参数在QGC中***********************/
  51. /*yaw compensation (flow sensor is not in center of rotation) -> params in QGC*/
  52. yaw_comp[0] = - params.flow_module_offset_y * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
  53. yaw_comp[1] = params.flow_module_offset_x * (flow_gyrospeed[2] - gyro_offset_filtered[2]);
  54. /***************************将原始流转换成角度流**********************************/
  55. /* convert raw flow to angular flow (rad/s) */
  56. float flow_ang[2];
  57. /***************************检查机体速度设定值->它低于阈值->不减去->更好悬停*********************/
  58. /* check for vehicle rates setpoint - it below threshold -> dont subtract -> better hover */
  59. orb_check(vehicle_rate_sp_sub, &updated);
  60. if (updated)
  61. orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
  62. double rate_threshold = 0.15f;
  63. if (fabs(rates_setpoint.pitch) < rate_threshold) {
  64. //warnx("[inav] test ohne comp");
  65. 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)
  66. }
  67. else {
  68. //warnx("[inav] test mit comp");
  69. //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
  70. //计算光流的速度[rad/s]并补偿旋转(和光流的陀螺仪的偏置)
  71. flow_ang[0] = ((flow.pixel_flow_x_integral - flow.gyro_x_rate_integral) / (float)flow.integration_timespan * 1000000.0f
  72. + gyro_offset_filtered[0]) * params.flow_k;//for now the flow has to be scaled (to small)
  73. }
  74. if (fabs(rates_setpoint.roll) < rate_threshold) {
  75. 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)
  76. }
  77. else {
  78. //calculate flow [rad/s] and compensate for rotations (and offset of flow-gyro)
  79. //计算光流的速度[rad/s]并补偿旋转(和光流的陀螺仪的偏置)
  80. flow_ang[1] = ((flow.pixel_flow_y_integral - flow.gyro_y_rate_integral) / (float)flow.integration_timespan * 1000000.0f
  81. + gyro_offset_filtered[1]) * params.flow_k;//for now the flow has to be scaled (to small)
  82. }
  83. /************************光流测量向量********************************/
  84. /* flow measurements vector */
  85. float flow_m[3];
  86. if (fabs(rates_setpoint.yaw) < rate_threshold) {
  87. flow_m[0] = -flow_ang[0] * flow_dist;
  88. flow_m[1] = -flow_ang[1] * flow_dist;
  89. } else {
  90. flow_m[0] = -flow_ang[0] * flow_dist - yaw_comp[0] * params.flow_k;
  91. flow_m[1] = -flow_ang[1] * flow_dist - yaw_comp[1] * params.flow_k;
  92. }
  93. flow_m[2] = z_est[1];
  94. /* velocity in NED */NED是北东地,还有一种旋转方式是东北天,都是属于右手系
  95. float flow_v[2] = { 0.0f, 0.0f };
  96. /************************基于NED工程测量向量,跳过Z分量*********************/
  97. /* project measurements vector to NED basis, skip Z component */
  98. for (int i = 0; i < 2; i++) {
  99. for (int j = 0; j < 3; j++) {
  100. flow_v[i] += PX4_R(att.R, i, j) * flow_m[j];
  101. }
  102. }
  103. /********************向量矫正***********************/
  104. /* velocity correction */
  105. corr_flow[0] = flow_v[0] - x_est[1];
  106. corr_flow[1] = flow_v[1] - y_est[1];
  107. /********************调整矫正权重***********************/
  108. /* adjust correction weight */
  109. float flow_q_weight = (flow_q - params.flow_q_min) / (1.0f - params.flow_q_min);
  110. w_flow = PX4_R(att.R, 2, 2) * flow_q_weight / fmaxf(1.0f, flow_dist);
  111. /********************如果光流是不准确的,那么减少他的权重***********************/
  112. /* if flow is not accurate, reduce weight for it */
  113. // TODO make this more fuzzy
  114. if (!flow_accurate) {
  115. w_flow *= 0.05f;
  116. }
  117. /**********************在理想条件下,在1m的距离EPH =10厘米****************/
  118. /* under ideal conditions, on 1m distance assume EPH = 10cm */
  119. eph_flow = 0.1f / w_flow;
  120. flow_valid = true;
  121. } else {
  122. w_flow = 0.0f;
  123. flow_valid = false;
  124. }
  125. flow_updates++;
  126. }
  127. /**************************************光流结束*********************************/
接下来就到了 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[]);
  1. int mc_pos_control_main(int argc, char *argv[])
  2. {
  3. if (argc < 2) {
  4. warnx("usage: mc_pos_control {start|stop|status}");
  5. return 1;
  6. }
  7. if (!strcmp(argv[1], "start")) {
  8. if (pos_control::g_control != nullptr) {
  9. warnx("already running");
  10. return 1;
  11. }
  12. pos_control::g_control = new MulticopterPositionControl;
  13. if (pos_control::g_control == nullptr) {
  14. warnx("alloc failed");
  15. return 1;
  16. }
  17. if (OK != pos_control::g_control->start()) {
  18. delete pos_control::g_control;
  19. pos_control::g_control = nullptr;
  20. warnx("start failed");
  21. return 1;
  22. }
  23. return 0;
  24. }
  25. if (!strcmp(argv[1], "stop")) {
  26. if (pos_control::g_control == nullptr) {
  27. warnx("not running");
  28. return 1;
  29. }
  30. delete pos_control::g_control;
  31. pos_control::g_control = nullptr;
  32. return 0;
  33. }
  34. if (!strcmp(argv[1], "status")) {
  35. if (pos_control::g_control) {
  36. warnx("running");
  37. return 0;
  38. } else {
  39. warnx("not running");
  40. return 1;
  41. }
  42. }
  43. warnx("unrecognized command");
  44. return 1;
  45. }
这个里面就start和status需要看

  1. int
  2. MulticopterPositionControl::start()
  3. {
  4. ASSERT(_control_task == -1);
  5. /* start the task */
  6. _control_task = px4_task_spawn_cmd("mc_pos_control",
  7. SCHED_DEFAULT,
  8. SCHED_PRIORITY_MAX - 5,
  9. 1900,
  10. (px4_main_t)&MulticopterPositionControl::task_main_trampoline,
  11. nullptr);
  12. if (_control_task < 0) {
  13. warn("task start failed");
  14. return -errno;
  15. }
  16. return OK;
  17. }
  1. void
  2. MulticopterPositionControl::task_main_trampoline(int argc, char *argv[])
  3. {
  4. pos_control::g_control->task_main();
  5. }
  1. void
  2. MulticopterPositionControl::task_main()
  3. {
  4. /***************************订阅各种信息***********************/
  5. /*
  6. * do subscriptions
  7. */
  8. _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  9. _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
  10. _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  11. _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
  12. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  13. _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
  14. _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
  15. _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
  16. //这个就是从position_estimator_inav_main.cpp中来的,里面包含光流数据
  17. _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
  18. _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
  19. _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
  20. parameters_update(true);//参数跟新
  21. /*****************初始化关键结构的值,直到第一次定期更新*****************/
  22. /* initialize values of critical structs until first regular update */
  23. _arming.armed = false;
  24. /*****************初始跟新,获取所有传感器的数据和状态数据*****************/
  25. /* get an initial update for all sensor and status data */
  26. poll_subscriptions();//具体在下面展开了
  27. bool reset_int_z = true;
  28. bool reset_int_z_manual = false;
  29. bool reset_int_xy = true;
  30. bool reset_yaw_sp = true;
  31. bool was_armed = false;
  32. hrt_abstime t_prev = 0;
  33. math::Vector<3> thrust_int;
  34. thrust_int.zero();
  35. math::Matrix<3, 3> R;
  36. R.identity();
  37. /* wakeup source */
  38. px4_pollfd_struct_t fds[1];
  39. fds[0].fd = _local_pos_sub;
  40. fds[0].events = POLLIN;
  41. /***********************大循环***************************/
  42. while (!_task_should_exit) {
  43. /* wait for up to 500ms for data */等待500ms来获取数据
  44. int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 500);
  45. /* timed out - periodic check for _task_should_exit */
  46. if (pret == 0) {
  47. continue;
  48. }
  49. /* this is undesirable but not much we can do */
  50. if (pret < 0) {
  51. warn("poll error %d, %d", pret, errno);
  52. continue;
  53. }
  54. //获取所有传感器的数据和状态数据//
  55. poll_subscriptions();
  56. ///参数跟新
  57. parameters_update(false);
  58. hrt_abstime t = hrt_absolute_time();
  59. float dt = t_prev != 0 ? (t - t_prev) * 0.000001f : 0.0f;//dt是控制周期吗?
  60. t_prev = t;
  61. // set dt for control blocks
  62. setDt(dt);
  63. /判断是否锁定
  64. if (_control_mode.flag_armed && !was_armed) {
  65. /* reset setpoints and integrals on arming */
  66. _reset_pos_sp = true;
  67. _reset_alt_sp = true;
  68. _vel_sp_prev.zero();
  69. reset_int_z = true;
  70. reset_int_xy = true;
  71. reset_yaw_sp = true;
  72. }
  73. //复位yaw和姿态的设定 为垂直起降 fw模式/
  74. /* reset yaw and altitude setpoint for VTOL which are in fw mode */
  75. if (_vehicle_status.is_vtol) {
  76. if (!_vehicle_status.is_rotary_wing) {
  77. reset_yaw_sp = true;
  78. _reset_alt_sp = true;
  79. }
  80. }
  81. 跟新前一时刻锁定的状态///
  82. //Update previous arming state
  83. was_armed = _control_mode.flag_armed;
  84. update_ref();//跟新参考点,是不是期望目标?该函数在下面会展开
  85. 跟新速度导数(加速度) 独立于当前飞行模式///
  86. /* Update velocity derivative,
  87. * independent of the current flight mode
  88. */
  89. if (_local_pos.timestamp > 0) {
  90. if (PX4_ISFINITE(_local_pos.x) && //ISFINITE是测试数据是否是个有限数的函数
  91. PX4_ISFINITE(_local_pos.y) &&
  92. PX4_ISFINITE(_local_pos.z)) {
  93. _pos(0) = _local_pos.x;
  94. _pos(1) = _local_pos.y;
  95. _pos(2) = _local_pos.z;
  96. }
  97. if (PX4_ISFINITE(_local_pos.vx) &&
  98. PX4_ISFINITE(_local_pos.vy) &&
  99. PX4_ISFINITE(_local_pos.vz)) {
  100. _vel(0) = _local_pos.vx;
  101. _vel(1) = _local_pos.vy;
  102. _vel(2) = _local_pos.vz;
  103. }
  104. _vel_err_d(0) = _vel_x_deriv.update(-_vel(0));
  105. _vel_err_d(1) = _vel_y_deriv.update(-_vel(1));
  106. _vel_err_d(2) = _vel_z_deriv.update(-_vel(2));
  107. }
  108. ///复位在非手动模式下的水平垂直位置保持标志位,让位置和姿态不被控制//
  109. // reset the horizontal and vertical position hold flags for non-manual modes
  110. // or if position / altitude is not controlled
  111. if (!_control_mode.flag_control_position_enabled || !_control_mode.flag_control_manual_enabled) {
  112. _pos_hold_engaged = false;
  113. }
  114. if (!_control_mode.flag_control_altitude_enabled || !_control_mode.flag_control_manual_enabled) {
  115. _alt_hold_engaged = false;
  116. }
  117. //根据控制模式选择对应的控制函数//
  118. if (_control_mode.flag_control_altitude_enabled ||
  119. _control_mode.flag_control_position_enabled ||
  120. _control_mode.flag_control_climb_rate_enabled ||
  121. _control_mode.flag_control_velocity_enabled) {
  122. _vel_ff.zero();
  123. /默认运行位置和姿态控制,在control_*函数中可以失能这种模式而直接在循环中运行速度控制模式/
  124. /* by default, run position/altitude controller. the control_* functions
  125. * can disable this and run velocity controllers directly in this cycle */
  126. _run_pos_control = true;
  127. _run_alt_control = true;
  128. /选择控制源/
  129. /* select control source */
  130. if (_control_mode.flag_control_manual_enabled) {
  131. /* manual control */
  132. control_manual(dt);//手动控制,在下面会展开
  133. _mode_auto = false;
  134. } else if (_control_mode.flag_control_offboard_enabled) {
  135. /* offboard control */
  136. control_offboard(dt);//和control_manual(dt);貌似都是根据具体情况设定期望值
  137. _mode_auto = false;
  138. } else {
  139. /* AUTO */
  140. control_auto(dt);//自动控制
  141. }
  142. /********感觉这3个函数功能是实现根据实际复杂情况调整期望值,之后用控制函数一个一个的达到期望值*************/
  143. /* weather-vane mode for vtol: disable yaw control */风向标模式垂直起降:禁用偏航控制
  144. if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.disable_mc_yaw_control == true) {
  145. _att_sp.disable_mc_yaw_control = true;
  146. } else {
  147. /* reset in case of setpoint updates */
  148. _att_sp.disable_mc_yaw_control = false;
  149. }
  150. /判断///
  151. if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
  152. && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_IDLE) {
  153. /* idle state, don't run controller and set zero thrust */
  154. //空闲状态,不运行控制,并设置为零推力//
  155. R.identity();
  156. memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
  157. _att_sp.R_valid = true;
  158. _att_sp.roll_body = 0.0f;
  159. _att_sp.pitch_body = 0.0f;
  160. _att_sp.yaw_body = _yaw;
  161. _att_sp.thrust = 0.0f;
  162. _att_sp.timestamp = hrt_absolute_time();
  163. /发布姿态设定值///
  164. /* publish attitude setpoint */
  165. if (_att_sp_pub != nullptr) {
  166. orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
  167. } else if (_attitude_setpoint_id) {
  168. _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
  169. }
  170. /另一个判断///
  171. } else if (_control_mode.flag_control_manual_enabled
  172. && _vehicle_status.condition_landed) {
  173. /* don't run controller when landed */着陆不要运行控制器
  174. _reset_pos_sp = true;
  175. _reset_alt_sp = true;
  176. _mode_auto = false;
  177. reset_int_z = true;
  178. reset_int_xy = true;
  179. R.identity();
  180. memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
  181. _att_sp.R_valid = true;
  182. _att_sp.roll_body = 0.0f;
  183. _att_sp.pitch_body = 0.0f;
  184. _att_sp.yaw_body = _yaw;
  185. _att_sp.thrust = 0.0f;
  186. _att_sp.timestamp = hrt_absolute_time();
  187. /* publish attitude setpoint */
  188. if (_att_sp_pub != nullptr) {
  189. orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
  190. } else if (_attitude_setpoint_id) {
  191. _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
  192. }
  193. /另一个判断///
  194. } else {
  195. /* run position & altitude controllers, if enabled (otherwise use already computed velocity setpoints) */
  196. if (_run_pos_control) {
  197. _vel_sp(0) = (_pos_sp(0) - _pos(0)) * _params.pos_p(0);
  198. _vel_sp(1) = (_pos_sp(1) - _pos(1)) * _params.pos_p(1);
  199. }
  200. // do not go slower than the follow target velocity when position tracking is active (set to valid)
  201. if(_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_FOLLOW_TARGET &&
  202. _pos_sp_triplet.current.velocity_valid &&
  203. _pos_sp_triplet.current.position_valid) {
  204. math::Vector<3> ft_vel(_pos_sp_triplet.current.vx, _pos_sp_triplet.current.vy, 0);
  205. float cos_ratio = (ft_vel*_vel_sp)/(ft_vel.length()*_vel_sp.length());
  206. // only override velocity set points when uav is traveling in same direction as target and vector component
  207. // is greater than calculated position set point velocity component
  208. if(cos_ratio > 0) {
  209. ft_vel *= (cos_ratio);
  210. // min speed a little faster than target vel
  211. ft_vel += ft_vel.normalized()*1.5f;
  212. } else {
  213. ft_vel.zero();
  214. }
  215. _vel_sp(0) = fabs(ft_vel(0)) > fabs(_vel_sp(0)) ? ft_vel(0) : _vel_sp(0);
  216. _vel_sp(1) = fabs(ft_vel(1)) > fabs(_vel_sp(1)) ? ft_vel(1) : _vel_sp(1);
  217. // track target using velocity only
  218. } else if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_FOLLOW_TARGET &&
  219. _pos_sp_triplet.current.velocity_valid) {
  220. _vel_sp(0) = _pos_sp_triplet.current.vx;
  221. _vel_sp(1) = _pos_sp_triplet.current.vy;
  222. }
  223. if (_run_alt_control) {
  224. _vel_sp(2) = (_pos_sp(2) - _pos(2)) * _params.pos_p(2);
  225. }
  226. /* make sure velocity setpoint is saturated in xy*/
  227. float vel_norm_xy = sqrtf(_vel_sp(0) * _vel_sp(0) +
  228. _vel_sp(1) * _vel_sp(1));
  229. if (vel_norm_xy > _params.vel_max(0)) {
  230. /* note assumes vel_max(0) == vel_max(1) */
  231. _vel_sp(0) = _vel_sp(0) * _params.vel_max(0) / vel_norm_xy;
  232. _vel_sp(1) = _vel_sp(1) * _params.vel_max(1) / vel_norm_xy;
  233. }
  234. /* make sure velocity setpoint is saturated in z*/
  235. float vel_norm_z = sqrtf(_vel_sp(2) * _vel_sp(2));
  236. if (vel_norm_z > _params.vel_max(2)) {
  237. _vel_sp(2) = _vel_sp(2) * _params.vel_max(2) / vel_norm_z;
  238. }
  239. if (!_control_mode.flag_control_position_enabled) {
  240. _reset_pos_sp = true;
  241. }
  242. if (!_control_mode.flag_control_altitude_enabled) {
  243. _reset_alt_sp = true;
  244. }
  245. if (!_control_mode.flag_control_velocity_enabled) {
  246. _vel_sp_prev(0) = _vel(0);
  247. _vel_sp_prev(1) = _vel(1);
  248. _vel_sp(0) = 0.0f;
  249. _vel_sp(1) = 0.0f;
  250. control_vel_enabled_prev = false;
  251. }
  252. if (!_control_mode.flag_control_climb_rate_enabled) {
  253. _vel_sp(2) = 0.0f;
  254. }
  255. /* use constant descend rate when landing, ignore altitude setpoint */
  256. if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
  257. && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) {
  258. _vel_sp(2) = _params.land_speed;
  259. }
  260. /* special thrust setpoint generation for takeoff from ground */
  261. if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid
  262. && _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF
  263. && _control_mode.flag_armed) {
  264. // check if we are not already in air.
  265. // if yes then we don't need a jumped takeoff anymore
  266. if (!_takeoff_jumped && !_vehicle_status.condition_landed && fabsf(_takeoff_thrust_sp) < FLT_EPSILON) {
  267. _takeoff_jumped = true;
  268. }
  269. if (!_takeoff_jumped) {
  270. // ramp thrust setpoint up
  271. if (_vel(2) > -(_params.tko_speed / 2.0f)) {
  272. _takeoff_thrust_sp += 0.5f * dt;
  273. _vel_sp.zero();
  274. _vel_prev.zero();
  275. } else {
  276. // copter has reached our takeoff speed. split the thrust setpoint up
  277. // into an integral part and into a P part
  278. thrust_int(2) = _takeoff_thrust_sp - _params.vel_p(2) * fabsf(_vel(2));
  279. thrust_int(2) = -math::constrain(thrust_int(2), _params.thr_min, _params.thr_max);
  280. _vel_sp_prev(2) = -_params.tko_speed;
  281. _takeoff_jumped = true;
  282. reset_int_z = false;
  283. }
  284. }
  285. if (_takeoff_jumped) {
  286. _vel_sp(2) = -_params.tko_speed;
  287. }
  288. } else {
  289. _takeoff_jumped = false;
  290. _takeoff_thrust_sp = 0.0f;
  291. }
  292. // limit total horizontal acceleration
  293. math::Vector<2> acc_hor;
  294. acc_hor(0) = (_vel_sp(0) - _vel_sp_prev(0)) / dt;
  295. acc_hor(1) = (_vel_sp(1) - _vel_sp_prev(1)) / dt;
  296. if (acc_hor.length() > _params.acc_hor_max) {
  297. acc_hor.normalize();
  298. acc_hor *= _params.acc_hor_max;
  299. math::Vector<2> vel_sp_hor_prev(_vel_sp_prev(0), _vel_sp_prev(1));
  300. math::Vector<2> vel_sp_hor = acc_hor * dt + vel_sp_hor_prev;
  301. _vel_sp(0) = vel_sp_hor(0);
  302. _vel_sp(1) = vel_sp_hor(1);
  303. }
  304. // limit vertical acceleration
  305. float acc_v = (_vel_sp(2) - _vel_sp_prev(2)) / dt;
  306. if (fabsf(acc_v) > 2 * _params.acc_hor_max) {
  307. acc_v /= fabsf(acc_v);
  308. _vel_sp(2) = acc_v * 2 * _params.acc_hor_max * dt + _vel_sp_prev(2);
  309. }
  310. _vel_sp_prev = _vel_sp;
  311. _global_vel_sp.vx = _vel_sp(0);
  312. _global_vel_sp.vy = _vel_sp(1);
  313. _global_vel_sp.vz = _vel_sp(2);
  314. /* publish velocity setpoint */
  315. if (_global_vel_sp_pub != nullptr) {
  316. orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
  317. } else {
  318. _global_vel_sp_pub = orb_advertise(ORB_ID(vehicle_global_velocity_setpoint), &_global_vel_sp);
  319. }
  320. if (_control_mode.flag_control_climb_rate_enabled || _control_mode.flag_control_velocity_enabled) {
  321. /* reset integrals if needed */
  322. if (_control_mode.flag_control_climb_rate_enabled) {
  323. if (reset_int_z) {
  324. reset_int_z = false;
  325. float i = _params.thr_min;
  326. if (reset_int_z_manual) {
  327. i = _params.thr_hover;
  328. if (i < _params.thr_min) {
  329. i = _params.thr_min;
  330. } else if (i > _params.thr_max) {
  331. i = _params.thr_max;
  332. }
  333. }
  334. thrust_int(2) = -i;
  335. }
  336. } else {
  337. reset_int_z = true;
  338. }
  339. if (_control_mode.flag_control_velocity_enabled) {
  340. if (reset_int_xy) {
  341. reset_int_xy = false;
  342. thrust_int(0) = 0.0f;
  343. thrust_int(1) = 0.0f;
  344. }
  345. } else {
  346. reset_int_xy = true;
  347. }
  348. /* velocity error */
  349. math::Vector<3> vel_err = _vel_sp - _vel;
  350. 检查是否从非速度模式转到速度控制模式,如果是的话,校正xy的速度设定值以便姿态设定值保持不变/
  351. // check if we have switched from a non-velocity controlled mode into a velocity controlled mode
  352. // if yes, then correct xy velocity setpoint such that the attitude setpoint is continuous
  353. if (!control_vel_enabled_prev && _control_mode.flag_control_velocity_enabled) {
  354. // choose velocity xyz setpoint such that the resulting thrust setpoint has the direction
  355. // given by the last attitude setpoint
  356. _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);
  357. _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);
  358. _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);
  359. _vel_sp_prev(0) = _vel_sp(0);
  360. _vel_sp_prev(1) = _vel_sp(1);
  361. _vel_sp_prev(2) = _vel_sp(2);
  362. control_vel_enabled_prev = true;
  363. // compute updated velocity error
  364. vel_err = _vel_sp - _vel;
  365. }
  366. /* thrust vector in NED frame */
  367. math::Vector<3> thrust_sp = vel_err.emult(_params.vel_p) + _vel_err_d.emult(_params.vel_d) + thrust_int;
  368. if (_pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_TAKEOFF
  369. && !_takeoff_jumped && !_control_mode.flag_control_manual_enabled) {
  370. // for jumped takeoffs use special thrust setpoint calculated above
  371. thrust_sp.zero();
  372. thrust_sp(2) = -_takeoff_thrust_sp;
  373. }
  374. if (!_control_mode.flag_control_velocity_enabled) {
  375. thrust_sp(0) = 0.0f;
  376. thrust_sp(1) = 0.0f;
  377. }
  378. if (!_control_mode.flag_control_climb_rate_enabled) {
  379. thrust_sp(2) = 0.0f;
  380. }
  381. /* limit thrust vector and check for saturation */
  382. bool saturation_xy = false;
  383. bool saturation_z = false;
  384. /* limit min lift */
  385. float thr_min = _params.thr_min;
  386. if (!_control_mode.flag_control_velocity_enabled && thr_min < 0.0f) {
  387. /* don't allow downside thrust direction in manual attitude mode */
  388. thr_min = 0.0f;
  389. }
  390. float thrust_abs = thrust_sp.length();
  391. float tilt_max = _params.tilt_max_air;
  392. float thr_max = _params.thr_max;
  393. /* filter vel_z over 1/8sec */
  394. _vel_z_lp = _vel_z_lp * (1.0f - dt * 8.0f) + dt * 8.0f * _vel(2);
  395. /* filter vel_z change over 1/8sec */
  396. float vel_z_change = (_vel(2) - _vel_prev(2)) / dt;
  397. _acc_z_lp = _acc_z_lp * (1.0f - dt * 8.0f) + dt * 8.0f * vel_z_change;
  398. /* adjust limits for landing mode */调整限制 着陆模式
  399. if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid &&
  400. _pos_sp_triplet.current.type == position_setpoint_s::SETPOINT_TYPE_LAND) {
  401. /* limit max tilt and min lift when landing */
  402. tilt_max = _params.tilt_max_land;
  403. if (thr_min < 0.0f) {
  404. thr_min = 0.0f;
  405. }
  406. /* descend stabilized, we're landing */
  407. if (!_in_landing && !_lnd_reached_ground
  408. && (float)fabs(_acc_z_lp) < 0.1f
  409. && _vel_z_lp > 0.5f * _params.land_speed) {
  410. _in_landing = true;
  411. }
  412. /* assume ground, cut thrust */
  413. if (_in_landing
  414. && _vel_z_lp < 0.1f) {
  415. thr_max = 0.0f;
  416. _in_landing = false;
  417. _lnd_reached_ground = true;
  418. }
  419. /* once we assumed to have reached the ground always cut the thrust.
  420. Only free fall detection below can revoke this
  421. */
  422. if (!_in_landing && _lnd_reached_ground) {
  423. thr_max = 0.0f;
  424. }
  425. /* if we suddenly fall, reset landing logic and remove thrust limit */
  426. if (_lnd_reached_ground
  427. /* XXX: magic value, assuming free fall above 4m/s2 acceleration */
  428. && (_acc_z_lp > 4.0f
  429. || _vel_z_lp > 2.0f * _params.land_speed)) {
  430. thr_max = _params.thr_max;
  431. _in_landing = false;
  432. _lnd_reached_ground = false;
  433. }
  434. } else {
  435. _in_landing = false;
  436. _lnd_reached_ground = false;
  437. }
  438. /* limit min lift */
  439. if (-thrust_sp(2) < thr_min) {
  440. thrust_sp(2) = -thr_min;
  441. saturation_z = true;
  442. }
  443. if (_control_mode.flag_control_velocity_enabled) {
  444. /* limit max tilt */
  445. if (thr_min >= 0.0f && tilt_max < M_PI_F / 2 - 0.05f) {
  446. /* absolute horizontal thrust */
  447. float thrust_sp_xy_len = math::Vector<2>(thrust_sp(0), thrust_sp(1)).length();
  448. if (thrust_sp_xy_len > 0.01f) {
  449. /* max horizontal thrust for given vertical thrust*/
  450. float thrust_xy_max = -thrust_sp(2) * tanf(tilt_max);
  451. if (thrust_sp_xy_len > thrust_xy_max) {
  452. float k = thrust_xy_max / thrust_sp_xy_len;
  453. thrust_sp(0) *= k;
  454. thrust_sp(1) *= k;
  455. saturation_xy = true;
  456. }
  457. }
  458. }
  459. }
  460. if (_control_mode.flag_control_altitude_enabled) {
  461. /* thrust compensation for altitude only control modes */推力的补偿 高度控制模式
  462. float att_comp;
  463. if (_R(2, 2) > TILT_COS_MAX) {
  464. att_comp = 1.0f / _R(2, 2);
  465. } else if (_R(2, 2) > 0.0f) {
  466. att_comp = ((1.0f / TILT_COS_MAX - 1.0f) / TILT_COS_MAX) * _R(2, 2) + 1.0f;
  467. saturation_z = true;
  468. } else {
  469. att_comp = 1.0f;
  470. saturation_z = true;
  471. }
  472. thrust_sp(2) *= att_comp;
  473. }
  474. ///限制最大推力///
  475. /* limit max thrust */
  476. thrust_abs = thrust_sp.length(); /* recalculate because it might have changed */
  477. if (thrust_abs > thr_max) {
  478. if (thrust_sp(2) < 0.0f) {
  479. if (-thrust_sp(2) > thr_max) {
  480. /* thrust Z component is too large, limit it */
  481. thrust_sp(0) = 0.0f;
  482. thrust_sp(1) = 0.0f;
  483. thrust_sp(2) = -thr_max;
  484. saturation_xy = true;
  485. saturation_z = true;
  486. } else {
  487. /* preserve thrust Z component and lower XY, keeping altitude is more important than position */
  488. float thrust_xy_max = sqrtf(thr_max * thr_max - thrust_sp(2) * thrust_sp(2));
  489. float thrust_xy_abs = math::Vector<2>(thrust_sp(0), thrust_sp(1)).length();
  490. float k = thrust_xy_max / thrust_xy_abs;
  491. thrust_sp(0) *= k;
  492. thrust_sp(1) *= k;
  493. saturation_xy = true;
  494. }
  495. } else {
  496. /* Z component is negative, going down, simply limit thrust vector */
  497. float k = thr_max / thrust_abs;
  498. thrust_sp *= k;
  499. saturation_xy = true;
  500. saturation_z = true;
  501. }
  502. thrust_abs = thr_max;
  503. }
  504. ///跟新积分//
  505. /* update integrals */
  506. if (_control_mode.flag_control_velocity_enabled && !saturation_xy) {
  507. thrust_int(0) += vel_err(0) * _params.vel_i(0) * dt;
  508. thrust_int(1) += vel_err(1) * _params.vel_i(1) * dt;
  509. }
  510. if (_control_mode.flag_control_climb_rate_enabled && !saturation_z) {
  511. thrust_int(2) += vel_err(2) * _params.vel_i(2) * dt;
  512. /* protection against flipping on ground when landing */
  513. if (thrust_int(2) > 0.0f) {
  514. thrust_int(2) = 0.0f;
  515. }
  516. }
  517. /根据推力矢量计算的姿态设定值//
  518. /* calculate attitude setpoint from thrust vector */
  519. if (_control_mode.flag_control_velocity_enabled) {
  520. /* desired body_z axis = -normalize(thrust_vector) */
  521. math::Vector<3> body_x;
  522. math::Vector<3> body_y;
  523. math::Vector<3> body_z;
  524. if (thrust_abs > SIGMA) {
  525. body_z = -thrust_sp / thrust_abs;
  526. } else {
  527. /* no thrust, set Z axis to safe value */
  528. body_z.zero();
  529. body_z(2) = 1.0f;
  530. }
  531. /* vector of desired yaw direction in XY plane, rotated by PI/2 */
  532. math::Vector<3> y_C(-sinf(_att_sp.yaw_body), cosf(_att_sp.yaw_body), 0.0f);
  533. if (fabsf(body_z(2)) > SIGMA) {
  534. /* desired body_x axis, orthogonal to body_z */
  535. body_x = y_C % body_z;
  536. /* keep nose to front while inverted upside down */
  537. if (body_z(2) < 0.0f) {
  538. body_x = -body_x;
  539. }
  540. body_x.normalize();
  541. } else {
  542. /* desired thrust is in XY plane, set X downside to construct correct matrix,
  543. * but yaw component will not be used actually */
  544. body_x.zero();
  545. body_x(2) = 1.0f;
  546. }
  547. /* desired body_y axis */
  548. body_y = body_z % body_x;
  549. /* fill rotation matrix */
  550. for (int i = 0; i < 3; i++) {
  551. R(i, 0) = body_x(i);
  552. R(i, 1) = body_y(i);
  553. R(i, 2) = body_z(i);
  554. }
  555. 复制旋转矩阵到姿态设定值主题中
  556. /* copy rotation matrix to attitude setpoint topic */
  557. memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
  558. _att_sp.R_valid = true;
  559. /复制四元数设定值到姿态设定值主题中///
  560. /* copy quaternion setpoint to attitude setpoint topic */
  561. math::Quaternion q_sp;
  562. q_sp.from_dcm(R);
  563. memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
  564. //计算欧拉角,只记录,不得用于控制//
  565. /* calculate euler angles, for logging only, must not be used for control */
  566. math::Vector<3> euler = R.to_euler();
  567. _att_sp.roll_body = euler(0);
  568. _att_sp.pitch_body = euler(1);
  569. /* yaw already used to construct rot matrix, but actual rotation matrix can have different yaw near singularity */
  570. /偏航已经用于构建rot矩阵,但实际旋转矩阵可以有奇点附近的不同偏航///
  571. } else if (!_control_mode.flag_control_manual_enabled) {
  572. /没有位置控制的自主高度控制(故障安全降落),强制水平姿态,不改变yaw///
  573. /* autonomous altitude control without position control (failsafe landing),
  574. * force level attitude, don't change yaw */
  575. R.from_euler(0.0f, 0.0f, _att_sp.yaw_body);
  576. 复制旋转矩阵到姿态设定值主题中
  577. /* copy rotation matrix to attitude setpoint topic */
  578. memcpy(&_att_sp.R_body[0], R.data, sizeof(_att_sp.R_body));
  579. _att_sp.R_valid = true;
  580. /复制四元数设定值到姿态设定值主题中///
  581. /* copy quaternion setpoint to attitude setpoint topic */
  582. math::Quaternion q_sp;
  583. q_sp.from_dcm(R);
  584. memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
  585. _att_sp.roll_body = 0.0f;
  586. _att_sp.pitch_body = 0.0f;
  587. }
  588. _att_sp.thrust = thrust_abs;
  589. /* save thrust setpoint for logging */保存推理设定值在logging里
  590. _local_pos_sp.acc_x = thrust_sp(0) * ONE_G;
  591. _local_pos_sp.acc_y = thrust_sp(1) * ONE_G;
  592. _local_pos_sp.acc_z = thrust_sp(2) * ONE_G;
  593. _att_sp.timestamp = hrt_absolute_time();
  594. } else {
  595. reset_int_z = true;
  596. }
  597. }
  598. /* fill local position, velocity and thrust setpoint */
  599. _local_pos_sp.timestamp = hrt_absolute_time();
  600. _local_pos_sp.x = _pos_sp(0);
  601. _local_pos_sp.y = _pos_sp(1);
  602. _local_pos_sp.z = _pos_sp(2);
  603. _local_pos_sp.yaw = _att_sp.yaw_body;
  604. _local_pos_sp.vx = _vel_sp(0);
  605. _local_pos_sp.vy = _vel_sp(1);
  606. _local_pos_sp.vz = _vel_sp(2);
  607. 发布当地位置设定值
  608. /***************这个应该是这段程序处理的最后结果********************/
  609. /* publish local position setpoint */
  610. if (_local_pos_sp_pub != nullptr) {
  611. orb_publish(ORB_ID(vehicle_local_position_setpoint), _local_pos_sp_pub, &_local_pos_sp);
  612. } else {
  613. _local_pos_sp_pub = orb_advertise(ORB_ID(vehicle_local_position_setpoint), &_local_pos_sp);
  614. }
  615. } else {位置控制模式失能,那么复位设定值
  616. /* position controller disabled, reset setpoints */
  617. _reset_alt_sp = true;
  618. _reset_pos_sp = true;
  619. _mode_auto = false;
  620. reset_int_z = true;
  621. reset_int_xy = true;
  622. control_vel_enabled_prev = false;
  623. /* store last velocity in case a mode switch to position control occurs */
  624. _vel_sp_prev = _vel;
  625. }
  626. //从手动控制中产生姿态设定值//
  627. /* generate attitude setpoint from manual controls */
  628. if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_attitude_enabled) {
  629. /* reset yaw setpoint to current position if needed */
  630. if (reset_yaw_sp) {
  631. reset_yaw_sp = false;
  632. _att_sp.yaw_body = _yaw;
  633. }
  634. //在地上时,不动偏航方向/
  635. /* do not move yaw while sitting on the ground */
  636. else if (!_vehicle_status.condition_landed &&
  637. !(!_control_mode.flag_control_altitude_enabled && _manual.z < 0.1f)) {
  638. /* we want to know the real constraint, and global overrides manual */
  639. const float yaw_rate_max = (_params.man_yaw_max < _params.global_yaw_max) ? _params.man_yaw_max :
  640. _params.global_yaw_max;
  641. const float yaw_offset_max = yaw_rate_max / _params.mc_att_yaw_p;
  642. _att_sp.yaw_sp_move_rate = _manual.r * yaw_rate_max;
  643. float yaw_target = _wrap_pi(_att_sp.yaw_body + _att_sp.yaw_sp_move_rate * dt);
  644. float yaw_offs = _wrap_pi(yaw_target - _yaw);
  645. 如果对于系统跟踪,yaw偏移变得过大,那么停止其转移
  646. // If the yaw offset became too big for the system to track stop
  647. // shifting it
  648. // XXX this needs inspection - probably requires a clamp, not an if
  649. if (fabsf(yaw_offs) < yaw_offset_max) {
  650. _att_sp.yaw_body = yaw_target;
  651. }
  652. }
  653. //直接控制侧倾和俯仰,如果协助速度控制器没有被激活
  654. /* control roll and pitch directly if we no aiding velocity controller is active */
  655. if (!_control_mode.flag_control_velocity_enabled) {
  656. _att_sp.roll_body = _manual.y * _params.man_roll_max;
  657. _att_sp.pitch_body = -_manual.x * _params.man_pitch_max;
  658. }
  659. //控制油门直接,如果没有爬升率控制器被激活/
  660. /* control throttle directly if no climb rate controller is active */
  661. if (!_control_mode.flag_control_climb_rate_enabled) {
  662. float thr_val = throttle_curve(_manual.z, _params.thr_hover);
  663. _att_sp.thrust = math::min(thr_val, _manual_thr_max.get());
  664. /* enforce minimum throttle if not landed */
  665. if (!_vehicle_status.condition_landed) {
  666. _att_sp.thrust = math::max(_att_sp.thrust, _manual_thr_min.get());
  667. }
  668. }
  669. math::Matrix<3, 3> R_sp;
  670. //构建姿态设定值的旋转矩阵///
  671. /* construct attitude setpoint rotation matrix */
  672. R_sp.from_euler(_att_sp.roll_body, _att_sp.pitch_body, _att_sp.yaw_body);
  673. memcpy(&_att_sp.R_body[0], R_sp.data, sizeof(_att_sp.R_body));
  674. 为所有非姿态飞行模式 复位加速度设定值/
  675. /* reset the acceleration set point for all non-attitude flight modes */
  676. if (!(_control_mode.flag_control_offboard_enabled &&
  677. !(_control_mode.flag_control_position_enabled ||
  678. _control_mode.flag_control_velocity_enabled))) {
  679. _thrust_sp_prev = R_sp * math::Vector<3>(0, 0, -_att_sp.thrust);
  680. }
  681. /将四元数设定值复制到姿态设定值的主题中/
  682. /* copy quaternion setpoint to attitude setpoint topic */
  683. math::Quaternion q_sp;
  684. q_sp.from_dcm(R_sp);
  685. memcpy(&_att_sp.q_d[0], &q_sp.data[0], sizeof(_att_sp.q_d));
  686. _att_sp.timestamp = hrt_absolute_time();
  687. } else {
  688. reset_yaw_sp = true;
  689. }
  690. /* update previous velocity for velocity controller D part */
  691. _vel_prev = _vel;
  692. /发布设定值//
  693. /* publish attitude setpoint
  694. * Do not publish if offboard is enabled but position/velocity control is disabled,
  695. * in this case the attitude setpoint is published by the mavlink app. Also do not publish
  696. * if the vehicle is a VTOL and it's just doing a transition (the VTOL attitude control module will generate
  697. * attitude setpoints for the transition).
  698. */
  699. if (!(_control_mode.flag_control_offboard_enabled &&
  700. !(_control_mode.flag_control_position_enabled ||
  701. _control_mode.flag_control_velocity_enabled))) {
  702. if (_att_sp_pub != nullptr) {
  703. orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
  704. } else if (_attitude_setpoint_id) {
  705. _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
  706. }
  707. }
  708. /手动油门控制后,将高度控制器积分(悬停油门)复位到手动油门///
  709. /* reset altitude controller integral (hovering throttle) to manual throttle after manual throttle control */
  710. reset_int_z_manual = _control_mode.flag_armed && _control_mode.flag_control_manual_enabled
  711. && !_control_mode.flag_control_climb_rate_enabled;
  712. }
  713. mavlink_log_info(&_mavlink_log_pub, "[mpc] stopped");
  714. _control_task = -1;
  715. }
这些设定值的确定是不是就是控制策略的体现?
  1. void
  2. MulticopterPositionControl::poll_subscriptions()
  3. {
  4. bool updated;
  5. /**********************机体状态跟新**************************/
  6. orb_check(_vehicle_status_sub, &updated);
  7. if (updated) {
  8. orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
  9. /* set correct uORB ID, depending on if vehicle is VTOL or not */
  10. if (!_attitude_setpoint_id) {
  11. if (_vehicle_status.is_vtol) {
  12. _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
  13. } else {
  14. _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
  15. }
  16. }
  17. }
  18. /**********************控制状态跟新**************************/
  19. orb_check(_ctrl_state_sub, &updated);
  20. if (updated) {
  21. orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
  22. /* get current rotation matrix and euler angles from control state quaternions */
  23. math::Quaternion q_att(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
  24. _R = q_att.to_dcm();
  25. math::Vector<3> euler_angles;
  26. euler_angles = _R.to_euler();
  27. _yaw = euler_angles(2);
  28. }
  29. /**********************setpoint状态跟新**************************/
  30. orb_check(_att_sp_sub, &updated);
  31. if (updated) {
  32. orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
  33. }
  34. orb_check(_control_mode_sub, &updated);
  35. if (updated) {
  36. orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode);
  37. }
  38. /**********************手动控制状态跟新**************************/
  39. orb_check(_manual_sub, &updated);
  40. if (updated) {
  41. orb_copy(ORB_ID(manual_control_setpoint), _manual_sub, &_manual);
  42. }
  43. /**********************解锁状态跟新**************************/
  44. orb_check(_arming_sub, &updated);
  45. if (updated) {
  46. orb_copy(ORB_ID(actuator_armed), _arming_sub, &_arming);
  47. }
  48. /**********************位置跟新**************************/
  49. orb_check(_local_pos_sub, &updated);
  50. if (updated) {
  51. orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
  52. }
  53. }
  1. void
  2. MulticopterPositionControl::update_ref()
  3. {
  4. if (_local_pos.ref_timestamp != _ref_timestamp) {
  5. double lat_sp, lon_sp;//维度设定、经度设定
  6. float alt_sp = 0.0f;//姿态设定
  7. if (_ref_timestamp != 0) {
  8. /*************在整体框架下计算当前位置设定值***************/
  9. /* calculate current position setpoint in global frame */
  10. map_projection_reproject(&_ref_pos, _pos_sp(0), _pos_sp(1), &lat_sp, &lon_sp);
  11. alt_sp = _ref_alt - _pos_sp(2);
  12. }
  13. /*************跟新投影参考*********************/
  14. /* update local projection reference */
  15. map_projection_init(&_ref_pos, _local_pos.ref_lat, _local_pos.ref_lon);
  16. _ref_alt = _local_pos.ref_alt;
  17. if (_ref_timestamp != 0) {
  18. /*********************设置新的位置设定值*******************/
  19. /* reproject position setpoint to new reference */
  20. map_projection_project(&_ref_pos, lat_sp, lon_sp, &_pos_sp.data[0], &_pos_sp.data[1]);
  21. _pos_sp(2) = -(alt_sp - _ref_alt);
  22. }
  23. _ref_timestamp = _local_pos.ref_timestamp;
  24. }
  25. }
  1. void
  2. MulticopterPositionControl::control_manual(float dt)
  3. {
  4. math::Vector<3> req_vel_sp; // X,Y in local frame and Z in global (D), in [-1,1] normalized range
  5. req_vel_sp.zero();
  6. if (_control_mode.flag_control_altitude_enabled) {
  7. /* set vertical velocity setpoint with throttle stick */用油门棒设置垂直速度
  8. req_vel_sp(2) = -scale_control(_manual.z - 0.5f, 0.5f, _params.alt_ctl_dz, _params.alt_ctl_dy); // D
  9. }
  10. if (_control_mode.flag_control_position_enabled) {
  11. /* set horizontal velocity setpoint with roll/pitch stick */用roll/pitch棒设置水平速度
  12. req_vel_sp(0) = _manual.x;
  13. req_vel_sp(1) = _manual.y;
  14. }
  15. if (_control_mode.flag_control_altitude_enabled) {
  16. /* reset alt setpoint to current altitude if needed */复位姿态设定值
  17. reset_alt_sp();
  18. }
  19. if (_control_mode.flag_control_position_enabled) {
  20. /* reset position setpoint to current position if needed */复位位置设定值
  21. reset_pos_sp();
  22. }
  23. /* limit velocity setpoint */限制速度设定值
  24. float req_vel_sp_norm = req_vel_sp.length();
  25. if (req_vel_sp_norm > 1.0f) {
  26. req_vel_sp /= req_vel_sp_norm;//相当于是向量除以它的模值
  27. }
  28. ///_req_vel_sp的范围是0到1,围绕yaw旋转
  29. /* _req_vel_sp scaled to 0..1, scale it to max speed and rotate around yaw */
  30. math::Matrix<3, 3> R_yaw_sp;
  31. R_yaw_sp.from_euler(0.0f, 0.0f, _att_sp.yaw_body);
  32. math::Vector<3> req_vel_sp_scaled = R_yaw_sp * req_vel_sp.emult(
  33. _params.vel_cruise); // in NED and scaled to actual velocity在NED旋转方式下缩放到实际速度
  34. /用户辅助模式:用户控制速度,但是,如果速度足够小,相应的轴的位置就会保持
  35. /*
  36. * assisted velocity mode: user controls velocity, but if velocity is small enough, position
  37. * hold is activated for the corresponding axis
  38. */
  39. /* horizontal axes */水平轴
  40. if (_control_mode.flag_control_position_enabled) {
  41. /* check for pos. hold */检测位置的保持状态
  42. if (fabsf(req_vel_sp(0)) < _params.hold_xy_dz && fabsf(req_vel_sp(1)) < _params.hold_xy_dz) {
  43. if (!_pos_hold_engaged) {
  44. if (_params.hold_max_xy < FLT_EPSILON || (fabsf(_vel(0)) < _params.hold_max_xy
  45. && fabsf(_vel(1)) < _params.hold_max_xy)) {
  46. _pos_hold_engaged = true;
  47. } else {
  48. _pos_hold_engaged = false;
  49. }
  50. }
  51. } else {
  52. _pos_hold_engaged = false;
  53. }
  54. /* set requested velocity setpoint */设置所需的速度设定值
  55. if (!_pos_hold_engaged) {
  56. _pos_sp(0) = _pos(0);
  57. _pos_sp(1) = _pos(1);
  58. //速度设定值会被利用,位置设定值不会被用/
  59. _run_pos_control = false; /* request velocity setpoint to be used, instead of position setpoint */
  60. _vel_sp(0) = req_vel_sp_scaled(0);
  61. _vel_sp(1) = req_vel_sp_scaled(1);
  62. }
  63. }
  64. /* vertical axis */垂直轴
  65. if (_control_mode.flag_control_altitude_enabled) {
  66. /* check for pos. hold */
  67. if (fabsf(req_vel_sp(2)) < FLT_EPSILON) {
  68. if (!_alt_hold_engaged) {
  69. if (_params.hold_max_z < FLT_EPSILON || fabsf(_vel(2)) < _params.hold_max_z) {
  70. _alt_hold_engaged = true;
  71. } else {
  72. _alt_hold_engaged = false;
  73. }
  74. }
  75. } else {
  76. _alt_hold_engaged = false;
  77. }
  78. /* set requested velocity setpoint */
  79. if (!_alt_hold_engaged) {
  80. _run_alt_control = false; /* request velocity setpoint to be used, instead of altitude setpoint */
  81. _vel_sp(2) = req_vel_sp_scaled(2);
  82. _pos_sp(2) = _pos(2);
  83. }
  84. }
  85. }
  1. #ifdef __cplusplus
  2. struct __EXPORT position_setpoint_triplet_s {
  3. #else
  4. struct position_setpoint_triplet_s {
  5. #endif
  6. struct position_setpoint_s previous;
  7. struct position_setpoint_s current;
  8. struct position_setpoint_s next;
  9. uint8_t nav_state;
  10. #ifdef __cplusplus
  11. #endif
  12. };

整个MulticopterPositionControl::task_main()的输出应该是

  1. orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
  2. orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
  3. 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)
 没有找到orb_copy(ORB_ID(vehicle_local_position_setpoint) 或者 orb_copy(_attitude_setpoint_id 

  1. if (!_attitude_setpoint_id) {
  2. if (_vehicle_status.is_vtol) {
  3. _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
  4. } else {
  5. _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
  6. }
  7. }
再看看
  1. void
  2. MulticopterPositionControl::task_main()
  3. {
  4. /*
  5. * do subscriptions
  6. */
  7. _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  8. _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
  9. _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  10. _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
  11. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  12. _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
  13. _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
  14. _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
  15. _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
  16. _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
  17. _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
全局搜索vehicle_attitude_setpoint
由此可以看出最后mc_pos_control_main.cpp最后处理的结果一方面被自己重新订阅,用于不断跟新;另一方面被mc_att_control订阅,用于控制姿态
在进入姿态前,再来理下光流信息如何流动的
//ardupilot/modules/PX4Firmware/src/drivers/px4flow/px4flow.cpp
orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
//ardupilot/modules/PX4Firmware/src/modules/position_estimator_inav/position_estimator_inav_main.cpp
int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);
orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
//ardupilot/modules/PX4Firmware/src/modules/mc_pos_contol/mc_pos_contol_main.cpp
_local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
  1. if (!_attitude_setpoint_id) {
  2. if (_vehicle_status.is_vtol) {
  3. _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
  4. } else {
  5. _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
  6. }
  7. }
//ardupilot/modules/PX4Firmware/src/modules/mc_att_control/mc_att_control_main.cpp
_v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  1. void
  2. MulticopterAttitudeControl::vehicle_attitude_setpoint_poll()
  3. {
  4. /* check if there is a new setpoint */
  5. bool updated;
  6. orb_check(_v_att_sp_sub, &updated);
  7. if (updated) {
  8. orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
  9. }
  10. }
突然发现//ardupilot/modules/PX4Firmware/src/modules/vtol_att_control//vtol_att_control_main.cpp中也有orb_copy(ORB_ID(vehicle_attitude_setpoint)
  1. void
  2. VtolAttitudeControl::vehicle_attitude_setpoint_poll()
  3. {
  4. /* check if there is a new setpoint */
  5. bool updated;
  6. orb_check(_v_att_sp_sub, &updated);
  7. if (updated) {
  8. orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
  9. }
  10. }
  1. void
  2. VtolAttitudeControl::mc_virtual_att_sp_poll()
  3. {
  4. bool updated;
  5. orb_check(_mc_virtual_att_sp_sub, &updated);
  6. if (updated) {
  7. orb_copy(ORB_ID(mc_virtual_attitude_setpoint), _mc_virtual_att_sp_sub , &_mc_virtual_att_sp);
  8. }
  9. }
  1. void VtolAttitudeControl::publish_att_sp()
  2. {
  3. if (_v_att_sp_pub != nullptr) {
  4. /* publish the attitude setpoint */
  5. orb_publish(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_pub, &_v_att_sp);
  6. } else {
  7. /* advertise and publish */
  8. _v_att_sp_pub = orb_advertise(ORB_ID(vehicle_attitude_setpoint), &_v_att_sp);
  9. }
  10. }
好奇葩啊,//ardupilot/modules/PX4Firmware/src/modules/vtol_att_control//vtol_att_control_main.cpp
字面意思应该是控制垂直起降的,怎么什么信息都会发布,都会接收啊?!暂时先放着
恩,产生一个新的想法:可以把这些订阅和发布的所有信息用图反映出来,大概就能直观的察觉到pixhawk的位置姿态估计和控制的结构,可以先看默认启动的那几个cpp文件
现在进入//ardupilot/modules/PX4Firmware/src/modules/mc_att_control/mc_att_control_main.cpp看看(上一篇写的有点乱,这一篇重新写)
extern "C" __EXPORT int mc_att_control_main(int argc, char *argv[]);
  1. int mc_att_control_main(int argc, char *argv[])
  2. {
  3. if (argc < 2) {
  4. warnx("usage: mc_att_control {start|stop|status}");
  5. return 1;
  6. }
  7. if (!strcmp(argv[1], "start")) {
  8. if (mc_att_control::g_control != nullptr) {
  9. warnx("already running");
  10. return 1;
  11. }
  12. mc_att_control::g_control = new MulticopterAttitudeControl;
  13. if (mc_att_control::g_control == nullptr) {
  14. warnx("alloc failed");
  15. return 1;
  16. }
  17. if (OK != mc_att_control::g_control->start()) {
  18. delete mc_att_control::g_control;
  19. mc_att_control::g_control = nullptr;
  20. warnx("start failed");
  21. return 1;
  22. }
  23. return 0;
  24. }
  25. if (!strcmp(argv[1], "stop")) {
  26. if (mc_att_control::g_control == nullptr) {
  27. warnx("not running");
  28. return 1;
  29. }
  30. delete mc_att_control::g_control;
  31. mc_att_control::g_control = nullptr;
  32. return 0;
  33. }
  34. if (!strcmp(argv[1], "status")) {
  35. if (mc_att_control::g_control) {
  36. warnx("running");
  37. return 0;
  38. } else {
  39. warnx("not running");
  40. return 1;
  41. }
  42. }
  43. warnx("unrecognized command");
  44. return 1;
  45. }
这里MulticopterAttitudeControl *g_control;*g_control是最大的一个类的实例
mc_att_control::g_control = new MulticopterAttitudeControl;相当于是分配空间
里面包含
  1. /* fetch initial parameter values */
  2. parameters_update();
里面好多参数,不知道是不是上位机配置的参数,就是说是不是把上位机的各种关于飞行的参数存到了sd卡中,在通过这个函数跟新到程序中用于飞行器的控制??
接着就进了start
  1. int
  2. MulticopterAttitudeControl::start()
  3. {
  4. ASSERT(_control_task == -1);
  5. /* start the task */
  6. _control_task = px4_task_spawn_cmd("mc_att_control",
  7. SCHED_DEFAULT,
  8. SCHED_PRIORITY_MAX - 5,
  9. 1500,
  10. (px4_main_t)&MulticopterAttitudeControl::task_main_trampoline,
  11. nullptr);
  12. if (_control_task < 0) {
  13. warn("task start failed");
  14. return -errno;
  15. }
  16. return OK;
  17. }
  1. void
  2. MulticopterAttitudeControl::task_main_trampoline(int argc, char *argv[])
  3. {
  4. mc_att_control::g_control->task_main();
  5. }
  1. void
  2. MulticopterAttitudeControl::task_main()
  3. {
  4. /**************************订阅各种信息**************************/
  5. /*
  6. * do subscriptions
  7. */
  8. _v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  9. _v_rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
  10. _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
  11. _v_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
  12. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  13. _manual_control_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
  14. _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
  15. _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  16. _motor_limits_sub = orb_subscribe(ORB_ID(multirotor_motor_limits));
  17. /**************************初始化各种参数**************************/
  18. /* initialize parameters cache */
  19. parameters_update();
  20. /**************************启动机体姿态原函数**************************/
  21. /* wakeup source: vehicle attitude */
  22. px4_pollfd_struct_t fds[1];
  23. fds[0].fd = _ctrl_state_sub;
  24. fds[0].events = POLLIN;
  25. /**************************大循环**************************/
  26. while (!_task_should_exit) {
  27. /等待100ms 为了获取数据/
  28. /* wait for up to 100ms for data */
  29. int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 100);
  30. /* timed out - periodic check for _task_should_exit */
  31. if (pret == 0) {
  32. continue;
  33. }
  34. /* this is undesirable but not much we can do - might want to flag unhappy status */
  35. if (pret < 0) {
  36. warn("mc att ctrl: poll error %d, %d", pret, errno);
  37. /* sleep a bit before next try */
  38. usleep(100000);
  39. continue;
  40. }
  41. perf_begin(_loop_perf);
  42. ///运行姿态变化控制器//
  43. /* run controller on attitude changes */
  44. if (fds[0].revents & POLLIN) {
  45. static uint64_t last_run = 0;
  46. float dt = (hrt_absolute_time() - last_run) / 1000000.0f;
  47. last_run = hrt_absolute_time();
  48. /防止dt太小或太大 2ms<dt<20ms
  49. /* guard against too small (< 2ms) and too large (> 20ms) dt's */
  50. if (dt < 0.002f) {
  51. dt = 0.002f;
  52. } else if (dt > 0.02f) {
  53. dt = 0.02f;
  54. }
  55. /* copy attitude and control state topics */
  56. orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
  57. /* check for updates in other topics */
  58. parameter_update_poll();
  59. vehicle_control_mode_poll();
  60. arming_status_poll();
  61. vehicle_manual_poll();
  62. vehicle_status_poll();
  63. vehicle_motor_limits_poll();
  64. 若xy轴的设定值大于阈值,那么不运行姿态控制/
  65. /* Check if we are in rattitude mode and the pilot is above the threshold on pitch
  66. * or roll (yaw can rotate 360 in normal att control). If both are true don't
  67. * even bother running the attitude controllers */
  68. if (_vehicle_status.main_state == vehicle_status_s::MAIN_STATE_RATTITUDE) {
  69. if (fabsf(_manual_control_sp.y) > _params.rattitude_thres ||
  70. fabsf(_manual_control_sp.x) > _params.rattitude_thres) {
  71. _v_control_mode.flag_control_attitude_enabled = false;
  72. }
  73. }
  74. /姿态控制使能
  75. if (_v_control_mode.flag_control_attitude_enabled) {
  76. if (_ts_opt_recovery == nullptr) {
  77. // the tailsitter recovery instance has not been created, thus, the vehicle
  78. // is not a tailsitter, do normal attitude control
  79. control_attitude(dt);
  80. } else {
  81. vehicle_attitude_setpoint_poll();
  82. _thrust_sp = _v_att_sp.thrust;
  83. math::Quaternion q(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
  84. math::Quaternion q_sp(&_v_att_sp.q_d[0]);
  85. _ts_opt_recovery->setAttGains(_params.att_p, _params.yaw_ff);
  86. _ts_opt_recovery->calcOptimalRates(q, q_sp, _v_att_sp.yaw_sp_move_rate, _rates_sp);
  87. /* limit rates */
  88. for (int i = 0; i < 3; i++) {
  89. _rates_sp(i) = math::constrain(_rates_sp(i), -_params.mc_rate_max(i), _params.mc_rate_max(i));
  90. }
  91. }
  92. /* publish attitude rates setpoint */
  93. _v_rates_sp.roll = _rates_sp(0);
  94. _v_rates_sp.pitch = _rates_sp(1);
  95. _v_rates_sp.yaw = _rates_sp(2);
  96. _v_rates_sp.thrust = _thrust_sp;
  97. _v_rates_sp.timestamp = hrt_absolute_time();
  98. if (_v_rates_sp_pub != nullptr) {
  99. orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
  100. } else if (_rates_sp_id) {
  101. _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
  102. }
  103. //}
  104. } else {
  105. /手动控制使能//
  106. /* attitude controller disabled, poll rates setpoint topic */
  107. if (_v_control_mode.flag_control_manual_enabled) {
  108. ///特技模式/
  109. /* manual rates control - ACRO mode */
  110. _rates_sp = math::Vector<3>(_manual_control_sp.y, -_manual_control_sp.x,
  111. _manual_control_sp.r).emult(_params.acro_rate_max);
  112. _thrust_sp = math::min(_manual_control_sp.z, MANUAL_THROTTLE_MAX_MULTICOPTER);
  113. /发布角速度设定值
  114. /* publish attitude rates setpoint */
  115. _v_rates_sp.roll = _rates_sp(0);
  116. _v_rates_sp.pitch = _rates_sp(1);
  117. _v_rates_sp.yaw = _rates_sp(2);
  118. _v_rates_sp.thrust = _thrust_sp;
  119. _v_rates_sp.timestamp = hrt_absolute_time();
  120. if (_v_rates_sp_pub != nullptr) {
  121. orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
  122. } else if (_rates_sp_id) {
  123. _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
  124. }
  125. }
  126. //非特技模式//
  127. else {
  128. //速度设定值来自于vehicle_rates_setpoint//
  129. //vehicle_rates_setpoint来自于哪里??///
  130. /* attitude controller disabled, poll rates setpoint topic */
  131. vehicle_rates_setpoint_poll();
  132. _rates_sp(0) = _v_rates_sp.roll;
  133. _rates_sp(1) = _v_rates_sp.pitch;
  134. _rates_sp(2) = _v_rates_sp.yaw;
  135. _thrust_sp = _v_rates_sp.thrust;
  136. }
  137. }
  138. ///速度控制/
  139. if (_v_control_mode.flag_control_rates_enabled) {
  140. //角速度控制
  141. control_attitude_rates(dt);
  142. //发布执行器控制///
  143. //这个就是pwm吗??
  144. /* publish actuator controls */
  145. _actuators.control[0] = (PX4_ISFINITE(_att_control(0))) ? _att_control(0) : 0.0f;
  146. _actuators.control[1] = (PX4_ISFINITE(_att_control(1))) ? _att_control(1) : 0.0f;
  147. _actuators.control[2] = (PX4_ISFINITE(_att_control(2))) ? _att_control(2) : 0.0f;
  148. _actuators.control[3] = (PX4_ISFINITE(_thrust_sp)) ? _thrust_sp : 0.0f;
  149. _actuators.timestamp = hrt_absolute_time();
  150. _actuators.timestamp_sample = _ctrl_state.timestamp;
  151. _controller_status.roll_rate_integ = _rates_int(0);
  152. _controller_status.pitch_rate_integ = _rates_int(1);
  153. _controller_status.yaw_rate_integ = _rates_int(2);
  154. _controller_status.timestamp = hrt_absolute_time();
  155. if (!_actuators_0_circuit_breaker_enabled) {
  156. if (_actuators_0_pub != nullptr) {
  157. orb_publish(_actuators_id, _actuators_0_pub, &_actuators);
  158. perf_end(_controller_latency_perf);
  159. } else if (_actuators_id) {
  160. _actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
  161. }
  162. }
  163. /* publish controller status */
  164. if (_controller_status_pub != nullptr) {
  165. orb_publish(ORB_ID(mc_att_ctrl_status), _controller_status_pub, &_controller_status);
  166. } else {
  167. _controller_status_pub = orb_advertise(ORB_ID(mc_att_ctrl_status), &_controller_status);
  168. }
  169. }
  170. }
  171. perf_end(_loop_perf);
  172. }
  173. _control_task = -1;
  174. return;
  175. }
看看这3段控制程序的输入输出,大概能猜想他们的运行逻辑并不是并列的,很有可能_v_control_mode.flag_control_rates_enabled跟在_v_control_mode.flag_control_attitude_enabled之后,这样就形成了常用的外环角度(也就是这里的姿态)内环角速度(姿态速度)的控制结构,这个还需要细看里面的输入输出和标志位如何赋值控制运行逻辑。
  1. /**
  2. * Attitude controller.
  3. * Input: 'vehicle_attitude_setpoint' topics (depending on mode)
  4. * Output: '_rates_sp' vector, '_thrust_sp'
  5. */
  6. /*************************注意看注释!!********************/
  7. /***********输入是'vehicle_attitude_setpoint'主题***********/
  8. /************输出是角速度设定值向量和油门设定值*************/
  9. void
  10. MulticopterAttitudeControl::control_attitude(float dt)
  11. {
  12. vehicle_attitude_setpoint_poll();//获取'vehicle_attitude_setpoint'主题
  13. _thrust_sp = _v_att_sp.thrust;
  14. //构建姿态设定值的旋转矩阵就是vehicle_attitude_setpoint_poll()获取的//
  15. /* construct attitude setpoint rotation matrix */
  16. math::Matrix<3, 3> R_sp;
  17. R_sp.set(_v_att_sp.R_body);//这里做的事只是把订阅_v_att_sp复制到一个新的地方
  18. /**** void set(const float *d) {
  19. **** memcpy(data, d, sizeof(data));
  20. **** }
  21. ****/
  22. //定义一个控制状态的四元数和相应的方向余弦矩阵(dcm)/
  23. /* get current rotation matrix from control state quaternions */
  24. math::Quaternion q_att(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
  25. math::Matrix<3, 3> R = q_att.to_dcm();
  26. /输入就准备好了,就是姿态设定值,并转变成能用的形式四元数和dcm///
  27. /* all input data is ready, run controller itself */
  28. /* try to move thrust vector shortest way, because yaw response is slower than roll/pitch */
  29. math::Vector<3> R_z(R(0, 2), R(1, 2), R(2, 2));//控制状态的z轴
  30. math::Vector<3> R_sp_z(R_sp(0, 2), R_sp(1, 2), R_sp(2, 2));//设定姿态的z轴
  31. /* axis and sin(angle) of desired rotation */轴与角的理想旋转
  32. math::Vector<3> e_R = R.transposed() * (R_z % R_sp_z);//transposed()换位函数,%是求叉积的意思
  33. /*** ardupilot/modules/PX4Firmware/src/lib/matrix/matrix/Matrix.hpp
  34. *** Matrix<Type, N, M> transpose() const
  35. *** {
  36. *** Matrix<Type, N, M> res;
  37. *** const Matrix<Type, M, N> &self = *this;
  38. ***
  39. *** for (size_t i = 0; i < M; i++) {
  40. *** for (size_t j = 0; j < N; j++) {
  41. *** res(j, i) = self(i, j);
  42. *** }
  43. *** }
  44. ***
  45. *** return res;
  46. *** }
  47. ***/
  48. /* calculate angle error */计算角的误差
  49. float e_R_z_sin = e_R.length();
  50. float e_R_z_cos = R_z * R_sp_z;
  51. //计算姿态角度误差(姿态误差),一个数学知识背景:由公式a×b=︱a︱︱b︱sinθ,a•b=︱a︱︱b︱cosθ
  52. //这里的R_z和R_sp_z都是单位向量,模值为1,因此误差向量e_R(a×b叉积就是误差)的模就是sinθ,点积就是cosθ。
  53. /*** ardupilot/modules/PX4Firmware/src/lib/mathlib/math/Vector.hpp
  54. *** float length() const {
  55. *** float res = 0.0f;
  56. ***
  57. *** for (unsigned int i = 0; i < N; i++)
  58. *** res += data[i] * data[i];
  59. ***
  60. *** return sqrtf(res);
  61. *** }
  62. ***/
  63. /* calculate weight for yaw control */计算yaw控制的权重
  64. float yaw_w = R_sp(2, 2) * R_sp(2, 2);//姿态设定值矩阵的第三行第三列元素的平方
  65. /* calculate rotation matrix after roll/pitch only rotation */
  66. math::Matrix<3, 3> R_rp;
  67. if (e_R_z_sin > 0.0f) {
  68. /* get axis-angle representation */
  69. float e_R_z_angle = atan2f(e_R_z_sin, e_R_z_cos);//得到z轴的误差角度
  70. math::Vector<3> e_R_z_axis = e_R / e_R_z_sin;
  71. /*** R.transposed() * (R_z % R_sp_z)
  72. *** -----------------------------------
  73. *** ||R.transposed() * (R_z % R_sp_z)||
  74. ***/
  75. /***********这些式子的数据具体怎么算的可以看得出来,具体含义应该与理论知识有关吧**********/
  76. e_R = e_R_z_axis * e_R_z_angle;
  77. /* cross product matrix for e_R_axis */
  78. math::Matrix<3, 3> e_R_cp;
  79. e_R_cp.zero();
  80. e_R_cp(0, 1) = -e_R_z_axis(2);
  81. e_R_cp(0, 2) = e_R_z_axis(1);
  82. e_R_cp(1, 0) = e_R_z_axis(2);
  83. e_R_cp(1, 2) = -e_R_z_axis(0);
  84. e_R_cp(2, 0) = -e_R_z_axis(1);
  85. e_R_cp(2, 1) = e_R_z_axis(0);
  86. /* rotation matrix for roll/pitch only rotation */
  87. R_rp = R * (_I + e_R_cp * e_R_z_sin + e_R_cp * e_R_cp * (1.0f - e_R_z_cos));
  88. } else {
  89. /* zero roll/pitch rotation */
  90. R_rp = R;
  91. }
  92. /* R_rp and R_sp has the same Z axis, calculate yaw error */
  93. math::Vector<3> R_sp_x(R_sp(0, 0), R_sp(1, 0), R_sp(2, 0));
  94. math::Vector<3> R_rp_x(R_rp(0, 0), R_rp(1, 0), R_rp(2, 0));
  95. e_R(2) = atan2f((R_rp_x % R_sp_x) * R_sp_z, R_rp_x * R_sp_x) * yaw_w;
  96. if (e_R_z_cos < 0.0f) {
  97. /* for large thrust vector rotations use another rotation method:
  98. * calculate angle and axis for R -> R_sp rotation directly */
  99. math::Quaternion q;
  100. q.from_dcm(R.transposed() * R_sp);
  101. math::Vector<3> e_R_d = q.imag();
  102. e_R_d.normalize();
  103. e_R_d *= 2.0f * atan2f(e_R_d.length(), q(0));
  104. /* use fusion of Z axis based rotation and direct rotation */
  105. float direct_w = e_R_z_cos * e_R_z_cos * yaw_w;//计算权重
  106. e_R = e_R * (1.0f - direct_w) + e_R_d * direct_w;
  107. }
  108. ///计算角速度设定值 也是矩阵表达的1*3矩阵///
  109. /* calculate angular rates setpoint */
  110. _rates_sp = _params.att_p.emult(e_R);
  111. /* limit rates */限制角速度大小
  112. for (int i = 0; i < 3; i++) {
  113. if (_v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
  114. _rates_sp(i) = math::constrain(_rates_sp(i), -_params.auto_rate_max(i), _params.auto_rate_max(i));
  115. } else {
  116. _rates_sp(i) = math::constrain(_rates_sp(i), -_params.mc_rate_max(i), _params.mc_rate_max(i));
  117. }
  118. }
  119. //风向标模式,抑制yaw角速度(风向标模式是定航向的意思吗??)///
  120. //yaw控制失能、速度模式使能、非手动模式/
  121. /* weather-vane mode, dampen yaw rate */
  122. if (_v_att_sp.disable_mc_yaw_control == true && _v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
  123. float wv_yaw_rate_max = _params.auto_rate_max(2) * _params.vtol_wv_yaw_rate_scale;
  124. _rates_sp(2) = math::constrain(_rates_sp(2), -wv_yaw_rate_max, wv_yaw_rate_max);
  125. // prevent integrator winding up in weathervane mode
  126. _rates_int(2) = 0.0f;
  127. }
  128. ///反馈角速度设定值(2) 矩阵中第三个元素/
  129. /* feed forward yaw setpoint rate */
  130. _rates_sp(2) += _v_att_sp.yaw_sp_move_rate * yaw_w * _params.yaw_ff;
  131. ///风向标模式,减小yaw角速度///
  132. /* weather-vane mode, scale down yaw rate */
  133. if (_v_att_sp.disable_mc_yaw_control == true && _v_control_mode.flag_control_velocity_enabled && !_v_control_mode.flag_control_manual_enabled) {
  134. float wv_yaw_rate_max = _params.auto_rate_max(2) * _params.vtol_wv_yaw_rate_scale;
  135. _rates_sp(2) = math::constrain(_rates_sp(2), -wv_yaw_rate_max, wv_yaw_rate_max);
  136. // prevent integrator winding up in weathervane mode
  137. _rates_int(2) = 0.0f;
  138. }
  139. }
  1. /*
  2. * Attitude rates controller.
  3. * Input: '_rates_sp' vector, '_thrust_sp'
  4. * Output: '_att_control' vector
  5. */
  6. /*************************注意看注释!!********************/
  7. /************输入是角速度设定值向量、油门设定值*************/
  8. /**************************姿态控制值***********************/
  9. void
  10. MulticopterAttitudeControl::control_attitude_rates(float dt)
  11. {
  12. /* reset integral if disarmed */如果锁定,则复位角速度积分
  13. if (!_armed.armed || !_vehicle_status.is_rotary_wing) {
  14. _rates_int.zero();
  15. }
  16. //当前机体角速度设定值//
  17. /由此可知_ctrl_state表示的传感器测得的机体状态
  18. //_ctrl_state来源应该是ardupilot/modules/PX4Firmware/src/modules/attitude_estimator_q/attitude_estimator_q.main.cpp//
  19. /* current body angular rates */
  20. math::Vector<3> rates;
  21. rates(0) = _ctrl_state.roll_rate;
  22. rates(1) = _ctrl_state.pitch_rate;
  23. rates(2) = _ctrl_state.yaw_rate;
  24. 角速度误差=角速度设定值-机体角速度///
  25. /* angular rates error */
  26. math::Vector<3> rates_err = _rates_sp - rates;
  27. /_att_control的三个量分别为pitch、roll、yaw方向的pwm值
  28. /*** _att_control的三个量就是下面的Roll、pitch、yaw
  29. *** Motor1=(int)(COMD.THR + Roll - pitch + yaw);
  30. *** Motor2=(int)(COMD.THR + Roll + pitch - yaw);
  31. *** Motor3=(int)(COMD.THR - Roll + pitch + yaw);
  32. *** Motor4=(int)(COMD.THR - Roll - pitch - yaw);
  33. ***/
  34. _att_control = _params.rate_p.emult(rates_err) + _params.rate_d.emult(_rates_prev - rates) / dt + _rates_int +
  35. _params.rate_ff.emult(_rates_sp - _rates_sp_prev) / dt;
  36. _rates_sp_prev = _rates_sp;
  37. _rates_prev = rates;
  38. //注意这里用的算法pwm=P*error+D*(角速度_last-角速度_now)/dt+角速度积分+(角速度设定值_now-角速度设定值_last)/dt
  39. /*** Matrix<Type, M, N> emult(const Matrix<Type, M, N> &other) const
  40. *** {
  41. *** Matrix<Type, M, N> res;
  42. *** const Matrix<Type, M, N> &self = *this;
  43. ***
  44. *** for (size_t i = 0; i < M; i++) {
  45. *** for (size_t j = 0; j < N; j++) {
  46. *** res(i , j) = self(i, j)*other(i, j);
  47. *** }
  48. *** }
  49. ***
  50. *** return res;
  51. *** }
  52. ***/
  53. /* update integral only if not saturated on low limit and if motor commands are not saturated */
  54. /下面是积分的计算,注意积分饱和问题
  55. if (_thrust_sp > MIN_TAKEOFF_THRUST && !_motor_limits.lower_limit && !_motor_limits.upper_limit) {
  56. for (int i = 0; i < 3; i++) {
  57. if (fabsf(_att_control(i)) < _thrust_sp) {
  58. float rate_i = _rates_int(i) + _params.rate_i(i) * rates_err(i) * dt;
  59. if (PX4_ISFINITE(rate_i) && rate_i > -RATES_I_LIMIT && rate_i < RATES_I_LIMIT &&
  60. _att_control(i) > -RATES_I_LIMIT && _att_control(i) < RATES_I_LIMIT) {
  61. _rates_int(i) = rate_i;
  62. }
  63. }
  64. }
  65. }
  66. }
  1. <pre name="code" class="cpp"> ardupilot/modules/PX4Firmware/src/modules/position_estimator_inav/position_estimator_inav_main.cpp
  2. int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
  3. int actuator_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
  4. int armed_sub = orb_subscribe(ORB_ID(actuator_armed));
  5. int sensor_combined_sub = orb_subscribe(ORB_ID(sensor_combined));
  6. int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
  7. int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
  8. int vehicle_gps_position_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
  9. int vision_position_estimate_sub = orb_subscribe(ORB_ID(vision_position_estimate));
  10. int att_pos_mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
  11. int distance_sensor_sub = orb_subscribe(ORB_ID(distance_sensor));
  12. int vehicle_rate_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
  13. orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
  14. orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);
  15. orb_copy(ORB_ID(parameter_update), parameter_update_sub, &update);
  16. orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_sub, &actuator);//actuator_controls_0
  17. orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);
  18. orb_copy(ORB_ID(distance_sensor), distance_sensor_sub, &lidar);
  19. orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);
  20. orb_copy(ORB_ID(vehicle_rates_setpoint), vehicle_rate_sp_sub, &rates_setpoint);
  21. orb_copy(ORB_ID(vision_position_estimate), vision_position_estimate_sub, &vision);
  22. orb_copy(ORB_ID(att_pos_mocap), att_pos_mocap_sub, &mocap);
  23. orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);
  24. orb_advert_t vehicle_local_position_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
  25. orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
  26. vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
  27. orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
  28. ardupilot/modules/PX4Firmware/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp
  29. _sensors_sub = orb_subscribe(ORB_ID(sensor_combined));
  30. _vision_sub = orb_subscribe(ORB_ID(vision_position_estimate));
  31. _mocap_sub = orb_subscribe(ORB_ID(att_pos_mocap));
  32. _airspeed_sub = orb_subscribe(ORB_ID(airspeed));
  33. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  34. _global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
  35. orb_copy(ORB_ID(sensor_combined), _sensors_sub, &sensors)
  36. orb_copy(ORB_ID(vision_position_estimate), _vision_sub, &_vision);
  37. orb_copy(ORB_ID(att_pos_mocap), _mocap_sub, &_mocap);
  38. orb_copy(ORB_ID(airspeed), _airspeed_sub, &_airspeed);
  39. orb_copy(ORB_ID(vehicle_global_position), _global_pos_sub, &_gpos);
  40. orb_copy(ORB_ID(att_pos_mocap), _mocap_sub, &_mocap);
  41. orb_publish_auto(ORB_ID(vehicle_attitude), &_att_pub, &att, &att_inst, ORB_PRIO_HIGH);
  42. orb_publish_auto(ORB_ID(control_state), &_ctrl_state_pub, &ctrl_state, &ctrl_inst, ORB_PRIO_HIGH);
  43. orb_publish_auto(ORB_ID(estimator_status), &_est_state_pub, &est, &est_inst, ORB_PRIO_HIGH);
  44. ardupilot/modules/PX4Firmware/src/modules/mc_pos_control/mc_pos_control_main.cpp
  45. _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  46. _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
  47. _att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  48. _control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
  49. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  50. _manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
  51. _arming_sub = orb_subscribe(ORB_ID(actuator_armed));
  52. _local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
  53. _pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
  54. _local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
  55. _global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
  56. orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
  57. orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
  58. orb_copy(ORB_ID(vehicle_attitude_setpoint), _att_sp_sub, &_att_sp);
  59. orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode);
  60. orb_copy(ORB_ID(manual_control_setpoint), _manual_sub, &_manual);
  61. orb_copy(ORB_ID(actuator_armed), _arming_sub, &_arming);
  62. orb_copy(ORB_ID(vehicle_local_position), _local_pos_sub, &_local_pos);
  63. orb_copy(ORB_ID(position_setpoint_triplet), _pos_sp_triplet_sub, &_pos_sp_triplet);
  64. orb_publish(_attitude_setpoint_id, _att_sp_pub, &_att_sp);
  65. _att_sp_pub = orb_advertise(_attitude_setpoint_id, &_att_sp);
  66. if (!_attitude_setpoint_id) {
  67. if (_vehicle_status.is_vtol) {
  68. _attitude_setpoint_id = ORB_ID(mc_virtual_attitude_setpoint);
  69. } else {
  70. _attitude_setpoint_id = ORB_ID(vehicle_attitude_setpoint);
  71. }
  72. }
  73. orb_publish(ORB_ID(vehicle_global_velocity_setpoint), _global_vel_sp_pub, &_global_vel_sp);
  74. _global_vel_sp_pub = orb_advertise(ORB_ID(vehicle_global_velocity_setpoint), &_global_vel_sp);
  75. ardupilot/modules/PX4Firmware/src/modules/mc_att_control/mc_att_control_main.cpp
  76. _v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
  77. _v_rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
  78. _ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
  79. _v_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
  80. _params_sub = orb_subscribe(ORB_ID(parameter_update));
  81. _manual_control_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
  82. _armed_sub = orb_subscribe(ORB_ID(actuator_armed));
  83. _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  84. _motor_limits_sub = orb_subscribe(ORB_ID(multirotor_motor_limits));
  85. orb_copy(ORB_ID(vehicle_attitude_setpoint), _v_att_sp_sub, &_v_att_sp);
  86. orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
  87. orb_copy(ORB_ID(parameter_update), _params_sub, ¶m_update);
  88. orb_copy(ORB_ID(vehicle_control_mode), _v_control_mode_sub, &_v_control_mode);
  89. orb_copy(ORB_ID(actuator_armed), _armed_sub, &_armed);
  90. orb_copy(ORB_ID(manual_control_setpoint), _manual_control_sp_sub, &_manual_control_sp);
  91. orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);
  92. if (!_rates_sp_id) {
  93. if (_vehicle_status.is_vtol) {
  94. _rates_sp_id = ORB_ID(mc_virtual_rates_setpoint);
  95. _actuators_id = ORB_ID(actuator_controls_virtual_mc);
  96. } else {
  97. _rates_sp_id = ORB_ID(vehicle_rates_setpoint);
  98. _actuators_id = ORB_ID(actuator_controls_0);
  99. }
  100. }
  101. }
  102. orb_copy(ORB_ID(multirotor_motor_limits), _motor_limits_sub, &_motor_limits);
  103. orb_copy(ORB_ID(vehicle_rates_setpoint), _v_rates_sp_sub, &_v_rates_sp);
  104. orb_publish(_rates_sp_id, _v_rates_sp_pub, &_v_rates_sp);
  105. _v_rates_sp_pub = orb_advertise(_rates_sp_id, &_v_rates_sp);
  106. orb_publish(_actuators_id, _actuators_0_pub, &_actuators);
  107. _actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
  108. orb_publish(ORB_ID(mc_att_ctrl_status), _controller_status_pub, &_controller_status);
  109. _controller_status_pub = orb_advertise(ORB_ID(mc_att_ctrl_status), &_controller_status);
 
  
上图是
姿态估计 Attitude_estimator_q  位置估计 position_estimator_inav  姿态控制 mc_att_control  位置控制 mc_pos_control 
的逻辑图
  1. #ifdef __cplusplus
  2. struct __EXPORT vehicle_local_position_s {
  3. #else
  4. struct vehicle_local_position_s {
  5. #endif
  6. uint64_t timestamp;
  7. bool xy_valid;
  8. bool z_valid;
  9. bool v_xy_valid;
  10. bool v_z_valid;
  11. float x;
  12. float y;
  13. float z;
  14. float vx;
  15. float vy;
  16. float vz;
  17. float yaw;
  18. bool xy_global;
  19. bool z_global;
  20. uint64_t ref_timestamp;
  21. double ref_lat;
  22. double ref_lon;
  23. float ref_alt;
  24. float dist_bottom;
  25. float dist_bottom_rate;
  26. uint64_t surface_bottom_timestamp;
  27. bool dist_bottom_valid;
  28. float eph;
  29. float epv;
  30. #ifdef __cplusplus
  31. #endif
  32. };
  33. #ifdef __cplusplus
  34. struct __EXPORT vehicle_global_position_s {
  35. #else
  36. struct vehicle_global_position_s {
  37. #endif
  38. uint64_t timestamp;
  39. uint64_t time_utc_usec;
  40. double lat;
  41. double lon;
  42. float alt;
  43. float vel_n;
  44. float vel_e;
  45. float vel_d;
  46. float yaw;
  47. float eph;
  48. float epv;
  49. float terrain_alt;
  50. bool terrain_alt_valid;
  51. bool dead_reckoning;
  52. float pressure_alt;
  53. #ifdef __cplusplus
  54. #endif
  55. };
  56. #ifdef __cplusplus
  57. struct __EXPORT vehicle_attitude_s {
  58. #else
  59. struct vehicle_attitude_s {
  60. #endif
  61. uint64_t timestamp;
  62. float roll;
  63. float pitch;
  64. float yaw;
  65. float rollspeed;
  66. float pitchspeed;
  67. float yawspeed;
  68. float rollacc;
  69. float pitchacc;
  70. float yawacc;
  71. float rate_vibration;
  72. float accel_vibration;
  73. float mag_vibration;
  74. float rate_offsets[3];
  75. float R[9];
  76. float q[4];
  77. float g_comp[3];
  78. bool R_valid;
  79. bool q_valid;
  80. #ifdef __cplusplus
  81. #endif
  82. };
  83. #ifdef __cplusplus
  84. struct __EXPORT control_state_s {
  85. #else
  86. struct control_state_s {
  87. #endif
  88. uint64_t timestamp;
  89. float x_acc;
  90. float y_acc;
  91. float z_acc;
  92. float x_vel;
  93. float y_vel;
  94. float z_vel;
  95. float x_pos;
  96. float y_pos;
  97. float z_pos;
  98. float airspeed;
  99. bool airspeed_valid;
  100. float vel_variance[3];
  101. float pos_variance[3];
  102. float q[4];
  103. float roll_rate;
  104. float pitch_rate;
  105. float yaw_rate;
  106. float horz_acc_mag;
  107. #ifdef __cplusplus
  108. #endif
  109. };
  110. #ifdef __cplusplus
  111. struct __EXPORT vehicle_attitude_setpoint_s {
  112. #else
  113. struct vehicle_attitude_setpoint_s {
  114. #endif
  115. uint64_t timestamp;
  116. float roll_body;
  117. float pitch_body;
  118. float yaw_body;
  119. float yaw_sp_move_rate;
  120. float R_body[9];
  121. bool R_valid;
  122. float q_d[4];
  123. bool q_d_valid;
  124. float q_e[4];
  125. bool q_e_valid;
  126. float thrust;
  127. bool roll_reset_integral;
  128. bool pitch_reset_integral;
  129. bool yaw_reset_integral;
  130. bool fw_control_yaw;
  131. bool disable_mc_yaw_control;
  132. bool apply_flaps;
  133. #ifdef __cplusplus
  134. #endif
  135. };
  136. #ifdef __cplusplus
  137. struct __EXPORT vehicle_rates_setpoint_s {
  138. #else
  139. struct vehicle_rates_setpoint_s {
  140. #endif
  141. uint64_t timestamp;
  142. float roll;
  143. float pitch;
  144. float yaw;
  145. float thrust;
  146. #ifdef __cplusplus
  147. #endif
  148. };
  149. #ifdef __cplusplus
  150. struct __EXPORT actuator_controls_0_s {
  151. #else
  152. struct actuator_controls_0_s {
  153. #endif
  154. uint64_t timestamp;
  155. uint64_t timestamp_sample;
  156. float control[8];
  157. #ifdef __cplusplus
  158. static const uint8_t NUM_ACTUATOR_CONTROLS = 8;
  159. static const uint8_t NUM_ACTUATOR_CONTROL_GROUPS = 4;
  160. #endif
  161. };
这是用到的结构体
上述结构还没有包括传感器的数据流,现在还没时间看到每个传感器。
恩,这篇就先到这吧,内容还挺多的。^_^
至于传感器系统、pwm系统,再另外写一篇blog。

如果您觉得此文对您的发展有用,请随意打赏。 
您的鼓励将是笔者书写高质量文章的最大动力^_^!!


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/488870
推荐阅读
相关标签
  

闽ICP备14008679号