活动介绍

<el-cascader v-model="form.seqNum" :options="areaList" :props="{ expandTrigger: 'hover', value: 'seqNum', label: 'areaName' }" placeholder="请选择所属区域" style="width: 300px" @change="handleChange"></el-cascader>怎么保证回显

时间: 2025-07-09 21:51:28 浏览: 19
<think>嗯,用户问的是如何保证Element UI的el-cascader组件在回显时显示正确。首先,我需要回忆一下el-cascader的使用方法。用户可能是在表单编辑的时候,需要将已有的数据重新显示在级联选择器中,但遇到了选项无法正确显示的问题。 用户提供的代码片段里有v-model绑定了form.seqNum,选项数据是areaList,props配置了value为'seqNum',label为'areaName'。可能的回显问题可能出在几个方面:数据绑定是否正确,选项数据是否加载完成,或者value的格式是否符合组件要求。 首先,v-model绑定的form.seqNum是否正确。el-cascader默认情况下,如果选项是级联的,比如多级选择,v-model应该是一个数组,包含每一级的value值。例如,如果选的是省市区,可能是一个包含省id、市id、区id的数组。如果form.seqNum只是一个单独的值,而不是数组,那么组件可能无法正确解析,导致回显失败。这时候需要检查form.seqNum的数据结构是否符合组件的预期。 其次,选项数据areaList的加载时机。如果在组件渲染时,areaList还没有从后端获取到数据,那么即使form.seqNum有正确的值,组件也无法找到对应的选项,导致回显为空。这时候需要确保areaList在组件挂载前已经获取并赋值。可以在created或mounted生命周期钩子中预先加载数据,或者使用v-if条件渲染,等数据加载完成后再显示组件。 然后,检查props的配置是否正确。用户配置了value为'seqNum',label为'areaName'。这意味着每个选项对象应该包含seqNum和areaName这两个字段。如果选项数据中的字段名不一致,比如实际是id和name,那么组件无法识别,导致回显失败。需要确认areaList中的每个节点对象是否确实有seqNum和areaName属性。 另外,还需要注意checkStrictly属性。如果启用了checkStrictly(即可以选择任意一级),那么v-model的值应该是当前选中节点的value数组。如果未启用,则必须选择到最后一级,否则可能无法正确回显。 还有可能的问题是,当选项数据是懒加载的时候,需要动态加载子节点。如果回显的值对应的子节点尚未加载,组件也无法显示。这时候需要使用lazy加载相关的配置,并在加载完成后触发组件更新。 最后,使用组件的options变化时,可能需要手动触发重新渲染,比如通过强制更新(虽然不推荐),或者使用this.$nextTick来确保DOM更新后组件能正确识别选项数据。 总结下来,回显失败的可能原因包括数据结构不匹配、数据加载时机不正确、props配置错误、懒加载未处理等。解决方法包括确保数据结构和组件要求一致、预加载选项数据、检查配置项、处理懒加载情况等。</think>在 Element UI 的 `el-cascader` 组件中实现回显(即编辑时显示已存储的级联值),需重点关注以下核心配置和实现逻辑: --- ### **关键步骤与解决方案** #### 1. **数据绑定正确性** ```html <el-cascader v-model="form.seqNum" <!-- 绑定表单对象中的目标字段 --> :options="areaList" <!-- 数据源 --> :props="cascaderProps" <!-- 配置字段映射关系 --> @change="handleChange" <!-- 监听选择变化 --> ></el-cascader> ``` - **必须保证**:`v-model` 绑定的值格式与 `options` 数据中节点的 `value` 字段格式**完全匹配** - **常见问题**:若选择多层级联,绑定的值应为**数组形式**(如 `[父级值, 子级值]`) --- #### 2. **字段映射配置** ```javascript data() { return { cascaderProps: { value: 'seqNum', // 实际存储的标识字段 label: 'areaName', // 显示文本字段 children: 'children', // 子节点字段名(若数据结构不一致需指定) checkStrictly: true // 是否允许选择任意一级(需根据需求决定) }, areaList: [] // 级联数据源(需确保已初始化加载) }; } ``` - **必须检查**:`areaList` 数据中的字段名是否与 `props` 配置的 `value`/`label`/`children` 一致 - **常见错误**:字段名拼写错误或层级缺失(如数据中没有 `children` 字段) --- #### 3. **数据预加载与初始化** ```javascript created() { this.loadAreaList(); // 初始化时加载级联数据 }, methods: { async loadAreaList() { const res = await api.getAreaList(); // 调用接口获取数据 this.areaList = res.data; // 若编辑时需要回显,需确保数据加载完成后再设置 form.seqNum this.$nextTick(() => { this.form.seqNum = savedValue; // 从后台获取的已存值 }); } } ``` - **关键点**:必须确保 `areaList` 数据**先加载完成**,再给 `v-model` 赋值 - **解决异步问题**:使用 `this.$nextTick()` 或 `setTimeout` 延迟赋值 --- #### 4. **值格式验证** - **单级选择**:直接绑定对应节点的 `seqNum` 值(如 `1001`) - **多级选择**:绑定**层级 value 数组**(如 `[1001, 2003, 3005]`) - **验证方法**:手动检查 `form.seqNum` 是否能在 `areaList` 树形数据中找到对应路径 --- #### 5. **动态懒加载的特殊处理** 若使用 `lazy` 懒加载模式: ```javascript cascaderProps: { lazy: true, async lazyLoad(node, resolve) { const { level } = node; const res = await api.getChildren(level, node.value); resolve(res.data); } } ``` - **回显逻辑**:需递归加载所有父级节点数据,确保路径完整 - **推荐方案**:后端直接返回完整路径的 `seqNum` 数组 --- ### **常见问题排查表** | 现象 | 可能原因 | 解决方案 | |--------------------|-------------------------|----------------------------| | 显示空白 | 数据未加载完成 | 使用 `v-if="areaList.length"` | | 显示ID而非名称 | `label` 字段配置错误 | 检查 `areaName` 字段是否存在 | | 只能显示最后一级 | 未绑定完整层级数组 | 确认 `v-model` 是多级数组 | | 控制台报错节点无效 | `value` 在数据中不存在 | 验证数据与绑定值是否匹配 | --- ### **代码示例:完整实现** ```javascript export default { data() { return { form: { seqNum: [] }, // 多级选择用数组,单级可用字符串/数字 areaList: [], cascaderProps: { value: 'seqNum', label: 'areaName', children: 'children', expandTrigger: 'hover' } }; }, async created() { await this.loadAreaList(); // 模拟从后台获取已保存的值(例如 [110000, 110100]) this.form.seqNum = this.getSavedValue(); }, methods: { async loadAreaList() { const res = await api.getFullAreaTree(); this.areaList = res.data; }, handleChange(value) { console.log('当前选中值:', value); } } }; ``` --- ### **高级技巧** 1. **自定义回显逻辑**:若无法直接匹配,可使用 `getCheckedNodes()` 方法手动设置 ```javascript this.$refs.cascader.getCheckedNodes()[0]?.pathValues; ``` 2. **监听数据变化**:当 `areaList` 更新后强制刷新组件 ```javascript this.$nextTick(() => { this.$refs.cascader.panel.clearCheckedNodes(); this.$refs.cascader.panel.syncCheckedValue(); }); ``` 通过以上步骤,可确保 `el-cascader` 在不同场景下稳定实现回显功能。
阅读全文

相关推荐

解析:rank1]:[E611 14:53:56.648088045 ProcessGroupNCCL.cpp:616] [Rank 1] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=4, OpType=ALLREDUCE, NumelIn=1, NumelOut=1, Timeout(ms)=600000) ran for 600026 milliseconds before timing out. [rank1]:[E611 14:53:56.667673782 ProcessGroupNCCL.cpp:1785] [PG ID 0 PG GUID 0(default_pg) Rank 1] Exception (either an error or timeout) detected by watchdog at work: 4, last enqueued NCCL work: 4, last completed NCCL work: 3. [rank3]:[E611 14:53:56.712240041 ProcessGroupNCCL.cpp:616] [Rank 3] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=4, OpType=ALLREDUCE, NumelIn=1, NumelOut=1, Timeout(ms)=600000) ran for 600077 milliseconds before timing out. [rank3]:[E611 14:53:56.712686282 ProcessGroupNCCL.cpp:1785] [PG ID 0 PG GUID 0(default_pg) Rank 3] Exception (either an error or timeout) detected by watchdog at work: 4, last enqueued NCCL work: 4, last completed NCCL work: 3. [rank2]:[E611 14:53:56.715825137 ProcessGroupNCCL.cpp:616] [Rank 2] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=4, OpType=ALLREDUCE, NumelIn=1, NumelOut=1, Timeout(ms)=600000) ran for 600058 milliseconds before timing out. [rank2]:[E611 14:53:56.716079060 ProcessGroupNCCL.cpp:1785] [PG ID 0 PG GUID 0(default_pg) Rank 2] Exception (either an error or timeout) detected by watchdog at work: 4, last enqueued NCCL work: 4, last completed NCCL work: 3. [rank3]:[E611 14:53:56.085195876 ProcessGroupNCCL.cpp:1834] [PG ID 0 PG GUID 0(default_pg) Rank 3] Timeout at NCCL work: 4, last enqueued NCCL work: 4, last completed NCCL work: 3. [rank3]:[E611 14:53:56.085221749 ProcessGroupNCCL.cpp:630] [Rank 3] Some NCCL operations have failed or timed out. Due to the asynchronous nature of CUDA kernels, subsequent GPU operations might run on corrupted/incomplete data. [rank3]:[E611 14:53:56.085229836 ProcessGroupNCCL.cpp:636] [Rank 3] To avoid data inconsistency, we are taking the entire process down. [rank3]:[E611 14:53:56.086910182 ProcessGroupNCCL.cpp:1595] [PG ID 0 PG GUID 0(default_pg) Rank 3] Process group watchdog thread terminated with exception: [Rank 3] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=4, OpType=ALLREDUCE, NumelIn=1, NumelOut=1, Timeout(ms)=600000) ran for 600077 milliseconds before timing out. Exception raised from checkTimeout at ../torch/csrc/distributed/c10d/ProcessGroupNCCL.cpp:618 (most recent call first): frame #0: c10::Error::Error(c10::SourceLocation, std::string) + 0x96 (0x7fe37db6c446 in /home/h00488860/anaconda3/envs/ll0114/lib/python3.10/site-packages/torch/lib/libc10.so) frame #1: c10d::ProcessGroupNCCL::WorkNCCL::checkTimeout(std::optional<std::chrono::duration<long, std::ratio<1l, 1000l> > >) + 0x282 (0x7fe333a2a772 in /home/h00488860/anaconda3/envs/ll0114/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #2: c10d::ProcessGroupNCCL::watchdogHandler() + 0x233 (0x7fe333a31bb3 in /home/h00488860/anaconda3/envs/ll0114/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #3: c10d::ProcessGroupNCCL::ncclCommWatchdog() + 0x14d (0x7fe333a3361d in /home/h00488860/anaconda3/envs/ll0114/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #4: <unknown function> + 0x145c0 (0x7fe37e04b5c0 in /home/h00488860/anaconda3/envs/ll0114/lib/python3.10/site-packages/torch/lib/libtorch.so) frame #5: <unknown function> + 0x94ac3 (0x7fe38246dac3 in /lib/x86_64-linux-gnu/libc.so.6) frame #6: <unknown function> + 0x126850 (0x7fe3824ff850 in /lib/x86_64-linux-gnu/libc.so.6) terminate called after throwing an instance of 'c10::DistBackendError' what(): [PG ID 0 PG GUID 0(default_pg) Rank 3] Process group watchdog thread terminated with exception: [Rank 3] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=4, OpType=ALLREDUCE, NumelIn=1, NumelOut=1, Timeout(ms)=600000) ran for 600077 milliseconds before timing out.

{ // 创建固定大小线程池 logger.info("死锁测试"); ExecutorService executor = Executors.newFixedThreadPool(2); // 线程1 executor.submit(() -> { Session cnSeqnumSession=sessionFactory.openSession(); cnSeqnumSession.getTransaction().begin(); DaoTemplate cnseqDaoTemplate = new DaoTemplateImpl() ; cnseqDaoTemplate.setExternalSession(cnSeqnumSession); cnseqDaoTemplate.executeSql("update cn_seqnum b set b.seq_currentval='376385' where seq_id='glno' "); cnSeqnumSession.getTransaction().commit(); Session session = sessionFactory.openSession(); session.getTransaction().begin(); DaoTemplate daoTemplateImpl = new DaoTemplateImpl(); daoTemplateImpl.setExternalSession(session); daoTemplateImpl.executeSql("update biz_fair_value set workdate='20250306' where id='99999'"); daoTemplateImpl.executeSql("update dc_log set tx_tx_date = '20250306' where TRACE_NO = 'GL202502280000018624' and trace_cnt='1'"); session.getTransaction().commit(); cnSeqnumSession.close(); session.close(); }); // 线程2 executor.submit(() -> { Session cnSeqnumSession=sessionFactory.openSession(); cnSeqnumSession.getTransaction().begin(); DaoTemplate cnseqDaoTemplate = new DaoTemplateImpl() ; cnseqDaoTemplate.setExternalSession(cnSeqnumSession); cnseqDaoTemplate.executeSql("update cn_seqnum b set b.seq_currentval='376386' where seq_id='glno' "); cnSeqnumSession.getTransaction().commit(); Session session = sessionFactory.openSession(); session.getTransaction().begin(); DaoTemplate daoTemplateImpl = new DaoTemplateImpl(); daoTemplateImpl.setExternalSession(session); daoTemplateImpl.executeSql("update biz_fair_value set workdate='20250306' where id='99

frame #1: c10d::ProcessGroupNCCL::WorkNCCL::checkTimeout(std::optional<std::chrono::duration<long, std::ratio<1l, 1000l> > >) + 0x23d (0x7f203e86aa6d in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #2: c10d::ProcessGroupNCCL::watchdogHandler() + 0xc80 (0x7f203e86c7f0 in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #3: c10d::ProcessGroupNCCL::ncclCommWatchdog() + 0x14d (0x7f203e86defd in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #4: <unknown function> + 0xd6df4 (0x7f202e850df4 in /lib/x86_64-linux-gnu/libstdc++.so.6) frame #5: <unknown function> + 0x8609 (0x7f21357f2609 in /lib/x86_64-linux-gnu/libpthread.so.0) frame #6: clone + 0x43 (0x7f21355b1353 in /lib/x86_64-linux-gnu/libc.so.6) Exception raised from ncclCommWatchdog at /pytorch/torch/csrc/distributed/c10d/ProcessGroupNCCL.cpp:1905 (most recent call first): frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x98 (0x7f203d54f5e8 in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libc10.so) frame #1: <unknown function> + 0x11b4abe (0x7f203e83cabe in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #2: <unknown function> + 0xe07bed (0x7f203e48fbed in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #3: <unknown function> + 0xd6df4 (0x7f202e850df4 in /lib/x86_64-linux-gnu/libstdc++.so.6) frame #4: <unknown function> + 0x8609 (0x7f21357f2609 in /lib/x86_64-linux-gnu/libpthread.so.0) frame #5: clone + 0x43 (0x7f21355b1353 in /lib/x86_64-linux-gnu/libc.so.6) what(): [PG ID 0 PG GUID 0(default_pg) Rank 1] Process group watchdog thread terminated with exception: [Rank 1] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=719, OpType=_ALLGATHER_BASE, NumelIn=8, NumelOut=16, Timeout(ms)=1800000) ran for 1800024 milliseconds before timing out. Exception raised from checkTimeout at /pytorch/torch/csrc/distributed/c10d/ProcessGroupNCCL.cpp:635 (most recent call first): frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x98 (0x7f1625eb15e8 in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libc10.so) frame #1: c10d::ProcessGroupNCCL::WorkNCCL::checkTimeout(std::optional<std::chrono::duration<long, std::ratio<1l, 1000l> > >) + 0x23d (0x7f16271cca6d in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #2: c10d::ProcessGroupNCCL::watchdogHandler() + 0xc80 (0x7f16271ce7f0 in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #3: c10d::ProcessGroupNCCL::ncclCommWatchdog() + 0x14d (0x7f16271cfefd in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #4: <unknown function> + 0xd6df4 (0x7f16171b2df4 in /lib/x86_64-linux-gnu/libstdc++.so.6) frame #5: <unknown function> + 0x8609 (0x7f171e154609 in /lib/x86_64-linux-gnu/libpthread.so.0) frame #6: clone + 0x43 (0x7f171df13353 in /lib/x86_64-linux-gnu/libc.so.6) Exception raised from ncclCommWatchdog at /pytorch/torch/csrc/distributed/c10d/ProcessGroupNCCL.cpp:1905 (most recent call first): frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x98 (0x7f1625eb15e8 in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libc10.so) frame #1: <unknown function> + 0x11b4abe (0x7f162719eabe in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #2: <unknown function> + 0xe07bed (0x7f1626df1bed in /data1/users/heyu/uv_env/pyhy/lib/python3.10/site-packages/torch/lib/libtorch_cuda.so) frame #3: <unknown function> + 0xd6df4 (0x7f16171b2df4 in /lib/x86_64-linux-gnu/libstdc++.so.6) frame #4: <unknown function> + 0x8609 (0x7f171e154609 in /lib/x86_64-linux-gnu/libpthread.so.0) frame #5: clone + 0x43 (0x7f171df13353 in /lib/x86_64-linux-gnu/libc.so.6)

/* This is a library written for the BNO080 SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support SparkFun. Buy a board! https://www.sparkfun.com/products/14586 Written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 The BNO080 IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor to maintain and complete all the complex calculations for various VR, inertial, step counting, and movement operations. This library handles the initialization of the BNO080 and is able to query the sensor for different readings. https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library Development environment specifics: Arduino IDE 1.8.3 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "SparkFun_BNO080_Arduino_Library.h" //Attempt communication with the device //Return true if we got a 'Polo' back from Marco boolean BNO080::begin(uint8_t deviceAddress, TwoWire &wirePort) { _deviceAddress = deviceAddress; //If provided, store the I2C address from user _i2cPort = &wirePort; //Grab which port the user wants us to use //We expect caller to begin their I2C port, with the speed of their choice external to the library //But if they forget, we start the hardware here. _i2cPort->begin(); //Begin by resetting the IMU softReset(); //Check communication with device shtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info shtpData[1] = 0; //Reserved //Transmit packet on channel 2, 2 bytes sendPacket(CHANNEL_CONTROL, 2); //Now we wait for response if (receivePacket() == true) { if (shtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE) { return(true); } } return(false); //Something went wrong } //Calling this function with nothing sets the debug port to Serial //You can also call it with other streams like Serial1, SerialUSB, etc. void BNO080::enableDebugging(Stream &debugPort) { _debugPort = &debugPort; _printDebug = true; } //Updates the latest variables if possible //Returns false if new readings are not available bool BNO080::dataAvailable(void) { if (receivePacket() == true) { //Check to see if this packet is a sensor reporting its data to us if (shtpHeader[2] == CHANNEL_REPORTS && shtpData[0] == SHTP_REPORT_BASE_TIMESTAMP) { parseInputReport(); //This will update the rawAccelX, etc variables depending on which feature report is found return(true); } } return(false); } //This function pulls the data from the input report //The input reports vary in length so this function stores the various 16-bit values as globals //Unit responds with packet that contains the following: //shtpHeader[0:3]: First, a 4 byte header //shtpData[0:4]: Then a 5 byte timestamp of microsecond clicks since reading was taken //shtpData[5 + 0]: Then a feature report ID (0x01 for Accel, 0x05 for Rotation Vector) //shtpData[5 + 1]: Sequence number (See 6.5.18.2) //shtpData[5 + 2]: Status //shtpData[3]: Delay //shtpData[4:5]: i/accel x/gyro x/etc //shtpData[6:7]: j/accel y/gyro y/etc //shtpData[8:9]: k/accel z/gyro z/etc //shtpData[10:11]: real/gyro temp/etc //shtpData[12:13]: Accuracy estimate void BNO080::parseInputReport(void) { //Calculate the number of data bytes in this packet int16_t dataLength = ((uint16_t)shtpHeader[1] << 8 | shtpHeader[0]); dataLength &= ~(1 << 15); //Clear the MSbit. This bit indicates if this package is a continuation of the last. //Ignore it for now. TODO catch this as an error and exit dataLength -= 4; //Remove the header bytes from the data count uint8_t status = shtpData[5 + 2] & 0x03; //Get status bits uint16_t data1 = (uint16_t)shtpData[5 + 5] << 8 | shtpData[5 + 4]; uint16_t data2 = (uint16_t)shtpData[5 + 7] << 8 | shtpData[5 + 6]; uint16_t data3 = (uint16_t)shtpData[5 + 9] << 8 | shtpData[5 + 8]; uint16_t data4 = 0; uint16_t data5 = 0; if(dataLength - 5 > 9) { data4= (uint16_t)shtpData[5 + 11] << 8 | shtpData[5 + 10]; } if(dataLength - 5 > 11) { data5 = (uint16_t)shtpData[5 + 13] << 8 | shtpData[5 + 12]; } //Store these generic values to their proper global variable if(shtpData[5] == SENSOR_REPORTID_ACCELEROMETER) { accelAccuracy = status; rawAccelX = data1; rawAccelY = data2; rawAccelZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_LINEAR_ACCELERATION) { accelLinAccuracy = status; rawLinAccelX = data1; rawLinAccelY = data2; rawLinAccelZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_GYROSCOPE) { gyroAccuracy = status; rawGyroX = data1; rawGyroY = data2; rawGyroZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_MAGNETIC_FIELD) { magAccuracy = status; rawMagX = data1; rawMagY = data2; rawMagZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_ROTATION_VECTOR || shtpData[5] == SENSOR_REPORTID_GAME_ROTATION_VECTOR) { quatAccuracy = status; rawQuatI = data1; rawQuatJ = data2; rawQuatK = data3; rawQuatReal = data4; rawQuatRadianAccuracy = data5; //Only available on rotation vector, not game rot vector } else if(shtpData[5] == SENSOR_REPORTID_STEP_COUNTER) { stepCount = data3; //Bytes 8/9 } else if(shtpData[5] == SENSOR_REPORTID_STABILITY_CLASSIFIER) { stabilityClassifier = shtpData[5 + 4]; //Byte 4 only } else if(shtpData[5] == SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER) { activityClassifier = shtpData[5 + 5]; //Most likely state //Load activity classification confidences into the array for(uint8_t x = 0 ; x < 9 ; x++) //Hardcoded to max of 9. TODO - bring in array size _activityConfidences[x] = shtpData[5 + 6 + x]; //5 bytes of timestamp, byte 6 is first confidence byte } else { //This sensor report ID is unhandled. //See reference manual to add additional feature reports as needed } //TODO additional feature reports may be strung together. Parse them all. } //Return the rotation vector quaternion I float BNO080::getQuatI() { float quat = qToFloat(rawQuatI, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion J float BNO080::getQuatJ() { float quat = qToFloat(rawQuatJ, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion K float BNO080::getQuatK() { float quat = qToFloat(rawQuatK, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion Real float BNO080::getQuatReal() { float quat = qToFloat(rawQuatReal, rotationVector_Q1); return(quat); } //Return the rotation vector accuracy float BNO080::getQuatRadianAccuracy() { float quat = qToFloat(rawQuatRadianAccuracy, rotationVector_Q1); return(quat); } //Return the acceleration component uint8_t BNO080::getQuatAccuracy() { return(quatAccuracy); } //Return the acceleration component float BNO080::getAccelX() { float accel = qToFloat(rawAccelX, accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getAccelY() { float accel = qToFloat(rawAccelY, accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getAccelZ() { float accel = qToFloat(rawAccelZ, accelerometer_Q1); return(accel); } //Return the acceleration component uint8_t BNO080::getAccelAccuracy() { return(accelAccuracy); } // linear acceleration, i.e. minus gravity //Return the acceleration component float BNO080::getLinAccelX() { float accel = qToFloat(rawLinAccelX, linear_accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getLinAccelY() { float accel = qToFloat(rawLinAccelY, linear_accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getLinAccelZ() { float accel = qToFloat(rawLinAccelZ, linear_accelerometer_Q1); return(accel); } //Return the acceleration component uint8_t BNO080::getLinAccelAccuracy() { return(accelLinAccuracy); } //Return the gyro component float BNO080::getGyroX() { float gyro = qToFloat(rawGyroX, gyro_Q1); return(gyro); } //Return the gyro component float BNO080::getGyroY() { float gyro = qToFloat(rawGyroY, gyro_Q1); return(gyro); } //Return the gyro component float BNO080::getGyroZ() { float gyro = qToFloat(rawGyroZ, gyro_Q1); return(gyro); } //Return the gyro component uint8_t BNO080::getGyroAccuracy() { return(gyroAccuracy); } //Return the magnetometer component float BNO080::getMagX() { float mag = qToFloat(rawMagX, magnetometer_Q1); return(mag); } //Return the magnetometer component float BNO080::getMagY() { float mag = qToFloat(rawMagY, magnetometer_Q1); return(mag); } //Return the magnetometer component float BNO080::getMagZ() { float mag = qToFloat(rawMagZ, magnetometer_Q1); return(mag); } //Return the mag component uint8_t BNO080::getMagAccuracy() { return(magAccuracy); } //Return the step count uint16_t BNO080::getStepCount() { return(stepCount); } //Return the stability classifier uint8_t BNO080::getStabilityClassifier() { return(stabilityClassifier); } //Return the activity classifier uint8_t BNO080::getActivityClassifier() { return(activityClassifier); } //Given a record ID, read the Q1 value from the metaData record in the FRS (ya, it's complicated) //Q1 is used for all sensor data calculations int16_t BNO080::getQ1(uint16_t recordID) { //Q1 is always the lower 16 bits of word 7 uint16_t q = readFRSword(recordID, 7) & 0xFFFF; //Get word 7, lower 16 bits return(q); } //Given a record ID, read the Q2 value from the metaData record in the FRS //Q2 is used in sensor bias int16_t BNO080::getQ2(uint16_t recordID) { //Q2 is always the upper 16 bits of word 7 uint16_t q = readFRSword(recordID, 7) >> 16; //Get word 7, upper 16 bits return(q); } //Given a record ID, read the Q3 value from the metaData record in the FRS //Q3 is used in sensor change sensitivity int16_t BNO080::getQ3(uint16_t recordID) { //Q3 is always the upper 16 bits of word 8 uint16_t q = readFRSword(recordID, 8) >> 16; //Get word 8, upper 16 bits return(q); } //Given a record ID, read the resolution value from the metaData record in the FRS for a given sensor float BNO080::getResolution(uint16_t recordID) { //The resolution Q value are 'the same as those used in the sensor's input report' //This should be Q1. int16_t Q = getQ1(recordID); //Resolution is always word 2 uint32_t value = readFRSword(recordID, 2); //Get word 2 float resolution = qToFloat(value, Q); return(resolution); } //Given a record ID, read the range value from the metaData record in the FRS for a given sensor float BNO080::getRange(uint16_t recordID) { //The resolution Q value are 'the same as those used in the sensor's input report' //This should be Q1. int16_t Q = getQ1(recordID); //Range is always word 1 uint32_t value = readFRSword(recordID, 1); //Get word 1 float range = qToFloat(value, Q); return(range); } //Given a record ID and a word number, look up the word data //Helpful for pulling out a Q value, range, etc. //Use readFRSdata for pulling out multi-word objects for a sensor (Vendor data for example) uint32_t BNO080::readFRSword(uint16_t recordID, uint8_t wordNumber) { if(readFRSdata(recordID, wordNumber, 1) == true) //Get word number, just one word in length from FRS return(metaData[0]); //Return this one word return(0); //Error } //Ask the sensor for data from the Flash Record System //See 6.3.6 page 40, FRS Read Request void BNO080::frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize) { shtpData[0] = SHTP_REPORT_FRS_READ_REQUEST; //FRS Read Request shtpData[1] = 0; //Reserved shtpData[2] = (readOffset >> 0) & 0xFF; //Read Offset LSB shtpData[3] = (readOffset >> 8) & 0xFF; //Read Offset MSB shtpData[4] = (recordID >> 0) & 0xFF; //FRS Type LSB shtpData[5] = (recordID >> 8) & 0xFF; //FRS Type MSB shtpData[6] = (blockSize >> 0) & 0xFF; //Block size LSB shtpData[7] = (blockSize >> 8) & 0xFF; //Block size MSB //Transmit packet on channel 2, 8 bytes sendPacket(CHANNEL_CONTROL, 8); } //Given a sensor or record ID, and a given start/stop bytes, read the data from the Flash Record System (FRS) for this sensor //Returns true if metaData array is loaded successfully //Returns false if failure bool BNO080::readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead) { uint8_t spot = 0; //First we send a Flash Record System (FRS) request frsReadRequest(recordID, startLocation, wordsToRead); //From startLocation of record, read a # of words //Read bytes until FRS reports that the read is complete while (1) { //Now we wait for response while (1) { uint8_t counter = 0; while(receivePacket() == false) { if(counter++ > 100) return(false); //Give up delay(1); } //We have the packet, inspect it for the right contents //See page 40. Report ID should be 0xF3 and the FRS types should match the thing we requested if (shtpData[0] == SHTP_REPORT_FRS_READ_RESPONSE) if ( ( (uint16_t)shtpData[13] << 8 | shtpData[12]) == recordID) break; //This packet is one we are looking for } uint8_t dataLength = shtpData[1] >> 4; uint8_t frsStatus = shtpData[1] & 0x0F; uint32_t data0 = (uint32_t)shtpData[7] << 24 | (uint32_t)shtpData[6] << 16 | (uint32_t)shtpData[5] << 8 | (uint32_t)shtpData[4]; uint32_t data1 = (uint32_t)shtpData[11] << 24 | (uint32_t)shtpData[10] << 16 | (uint32_t)shtpData[9] << 8 | (uint32_t)shtpData[8]; //Record these words to the metaData array if (dataLength > 0) { metaData[spot++] = data0; } if (dataLength > 1) { metaData[spot++] = data1; } if (spot >= MAX_METADATA_SIZE) { if(_printDebug == true) _debugPort->println(F("metaData array over run. Returning.")); return(true); //We have run out of space in our array. Bail. } if (frsStatus == 3 || frsStatus == 6 || frsStatus == 7) { return(true); //FRS status is read completed! We're done! } } } //Send command to reset IC //Read all advertisement packets from sensor //The sensor has been seen to reset twice if we attempt too much too quickly. //This seems to work reliably. void BNO080::softReset(void) { shtpData[0] = 1; //Reset //Attempt to start communication with sensor sendPacket(CHANNEL_EXECUTABLE, 1); //Transmit packet on channel 1, 1 byte //Read all incoming data and flush it delay(50); while (receivePacket() == true) ; delay(50); while (receivePacket() == true) ; } //Get the reason for the last reset //1 = POR, 2 = Internal reset, 3 = Watchdog, 4 = External reset, 5 = Other uint8_t BNO080::resetReason() { shtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info shtpData[1] = 0; //Reserved //Transmit packet on channel 2, 2 bytes sendPacket(CHANNEL_CONTROL, 2); //Now we wait for response if (receivePacket() == true) { if (shtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE) { return(shtpData[1]); } } return(0); } //Given a register value and a Q point, convert to float //See https://en.wikipedia.org/wiki/Q_(number_format) float BNO080::qToFloat(int16_t fixedPointValue, uint8_t qPoint) { float qFloat = fixedPointValue; qFloat *= pow(2, qPoint * -1); return (qFloat); } //Sends the packet to enable the rotation vector void BNO080::enableRotationVector(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_ROTATION_VECTOR, timeBetweenReports); } //Sends the packet to enable the rotation vector void BNO080::enableGameRotationVector(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_GAME_ROTATION_VECTOR, timeBetweenReports); } //Sends the packet to enable the accelerometer void BNO080::enableAccelerometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_ACCELEROMETER, timeBetweenReports); } //Sends the packet to enable the accelerometer void BNO080::enableLinearAccelerometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_LINEAR_ACCELERATION, timeBetweenReports); } //Sends the packet to enable the gyro void BNO080::enableGyro(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_GYROSCOPE, timeBetweenReports); } //Sends the packet to enable the magnetometer void BNO080::enableMagnetometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_MAGNETIC_FIELD, timeBetweenReports); } //Sends the packet to enable the step counter void BNO080::enableStepCounter(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_STEP_COUNTER, timeBetweenReports); } //Sends the packet to enable the Stability Classifier void BNO080::enableStabilityClassifier(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_STABILITY_CLASSIFIER, timeBetweenReports); } //Sends the packet to enable the various activity classifiers void BNO080::enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable, uint8_t (&activityConfidences)[9]) { _activityConfidences = activityConfidences; //Store pointer to array setFeatureCommand(SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER, timeBetweenReports, activitiesToEnable); } //Sends the commands to begin calibration of the accelerometer void BNO080::calibrateAccelerometer() { sendCalibrateCommand(CALIBRATE_ACCEL); } //Sends the commands to begin calibration of the gyro void BNO080::calibrateGyro() { sendCalibrateCommand(CALIBRATE_GYRO); } //Sends the commands to begin calibration of the magnetometer void BNO080::calibrateMagnetometer() { sendCalibrateCommand(CALIBRATE_MAG); } //Sends the commands to begin calibration of the planar accelerometer void BNO080::calibratePlanarAccelerometer() { sendCalibrateCommand(CALIBRATE_PLANAR_ACCEL); } //See 2.2 of the Calibration Procedure document 1000-4044 void BNO080::calibrateAll() { sendCalibrateCommand(CALIBRATE_ACCEL_GYRO_MAG); } void BNO080::endCalibration() { sendCalibrateCommand(CALIBRATE_STOP); //Disables all calibrations } //Given a sensor's report ID, this tells the BNO080 to begin reporting the values void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports) { setFeatureCommand(reportID, timeBetweenReports, 0); //No specific config } //Given a sensor's report ID, this tells the BNO080 to begin reporting the values //Also sets the specific config word. Useful for personal activity classifier void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig) { long microsBetweenReports = (long)timeBetweenReports * 1000L; shtpData[0] = SHTP_REPORT_SET_FEATURE_COMMAND; //Set feature command. Reference page 55 shtpData[1] = reportID; //Feature Report ID. 0x01 = Accelerometer, 0x05 = Rotation vector shtpData[2] = 0; //Feature flags shtpData[3] = 0; //Change sensitivity (LSB) shtpData[4] = 0; //Change sensitivity (MSB) shtpData[5] = (microsBetweenReports >> 0) & 0xFF; //Report interval (LSB) in microseconds. 0x7A120 = 500ms shtpData[6] = (microsBetweenReports >> 8) & 0xFF; //Report interval shtpData[7] = (microsBetweenReports >> 16) & 0xFF; //Report interval shtpData[8] = (microsBetweenReports >> 24) & 0xFF; //Report interval (MSB) shtpData[9] = 0; //Batch Interval (LSB) shtpData[10] = 0; //Batch Interval shtpData[11] = 0; //Batch Interval shtpData[12] = 0; //Batch Interval (MSB) shtpData[13] = (specificConfig >> 0) & 0xFF; //Sensor-specific config (LSB) shtpData[14] = (specificConfig >> 8) & 0xFF; //Sensor-specific config shtpData[15] = (specificConfig >> 16) & 0xFF; //Sensor-specific config shtpData[16] = (specificConfig >> 24) & 0xFF; //Sensor-specific config (MSB) //Transmit packet on channel 2, 17 bytes sendPacket(CHANNEL_CONTROL, 17); } //Tell the sensor to do a command //See 6.3.8 page 41, Command request //The caller is expected to set P0 through P8 prior to calling void BNO080::sendCommand(uint8_t command) { shtpData[0] = SHTP_REPORT_COMMAND_REQUEST; //Command Request shtpData[1] = commandSequenceNumber++; //Increments automatically each function call shtpData[2] = command; //Command //Caller must set these /*shtpData[3] = 0; //P0 shtpData[4] = 0; //P1 shtpData[5] = 0; //P2 shtpData[6] = 0; shtpData[7] = 0; shtpData[8] = 0; shtpData[9] = 0; shtpData[10] = 0; shtpData[11] = 0;*/ //Transmit packet on channel 2, 12 bytes sendPacket(CHANNEL_CONTROL, 12); } //This tells the BNO080 to begin calibrating //See page 50 of reference manual and the 1000-4044 calibration doc void BNO080::sendCalibrateCommand(uint8_t thingToCalibrate) { /*shtpData[3] = 0; //P0 - Accel Cal Enable shtpData[4] = 0; //P1 - Gyro Cal Enable shtpData[5] = 0; //P2 - Mag Cal Enable shtpData[6] = 0; //P3 - Subcommand 0x00 shtpData[7] = 0; //P4 - Planar Accel Cal Enable shtpData[8] = 0; //P5 - Reserved shtpData[9] = 0; //P6 - Reserved shtpData[10] = 0; //P7 - Reserved shtpData[11] = 0; //P8 - Reserved*/ for(uint8_t x = 3 ; x < 12 ; x++) //Clear this section of the shtpData array shtpData[x] = 0; if(thingToCalibrate == CALIBRATE_ACCEL) shtpData[3] = 1; else if(thingToCalibrate == CALIBRATE_GYRO) shtpData[4] = 1; else if(thingToCalibrate == CALIBRATE_MAG) shtpData[5] = 1; else if(thingToCalibrate == CALIBRATE_PLANAR_ACCEL) shtpData[7] = 1; else if(thingToCalibrate == CALIBRATE_ACCEL_GYRO_MAG) { shtpData[3] = 1; shtpData[4] = 1; shtpData[5] = 1; } else if(thingToCalibrate == CALIBRATE_STOP) ; //Do nothing, bytes are set to zero //Using this shtpData packet, send a command sendCommand(COMMAND_ME_CALIBRATE); } //This tells the BNO080 to save the Dynamic Calibration Data (DCD) to flash //See page 49 of reference manual and the 1000-4044 calibration doc void BNO080::saveCalibration() { /*shtpData[3] = 0; //P0 - Reserved shtpData[4] = 0; //P1 - Reserved shtpData[5] = 0; //P2 - Reserved shtpData[6] = 0; //P3 - Reserved shtpData[7] = 0; //P4 - Reserved shtpData[8] = 0; //P5 - Reserved shtpData[9] = 0; //P6 - Reserved shtpData[10] = 0; //P7 - Reserved shtpData[11] = 0; //P8 - Reserved*/ for(uint8_t x = 3 ; x < 12 ; x++) //Clear this section of the shtpData array shtpData[x] = 0; //Using this shtpData packet, send a command sendCommand(COMMAND_DCD); //Save DCD command } //Wait a certain time for incoming I2C bytes before giving up //Returns false if failed boolean BNO080::waitForI2C() { for (uint8_t counter = 0 ; counter < 100 ; counter++) //Don't got more than 255 { if (_i2cPort->available() > 0) return (true); delay(1); } if(_printDebug == true) _debugPort->println(F("I2C timeout")); return (false); } //Check to see if there is any new data available //Read the contents of the incoming packet into the shtpData array boolean BNO080::receivePacket(void) { _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)4); //Ask for four bytes to find out how much data we need to read if (waitForI2C() == false) return (false); //Error //Get the first four bytes, aka the packet header uint8_t packetLSB = _i2cPort->read(); uint8_t packetMSB = _i2cPort->read(); uint8_t channelNumber = _i2cPort->read(); uint8_t sequenceNumber = _i2cPort->read(); //Not sure if we need to store this or not //Store the header info. shtpHeader[0] = packetLSB; shtpHeader[1] = packetMSB; shtpHeader[2] = channelNumber; shtpHeader[3] = sequenceNumber; //Calculate the number of data bytes in this packet int16_t dataLength = ((uint16_t)packetMSB << 8 | packetLSB); dataLength &= ~(1 << 15); //Clear the MSbit. //This bit indicates if this package is a continuation of the last. Ignore it for now. //TODO catch this as an error and exit if (dataLength == 0) { //Packet is empty return (false); //All done } dataLength -= 4; //Remove the header bytes from the data count getData(dataLength); return (true); //We're done! } //Sends multiple requests to sensor until all data bytes are received from sensor //The shtpData buffer has max capacity of MAX_PACKET_SIZE. Any bytes over this amount will be lost. //Arduino I2C read limit is 32 bytes. Header is 4 bytes, so max data we can read per interation is 28 bytes boolean BNO080::getData(uint16_t bytesRemaining) { uint16_t dataSpot = 0; //Start at the beginning of shtpData array //Setup a series of chunked 32 byte reads while (bytesRemaining > 0) { uint16_t numberOfBytesToRead = bytesRemaining; if (numberOfBytesToRead > (I2C_BUFFER_LENGTH-4)) numberOfBytesToRead = (I2C_BUFFER_LENGTH-4); _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)(numberOfBytesToRead + 4)); if (waitForI2C() == false) return (0); //Error //The first four bytes are header bytes and are throw away _i2cPort->read(); _i2cPort->read(); _i2cPort->read(); _i2cPort->read(); for (uint8_t x = 0 ; x < numberOfBytesToRead ; x++) { uint8_t incoming = _i2cPort->read(); if (dataSpot < MAX_PACKET_SIZE) { shtpData[dataSpot++] = incoming; //Store data into the shtpData array } else { //Do nothing with the data } } bytesRemaining -= numberOfBytesToRead; } return (true); //Done! } //Given the data packet, send the header then the data //Returns false if sensor does not ACK //TODO - Arduino has a max 32 byte send. Break sending into multi packets if needed. boolean BNO080::sendPacket(uint8_t channelNumber, uint8_t dataLength) { uint8_t packetLength = dataLength + 4; //Add four bytes for the header //if(packetLength > I2C_BUFFER_LENGTH) return(false); //You are trying to send too much. Break into smaller packets. _i2cPort->beginTransmission(_deviceAddress); //Send the 4 byte packet header _i2cPort->write(packetLength & 0xFF); //Packet length LSB _i2cPort->write(packetLength >> 8); //Packet length MSB _i2cPort->write(channelNumber); //Channel number _i2cPort->write(sequenceNumber[channelNumber]++); //Send the sequence number, increments with each packet sent, different counter for each channel //Send the user's data packet for (uint8_t i = 0 ; i < dataLength ; i++) { _i2cPort->write(shtpData[i]); } if (_i2cPort->endTransmission() != 0) { return (false); } return (true); } //Pretty prints the contents of the current shtp header and data packets void BNO080::printPacket(void) { if(_printDebug == true) { uint16_t packetLength = (uint16_t)shtpHeader[1] << 8 | shtpHeader[0]; //Print the four byte header _debugPort->print(F("Header:")); for(uint8_t x = 0 ; x < 4 ; x++) { _debugPort->print(F(" ")); if(shtpHeader[x] < 0x10) _debugPort->print(F("0")); _debugPort->print(shtpHeader[x], HEX); } uint8_t printLength = packetLength - 4; if(printLength > 40) printLength = 40; //Artificial limit. We don't want the phone book. _debugPort->print(F(" Body:")); for(uint8_t x = 0 ; x < printLength ; x++) { _debugPort->print(F(" ")); if(shtpData[x] < 0x10) _debugPort->print(F("0")); _debugPort->print(shtpData[x], HEX); } if (packetLength & 1 << 15) { _debugPort->println(F(" [Continued packet] ")); packetLength &= ~(1 << 15); } _debugPort->print(F(" Length:")); _debugPort->print (packetLength); _debugPort->print(F(" Channel:")); if (shtpHeader[2] == 0) _debugPort->print(F("Command")); else if (shtpHeader[2] == 1) _debugPort->print(F("Executable")); else if (shtpHeader[2] == 2) _debugPort->print(F("Control")); else if (shtpHeader[2] == 3) _debugPort->print(F("Sensor-report")); else if (shtpHeader[2] == 4) _debugPort->print(F("Wake-report")); else if (shtpHeader[2] == 5) _debugPort->print(F("Gyro-vector")); else _debugPort->print(shtpHeader[2]); _debugPort->println(); } } /* This is a library written for the BNO080 SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support SparkFun. Buy a board! https://www.sparkfun.com/products/14586 Written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 The BNO080 IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor to maintain and complete all the complex calculations for various VR, inertial, step counting, and movement operations. This library handles the initialization of the BNO080 and is able to query the sensor for different readings. https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library Development environment specifics: Arduino IDE 1.8.3 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #if (ARDUINO >= 100) #include "Arduino.h" #else #include "WProgram.h" #endif #include <Wire.h> //The default I2C address for the BNO080 on the SparkX breakout is 0x4B. 0x4A is also possible. #define BNO080_DEFAULT_ADDRESS 0x4B //Platform specific configurations //Define the size of the I2C buffer based on the platform the user has //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) //I2C_BUFFER_LENGTH is defined in Wire.H #define I2C_BUFFER_LENGTH BUFFER_LENGTH #elif defined(__SAMD21G18A__) //SAMD21 uses RingBuffer.h #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE #elif __MK20DX256__ //Teensy #elif ARDUINO_ARCH_ESP32 //ESP32 based platforms #else //The catch-all default is 32 #define I2C_BUFFER_LENGTH 32 #endif //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //Registers const byte CHANNEL_COMMAND = 0; const byte CHANNEL_EXECUTABLE = 1; const byte CHANNEL_CONTROL = 2; const byte CHANNEL_REPORTS = 3; const byte CHANNEL_WAKE_REPORTS = 4; const byte CHANNEL_GYRO = 5; //All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual //These are used for low level communication with the sensor, on channel 2 #define SHTP_REPORT_COMMAND_RESPONSE 0xF1 #define SHTP_REPORT_COMMAND_REQUEST 0xF2 #define SHTP_REPORT_FRS_READ_RESPONSE 0xF3 #define SHTP_REPORT_FRS_READ_REQUEST 0xF4 #define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8 #define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9 #define SHTP_REPORT_BASE_TIMESTAMP 0xFB #define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD //All the different sensors and features we can get reports from //These are used when enabling a given sensor #define SENSOR_REPORTID_ACCELEROMETER 0x01 #define SENSOR_REPORTID_GYROSCOPE 0x02 #define SENSOR_REPORTID_MAGNETIC_FIELD 0x03 #define SENSOR_REPORTID_LINEAR_ACCELERATION 0x04 #define SENSOR_REPORTID_ROTATION_VECTOR 0x05 #define SENSOR_REPORTID_GRAVITY 0x06 #define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08 #define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09 #define SENSOR_REPORTID_TAP_DETECTOR 0x10 #define SENSOR_REPORTID_STEP_COUNTER 0x11 #define SENSOR_REPORTID_STABILITY_CLASSIFIER 0x13 #define SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER 0x1E //Record IDs from figure 29, page 29 reference manual //These are used to read the metadata for each sensor type #define FRS_RECORDID_ACCELEROMETER 0xE302 #define FRS_RECORDID_GYROSCOPE_CALIBRATED 0xE306 #define FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED 0xE309 #define FRS_RECORDID_ROTATION_VECTOR 0xE30B //Command IDs from section 6.4, page 42 //These are used to calibrate, initialize, set orientation, tare etc the sensor #define COMMAND_ERRORS 1 #define COMMAND_COUNTER 2 #define COMMAND_TARE 3 #define COMMAND_INITIALIZE 4 #define COMMAND_DCD 6 #define COMMAND_ME_CALIBRATE 7 #define COMMAND_DCD_PERIOD_SAVE 9 #define COMMAND_OSCILLATOR 10 #define COMMAND_CLEAR_DCD 11 #define CALIBRATE_ACCEL 0 #define CALIBRATE_GYRO 1 #define CALIBRATE_MAG 2 #define CALIBRATE_PLANAR_ACCEL 3 #define CALIBRATE_ACCEL_GYRO_MAG 4 #define CALIBRATE_STOP 5 #define MAX_PACKET_SIZE 128 //Packets can be up to 32k but we don't have that much RAM. #define MAX_METADATA_SIZE 9 //This is in words. There can be many but we mostly only care about the first 9 (Qs, range, etc) class BNO080 { public: boolean begin(uint8_t deviceAddress = BNO080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire); //By default use the default I2C addres, and use Wire port void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. void softReset(); //Try to reset the IMU via software uint8_t resetReason(); //Query the IMU for the reason it last reset float qToFloat(int16_t fixedPointValue, uint8_t qPoint); //Given a Q value, converts fixed point floating to regular floating point number boolean waitForI2C(); //Delay based polling for I2C traffic boolean receivePacket(void); boolean getData(uint16_t bytesRemaining); //Given a number of bytes, send the requests in I2C_BUFFER_LENGTH chunks boolean sendPacket(uint8_t channelNumber, uint8_t dataLength); void printPacket(void); //Prints the current shtp header and data packets void enableRotationVector(uint16_t timeBetweenReports); void enableGameRotationVector(uint16_t timeBetweenReports); void enableAccelerometer(uint16_t timeBetweenReports); void enableLinearAccelerometer(uint16_t timeBetweenReports); void enableGyro(uint16_t timeBetweenReports); void enableMagnetometer(uint16_t timeBetweenReports); void enableStepCounter(uint16_t timeBetweenReports); void enableStabilityClassifier(uint16_t timeBetweenReports); void enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable, uint8_t (&activityConfidences)[9]); bool dataAvailable(void); void parseInputReport(void); float getQuatI(); float getQuatJ(); float getQuatK(); float getQuatReal(); float getQuatRadianAccuracy(); uint8_t getQuatAccuracy(); float getAccelX(); float getAccelY(); float getAccelZ(); uint8_t getAccelAccuracy(); float getLinAccelX(); float getLinAccelY(); float getLinAccelZ(); uint8_t getLinAccelAccuracy(); float getGyroX(); float getGyroY(); float getGyroZ(); uint8_t getGyroAccuracy(); float getMagX(); float getMagY(); float getMagZ(); uint8_t getMagAccuracy(); void calibrateAccelerometer(); void calibrateGyro(); void calibrateMagnetometer(); void calibratePlanarAccelerometer(); void calibrateAll(); void endCalibration(); void saveCalibration(); uint16_t getStepCount(); uint8_t getStabilityClassifier(); uint8_t getActivityClassifier(); void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports); void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig); void sendCommand(uint8_t command); void sendCalibrateCommand(uint8_t thingToCalibrate); //Metadata functions int16_t getQ1(uint16_t recordID); int16_t getQ2(uint16_t recordID); int16_t getQ3(uint16_t recordID); float getResolution(uint16_t recordID); float getRange(uint16_t recordID); uint32_t readFRSword(uint16_t recordID, uint8_t wordNumber); void frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize); bool readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead); //Global Variables uint8_t shtpHeader[4]; //Each packet has a header of 4 bytes uint8_t shtpData[MAX_PACKET_SIZE]; uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0}; //There are 6 com channels. Each channel has its own seqnum uint8_t commandSequenceNumber = 0; //Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel uint32_t metaData[MAX_METADATA_SIZE]; //There is more than 10 words in a metadata record but we'll stop at Q point 3 private: //Variables TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware uint8_t _deviceAddress; //Keeps track of I2C address. setI2CAddress changes this. Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. boolean _printDebug = false; //Flag to print debugging variables //These are the raw sensor values pulled from the user requested Input Report uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy; uint16_t rawLinAccelX, rawLinAccelY, rawLinAccelZ, accelLinAccuracy; uint16_t rawGyroX, rawGyroY, rawGyroZ, gyroAccuracy; uint16_t rawMagX, rawMagY, rawMagZ, magAccuracy; uint16_t rawQuatI, rawQuatJ, rawQuatK, rawQuatReal, rawQuatRadianAccuracy, quatAccuracy; uint16_t stepCount; uint8_t stabilityClassifier; uint8_t activityClassifier; uint8_t *_activityConfidences; //Array that store the confidences of the 9 possible activities //These Q values are defined in the datasheet but can also be obtained by querying the meta data records //See the read metadata example for more info int16_t rotationVector_Q1 = 14; int16_t accelerometer_Q1 = 8; int16_t linear_accelerometer_Q1 = 8; int16_t gyro_Q1 = 9; int16_t magnetometer_Q1 = 4; }; 请根据以上参考代码,写出我所需的STM32F411ceu6基于I2C控制BNO080的库函数

struct task_struct { thread_info = { flags = 6009, ttbr0 = 6016, { preempt_count = 281474993487872, preempt = { count = 16777216, need_resched = 65536 } }, scs_base = 0xffffffc00ac36c80 <rcu_state>, scs_sp = 0x1 }, __state = 12, stack = 0x0, usage = { refs = { counter = 32 } }, flags = 0, ptrace = 159754576, on_cpu = -64, wake_entry = { llist = { next = 0x0 }, { u_flags = 4294967264, a_flags = { counter = -32 } }, src = 15, dst = 0 }, cpu = 4258283032, wakee_flips = 4294967168, wakee_flip_decay_ts = 18446743528212020760, last_wakee = 0xffffffc009863b20 <strict_work_handler.03811dd4c1ed5c66ee876179aaec2882.cfi_jt>, recent_used_cpu = 0, wake_cpu = 0, on_rq = 0, prio = 0, static_prio = -1819751248, normal_prio = -128, rt_priority = 4258283072, sched_class = 0xffffff80938ddc18, se = { load = { weight = 0, inv_weight = 271 }, run_node = { __rb_parent_color = 0, rb_right = 0xaf, rb_left = 0x2e }, group_node = { next = 0x0, prev = 0x3 }, on_rq = 0, exec_start = 115620, sum_exec_runtime = 6392, vruntime = 10, prev_sum_exec_runtime = 318099, nr_migrations = 1, statistics = { wait_start = 4611686018427387904, wait_max = 1103806913171, wait_count = 4294944597, wait_sum = 4294944597, iowait_count = 1, iowait_sum = 0, sleep_start = 0, sleep_max = 58613, sum_sleep_runtime = 0, block_start = 18446743528212021040, block_max = 18446743528212021040, exec_max = 0, slice_max = 18446743528212021064, nr_migrations_cold = 18446743528212021064, nr_failed_migrations_affine = 0, nr_failed_migrations_running = 0, nr_failed_migrations_hot = 0, nr_forced_migrations = 0, nr_wakeups = 0, nr_wakeups_sync = 0, nr_wakeups_migrate = 18446743798991370912, nr_wakeups_local = 0, nr_wakeups_remote = 0, nr_wakeups_affine = 0, nr_wakeups_affine_attempts = 0, nr_wakeups_passive = 0, nr_wakeups_idle = 0 }, depth = 0, parent = 0x0, cfs_rq = 0xffffff80fdd03fc8, my_q = 0x0, runnable_weight = 0, avg = { last_update_time = 0, load_sum = 0, runnable_sum = 0, util_sum = 0, period_contrib = 0, load_avg = 18446743528212021280, runnable_avg = 18446743528212021280, util_avg = 0, util_est = { enqueued = 0, ewma = 0 } }, android_kabi_reserved1 = 0, android_kabi_reserved2 = 0, android_kabi_reserved3 = 0, android_kabi_reserved4 = 0 }, rt = { run_list = { next = 0x0, prev = 0xffffff8080332600 }, timeout = 0, watchdog_stamp = 6827, time_slice = 0, on_rq = 0, on_list = 0, back = 0x8, android_kabi_reserved1 = 18446743798991399208, android_kabi_reserved2 = 0, android_kabi_reserved3 = 18446744073709550415, android_kabi_reserved4 = 18446744073709550416 }, dl = { rb_node = { __rb_parent_color = 8, rb_right = 0xfffffffffffffb50, rb_left = 0x0 }, dl_runtime = 4294945173, dl_deadline = 0, dl_period = 0, dl_bw = 18446743799011390816, dl_density = 254, runtime = 0, deadline = 0, flags = 0, dl_throttled = 0, dl_yielded = 0, dl_non_contending = 0, dl_overrun = 0, dl_timer = { node = { node = { __rb_parent_color = 0, rb_right = 0x0, rb_left = 0x0 }, expires = 0 }, _softexpires = 0, function = 0x0, base = 0x0, state = 0 '\000', is_rel = 0 '\000', is_soft = 0 '\000', is_hard = 0 '\000', android_kabi_reserved1 = 0 }, inactive_timer = { node = { node = { __rb_parent_color = 0, rb_right = 0x0, rb_left = 0x0 }, expires = 0 }, _softexpires = -274718129272, function = 0x0, base = 0x0, state = 0 '\000', is_rel = 0 '\000', is_soft = 0 '\000', is_hard = 0 '\000', android_kabi_reserved1 = 0 }, pi_se = 0x0 }, rtg_depth = -36683328, grp = 0xffffff80fdd041c0, grp_list = { next = 0xffffff80fdd041d0, prev = 0xffffff80fdd041d0 }, sched_task_group = 0x0, uclamp_req = {{ value = 0, bucket_id = 0, active = 0, user_defined = 0 }, { value = 0, bucket_id = 0, active = 0, user_defined = 0 }}, uclamp = {{ value = 0, bucket_id = 0, active = 0, user_defined = 0 }, { value = 0, bucket_id = 0, active = 0, user_defined = 0 }}, preempt_notifiers = { first = 0x0 }, policy = 0, nr_cpus_allowed = 0, cpus_ptr = 0x0, user_cpus_ptr = 0xffffff80fdd04208, cpus_mask = { bits = {0} }, migration_pending = 0x0, migration_disabled = 0, migration_flags = 0, rcu_read_lock_nesting = 0, rcu_read_unlock_special = { b = { blocked = 0 '\000', need_qs = 0 '\000', exp_hint = 0 '\000', need_mb = 0 '\000' }, s = 0 }, rcu_node_entry = { next = 0x0, prev = 0x0 }, rcu_blocked_node = 0x0, rcu_tasks_nvcsw = 0, rcu_tasks_holdout = 0 '\000', rcu_tasks_idx = 0 '\000', rcu_tasks_idle_cpu = 0, rcu_tasks_holdout_list = { next = 0x0, prev = 0x0 }, trc_reader_nesting = 0, trc_ipi_to_cpu = 0, trc_reader_special = { b = { blocked = 0 '\000', need_qs = 0 '\000', exp_hint = 0 '\000', need_mb = 0 '\000' }, s = 0 }, trc_reader_checked = false, trc_holdout_list = { next = 0x0, prev = 0x0 }, sched_info = { pcount = 18446743798991423672, run_delay = 18446743528212021696, last_arrival = 0, last_queued = 0 }, tasks = { next = 0x0, prev = 0xffffff80fdd042b8 }, pushable_tasks = { prio = -36683080, prio_list = { next = 0x0, prev = 0x0 }, node_list = { next = 0x0, prev = 0x0 } }, pushable_dl_tasks = { __rb_parent_color = 64, rb_right = 0x0, rb_left = 0xffffffc009838958 }, mm = 0x0, active_mm = 0xffffff80fdd04308, vmacache = { seqnum = 18446743528212022024, vmas = {0x0, 0xffffff80fdd04320, 0xffffff80fdd04320, 0x0} }, rss_stat = { events = -36682952, count = {-128, -36682952, -128, 0} }, exit_state = 0, exit_code = -36682928, exit_signal = -128, pdeath_signal = -36682928, jobctl = 0, personality = 4258284392, sched_reset_on_fork = 0, sched_contributes_to_load = 0, sched_migrated = 0, sched_psi_wake_requeue = 0, sched_remote_wakeup = 0, in_execve = 0, in_iowait = 0, in_user_fault = 1, in_lru_fault = 0, no_cgroup_migration = 1, frozen = 1, use_memdelay = 0, in_memstall = 1, in_page_owner = 1, in_eventfd_signal = 0, atomic_flags = 0, restart_block = { arch_data = 18446743528212022144, fn = 0xffffff80fdd04380, { futex = { uaddr = 0x0, val = 4258284440, flags = 4294967168, bitset = 4258284440, time = 0, uaddr2 = 0xffffff80fdd043b0 }, nanosleep = { clockid = 0, type = TT_NONE, { rmtp = 0xffffff80fdd04398, compat_rmtp = 0xffffff80fdd04398 }, expires = 18446743528212022168 }, poll = { ufds = 0x0, nfds = -36682856, has_timeout = -128, tv_sec = 18446743528212022168, tv_nsec = 0 } } }, pid = -36682832, tgid = -128, stack_canary = 0, real_parent = 0x0, parent = 0x0, children = { next = 0x0, prev = 0x0 }, sibling = { next = 0x0, prev = 0x0 }, group_leader = 0x0, ptraced = { next = 0x0, prev = 0x0 }, ptrace_entry = { next = 0x0, prev = 0x0 }, thread_pid = 0x0, pid_links = {{ next = 0x0, pprev = 0x0 }, { next = 0x0, pprev = 0x0 }, { next = 0x0, pprev = 0x0 }, { next = 0x0, pprev = 0x0 }}, thread_group = { next = 0x0, prev = 0x0 }, thread_node = { next = 0x0, prev = 0x0 }, vfork_done = 0xffffff80fdd04488, set_child_tid = 0xffffff80fdd04488, clear_child_tid = 0x0, pf_io_worker = 0x0, utime = 0, stime = 0, gtime = 0, time_in_state = 0x0, max_state = 4258284744, prev_cputime = { utime = 18446743528212022472, stime = 0, lock = { raw_lock = { { val = { counter = 0 }, { locked = 0 '\000', pending = 0 '\000' }, { locked_pending = 0, tail = 0 } } } } }, nvcsw = 0, nivcsw = 0, start_time = 0, start_boottime = 0, min_flt = 0, maj_flt = 0, posix_cputimers = { bases = {{ nextevt = 0, tqhead = { rb_root = { rb_root = { rb_node = 0x0 }, rb_leftmost = 0x0 } } }, { nextevt = 0, tqhead = { rb_root = { rb_root = { rb_node = 0x0 }, rb_leftmost = 0x0 } } }, { nextevt = 0, tqhead = { rb_root = { rb_root = { rb_node = 0x0 }, rb_leftmost = 0x0 } } }}, timers_active = 0, expiry_active = 0 }, ptracer_cred = 0x0, real_cred = 0x0, cred = 0x0, cached_requested_key = 0x0, comm = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", nameidata = 0x0, sysvsem = { undo_list = 0x0 }, sysvshm = { shm_clist = { next = 0x0, prev = 0x0 } }, last_switch_count = 0, last_switch_time = 0, fs = 0x0, files = 0x0, io_uring = 0x0, nsproxy = 0x0, signal = 0x0, sighand = 0x0, blocked = { sig = {0} }, real_blocked = { sig = {0} }, saved_sigmask = { sig = {0} }, pending = { list = { next = 0x0, prev = 0x0 }, signal = { sig = {0} } }, sas_ss_sp = 0, sas_ss_size = 0, sas_ss_flags = 0, task_works = 0x0, audit_context = 0x0, loginuid = { val = 0 }, sessionid = 0, seccomp = { mode = 0, filter_count = { counter = 0 }, filter = 0x0 }, syscall_dispatch = {<No data fields>}, parent_exec_id = 0, self_exec_id = 0, alloc_lock = { { rlock = { raw_lock = { { val = { counter = 0 }, { locked = 0 '\000', pending = 0 '\000' }, { locked_pending = 0, tail = 0 } } } } } }, pi_lock = { raw_lock = { { val = { counter = 0 }, { locked = 0 '\000', pending = 0 '\000' }, { locked_pending = 0, tail = 0 } } } }, wake_q = { next = 0x0 }, wake_q_count = 0, pi_waiters = { rb_root = { rb_node = 0x0 }, rb_leftmost = 0x0 }, pi_top_task = 0x0, pi_blocked_on = 0x0, irqtrace = { irq_events = 0, hardirq_enable_ip = 0, hardirq_disable_ip = 0, hardirq_enable_event = 0, hardirq_disable_event = 0, softirq_disable_ip = 0, softirq_enable_ip = 0, softirq_disable_event = 0, softirq_enable_event = 0 }, hardirq_threaded = 0, hardirq_chain_key = 0, softirqs_enabled = 0, softirq_context = 0, irq_config = 0, journal_info = 0x0, bio_list = 0x0, plug = 0x0, reclaim_state = 0x0, backing_dev_info = 0x0, io_context = 0x0, capture_control = 0x0, ptrace_message = 0, last_siginfo = 0x0, ioac = { rchar = 0, wchar = 0, syscr = 0, syscw = 0, syscfs = 0, read_bytes = 0, write_bytes = 0, cancelled_write_bytes = 0 }, psi_flags = 0, acct_rss_mem1 = 0, acct_vm_mem1 = 0, acct_timexpd = 0, mems_allowed = { bits = {0} }, mems_allowed_seq = { seqcount = { sequence = 0 } }, cpuset_mem_spread_rotor = 0, cpuset_slab_spread_rotor = 0, cgroups = 0x0, cg_list = { next = 0x0, prev = 0x0 }, robust_list = 0x0, compat_robust_list = 0x0, pi_state_list = { next = 0x0, prev = 0x0 }, pi_state_cache = 0x0, futex_exit_mutex = { owner = { counter = 0 }, wait_lock = { raw_lock = { { val = { counter = 0 }, { locked = 0 '\000', pending = 0 '\000' }, { locked_pending = 0, tail = 0 } } } }, osq = { tail = { counter = 0 } }, wait_list = { next = 0x0, prev = 0x0 }, android_oem_data1 = {0, 0} }, futex_state = 0, perf_event_ctxp = {0x0, 0x0}, perf_event_mutex = { owner = { counter = 0 }, wait_lock = { raw_lock = { { val = { counter = 0 }, { locked = 0 '\000', pending = 0 '\000' }, { locked_pending = 0, tail = 0 } } } }, osq = { tail = { counter = 0 } }, wait_list = { next = 0x0, prev = 0x0 }, android_oem_data1 = {0, 0} }, perf_event_list = { next = 0x0, prev = 0x0 }, tlb_ubc = {<No data fields>}, { rcu_users = { refs = { counter = 0 } }, rcu = { next = 0x0, func = 0x0 } }, splice_pipe = 0x0, task_frag = { page = 0x0, offset = 0, size = 0 }, make_it_fail = 0, fail_nth = 0, nr_dirtied = 0, nr_dirtied_pause = 0, dirty_paused_when = 0, timer_slack_ns = 0, default_timer_slack_ns = 0, kunit_test = 0x0, curr_ret_stack = 0, curr_ret_depth = 0, ret_stack = 0x0, ftrace_timestamp = 0, trace_overrun = { counter = 0 }, tracing_graph_pause = { counter = 0 }, trace = 0, trace_recursion = 0, memcg_in_oom = 0x0, memcg_oom_gfp_mask = 0, memcg_oom_order = 0, memcg_nr_pages_over_high = 0, active_memcg = 0x0, throttle_queue = 0x0, utask = 0x0, kmap_ctrl = {<No data fields>}, pagefault_disabled = 0, oom_reaper_list = 0x0, oom_reaper_timer = { entry = { next = 0x0, pprev = 0x0 }, expires = 0, function = 0x0, flags = 0, android_kabi_reserved1 = 0, android_kabi_reserved2 = 0 }, stack_vm_area = 0x0, stack_refcount = { refs = { counter = 0 } }, security = 0x0, bpf_storage = 0x0, bpf_ctx = 0x0, android_vendor_data1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, android_oem_data1 = {0, 0, 0, 0, 0, 0}, kretprobe_instances = { first = 0x0 }, token = 0, ftoken = 0, qts = { in_qos = 0, qos_list = { next = 0x0, prev = 0x0 } }, android_kabi_reserved1 = 0, android_kabi_reserved2 = 0, android_kabi_reserved3 = 0, android_kabi_reserved4 = 0, android_kabi_reserved5 = 0, android_kabi_reserved6 = 0, android_kabi_reserved7 = 0, android_kabi_reserved8 = 0, thread = { cpu_context = { x19 = 0, x20 = 0, x21 = 0, x22 = 0, x23 = 0, x24 = 0, x25 = 0, x26 = 0, x27 = 0, x28 = 0, fp = 0, sp = 0, pc = 0 }, uw = { tp_value = 0, tp2_value = 0, fpsimd_state = { vregs = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fpsr = 0, fpcr = 0, __reserved = {0, 0} } }, android_vendor_data1 = 0, fpsimd_cpu = 0, sve_state = 0x0, sve_vl = 0, sve_vl_onexec = 0, fault_address = 0, fault_code = 0, debug = { suspended_step = 0, bps_disabled = 0, wps_disabled = 0, hbp_break = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, hbp_watch = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, keys_user = { apia = { lo = 0, hi = 0 }, apib = { lo = 0, hi = 0 }, apda = { lo = 0, hi = 0 }, apdb = { lo = 0, hi = 0 }, apga = { lo = 0, hi = 0 } }, keys_kernel = { apia = { lo = 0, hi = 0 } }, mte_ctrl = 0, sctlr_user = 0 } }

最新推荐

recommend-type

springboot尿毒症健康管理系统的设计与实现论文

springboot尿毒症健康管理系统的设计与实现
recommend-type

python 列表文本转表格

python
recommend-type

Mockingbird v2:PocketMine-MP新防作弊机制详解

标题和描述中所涉及的知识点如下: 1. Mockingbird反作弊系统: Mockingbird是一个正在开发中的反作弊系统,专门针对PocketMine-MP服务器。PocketMine-MP是Minecraft Pocket Edition(Minecraft PE)的一个服务器软件,允许玩家在移动平台上共同游戏。随着游戏的普及,作弊问题也随之而来,因此Mockingbird的出现正是为了应对这种情况。 2. Mockingbird的版本迭代: 从描述中提到的“Mockingbird的v1变体”和“v2版本”的变化来看,Mockingbird正在经历持续的开发和改进过程。软件版本迭代是常见的开发实践,有助于修复已知问题,改善性能和用户体验,添加新功能等。 3. 服务器性能要求: 描述中强调了运行Mockingbird的服务器需要具备一定的性能,例如提及“WitherHosting的$ 1.25计划”,这暗示了反作弊系统对服务器资源的需求较高。这可能是因为反作弊机制需要频繁处理大量的数据和事件,以便及时检测和阻止作弊行为。 4. Waterdog问题: Waterdog是另一种Minecraft服务器软件,特别适合 PocketMine-MP。描述中提到如果将Mockingbird和Waterdog结合使用可能会遇到问题,这可能是因为两者在某些机制上的不兼容或Mockingbird对Waterdog的特定实现尚未完全优化。 5. GitHub使用及问题反馈: 作者鼓励用户通过GitHub问题跟踪系统来报告问题、旁路和功能建议。这是一个公共代码托管平台,广泛用于开源项目协作,便于开发者和用户进行沟通和问题管理。作者还提到请用户在GitHub上发布问题而不是在评论区留下不好的评论,这体现了良好的社区维护和用户交流的实践。 6. 软件标签: “pocketmine”和“anticheat”(反作弊)作为标签,说明Mockingbird是一个特别为PocketMine-MP平台开发的反作弊软件。而“PHP”则可能指的是Mockingbird的开发语言,虽然这个信息与常见的Java或C++等开发Minecraft相关软件的语言不同,但并不排除使用PHP进行服务器端开发的可能性,尤其是对于处理动态网页、服务器端脚本等场景。 7. 压缩包文件: “Mockingbird-stable”是一个文件名称,很可能表示这是一个包含最新稳定版Mockingbird反作弊系统的压缩包。通常,这样的文件名中包含“stable”意味着这是一个经过充分测试且推荐用于生产环境的版本。 8. 社区协作和用户参与: 特别感谢部分提到了shur,这可能是对某位贡献者或社区成员的感激之情。这种感谢表明了软件开发不仅是开发者个人的劳动成果,同时也依赖于社区的支持和参与,包括提供反馈、报告问题、贡献代码和文档等。 总结以上内容,我们可以看到Mockingbird作为一款反作弊系统,其开发和维护需要依赖于社区的广泛参与和支持,同时还需要强大的服务器后端作为支撑。通过不断迭代更新版本,开发者希望解决现有问题,提高反作弊效率,并希望与社区保持良好的沟通,以持续优化产品。
recommend-type

“历史人物独白解说”视频:数据处理的6种革命性技术

# 1. 数据处理的历史回顾与技术演进 数据处理的历史,从最初的简单机械记录,到如今复杂的数据处理体系,不仅反映了技术的演进,也映射了人类社会进步的轨迹。在计算机技术发展初期,数据处理主要依靠打孔卡片和磁带,通过批处理的方式进行,效率低下且出错率高。随着技术的发展,上世纪70年代,关系型数据库的出现大大提高了数据处理的效率和准确性,为数据处理技术的发展奠定了基础。 随后,随着互
recommend-type

怎么判断多级运放电路的稳定性?

<think>首先,用户的问题是关于判断多级运算放大器电路的稳定性。我需要根据系统级指令来构建回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考引用: - 引用[1]:关于集成运算放大电路的设计、组成和性能评估。 - 引用[2]:高频电路中运放的带宽限制,一级放大电路的增益通常为100倍,过高会引起振
recommend-type

利用AHP和节点集中度解决影响力最大化问题的Flask应用教程

从给定的文件信息中,我们可以提取以下相关知识点进行详细说明: ### 标题知识点 **IM问题与AHP结合** IM问题(Influence Maximization)是网络分析中的一个核心问题,旨在识别影响网络中信息传播的关键节点。为了求解IM问题,研究者们常常结合使用不同的算法和策略,其中AHP(Analytic Hierarchy Process,分析层次结构过程)作为一种决策分析方法,被用于评估网络节点的重要性。AHP通过建立层次模型,对各个因素进行比较排序,从而量化影响度,并通过一致性检验保证决策结果的有效性。将AHP应用于IM问题,意味着将分析网络节点影响的多个维度,比如节点的中心性(centrality)和影响力。 **集中度措施** 集中度(Centralization)是衡量网络节点分布状况的指标,它反映了网络中节点之间的连接关系。在网络分析中,集中度常用于识别网络中的“枢纽”或“中心”节点。例如,通过计算网络的度中心度(degree centrality)可以了解节点与其他节点的直接连接数量;接近中心度(closeness centrality)衡量节点到网络中其他所有节点的平均距离;中介中心度(betweenness centrality)衡量节点在连接网络中其他节点对的最短路径上的出现频率。集中度高意味着节点在网络中处于重要位置,对信息的流动和控制具有较大影响力。 ### 描述知识点 **Flask框架** Flask是一个轻量级的Web应用框架,它使用Python编程语言开发。它非常适合快速开发小型Web应用,以及作为微服务架构的一部分。Flask的一个核心特点是“微”,意味着它提供了基本的Web开发功能,同时保持了框架的小巧和灵活。Flask内置了开发服务器,支持Werkzeug WSGI工具包和Jinja2模板引擎,提供了RESTful请求分发和请求钩子等功能。 **应用布局** 一个典型的Flask应用会包含以下几个关键部分: - `app/`:这是应用的核心目录,包含了路由设置、视图函数、模型和控制器等代码文件。 - `static/`:存放静态文件,比如CSS样式表、JavaScript文件和图片等,这些文件的内容不会改变。 - `templates/`:存放HTML模板文件,Flask将使用这些模板渲染最终的HTML页面。模板语言通常是Jinja2。 - `wsgi.py`:WSGI(Web Server Gateway Interface)是Python应用程序和Web服务器之间的一种标准接口。这个文件通常用于部署到生产服务器时,作为应用的入口点。 **部署到Heroku** Heroku是一个支持多种编程语言的云平台即服务(PaaS),它允许开发者轻松部署、运行和管理应用。部署Flask应用到Heroku,需要几个步骤:首先,创建一个Procfile文件,告知Heroku如何启动应用;其次,确保应用的依赖关系被正确管理,通常通过一个requirements.txt文件列出所有依赖;最后,使用Git将应用推送到Heroku提供的仓库,Heroku会自动识别Procfile并开始部署过程。 ### 标签知识点 **HTML** HTML(HyperText Markup Language,超文本标记语言)是用于创建网页和Web应用的标准标记语言。它定义了网页的结构和内容。HTML文件由一系列元素组成,这些元素通过标签(tags)来表示,如`<p>`代表段落,`<a>`代表链接,`<img>`代表图像等。HTML5是当前使用的最新版本,支持更多的特性,如离线存储、多媒体和图形等。 ### 压缩包子文件的文件名称列表知识点 **IMproblem-using-AHP-and-centralisation-of-nodes-master** 这里的文件名称“IMproblem-using-AHP-and-centralisation-of-nodes-master”表明了一个GitHub仓库的名称,其中包含了源代码以及与项目相关的所有文件。从名称中可以看出,该仓库是关于如何结合AHP和节点集中度分析来解决IM问题的Flask应用程序。文件名中的“master”表明这是仓库的主分支(现在叫做main分支),它是项目最新的、可部署的代码版本。 综合来看,本段信息为我们提供了构建和部署一个使用Flask框架、针对IM问题使用AHP和节点集中度分析的Web应用的方法和步骤。同时,介绍了应用在不同环节中所需技术和组件的详细知识点。
recommend-type

视频内容自动生成算法:突破性的8大最新进展

# 1. 视频内容自动生成算法概述 ## 算法发展背景 随着人工智能技术的迅速发展,视频内容自动生成算法已经成为媒体和娱乐行业的重要工具。这些算法能够自动编辑和合成视频内容,使内容创作者能够以较低的成本和时间生成高质量的视频。从社交媒体动态到在线教育内容,视频内容自动生成的应用场景正在不断扩大。 ## 核心技术简述 视
recommend-type

Softmax函数实际应用举例

<think>嗯,用户现在想了解Softmax函数的实际应用场景,这和我之前详细解释过的Softmax原理是直接相关的。用户特意提到要参考站内引用,看来是想看到具体案例支撑。 从用户提问方式看,ta应该已经理解了Softmax的基本数学原理(毕竟我上次用向量[2,1,0.1]的例子详细演示过计算过程),现在需要落地到实践层面。这种从理论到应用的递进很合理,可能是个正在学习机器学习的学生,或者需要解决实际问题的工程师。 我注意到用户提供的引用里有些关键线索:引用[1]提到图像分类和概率解释,引用[4]强调指数放大的特性,引用[5]则对比了Sigmoid在多标签分类的应用差异。这些正好能支撑我
recommend-type

WDI项目1:PriceIsRight游戏开发实践

### 标题解析 标题“price-is-right:WDI项目1-PriceIsRight游戏”表明这是一个名为“Price Is Right”的游戏项目,这是WDI(Web Development Immersive,全栈网页开发沉浸式课程)的第一个项目。WDI是一种常用于IT培训机构的课程名称,旨在通过实战项目来培养学员的全栈网页开发能力。 ### 描述解析 描述中提到,该游戏的目的是为了练习基本的JavaScript技能。这表明游戏被设计成一个编程练习,让开发者通过实现游戏逻辑来加深对JavaScript的理解。描述中也提到了游戏是一个支持两个玩家的版本,包含了分配得分、跟踪得分以及宣布获胜者等逻辑,这是游戏开发中常见的功能实现。 开发者还提到使用了Bootstrap框架来增加网站的可伸缩性。Bootstrap是一个流行的前端框架,它让网页设计和开发工作更加高效,通过提供预设的CSS样式和JavaScript组件,让开发者能够快速创建出响应式的网站布局。此外,开发者还使用了HTML5和CSS进行网站设计,这表明项目也涉及到了前端开发的基础技能。 ### 标签解析 标签“JavaScript”指出了该游戏中核心编程语言的使用。JavaScript是一种高级编程语言,常用于网页开发中,负责实现网页上的动态效果和交互功能。通过使用JavaScript,开发者可以在不离开浏览器的情况下实现复杂的游戏逻辑和用户界面交互。 ### 文件名称解析 压缩包子文件的文件名称列表中仅提供了一个条目:“price-is-right-master”。这里的“master”可能指明了这是项目的主分支或者主版本,通常在版本控制系统(如Git)中使用。文件名中的“price-is-right”与标题相呼应,表明该文件夹内包含的代码和资源是与“Price Is Right”游戏相关的。 ### 知识点总结 #### 1. JavaScript基础 - **变量和数据类型**:用于存储得分等信息。 - **函数和方法**:用于实现游戏逻辑,如分配得分、更新分数。 - **控制结构**:如if-else语句和循环,用于实现游戏流程控制。 - **事件处理**:监听玩家的输入(如点击按钮)和游戏状态的变化。 #### 2. Bootstrap框架 - **网格系统**:实现响应式布局,让游戏界面在不同设备上都能良好展示。 - **预设组件**:可能包括按钮、表单、警告框等,用于快速开发用户界面。 - **定制样式**:根据需要自定义组件样式来符合游戏主题。 #### 3. HTML5与CSS - **语义化标签**:使用HTML5提供的新标签来构建页面结构,如`<header>`, `<section>`, `<footer>`等。 - **CSS布局**:使用Flexbox或Grid等布局技术对页面元素进行定位和排版。 - **样式设计**:通过CSS为游戏界面增添美观的视觉效果。 #### 4. 项目结构和版本控制 - **主分支管理**:`master`分支通常保存着项目的稳定版本,用于部署生产环境。 - **代码组织**:合理的文件结构有助于维护和扩展项目。 #### 5. 前端开发最佳实践 - **分离关注点**:将样式、脚本和内容分离,确保代码清晰易维护。 - **响应式设计**:确保游戏在多种设备和屏幕尺寸上均有良好的用户体验。 - **可访问性**:考虑键盘导航、屏幕阅读器等无障碍功能,让游戏更加友好。 #### 6. 交互式游戏开发 - **游戏逻辑实现**:创建一个简单的游戏循环,管理玩家输入和得分更新。 - **状态管理**:游戏中的得分和其他游戏状态需要妥善保存和更新。 - **用户界面反馈**:提供即时的视觉和听觉反馈,增强玩家体验。 通过上述知识点的解析,可以看出“Price Is Right”游戏项目不仅仅是一个简单的编程练习,它还融合了多种前端技术,包括JavaScript、Bootstrap、HTML5和CSS,以实现一个完整的、可交互的游戏体验。此项目也反映了开发者在掌握前端开发技能的同时,了解了如何组织代码、维护项目结构和实践开发最佳实践。
recommend-type

人工智能视频编辑:如何利用技术进步提升内容创作质量

# 1. 人工智能视频编辑概述 随着人工智能技术的飞速发展,视频编辑领域正在经历一场前所未有的革命。AI的介入,不仅极大地提升了视频编辑的效率,还赋予了内容创作者全新的表达方式。本章旨在概述人工智能视频编辑的概念、发展历程和当前的应用现状,为读者提供一个全面而深入的了解。 ## 1.1 人工智能视频编辑的兴起 人工智能视频编辑是将先进的机器学习算法与传统视频处理技术相