#include <stdio.h> struct condition { int obj1; // 用于存储输入的第一个字母- 'A'的值 int obj2; // 存储第二个字母的 int num; // 存储数字 int ret; // 是否是 = } condition[20]; int judge(int *a, int n) { int i = 0; int ret = 1; // 判断传入的值班日期与输入的条件是否符合。 for (i = 0; i < n; i++) { // 如果是 = ,就判断值班日期和条件日期-1是否相等 .(值班日期是从0开始算的) if (condition[i].ret) { if (a[condition[i].obj1] != condition[i].num - 1) ret = 0; break; } else if (a[condition[i].obj1] + condition[i].num != a[condition[i].obj2]) { ret = 0; break; } } return ret; }

时间: 2024-02-14 11:16:08 浏览: 69
好的,让我来为您分析和优化这段 C 代码,并为其添加注释。 ```c #include <stdio.h> // 定义一个结构体 condition,用于存储输入的条件 struct condition { int obj1; // 存储条件中的第一个字符-'A'的值 int obj2; // 存储条件中的第二个字符-'A'的值 int num; // 存储数字 int ret; // 是否是等于号,0表示不是,1表示是 } condition[20]; // 存储20个条件 // 判断值班日期与输入的条件是否符合 int judge(int *a, int n) { int i = 0; int ret = 1; // 默认符合条件 // 遍历所有条件 for (i = 0; i < n; i++) { // 如果是等于号,判断值班日期和条件日期-1是否相等 if (condition[i].ret) { if (a[condition[i].obj1] != condition[i].num - 1) ret = 0; break; } // 否则,判断两个日期之间的差是否等于条件中的数字 else if (a[condition[i].obj1] + condition[i].num != a[condition[i].obj2]) { ret = 0; break; } } return ret; } ``` 这段代码主要功能是判断输入的日期是否符合条件。下面是对代码的优化和注释: 1. 结构体 condition 的定义 结构体 condition 用于存储输入的条件,包括两个字母和一个数字,以及一个标志位,表示是否为等于号。其中,obj1 和 obj2 存储的是条件中的两个字母-'A'的值,即 A 对应的是 0,B 对应的是 1,C 对应的是 2,以此类推;num 存储的是条件中的数字;ret 存储的是是否为等于号的标志位,0 表示不是,1 表示是。 2. 函数 judge 的定义 函数 judge 接收两个参数,一个是指向数组 a 的指针,表示输入的日期,另一个是整数 n,表示条件的个数。judge 函数的返回值为 0 或 1,表示输入日期是否符合条件。 3. 循环遍历条件 judge 函数中使用 for 循环遍历所有的条件。i 从 0 到 n-1,表示遍历条件的次数。ret 初值为 1,表示默认情况下输入日期符合条件。 4. 判断等于号条件 判断条件中是否有等于号,如果有,判断值班日期和条件日期-1是否相等。如果不相等,将 ret 设为 0,表示输入日期不符合条件。 5. 判断不等于号条件 如果条件中没有等于号,判断两个日期之间的差是否等于条件中的数字。如果不相等,将 ret 设为 0,表示输入日期不符合条件。 6. 返回函数值 循环结束后,返回 ret 的值,表示输入日期是否符合条件。 总的来说,这段代码没有明显的问题,但可以进一步优化,使其更加简洁、易读。例如,可以将结构体和函数名改为更加清晰、规范的名称,增加代码的可读性。
阅读全文

相关推荐

c
#include #include struct DATA { int ID; char name[4]; char sex[3]; int score; }; void paixu(int*,DATA*,int); int sishewuru(double); void func1(int*,int*,DATA*,int*,int,int,int,int);//统计男女比例 int func2(int*,int,DATA*);//查找考生序号 void print(); void main() { int length=0,i,yiben,erben,sanben,dazhuan,male[4],female[4]; int yi,er,san,si; char input; FILE* file=fopen("f1.txt","r"),*file1; if(file==NULL) { printf("No such file!\n"); return; } while(EOF!=fscanf(file,"%*[^\n]\n")) length++;//自动计算考生数罝ATA* data=(DATA*)malloc(length*sizeof(DATA)); int* pai=(int*)malloc(length*sizeof(int)); rewind(file); for(i=0;i='0'&&input<='4')) { printf("非法输入,请重新输入\n请输入:"); fflush(stdin); } else break; } getchar(); switch(input) { case '0': printf("\n一类本科招生线:%d\n二类本科招生线:%d\三类本科招生线:%d\\n高职高专招生线:%d\n",yi,er,san,si); printf("是否打印为文件?(y/n):"); if(getchar()=='y') { file1=fopen("各批次录取分数线.txt","w"); fprintf(file1,"一类本科招生线:%d\n二类本科招生线:%d\\n三类本科招生线:%d\n高职高专招生线:%d\n",yi,er,san,si); fclose(file1); } fflush(stdin); break; case '1': func1(male,female,data,pai,yiben,erben,sanben,dazhuan); printf("一类本科招生线男女比例:%d:%d\n",male[0],female[0]); printf("二类本科招生线男女比例:%d:%d\n",male[1],female[1]); printf("三类本科招生线男女比例:%d:%d\n",male[2],female[2]); printf("高职高专招生线招生线男女比例:%d:%d\n",male[3],female[3]); printf("是否打印为文件?(y/n):"); if(getchar()=='y') { file1=fopen("各批次录取男女比例.txt","w"); fprintf(file1,"一类本科招生线男女比例:%d:%d\n",male[0],female[0]);

#include "lvgl/lvgl.h" #include "lvgl/demos/lv_demos.h" #include <unistd.h> #include #include <time.h> #include <stdio.h> #include <stdlib.h> struct node { char path[1024]; struct node *next; struct node *prev; }; static const char * getenv_default(const char * name, const char * dflt) { return getenv(name) ?: dflt; } #if LV_USE_LINUX_FBDEV static void lv_linux_disp_init(void) { const char * device = getenv_default("LV_LINUX_FBDEV_DEVICE", "/dev/fb0"); lv_display_t * disp = lv_linux_fbdev_create(); lv_linux_fbdev_set_file(disp, device); } #elif LV_USE_LINUX_DRM static void lv_linux_disp_init(void) { const char * device = getenv_default("LV_LINUX_DRM_CARD", "/dev/dri/card0"); lv_display_t * disp = lv_linux_drm_create(); lv_linux_drm_set_file(disp, device, -1); } #elif LV_USE_SDL static void lv_linux_disp_init(void) { const int width = atoi(getenv("LV_SDL_VIDEO_WIDTH") ?: "800"); const int height = atoi(getenv("LV_SDL_VIDEO_HEIGHT") ?: "480"); lv_sdl_window_create(width, height); } #else #error Unsupported configuration #endif lv_obj_t *btn; lv_obj_t *btn1; lv_obj_t *btn2; lv_obj_t *btn3; static lv_obj_t *current_img = NULL; struct node *pos = NULL; struct node * up_showpic(){ lv_obj_t *img1 = lv_image_create(lv_screen_active()); pos = pos -> prev; char path[1024]; char ch = 'A'; sprintf(path,"%c:%s",ch,pos->path); lv_image_set_src(img1,path); return pos; } struct node * down_showpic(){ lv_obj_t *img1 = lv_image_create(lv_screen_active()); pos = pos -> next; char path[1024]; char ch = 'A'; sprintf(path,"%c:%s",ch,pos->path); lv_image_set_src(img1,path); return pos; } static void button_cb(lv_event_t *e){ void *obj = lv_event_get_target(e); printf("按钮被点击%p\n",obj); if(btn == obj){ printf("往上切换图片\n"); pos = up_showpic(); } else if(btn1 == obj){ printf("往下切换图片\n"); pos = down_showpic(); } else if(btn2 == obj){ lv_obj_t *img1 = lv_image_create(lv_screen_active()); char path[4096]; char ch = 'A'; sprintf(path,"%c:%s",ch,pos->path); printf("放大图片\n"); lv_image_set_scale(img1,512); } else if(btn3 == obj){ printf("缩小图片\n"); } }改成这样,放大图片不会段错误了。但是没有反应

#include <jansson.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_ECU 10 typedef struct { char ddd[16]; } ECU; typedef struct { char zhushini[16]; char qusi[16]; } Nishizhu; typedef struct { char sourceaddress[5]; char target_ip[16]; char local_ip[16]; char target_port[6]; ECU ecu[MAX_ECU]; Nishizhu nishizhu; } TCPSetting; typedef struct { TCPSetting tcp_setting; } Config; int main() { // 初始化结构体 Config config; memset(&config, 0, sizeof(Config)); strcpy(config.tcp_setting.sourceaddress, "abcd"); strcpy(config.tcp_setting.target_ip, "192.168.1.100"); strcpy(config.tcp_setting.local_ip, "192.168.1.200"); strcpy(config.tcp_setting.target_port, "12345"); strcpy(config.tcp_setting.ecu[0].ddd, "ecu1"); strcpy(config.tcp_setting.ecu[1].ddd, "ecu2"); strcpy(config.tcp_setting.nishizhu.zhushini, "zhushini"); strcpy(config.tcp_setting.nishizhu.qusi, "qusi"); // 将结构体转成json json_t *root = json_object(); json_t *tcp_setting = json_object(); json_object_set_new(root, "tcp_setting", tcp_setting); json_object_set_new(tcp_setting, "sourceaddress", json_string(config.tcp_setting.sourceaddress)); json_object_set_new(tcp_setting, "target_ip", json_string(config.tcp_setting.target_ip)); json_object_set_new(tcp_setting, "local_ip", json_string(config.tcp_setting.local_ip)); json_object_set_new(tcp_setting, "target_port", json_string(config.tcp_setting.target_port)); json_t *ecu = json_array(); for (int i = 0; i < MAX_ECU; ++i) { json_t *ecu_obj = json_object(); json_object_set_new(ecu_obj, "ddd", json_string(config.tcp_setting.ecu[i].ddd)); json_array_append_new(ecu, ecu_obj); } json_object_set_new(tcp_setting, "ecu", ecu); json_t *nishizhu = json_object(); json_object_set_new(nishizhu, "zhushini", json_string(config.tcp_setting.nishizhu.zhushini)); json_object_set_new(nishizhu, "qusi", json_string(config.tcp_setting.nishizhu.qusi)); json_object_set_new(tcp_setting, "nishizhu", nishizhu); // 保存成json文件 FILE *fp = fopen("config.json", "w"); if (fp == NULL) { printf("Failed to open file\n"); exit(1); } json_dumpf(root, fp, JSON_INDENT(4)); fclose(fp); // 释放内存 json_decref(root); return 0; } 运行上面的代码 保持的json文件中不包含ecu参数的内容

#include <stdio.h> #include <stdlib.h> // 双向链表节点 typedef struct DLinkedNode { int key; int value; struct DLinkedNode* prev; struct DLinkedNode* next; } DLinkedNode; // 哈希表节点(用于处理冲突) typedef struct HashNode { int key; DLinkedNode* cacheNode; struct HashNode* next; } HashNode; // LRU缓存结构体 typedef struct { int capacity; int size; DLinkedNode* head; // 哨兵头节点 DLinkedNode* tail; // 哨兵尾节点 HashNode** hashTable; // 哈希表数组 int hashSize; // 哈希表大小 } LRUCache; // 创建LRU缓存 LRUCache* lRUCacheCreate(int capacity) { LRUCache* cache = (LRUCache*)malloc(sizeof(LRUCache)); cache->capacity = capacity; cache->size = 0; // 初始化双向链表 cache->head = (DLinkedNode*)malloc(sizeof(DLinkedNode)); cache->tail = (DLinkedNode*)malloc(sizeof(DLinkedNode)); cache->head->prev = NULL; cache->head->next = cache->tail; cache->tail->prev = cache->head; cache->tail->next = NULL; // 初始化哈希表 cache->hashSize = capacity * 2; // 简化处理哈希表大小 cache->hashTable = (HashNode**)calloc(cache->hashSize, sizeof(HashNode*)); return cache; } // 哈希表辅助函数 DLinkedNode* findInHashTable(LRUCache* obj, int key) { int idx = key % obj->hashSize; HashNode* entry = obj->hashTable[idx]; while (entry != NULL) { if (entry->key == key) { return entry->cacheNode; } entry = entry->next; } return NULL; } void insertIntoHashTable(LRUCache* obj, int key, DLinkedNode* node) { int idx = key % obj->hashSize; HashNode* newEntry = (HashNode*)malloc(sizeof(HashNode)); newEntry->key = key; newEntry->cacheNode = node; newEntry->next = obj->hashTable[idx]; obj->hashTable[idx] = newEntry; } void removeFromHashTable(LRUCache* obj, int key) { int idx = key % obj->hashSize; HashNode* curr = obj->hashTable[idx]; HashNode* prev = NULL; while (curr != NULL) { if (curr->key == key) { if (prev == NULL) { obj->hashTable[idx] = curr->next; } else { prev->next = curr->next; } free(curr); return; } prev = curr; curr = curr->next; } } // 链表操作辅助函数 void moveToHead(LRUCache* obj, DLinkedNode* node) { // 断开原链接 node->prev->next = node->next; node->next->prev = node->prev; // 插入头部 node->prev = obj->head; node->next = obj->head->next; obj->head->next->prev = node; obj->head->next = node; } void addToHead(LRUCache* obj, DLinkedNode* node) { node->prev = obj->head; node->next = obj->head->next; obj->head->next->prev = node; obj->head->next = node; } DLinkedNode* removeTail(LRUCache* obj) { DLinkedNode* node = obj->tail->prev; node->prev->next = obj->tail; obj->tail->prev = node->prev; return node; } // 获取缓存值 int lRUCacheGet(LRUCache* obj, int key) { DLinkedNode* node = findInHashTable(obj, key); if (node == NULL) return -1; moveToHead(obj, node); // 更新为最近使用 return node->value; } // 插入缓存值 void lRUCachePut(LRUCache* obj, int key, int value) { DLinkedNode* node = findInHashTable(obj, key); if (node != NULL) { // 存在则更新 node->value = value; moveToHead(obj, node); } else { // 不存在则新建 DLinkedNode* newNode = (DLinkedNode*)malloc(sizeof(DLinkedNode)); newNode->key = key; newNode->value = value; insertIntoHashTable(obj, key, newNode); addToHead(obj, newNode); obj->size++; // 超过容量则淘汰尾部 if (obj->size > obj->capacity) { DLinkedNode* tailNode = removeTail(obj); removeFromHashTable(obj, tailNode->key); free(tailNode); obj->size--; } } } // 释放缓存 void lRUCacheFree(LRUCache* obj) { // 释放链表节点 DLinkedNode* curr = obj->head->next; while (curr != obj->tail) { DLinkedNode* tmp = curr; curr = curr->next; free(tmp); } free(obj->head); free(obj->tail); // 释放哈希表 for (int i = 0; i < obj->hashSize; i++) { HashNode* entry = obj->hashTable[i]; while (entry != NULL) { HashNode* tmp = entry; entry = entry->next; free(tmp); } } free(obj->hashTable); free(obj); }给出这段代码的完整形式,包括头文件,输出输出,输入输出要求可以在控制台自由控制,并给出代码详细的注释

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #include<openssl/hmac.h> char *signature_calculate(char *json_obj, char *key){ unsigned char *key_byte = (unsigned char *)key; char *sorted_json = to_url_query(json_obj); unsigned char *dataddd = (unsigned char *)sorted_json; unsigned char *signature = HMAC(EVP_sha256(), key_byte, strlen(key), dataddd, strlen(dataddd), NULL, NULL); char hex_signature = malloc(2 * EVP_MAX_MD_SIZE + 1); for(int i=0; i<EVP_MAX_MD_SIZE; i++) { sprintf(&hex_signature[i2], "%02x", signature[i]); } return hex_signature; } typedef struct { char key[256]; char value[256]; } KeyValue; int compare(const void a, const void b) { return strcmp(((KeyValue)a)->key, ((KeyValue)b)->key); } char *sort_dict(KeyValue *array, int size) { // 对KeyValue数组按ASCII码升序排序 qsort(array, size, sizeof(KeyValue), compare); char *query_list = malloc(size * 256); int len=0; for(int i=0; i<size; i++) { if(strlen(array[i].value)==0){ // 如果值为空或者空字符串则不拼接 continue; } char *key = array[i].key; char *value = array[i].value; if(isalpha(value[0]) && isalnum(value[1]) && strcmp(value, "true")!=0 && strcmp(value, "false")!=0) { sprintf(&query_list[len], "%s=%s&", key, value); } else { sprintf(&query_list[len], "%s="%s"&", key, value); } len = strlen(query_list); } if(len>0) { query_list[len-1] = 0; } return query_list; } char *to_url_query(char *json, char *prefix){ // 将json字符串转换为URL键值对形式的字符串 int len = strlen(json); KeyValue *array = malloc(len * sizeof(KeyValue)); int i=0; int j=0; int level=0; char *key; // 处理嵌套字典的键名 while(i<len){ if(json[i]=='{' || json[i]=='['){ level++; i++; } else if(json[i]=='}' || json[i]==']'){ level--; i++; } else if(json[i]==','){ array[j].value[i-array[j].key] = 0; i++; j++; } else if(json[i]==':'){ key = array[j].key; array[j].value[0] = 0; i++; } else if(json[i]=='"' && level%2==0){ i++; int k=0; while(json[i]!='"') { array[j].value[k] = json[i]; i++; k++; } array[j].value[k] = 0; i++; } else if(json[i]!=',' && json[i]!=':' && json[i]!=' '){ array[j].key[i-j] = json[i]; i++; } else { i++; } } array[j].value[i-array[j].key] = 0; j++; char *sorted_json = sort_dict(array, j); char *query_list = malloc(strlen(sorted_json)+1); if(strlen(prefix)>0){ sprintf(query_list, "%s.%s", prefix, sorted_json); } else { strcpy(query_list, sorted_json); } free(array); free(sorted_json); return query_list; } 请对上面的代码添加注释

/** **************************************************************************************************** * @file main.c * @version V1.0 * @brief LVGL V8无操作系统移植 实验 **************************************************************************************************** * @attention Waiken-Smart 慧勤智远 * * 实验平台: STM32F103ZET6小系统板 * **************************************************************************************************** */ #include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./USMART/usmart.h" #include "./BSP/LED/led.h" #include "./BSP/LCD/lcd.h" #include "./BSP/KEY/key.h" #include "./BSP/TOUCH/touch.h" #include "./MALLOC/malloc.h" #include "./BSP/TIMER/btim.h" #include "lvgl.h" #include "lv_port_indev_template.h" #include "lv_port_disp_template.h" #include "stdlib.h" #include "time.h" #include "stm32f1xx_hal.h" #include <stdio.h> static int32_t slider_value = 0; //滑块数值--升降台高度 static int32_t arc_value = 0; //圆弧数值--LED亮度 static int32_t c=0; static int32_t b=0; unsigned int gaodu; //高度变量 uint8_t send[2] = {0,0}; //串口发送 static lv_obj_t *label; static lv_obj_t *label1; static lv_obj_t *label_s; static lv_obj_t *label_t; static lv_obj_t *label_t_1; //升降 static lv_obj_t *btn_s; static lv_obj_t *btn; static lv_obj_t *btn1; static lv_obj_t *btn2; static lv_obj_t *msgbox; static lv_obj_t *msgbox1; static lv_obj_t *msgbox2; static lv_obj_t *msgbox3; static lv_obj_t *title; static lv_obj_t *title1; static lv_obj_t *title2; static lv_obj_t *title3; static const char *btn5[]={"Counite",""}; static const char *btn6[]={"Counite",""}; static const char *btn7[]={"Counite",""}; static const char *btn8[]={"Counite",""}; LV_IMG_DECLARE (gaohaoguang); LV_IMG_DECLARE (weixia); LV_IMG_DECLARE (shengjiangtai); LV_IMG_DECLARE (daideng); //static lv_obj_t *led; //static lv_obj_t *switch2; //static lv_obj_t *spinner; //static lv_obj_t *list; //static lv_obj_t *checkbox; //static lv_obj_t *dd; //static lv_obj_t *roller; //static lv_obj_t *bar; //static lv_obj_t *spinbox; //static lv_point_t line_points[]={{150,50},{250,200},{50,200},{150,50}}; //static const char *map[]={"#ff0000 btn1#","\n","btn2","btn3",""}; //static const char *btns[]={"continue","close",""}; UART_HandleTypeDef huart1; void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &huart1) { printf("arc_value"); send[0] = (int)slider_value; send[1] = (int)arc_value; // send[1] += 5; HAL_UART_Transmit_IT(&huart1,send,2); } } int i,n,m,p; uint16_t Num; static void my_event_cb(lv_event_t * e) //回调函数 { lv_obj_t *a=lv_event_get_target(e); if(a==btn) { n=1; } if(a==btn1) {n=0; p=3;} if(p==3){ if(c==1){p=0;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} // lv_obj_clear_flag(msgbox, LV_OBJ_FLAG_HIDDEN); if(c==2){p=0;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} // lv_obj_clear_flag(msgbox1, LV_OBJ_FLAG_HIDDEN); if(c==3){p=0;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} // lv_obj_clear_flag(msgbox2, LV_OBJ_FLAG_HIDDEN); if(c==4){p=0;lv_label_set_text_fmt (label_s,"No");}} // lv_obj_clear_flag(msgbox3, LV_OBJ_FLAG_HIDDEN); } //滑块事件回调------------------------------------------------------------------------------------------- static void slider_event_cb(lv_event_t *e) { lv_event_code_t code = lv_event_get_code(e); if (code != LV_EVENT_VALUE_CHANGED) return; lv_obj_t *slider = lv_event_get_target(e); slider_value = lv_slider_get_value(slider); // 更新全局变量 lv_label_set_text_fmt(label_t, "high: %d", slider_value); } //圆弧事件回调------------------------------------------------------------------------------------------- static void arc_event_cb(lv_event_t *e) { lv_obj_t *target = lv_event_get_target(e); arc_value = lv_arc_get_value(target); } int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ delay_init(72); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ usmart_dev.init(72); /* 初始化USMART */ led_init(); /* 初始化LED */ lcd_init(); /* 初始化LCD */ key_init(); /* 初始化按键 */ my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */ tp_dev.init(); /* 触摸屏初始化 */ btim_timx_int_init(10-1,7200-1); /* 初始化定时器 */ lv_init(); /* lvgl系统初始化 */ lv_port_disp_init(); /* lvgl显示接口初始化,放在lv_init()的后面 */ lv_port_indev_init(); /* lvgl输入接口初始化,放在lv_init()的后面 */ //串口------------------------------------------------------------------------------------------ HAL_UART_Transmit_IT(&huart1,send,2); //背景板------------------------------------------------------------------------------------------ // label_t = lv_label_create(lv_scr_act ()); //图片-------------------------------------------------------------------------------------------- lv_obj_t *img = lv_img_create(lv_scr_act()); lv_img_set_src (img,&gaohaoguang); lv_obj_set_pos (img,15,195); lv_obj_t *img1 = lv_img_create(lv_scr_act()); lv_img_set_src (img1,&weixia); lv_obj_set_pos (img1,315,171); lv_obj_t *img2 = lv_img_create(lv_scr_act()); lv_img_set_src (img2,&shengjiangtai); lv_obj_set_pos (img2,26,60); lv_obj_t *img3 = lv_img_create(lv_scr_act()); lv_img_set_src (img3,&daideng); lv_obj_set_pos (img3,197,160); //滑块-------------------------------------------------------------------------------------------- lv_obj_t *slider = lv_slider_create(lv_scr_act()); lv_obj_set_pos(slider,25,-85); lv_obj_set_size(slider,330,30); lv_slider_set_value(slider,0,LV_ANIM_OFF); lv_slider_set_range(slider,0,100); lv_obj_add_event_cb(slider,slider_event_cb,LV_EVENT_VALUE_CHANGED,NULL); // 设置轨道背景色 lv_obj_set_style_bg_color(slider, lv_color_hex(0x808080), LV_PART_MAIN); // 设置指示器颜色 lv_obj_set_style_bg_color(slider, lv_color_hex(0x0000FF), LV_PART_INDICATOR); // 设置旋钮颜色和尺寸 lv_obj_set_style_bg_color(slider, lv_color_hex(0x00ffff), LV_PART_KNOB); lv_obj_set_style_pad_all(slider, 8, LV_PART_KNOB); // 旋钮大小 lv_obj_set_align(slider,LV_ALIGN_CENTER); // 数值显示 label_t = lv_label_create(lv_scr_act()); lv_obj_set_align(label_t, LV_ALIGN_TOP_RIGHT); char text_buffer[20]; // 定义足够大的字符数组存储转换后的字符串 sprintf(text_buffer, "%d", slider_value); // 将整数转换为字符串 lv_label_set_text(label_t, text_buffer); // 传递字符串指针 lv_obj_set_style_text_font(label_t, &lv_font_montserrat_48, 0); // lv_obj_set_style_text_color(label_t_1, lv_color_hex(0x0fff0f), 0); //圆弧-------------------------------------------------------------------------------------------- lv_obj_t *arc = lv_arc_create(lv_scr_act()); /* 设置圆弧尺寸 */ lv_obj_set_size(arc, 174, 174); // 宽度和高度均为 200px /* 调整圆弧线条粗细 */ lv_obj_set_style_arc_width(arc, 20, LV_PART_MAIN); // 背景线条粗细 lv_obj_set_style_arc_width(arc, 20, LV_PART_INDICATOR); // 前景线条粗细 /* 设置位置和范围 */ lv_obj_set_pos(arc, 151, 110); // 调整位置(根据新尺寸可能需要重新定位) lv_arc_set_range(arc, 0, 100); // 值范围 0~100 /* 绑定事件 */ lv_obj_add_event_cb(arc, arc_event_cb, LV_EVENT_VALUE_CHANGED, NULL); // ///////////////////////////////////////////////////////////////////////////////////////////////////////// //拓展内容 1. 实体按键输入 while(1) { srand(Num); // send[0] = slider_value; // send[1] = arc_value; HAL_UART_Transmit_IT(&huart1, send, 2); HAL_Delay(10); // 示例:10ms发送一次 // if(n==1){i=rand()%50+1;} // lv_label_set_text_fmt (label_t," %d ",i); tp_dev.scan(0); /* 触摸扫描 */ lv_task_handler(); Num+=7; if(i>=1&&i<=3){m=1;c=m;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} if(i>=4&&i<10||i>35&&i<40){m=2;c=m;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} if(i>=15&&i<=20||i>45&&i<=50){m=3;c=m;lv_label_set_text_fmt (label_s,"Prize: %d ",c);} if(i>=10&&i<15||i>=40&&i<=45||i>=26&&i<=35||i>20&&i<=25){m=4;c=m;lv_label_set_text_fmt (label_s,"No");} } } 我如何把这两个数据发给电脑send[0] = (int)slider_value; send[1] = (int)arc_value;

#include <ros/ros.h> #include <image_transport/image_transport.h> #include <cv_bridge/cv_bridge.h> #include <sensor_msgs/image_encodings.h> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <stdio.h> #include <stdlib.h> #include "opencv2/opencv.hpp" #include <moveit/move_group_interface/move_group_interface.h> #include <tf/transform_listener.h> #include <moveit/planning_scene_interface/planning_scene_interface.h> #include <moveit/robot_trajectory/robot_trajectory.h> #include "myself_pkg/uart.h" #include <sys/stat.h> #include <cmath> #include <xarm_driver.h> #include <thread> // 引入线程库 #include <atomic> static const std::string OPENCV_WINDOW = "Image window"; #define M_PI 3.14159265358979323846 tf::Vector3 obj_camera_frame1, obj_robot_frame; int flag_start=1; ros::Subscriber rgb_sub; // 相机内参 double fx = 953.4568; // x轴方向的焦距 double fy = 949.837; // y轴方向的焦距 double cx = 658.66659; // x轴方向的光学中心 double cy = 366.82704; // y轴方向的光学中心 // 物体高度 double objectHeight = 0.34432666; // 假设物体的高度为1米 double k1 = 0.133507; // double k2 =-0.213178; // double p1 = 0.006242; // double p2 = 0.005494; // /* double fx = 1084.54479; // x轴方向的焦距 double fy = 950.11576; // y轴方向的焦距 double cx = 642.85519; // x轴方向的光学中心 double cy = 354.52482; // y轴方向的光学中心 // 物体高度 double objectHeight = 0.34432666; // 假设物体的高度为1米 double k1 = 0.141430; // double k2 =-0.384089; // double p1 = 0.003167; // double p2 = 0.002440; // */ cv::Mat K = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1); // 构造畸变参数向量 cv::Mat distCoeffs = (cv::Mat_<double>(5, 1) << k1, k2, p1, p2, 0); // 待校正的像素坐标 cv::Point2d pixelPoint(640, 360); // 假设像素坐标为(320, 240) cv::Mat cameraPointMat = (cv::Mat_<double>(3, 1) << 0, 0,0); /** // 定义一个结构体表示四元数,用于三维空间中的旋转表示 struct Quaternion { double w; // 四元数的实部 double x; // 四元数的虚部 x double y; // 四元数的虚部 y double z; // 四元数的虚部 z }; Quaternion eulerToQuaternion(double roll, double pitch, double yaw) { // 计算半角 double cy = cos(yaw * 0.5); double sy = sin(yaw * 0.5); double cp = cos(pitch * 0.5); double sp = sin(pitch * 0.5); double cr = cos(roll * 0.5); double sr = sin(roll * 0.5); Quaternion q; // 根据欧拉角到四元数的转换公式计算四元数的实部 q.w = cr * cp * cy + sr * sp * sy; // 根据欧拉角到四元数的转换公式计算四元数的虚部 x q.x = sr * cp * cy - cr * sp * sy; // 根据欧拉角到四元数的转换公式计算四元数的虚部 y q.y = cr * sp * cy + sr * cp * sy; // 根据欧拉角到四元数的转换公式计算四元数的虚部 z q.z = cr * cp * sy - sr * sp * cy; return q; } */ int move_lineb_test(xarm_msgs::Move srv, ros::ServiceClient client, float x_mm0, float y_mm0, float z_mm0, double roll0, double pitch0, double yaw0, float x_mm1, float y_mm1, float z_mm1, double roll1, double pitch1, double yaw1, float x_mm2, float y_mm2, float z_mm2, double roll2, double pitch2, double yaw2, float x_mm3, float y_mm3, float z_mm3, double roll3, double pitch3, double yaw3, float x_mm4, float y_mm4, float z_mm4, double roll4, double pitch4, double yaw4); void control_suction_during_move(float x_mm4, float y_mm4, float z_mm4); // 异步吸盘控制 auto suction_control = [](int speed){ std::thread([speed](){ for(int i=0; i<1; i++){ writeSpeed(speed); std::this_thread::sleep_for(std::chrono::milliseconds(800)); } }).detach(); // 分离线程 }; class XArmAPItest { ros::NodeHandle nh_; image_transport::ImageTransport it_; image_transport::Subscriber image_sub_; tf::TransformListener listener_; tf::StampedTransform camera_to_robot_; public: XArmAPItest() : it_(nh_) { moveit::planning_interface::MoveGroupInterface arm("xarm7"); sleep(0.5); moveit::planning_interface::PlanningSceneInterface planning_scene_interface; sleep(0.5); //异步任务处理器,防阻塞 ros::AsyncSpinner spinner(1); spinner.start(); // 创建一个新的障碍物消息 moveit_msgs::CollisionObject collision_object; collision_object.header.frame_id = "world"; // 设置障碍物的参考坐标系,通常为世界坐标系 // 设置障碍物的 ID collision_object.id = "table"; // 定义障碍物的形状和尺寸 shape_msgs::SolidPrimitive primitive; primitive.type = primitive.BOX; primitive.dimensions.resize(3); primitive.dimensions[0] = 2.0; // 长 primitive.dimensions[1] = 2.0; // 宽 primitive.dimensions[2] = 0.1; // 高 // 定义障碍物的姿态 geometry_msgs::Pose obstacle_pose; obstacle_pose.orientation.w = 1.0; // 默认姿态为单位四元数 obstacle_pose.position.x = 0.0; // x 位置 obstacle_pose.position.y = 0.0; // y 位置 obstacle_pose.position.z = -0.06; // z 位置 // 将障碍物的形状和姿态添加到障碍物消息中 collision_object.primitives.push_back(primitive); collision_object.primitive_poses.push_back(obstacle_pose); // 设置操作类型为添加障碍物 collision_object.operation = collision_object.ADD; // 发送障碍物消息到规划场景 moveit_msgs::PlanningScene planning_scene; planning_scene.world.collision_objects.push_back(collision_object); planning_scene.is_diff = true; planning_scene_interface.applyPlanningScene(planning_scene); // 应用障碍物到规划场景 ROS_INFO("Obstacle added"); /** //回初位置 arm.setNamedTarget("home");//设置目标 arm.move();//执行 sleep(0.5); double targetPose[7] = {-0.166690,0.00000, -0.076904,1.173601, 0.015010,1.21220,-0.260379}; std::vector<double> joint_group_positions(7); joint_group_positions[0] = targetPose[0]; joint_group_positions[1] = targetPose[1]; joint_group_positions[2] = targetPose[2]; joint_group_positions[3] = targetPose[3]; joint_group_positions[4] = targetPose[4]; joint_group_positions[5] = targetPose[5]; joint_group_positions[6] = targetPose[6]; arm.setJointValueTarget(joint_group_positions); arm.move(); sleep(0.5); */ try { listener_.waitForTransform("link_base", "camera_link", ros::Time(0), ros::Duration(50.0)); } catch (tf::TransformException &ex) { ROS_ERROR("[adventure_tf]: (wait) %s", ex.what()); ros::Duration(1.0).sleep(); } try { listener_.lookupTransform("link_base", "camera_link", ros::Time(0), camera_to_robot_); tf::Vector3 translation = camera_to_robot_.getOrigin(); objectHeight=translation.getZ(); std::cout << objectHeight << std::endl; } catch (tf::TransformException &ex) { ROS_ERROR("[adventure_tf]: (lookup) %s", ex.what()); } // 订阅相机图像 image_sub_ = it_.subscribe("/camera/color/image_raw", 1, &XArmAPItest::Cam_RGB_Callback, this); sleep(1); } /** // 封装四元数转欧拉角的函数 std::tuple<double, double, double> quaternionToEuler(const geometry_msgs::Quaternion& q) { double x = q.x; double y = q.y; double z = q.z; double w = q.w; // 计算绕 x 轴旋转的弧度(roll) double sinr_cosp = 2 * (w * x + y * z); double cosr_cosp = 1 - 2 * (x * x + y * y); double roll = std::atan2(sinr_cosp, cosr_cosp); // 计算绕 y 轴旋转的弧度(pitch) double sinp = 2 * (w * y - z * x); double pitch; if (std::abs(sinp) >= 1) pitch = std::copysign(M_PI / 2, sinp); // 使用 90 度避免数值问题 else pitch = std::asin(sinp); // 计算绕 z 轴旋转的弧度(yaw) double siny_cosp = 2 * (w * z + x * y); double cosy_cosp = 1 - 2 * (y * y + z * z); double yaw = std::atan2(siny_cosp, cosy_cosp); return std::make_tuple(roll, pitch, yaw); } */ void Grasping(double a, double b, double z, double Angle) { std::cout << "Grasping" << std::endl; // 输出提示信息 moveit::planning_interface::MoveGroupInterface arm("xarm7"); ros::AsyncSpinner spinner(1); spinner.start(); std::string end_effector_link = arm.getEndEffectorLink(); std::string reference_frame = "link_base"; arm.setPoseReferenceFrame(reference_frame); // 声明一个变量用于存储机械臂当前的位姿信息 geometry_msgs::PoseStamped homePose; // 获取机械臂末端执行器当前的位姿并赋值给 homePose 变量 homePose = arm.getCurrentPose(); sleep(1); writeSpeed(1); writeSpeed(1); writeSpeed(1); sleep(0.8); /*******************第1次抓取*********************/ /*** if(flag_start==1) { //移动到抓取方块上方 flag_start=2; //将初始位姿加入路点列表 //waypoints.push_back(target_pose); geometry_msgs::Pose target_pose; target_pose.position.x = x; target_pose.position.y = y; target_pose.position.z = 0; double roll = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch = 0; // 绕 y 轴旋转的弧度 double yaw = 0; // 绕 z 轴旋转的弧度 // 将目标姿态的位置坐标从米转换为毫米 float x_mm = static_cast<float>(target_pose.position.x * 1000); float y_mm = static_cast<float>(target_pose.position.y * 1000); float z_mm = static_cast<float>(target_pose.position.z * 1000); } */ double x = a + 0.0001-0.0041; double y = b + 0.0009+0.0082+0.001; /*******************抓取*********************/ if(flag_start>=1&&flag_start<35) { //抓取物块 geometry_msgs::Pose target_pose0; target_pose0 = arm.getCurrentPose(end_effector_link).pose; target_pose0.position.z = 0+0.14+0.013; target_pose0.position.x = x; target_pose0.position.y = y; double roll0 = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch0 =0*M_PI/180; // 绕 y 轴旋转的弧度 double yaw0 = 0; // 绕 z 轴旋转的弧度 // 将目标姿态的位置坐标从米转换为毫米 float x_mm0 = static_cast<float>(target_pose0.position.x * 1000); float y_mm0 = static_cast<float>(target_pose0.position.y * 1000); float z_mm0 = static_cast<float>(target_pose0.position.z * 1000); ROS_INFO("zuobiao0: %f, %f, %f", x_mm0, y_mm0, z_mm0); // 定位抓取物块 geometry_msgs::Pose target_pose1; target_pose1 = arm.getCurrentPose(end_effector_link).pose; target_pose1.position.x = x; target_pose1.position.y = y; target_pose1.position.z = 0.09+0.0003+0.01246-0.01; double roll1 = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch1 =0*M_PI/180; // 绕 y 轴旋转的弧度 double yaw1 = 0; // 绕 z 轴旋转的弧度 // 将目标姿态的位置坐标从米转换为毫米 float x_mm1 = static_cast<float>(target_pose1.position.x * 1000); float y_mm1 = static_cast<float>(target_pose1.position.y * 1000); float z_mm1 = static_cast<float>(target_pose1.position.z * 1000); ROS_INFO("zuobiao1: %f, %f, %f", x_mm1, y_mm1, z_mm1); //抓取物块 geometry_msgs::Pose target_pose2; target_pose2 = arm.getCurrentPose(end_effector_link).pose; target_pose2.position.z = 0+0.14+0.013; target_pose2.position.x = x; target_pose2.position.y = y; double roll2 = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch2 =0*M_PI/180; // 绕 y 轴旋转的弧度 double yaw2 = 0; // 绕 z 轴旋转的弧度 // 将目标姿态的位置坐标从米转换为毫米 float x_mm2 = static_cast<float>(target_pose2.position.x * 1000); float y_mm2 = static_cast<float>(target_pose2.position.y * 1000); float z_mm2 = static_cast<float>(target_pose2.position.z * 1000); ROS_INFO("zuobiao2: %f, %f, %f", x_mm2, y_mm2, z_mm2); geometry_msgs::Pose target_pose3; target_pose3 = arm.getCurrentPose(end_effector_link).pose; //放置物块 target_pose3.position.z= 0.14+0.013; double roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 double yaw3 = Angle*M_PI/180; // 绕 z 轴旋转的弧度 /**********************************************zi色*************************************/ if(flag_start==1){ target_pose3.position.x = 0.38578-0.023+0.002; target_pose3.position.y = 0.217467-0.052;} if(flag_start==2){ target_pose3.position.x = 0.38578+0.06-0.023; target_pose3.position.y = 0.217467+0.02-0.052;} if(flag_start==3){ target_pose3.position.x = 0.38578+0.08-0.023; target_pose3.position.y = 0.217467-0.052;} /**********************************************橙色*************************************/ if(flag_start==4){ target_pose3.position.x = 0.38578+0.01-0.023; target_pose3.position.y = 0.217467+0.052-0.055;} if(flag_start==5){ target_pose3.position.x = 0.38578+0.05-0.023; target_pose3.position.y = 0.217467+0.052-0.055;} if(flag_start==6){ target_pose3.position.x = 0.38578+0.09-0.023; target_pose3.position.y = 0.217467+0.052-0.055;} /*********************************************hong色 *****************************************/ if(flag_start==7){ target_pose3.position.x = 0.38578-0.023; target_pose3.position.y = 0.217467+0.11-0.055+0.002;} if(flag_start==8){ target_pose3.position.x = 0.38578+0.02-0.023-0.002; target_pose3.position.y = 0.217467+0.11-0.055+0.002;} if(flag_start==9){ target_pose3.position.x = 0.38578+0.04-0.023-0.002; target_pose3.position.y = 0.217467+0.11-0.055;} /********************************************************huang色*****************************/ if(flag_start==10){ target_pose3.position.x = 0.38578-0.023+0.002; target_pose3.position.y = 0.217467+0.18+-0.05-0.001;} if(flag_start==11){ target_pose3.position.x = 0.38578+0.06-0.023-0.002; target_pose3.position.y = 0.217467+0.16-0.05;} if(flag_start==12){ target_pose3.position.x = 0.38578+0.08-0.023; target_pose3.position.y = 0.217467+0.18-0.05;} if(flag_start==13){ target_pose3.position.x = 0.38578+0.14-0.023-0.001; target_pose3.position.y = 0.217467+0.16-0.05;} /*****************************************************hei色*********************************** */ if(flag_start==14){ target_pose3.position.x = 0.38578+0.06-0.023; target_pose3.position.y = 0.217467+0.10-0.05;} if(flag_start==15){ target_pose3.position.x = 0.38578+0.08-0.023; target_pose3.position.y = 0.217467+0.14-0.05-0.001;} /*****************************************************zi色*************************** */ if(flag_start==16){ target_pose3.position.x = 0.38578+0.12-0.023-0.001; target_pose3.position.y = 0.217467+0.08-0.0575;} /***************************************************lan色******************************* */ if(flag_start==17){ target_pose3.position.x = 0.38578+0.11-0.023+0.001; target_pose3.position.y = 0.217467+0.12-0.05-0.001; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 + M_PI/2; // 绕 z 轴旋转的弧度 } if(flag_start==18){ target_pose3.position.x = 0.38578+0.11+0.03-0.02; target_pose3.position.y = 0.217467+0.09-0.05;} if(flag_start==19){ target_pose3.position.x = 0.38578+0.11+0.03+0.04-0.02-0.002; target_pose3.position.y = 0.217467+0.09-0.05+0.001;} if(flag_start==20){ target_pose3.position.x = 0.38578+0.11+0.03+0.04+0.02-0.02-0.02-0.07; target_pose3.position.y = 0.217467+0.09+0.02-0.05+0.002;} /***************************************************ceng色*************************** */ if(flag_start==21){ target_pose3.position.x = 0.38578+0.15-0.02-0.002; target_pose3.position.y = 0.217467+0.13-0.045-0.002;} /*****************************************************lv色**************************************** */ if(flag_start==22){ target_pose3.position.x = 0.38578+0.12-0.02-0.004; target_pose3.position.y = 0.217467+0.03-0.05;} if(flag_start==23){ target_pose3.position.x = 0.38578+0.16-0.02-0.004-0.0005; target_pose3.position.y = 0.217467+0.03-0.05;} if(flag_start==24){ target_pose3.position.x = 0.38578+0.20-0.02-0.004-0.0005; target_pose3.position.y = 0.217467+0.03-0.05;} if(flag_start==25){ target_pose3.position.x = 0.38578+0.17-0.02-0.004-0.0001; target_pose3.position.y = 0.217467+0.11+0.06-0.05-0.005; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 - M_PI/2; // 绕 z 轴旋转的弧度 } /***********************************************************huang色************************************** */ if(flag_start==26){ target_pose3.position.x = 0.38578+0.20-0.022; target_pose3.position.y = 0.217467+0.11+0.08-0.05-0.004-0.004;} /***********************************************************hong色************************************** */ if(flag_start==27){ target_pose3.position.x = 0.38578+0.17-0.021; target_pose3.position.y = 0.217467-0.05; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 - M_PI/2; // 绕 z 轴旋转的弧度 } if(flag_start==28){ target_pose3.position.x = 0.38578+0.17-0.021; target_pose3.position.y = 0.217467+0.06-0.05; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 - M_PI/2; // 绕 z 轴旋转的弧度 } /***************************************************************hei色************************************* */ if(flag_start==29){ target_pose3.position.x = 0.38578+0.22-0.025+0.002; target_pose3.position.y = 0.217467+0.10+0.04-0.05;} if(flag_start==30){ target_pose3.position.x = 0.38578+0.24-0.025; target_pose3.position.y = 0.217467+0.18-0.05;} /*************************************************ceng色*************************** */ if(flag_start==31){ target_pose3.position.x = 0.38578+0.23-0.02-0.002-0.0002; target_pose3.position.y = 0.217467+0.07-0.045-0.002-0.002;} /*************************************************lan色*************************** */ if(flag_start==32){ target_pose3.position.x = 0.38578+0.23-0.024; target_pose3.position.y = 0.217467+0.02-0.051-0.0001; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 + M_PI/2; // 绕 z 轴旋转的弧度 } /*************************************************zi色*************************** */ if(flag_start==33){ target_pose3.position.x = 0.38578+0.26-0.024; target_pose3.position.y = 0.217467-0.051+0.001;} /*************************************************lv色*************************** */ if(flag_start==34){ target_pose3.position.x = 0.38578+0.25-0.024; target_pose3.position.y = 0.217467+0.10-0.051+0.001; target_pose3.position.z= 0.14+0.013+0.002; roll3 = 180*M_PI/180; // 绕 x 轴旋转的弧度 pitch3 =0*M_PI/180; // 绕 y 轴旋转的弧度 yaw3 = Angle*M_PI/180 - M_PI/2; // 绕 z 轴旋转的弧度 } // 将目标姿态的位置坐标从米转换为毫米 float x_mm3 = static_cast<float>(target_pose3.position.x * 1000); float y_mm3 = static_cast<float>(target_pose3.position.y * 1000); float z_mm3 = static_cast<float>(target_pose3.position.z * 1000); ROS_INFO("zuobiao3: %f, %f, %f", x_mm3, y_mm3, z_mm3); geometry_msgs::Pose target_pose4; target_pose4.position.z= 0.109+0.01236-0.0078+0.005; double roll4 = 180*M_PI/180; // 绕 x 轴旋转的弧度 double pitch4 =0*M_PI/180; // 绕 y 轴旋转的弧度 double yaw4 = yaw3; // 绕 z 轴旋转的弧度 float x_mm4 = static_cast<float>(target_pose3.position.x * 1000); float y_mm4 = static_cast<float>(target_pose3.position.y * 1000); float z_mm4 = static_cast<float>(target_pose4.position.z * 1000); ROS_INFO("zuobiao4: %f, %f, %f", x_mm4, y_mm4, z_mm4); // 调用 move_lineb_test 函数并传递坐标 ros::NodeHandle nh; ros::ServiceClient move_lineb_client_ = nh.serviceClient<xarm_msgs::Move>("/xarm/move_lineb"); xarm_msgs::Move move_srv_; if(move_lineb_test(move_srv_, move_lineb_client_, x_mm0, y_mm0, z_mm0, roll0, pitch0, yaw0, x_mm1, y_mm1, z_mm1, roll1, pitch1, yaw1, x_mm2, y_mm2, z_mm2, roll2, pitch2, yaw2, x_mm3, y_mm3, z_mm3, roll3, pitch3, yaw3, x_mm4, y_mm4, z_mm4, roll4, pitch4, yaw4) == 1) return; control_suction_during_move(x_mm4, y_mm4, z_mm4); flag_start++; } else {ros::shutdown(); } } void Cam_RGB_Callback(const sensor_msgs::ImageConstPtr &msg)// 摄像头回调函数 { using namespace cv; image_sub_.shutdown(); // 定义一个cv_bridge指针 cv_bridge::CvImagePtr cv_ptr; try { // 将ROS图像转换为OpenCV图像 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); } catch (cv_bridge::Exception &e) { ROS_ERROR("cv_bridge exception:%s", e.what()); } // 获取原始图像 Mat imgOriginal = cv_ptr->image; // 定义亮度增强因子 double brightness_scale = 1.8; // 应用亮度增强 Mat brightened; imgOriginal.convertTo(brightened, -1, brightness_scale); // 图像预处理:高斯模糊 Mat blurred; GaussianBlur(brightened, blurred, Size(5, 5), 0); Mat hsv; cvtColor(blurred, hsv, cv::COLOR_BGR2HSV); // 将原始图像转换为HSV图像 // 分离HSV通道 std::vector<Mat> hsv_channels; split(hsv, hsv_channels); // 增强饱和度(S 通道) double saturation_scale = 1.5; // 饱和度增强因子,可以根据实际情况调整 hsv_channels[1].convertTo(hsv_channels[1], -1, saturation_scale); // 合并通道 merge(hsv_channels, hsv); Mat mask_red, mask_green,mask_blue,mask_orange,mask_brown,mask_yellow,mask_purple; // inRange(blurred, cv::Scalar(0, 0, 130), cv::Scalar(255, 108, 226), mask_red); inRange(blurred, cv::Scalar(0, 0, 144), cv::Scalar(252, 111, 203), mask_red); inRange(blurred, cv::Scalar(0, 112, 174), cv::Scalar(159, 139, 237), mask_orange);//BGR inRange(blurred, cv::Scalar(0, 0, 0), cv::Scalar(123, 112, 108), mask_brown); inRange(blurred, cv::Scalar(0, 127, 97), cv::Scalar(157, 255, 136), mask_green); inRange(blurred, cv::Scalar(156, 119, 0), cv::Scalar(218, 146, 102), mask_blue); inRange(blurred, cv::Scalar(0, 142, 152), cv::Scalar(150, 255, 255), mask_yellow); inRange(hsv, cv::Scalar(99, 33, 120), cv::Scalar(134, 146, 181), mask_purple); Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));// 形态学操作的内核大小 //dilate(mask_red, mask_red, kernel); //dilate(mask_green, mask_green, kernel); erode(mask_red, mask_red, kernel);//腐蚀 erode(mask_green, mask_green, kernel); erode(mask_blue, mask_blue, kernel); erode(mask_yellow, mask_yellow, kernel); erode(mask_orange, mask_orange, kernel); erode(mask_purple, mask_purple, kernel); erode(mask_brown, mask_brown, kernel); //erode(mask_purple, mask_purple, kernel); dilate(mask_orange, mask_orange, kernel); dilate(mask_brown, mask_brown, kernel); //imshow("green", mask_green);//显示原始图像 //获取储存不同颜色的灰度图 std::vector<std::vector<cv::Point>> contours_red; std::vector<std::vector<cv::Point>> contours_red_output; cv::findContours(mask_red,contours_red, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_orange; std::vector<std::vector<cv::Point>> contours_orange_output; cv::findContours(mask_orange,contours_orange, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_brown; std::vector<std::vector<cv::Point>> contours_brown_output; cv::findContours(mask_brown,contours_brown, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_green; std::vector<std::vector<cv::Point>> contours_green_output; cv::findContours(mask_green,contours_green, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_blue; std::vector<std::vector<cv::Point>> contours_blue_output; cv::findContours(mask_blue,contours_blue, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_yellow; std::vector<std::vector<cv::Point>> contours_yellow_output; cv::findContours(mask_yellow,contours_yellow, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector<std::vector<cv::Point>> contours_purple; std::vector<std::vector<cv::Point>> contours_purple_output; cv::findContours(mask_purple,contours_purple, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //drawContours(blurred, contours, -1, Scalar(0, 255, 0), 3);//轮廓 /********************************红色********************/ for (size_t i = 0; i < contours_red.size(); i++) { std::vector<cv::Point>& contour_red = contours_red[i]; if (contour_red.size()>200) { // 检查轮廓是否为空 contours_red_output.push_back(contours_red[i]); } else { ROS_INFO("No red contours found."); } } /********************************橙色********************/ for (size_t i = 0; i < contours_orange.size(); i++) { std::vector<cv::Point>& contour_orange = contours_orange[i]; if (contour_orange.size()>200) { // 检查轮廓是否为空 contours_orange_output.push_back(contours_orange[i]); } else { ROS_INFO("No orange contours found."); } } /********************************棕色********************/ for (size_t i = 0; i < contours_brown.size(); i++) { std::vector<cv::Point>& contour_brown = contours_brown[i]; if (contour_brown.size()>200) { // 检查轮廓是否为空 contours_brown_output.push_back(contours_brown[i]); } else { ROS_INFO("No brown contours found."); } } /********************************绿色********************/ for (size_t i = 0; i < contours_green.size(); i++) { std::vector<cv::Point>& contour_green = contours_green[i]; if (contour_green.size()>200) { // 检查轮廓是否为空 contours_green_output.push_back(contours_green[i]); } else { ROS_INFO("No green contours found."); } } /********************************蓝色********************/ for (size_t i = 0; i < contours_blue.size(); i++) { std::vector<cv::Point>& contour_blue = contours_blue[i]; if (contour_blue.size()>200) { // 检查轮廓是否为空 contours_blue_output.push_back(contours_blue[i]); } else { ROS_INFO("No blue contours found."); } } /********************************黄色********************/ for (size_t i = 0; i < contours_yellow.size(); i++) { std::vector<cv::Point>& contour_yellow = contours_yellow[i]; if (contour_yellow.size()>200) { // 检查轮廓是否为空 contours_yellow_output.push_back(contours_yellow[i]); } else { ROS_INFO("No yellow contours found."); } } /********************************紫色********************/ // 存储每个轮廓的面积及其索引 std::vector<std::pair<double, size_t>> area_index_pairs; for (size_t i = 0; i < contours_purple.size(); ++i) { double area = cv::contourArea(contours_purple[i]); area_index_pairs.emplace_back(area, i); } // 按面积从大到小排序 std::sort(area_index_pairs.begin(), area_index_pairs.end(), [](const std::pair<double, size_t>& a, const std::pair<double, size_t>& b) { return a.first > b.first; }); // 处理面积最大的5个轮廓 size_t count = std::min<size_t>(5, area_index_pairs.size()); if (count == 0) { ROS_INFO("No contours found."); } for (size_t i = 0; i < count; ++i) { size_t index = area_index_pairs[i].second; contours_purple_output.push_back(contours_purple[index]); } //传递颜色灰度图像 Camera_TO_Robot_Process_YP(contours_purple_output,0,3); Camera_TO_Robot_Process_RO(contours_orange_output,0,3); Camera_TO_Robot_Process_RO(contours_red_output,0,3); Camera_TO_Robot_Process_YP(contours_yellow_output,0,4); Camera_TO_Robot_Process_brown(contours_brown_output,0,2); Camera_TO_Robot_Process_YP(contours_purple_output,3,4); Camera_TO_Robot_Process_GB(contours_blue_output,0,4); Camera_TO_Robot_Process_RO(contours_orange_output,3,4); Camera_TO_Robot_Process_GB(contours_green_output,0,4); Camera_TO_Robot_Process_YP(contours_yellow_output,4,5); Camera_TO_Robot_Process_RO(contours_red_output,3,5); Camera_TO_Robot_Process_brown(contours_brown_output,2,4); Camera_TO_Robot_Process_RO(contours_orange_output,4,5); Camera_TO_Robot_Process_GB(contours_blue_output,4,5); Camera_TO_Robot_Process_YP(contours_purple_output,4,5); Camera_TO_Robot_Process_GB(contours_green_output,4,5); // imshow("imgOriginal", imgOriginal); std::cout << "success!" << std::endl; ros::shutdown(); } //红色和橙色 void Camera_TO_Robot_Process_RO(const std::vector<std::vector<cv::Point>>& contours, int start_number, int end_number) { std::cout << "Red or Orange" << std::endl; cv::Point2f center; for (start_number; start_number < end_number; start_number++) { const std::vector<cv::Point>& contour = contours[start_number]; if (contour.size()>300) // 检查轮廓是否为空 { // 获取最小外接圆 // float radius; // cv::minEnclosingCircle(contours[i], center, radius); // 获取最小外接矩形 cv::RotatedRect minRect = cv::minAreaRect(contours[start_number]); center = minRect.center; if(center.y<60) { center.y=60; } if(center.x<82) { center.x=82; } if(center.y>=60&¢er.x>=82) { cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x, center.y,1); //cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x*1.2-91.0, center.y*1.275-74.5,1); std::cout << pixelPointMat << std::endl; // pixelPointMat = (cv::Mat_<double>(3, 1) << 640, 360, 1); cameraPointMat = objectHeight * K.inv() * pixelPointMat; // std::cout << "相机坐标系下的三维坐标:" << std::endl; // std::cout << cameraPointMat << std::endl; obj_camera_frame1.setX(cameraPointMat.at<double>(0,0)); obj_camera_frame1.setY(cameraPointMat.at<double>(1,0)); obj_camera_frame1.setZ(cameraPointMat.at<double>(2,0)); obj_robot_frame = camera_to_robot_ * obj_camera_frame1; // ros::shutdown(); //std::cout << "11111" << std::endl; /**************** 获取矩形的角度*******************/ double angle = minRect.angle; cv::Size2f size = minRect.size; double width = size.width; double height = size.height; //放平角度 if (width < height) { angle += 90; } // 输出角度 // std::cout << "Contour #" << start_number << " angle: " << angle << std::endl; /**************** 获取矩形的角度*******************/ Grasping(obj_robot_frame.getX(),obj_robot_frame.getY(),obj_robot_frame.getZ(),angle); } } else if(contour.size()>0&&contour.size()<100) { std::cout << "没有红橙像素坐标:" << std::endl; } } } //棕色 void Camera_TO_Robot_Process_brown(const std::vector<std::vector<cv::Point>>& contours, int start_number, int end_number) { std::cout << "Brown start" << std::endl; cv::Point2f center; for (start_number; start_number < end_number; start_number++) { const std::vector<cv::Point>& contour = contours[start_number]; if (contour.size()>300) // 检查轮廓是否为空 { // 获取最小外接圆 float radius; cv::minEnclosingCircle(contours[start_number], center, radius); /**************** 获取矩形的角度*******************/ // 获取最小外接矩形 cv::RotatedRect minRect = cv::minAreaRect(contours[start_number]); double angle2 = minRect.angle; cv::Size2f size = minRect.size; double width = size.width; double height = size.height; /**************** 获取矩形的角度*******************/ double epsilon = 0.1 * cv::arcLength(contours[start_number], true); std::cout << "1111" << std::endl; std::vector<int> lenth(8); std::vector<cv::Point2f> approx; cv::Point2f pt; cv::Point2f pt1; cv::Point2f pt0; cv::approxPolyDP(contours[start_number], approx, epsilon, true); pt0 = approx[0]; if (approx.size() == 3) { for (size_t j = 0; j < approx.size(); j++) { pt= approx[j]; pt1= approx[j+1]; lenth[j]=(pt.x-pt1.x)*(pt.x-pt1.x)+(pt.y-pt1.y)*(pt.y-pt1.y); if(j==2) { lenth[j]=(pt.x-pt0.x)*(pt.x-pt0.x)+(pt.y-pt0.y)*(pt.y-pt0.y); } } if ( lenth[0]>lenth[1]&&lenth[0]>lenth[2]) { if(width > height){ switch (start_number) { case 0: angle2 = angle2; break; case 1: angle2 -= 90; break; case 2: angle2 = angle2; break; case 3: angle2 -= 90; break; } } else if(width < height){ switch (start_number) { case 0: angle2 -= 90; break; case 1: angle2 += 180; break; case 2: angle2 -= 90; break; case 3: angle2 += 180; break; } } } else if ( lenth[2]>lenth[1]&&lenth[2]>lenth[0]) { if(width > height){ switch (start_number) { case 0: angle2 += 180; break; case 1: angle2 += 90; break; case 2: angle2 += 180; break; case 3: angle2 += 90; break; } } else if(width < height){ switch (start_number) { case 0: angle2 += 90; break; case 1: angle2 = angle2; break; case 2: angle2 += 90; break; case 3: angle2 = angle2; break; } } } } // center = minRect.center; if(center.y<60) { center.y=60; } if(center.x<82) { center.x=82; } if(center.y>=60&¢er.x>=82) { //cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x*1.2-91.5, center.y*1.275-74.5,1); //cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x*1.2-92, center.y*1.285-76.5,1); cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x, center.y,1); std::cout << pixelPointMat << std::endl; // pixelPointMat = (cv::Mat_<double>(3, 1) << 640, 360, 1); cameraPointMat = objectHeight * K.inv() * pixelPointMat; // std::cout << "相机坐标系下的三维坐标:" << std::endl; // std::cout << cameraPointMat << std::endl; obj_camera_frame1.setX(cameraPointMat.at<double>(0,0)); obj_camera_frame1.setY(cameraPointMat.at<double>(1,0)); obj_camera_frame1.setZ(cameraPointMat.at<double>(2,0)); obj_robot_frame = camera_to_robot_ * obj_camera_frame1; if(angle2>176) angle2=176; if(angle2<-176) angle2=-176; std::cout << " angle2 :" << angle2 << std::endl; Grasping(obj_robot_frame.getX(),obj_robot_frame.getY(),obj_robot_frame.getZ(),angle2); } } else if(contour.size()>0&&contour.size()<100) { std::cout << "没有棕色像素坐标:" << std::endl; }} } //紫色和黄色 void Camera_TO_Robot_Process_YP(const std::vector<std::vector<cv::Point>>& contours, int start_number, int end_number) { std::cout << "Yellow or Purple start" << std::endl; double angle2=0; for (start_number; start_number < end_number; start_number++) { const std::vector<cv::Point>& contour = contours[start_number]; if (contour.size()>300) // 检查轮廓是否为空 { /**************** 获取矩形的角度*******************/ cv::RotatedRect minRect = cv::minAreaRect(contours[start_number]); angle2 = minRect.angle; cv::Size2f size = minRect.size; double width = size.width; double height = size.height; /**************** 获取矩形的角度*******************/ cv::Point2f center; cv::Point2f center2; double epsilon = 0.04 * cv::arcLength(contours[start_number], true); // 多边形逼近 std::vector<int> lenth(6); std::vector<cv::Point2f> approx; cv::Point2f pt; cv::Point2f pt1; cv::Point2f pt0; cv::approxPolyDP(contours[start_number], approx, epsilon, true); // std::cout <<" lenth[i] "<< approx.size() << std::endl; pt0 = approx[0]; if (approx.size() == 6) { for (size_t i = 0; i < approx.size(); i++) { pt= approx[i]; pt1= approx[i+1]; lenth[i]=(pt.x-pt1.x)*(pt.x-pt1.x)+(pt.y-pt1.y)*(pt.y-pt1.y); if(i==5) lenth[i]=(pt.x-pt0.x)*(pt.x-pt0.x)+(pt.y-pt0.y)*(pt.y-pt0.y); } /********************************purple***************************************/ if ( lenth[5]>lenth[1]&&lenth[5]>lenth[0]&&lenth[5]>lenth[2]&&lenth[5]>lenth[3]&&lenth[5]>lenth[4]) { // center2 = (approx[1]+approx[2])/2; // center = (approx[5]+center2)/2; center = (approx[5]+approx[2])/2; if(width > height){ switch (start_number) { case 0: angle2 -= 90; break; case 1: angle2 += 90; break; case 2: angle2 -= 90; break; case 3: angle2 += 90; break; case 4: angle2 = angle2; break; }} else if(width < height){ switch (start_number) { case 0: angle2 += 180; break; case 1: angle2 = angle2; break; case 2: angle2 += 180; break; case 3: angle2 = angle2; break; case 4: angle2 -= 90; break; }} std::cout << "555555" << std::endl; } /********************************purple***************************************/ else if ( lenth[1]>lenth[2]&&lenth[1]>lenth[0]&&lenth[1]>lenth[5]&&lenth[1]>lenth[3]&&lenth[1]>lenth[4]) { //center2 = (approx[3]+approx[4])/2; //center = (approx[1]+center2)/2; center = (approx[1]+approx[4])/2; if(width > height){ if(approx[1].y<approx[0].y&&approx[1].y<approx[2].y&&approx[1].y<approx[3].y&&approx[1].y<approx[4].y&&approx[1].y<approx[5].y){ switch (start_number) { case 0: angle2 += 90; break; case 1: angle2 -= 90; break; case 2: angle2 += 90; break; case 3: angle2 -= 90; break; case 4: angle2 += 180; break; }} else{ switch (start_number) { case 0: angle2 -= 90; break; case 1: angle2 += 90; break; case 2: angle2 -= 90; break; case 3: angle2 += 90; break; case 4: angle2 = angle2; break; } } } else if(width < height) { switch (start_number) { case 0: angle2 = angle2; break; case 1: angle2 += 180; break; case 2: angle2 = angle2; break; case 3: angle2 += 180; break; case 4: angle2 += 90; break; }} std::cout << "11111111" << std::endl; } /********************************purple***************************************/ /********************************yellow***************************************/ else if ( lenth[0]>lenth[1]&&lenth[0]>lenth[2]&&lenth[0]>lenth[5]&&lenth[0]>lenth[3]&&lenth[0]>lenth[4]) { //center2 = (approx[4]+approx[5])/2; //center = (center2+approx[1])/2; center = (approx[4]+approx[1])/2; if(width < height){ switch (start_number) { case 0: angle2 += 180; break; case 1: angle2 = angle2; break; case 2: angle2 += 180; break; case 3: angle2 = angle2; break; case 4: angle2 += 90; break; } } else{ switch (start_number) { case 0: angle2 -= 90; break; case 1: angle2 += 90; break; case 2: angle2 -= 90; break; case 3: angle2 += 90; break; case 4: angle2 += 180; break; } } std::cout << "000000" << std::endl; } /********************************yellow***************************************/ else if ( lenth[4]>lenth[1]&&lenth[4]>lenth[0]&&lenth[4]>lenth[5]&&lenth[4]>lenth[3]&&lenth[4]>lenth[2])/////yellow { //center2 = (approx[2]+approx[3])/2; // center = (center2+approx[5])/2; center = (approx[2]+approx[5])/2; if(width < height){ if(approx[5].y<approx[0].y&&approx[5].y<approx[1].y&&approx[5].y<approx[2].y&&approx[5].y<approx[3].y&&approx[5].y<approx[4].y){ switch (start_number) { case 0: angle2 = angle2; break; case 1: angle2 += 180; break; case 2: angle2 = angle2; break; case 3: angle2 += 180; break; case 4: angle2 -= 90; break; } } else { switch (start_number) { case 0: angle2 += 180; break; case 1: angle2 = angle2; break; case 2: angle2 += 180; break; case 3: angle2 = angle2; break; case 4: angle2 += 90; break; } } } else if(width > height){ switch (start_number) { case 0: angle2 += 90; break; case 1: angle2 -= 90; break; case 2: angle2 += 90; break; case 3: angle2 -= 90; break; case 4: angle2 = angle2; break; } } std::cout << "444444" << std::endl; } /********************************yellow***************************************/ } if(center.y<60) { center.y=60; } if(center.x<82) { center.x=82; } if(center.y>=60&¢er.x>=82) { //cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x*1.2-92, center.y*1.285-76.5,1); cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x, center.y,1); // std::cout << pixelPointMat << std::endl; // pixelPointMat = (cv::Mat_<double>(3, 1) << 640, 360, 1); cameraPointMat = objectHeight * K.inv() * pixelPointMat; // std::cout << "相机坐标系下的三维坐标:" << std::endl; // std::cout << cameraPointMat << std::endl; obj_camera_frame1.setX(cameraPointMat.at<double>(0,0)); obj_camera_frame1.setY(cameraPointMat.at<double>(1,0)); obj_camera_frame1.setZ(cameraPointMat.at<double>(2,0)); obj_robot_frame = camera_to_robot_ * obj_camera_frame1; std::cout<< " X :" << obj_robot_frame.getX() << std::endl; std::cout<< " Y :" << obj_robot_frame.getY() << std::endl; std::cout<< " Z :" << obj_robot_frame.getZ() << std::endl; if(angle2>176) angle2=176; if(angle2<-176) angle2=-176; std::cout << " angle2 :" << angle2 << std::endl; Grasping(obj_robot_frame.getX(),obj_robot_frame.getY(),obj_robot_frame.getZ(),angle2); } } else if(contour.size()>0&&contour.size()<280) { std::cout << "没有黄紫像素坐标:" << std::endl; }} } //绿色和蓝色 void Camera_TO_Robot_Process_GB(const std::vector<std::vector<cv::Point>>& contours, int start_number, int end_number) { std::cout << "green or blue" << std::endl; // 输出提示信息 cv::Point2f center; for(start_number; start_number < end_number; start_number++) { const std::vector<cv::Point>& contour = contours[start_number]; if (contour.size()>300) { // 检查轮廓是否为空 // 获取最小外接矩形 cv::RotatedRect minRect = cv::minAreaRect(contours[start_number]); center = minRect.center; double angleInRadians = minRect.angle * M_PI / 180.0; if(center.y<60) { center.y=60; } if(center.x<82) { center.x=82; } if(center.y>=60&¢er.x>=82) { cv::Mat pixelPointMat = (cv::Mat_<double>(3, 1) << center.x, center.y,1); std::cout << pixelPointMat << std::endl; cameraPointMat = objectHeight * K.inv() * pixelPointMat; //平面下的坐标转为相机三维坐标 //相机坐标转为基座标 obj_camera_frame1.setX(cameraPointMat.at<double>(0, 0)); obj_camera_frame1.setY(cameraPointMat.at<double>(1, 0)); obj_camera_frame1.setZ(cameraPointMat.at<double>(2, 0)); obj_robot_frame= camera_to_robot_ * obj_camera_frame1; std::cout << "坐标为: " << obj_robot_frame << std::endl; /**************** 获取矩形的角度*******************/ double angle = minRect.angle; cv::Size2f size = minRect.size; double width = size.width; double height = size.height; //放平角度 if (width > height) { angle += 90; } Grasping(obj_robot_frame.getX(),obj_robot_frame.getY(),obj_robot_frame.getZ(),angle); } } else if(contour.size()>0&&contour.size()<100) { std::cout << "没有蓝绿像素坐标:" << std::endl; } } } }; /**********调用服务运行机械臂*********************/ int move_lineb_test(xarm_msgs::Move srv, ros::ServiceClient client, float x_mm0, float y_mm0, float z_mm0, double roll0, double pitch0, double yaw0, float x_mm1, float y_mm1, float z_mm1, double roll1, double pitch1, double yaw1, float x_mm2, float y_mm2, float z_mm2, double roll2, double pitch2, double yaw2, float x_mm3, float y_mm3, float z_mm3, double roll3, double pitch3, double yaw3, float x_mm4, float y_mm4, float z_mm4, double roll4, double pitch4, double yaw4) { // 设置机械臂的运动速度 srv.request.mvvelo = 160; // 设置机械臂的运动加速度 srv.request.mvacc = 1000; // 设置机械臂的运动时间 srv.request.mvtime = 0; // 设置机械臂运动路径的圆角半径 srv.request.mvradii = 20; ROS_INFO("ZUOBIAOR: %f, %f,%f", x_mm1, y_mm1, z_mm1); std::vector<float> pose[5] = { {x_mm0, y_mm0, z_mm0, static_cast<float>(roll0), static_cast<float>(pitch0), static_cast<float>(yaw0)}, {x_mm1, y_mm1, z_mm1, static_cast<float>(roll1), static_cast<float>(pitch1), static_cast<float>(yaw1)}, {x_mm2, y_mm2, z_mm2, static_cast<float>(roll2), static_cast<float>(pitch2), static_cast<float>(yaw2)}, {x_mm3, y_mm3, z_mm3, static_cast<float>(roll3), static_cast<float>(pitch3), static_cast<float>(yaw3)}, {x_mm4, y_mm4, z_mm4, static_cast<float>(roll4), static_cast<float>(pitch4), static_cast<float>(yaw4)} }; for(int i = 0; i < 5; i++) { srv.request.pose = pose[i]; if(client.call(srv)) { ROS_INFO("%s\n", srv.response.message.c_str()); std::cout << "success111" << std::endl; } else { ROS_ERROR("Failed to call service move_lineb"); } } return 0; } bool is_at_pose(const geometry_msgs::Pose& current_pose, const geometry_msgs::Pose& target_pose, double tolerance = 0.005) { return std::abs(current_pose.position.x - target_pose.position.x) < tolerance && std::abs(current_pose.position.y - target_pose.position.y) < tolerance && std::abs(current_pose.position.z - target_pose.position.z) < tolerance; } //阻塞服务,检测是否到达目标位置 void control_suction_during_move(float x_mm4, float y_mm4, float z_mm4) { // 定义目标位 moveit::planning_interface::MoveGroupInterface arm("xarm7"); ros::AsyncSpinner spinner(1); spinner.start(); geometry_msgs::Pose target_pose4; target_pose4.position.x = x_mm4 / 1000.0; target_pose4.position.y = y_mm4 / 1000.0; target_pose4.position.z = (z_mm4-76.7398-13.9+8.5) / 1000.0; bool suction_off_triggered = false; // 循环检查当前位姿 ros::Rate rate(10); // 10 Hz 检查频率 while (ros::ok()) { geometry_msgs::Pose current_pose = arm.getCurrentPose().pose; // ROS_INFO("ZUOBIAO_SHISHI: %f, %f, %f", current_pose.position.x, current_pose.position.y, current_pose.position.z); // 检查是否到达关闭吸盘的位置 if (!suction_off_triggered && is_at_pose(current_pose, target_pose4)) { ROS_INFO("Reached suction off position, trying to turn off suction."); sleep(0.8); writeSpeed(0); writeSpeed(0); writeSpeed(0); sleep(0.5); ROS_INFO("Suction off commands sent."); suction_off_triggered = true; } // 如果两个条件都满足,退出循环 if (suction_off_triggered) { break; } rate.sleep(); } } int main(int argc, char** argv) { // 初始化ROS节点 ros::init(argc, argv, "xarm_api"); ros::NodeHandle nh; XArmAPItest ic; nh.setParam("/xarm/wait_for_finish", true); ros::Publisher sleep_pub_ = nh.advertise<std_msgs::Float32>("/xarm/sleep_sec", 1); ros::ServiceClient motion_ctrl_client_ = nh.serviceClient<xarm_msgs::SetAxis>("/xarm/motion_ctrl"); ros::ServiceClient set_mode_client_ = nh.serviceClient<xarm_msgs::SetInt16>("/xarm/set_mode"); ros::ServiceClient set_state_client_ = nh.serviceClient<xarm_msgs::SetInt16>("/xarm/set_state"); ros::ServiceClient move_lineb_client_ = nh.serviceClient<xarm_msgs::Move>("/xarm/move_lineb"); xarm_msgs::SetAxis set_axis_srv_; xarm_msgs::SetInt16 set_int16_srv_; xarm_msgs::Move move_srv_; float x_mm0, y_mm0, z_mm0; double roll0, pitch0, yaw0; float x_mm1, y_mm1, z_mm1; double roll1, pitch1, yaw1; float x_mm2, y_mm2, z_mm2; double roll2, pitch2, yaw2; float x_mm3, y_mm3, z_mm3; double roll3, pitch3, yaw3; float x_mm4, y_mm4, z_mm4; double roll4, pitch4, yaw4; set_axis_srv_.request.id = 8; set_axis_srv_.request.data = 1; if(motion_ctrl_client_.call(set_axis_srv_)) { ROS_INFO("%s\n", set_axis_srv_.response.message.c_str()); } else { ROS_ERROR("Failed to call service motion_ctrl"); return 1; } set_int16_srv_.request.data = 0; if(set_mode_client_.call(set_int16_srv_)) { ROS_INFO("%s\n", set_int16_srv_.response.message.c_str()); } else { ROS_ERROR("Failed to call service set_mode"); return 1; } set_int16_srv_.request.data = 0; if(set_state_client_.call(set_int16_srv_)) { ROS_INFO("%s\n", set_int16_srv_.response.message.c_str()); } else { ROS_ERROR("Failed to call service set_state"); return 1; } nh.setParam("/xarm/wait_for_finish", false); std_msgs::Float32 sleep_msg; sleep_msg.data = 1.0; sleep_pub_.publish(sleep_msg); if(move_lineb_test(move_srv_, move_lineb_client_, x_mm0, y_mm0, z_mm0, roll0, pitch0, yaw0, x_mm1, y_mm1, z_mm1, roll1, pitch1, yaw1, x_mm2, y_mm2, z_mm2, roll2, pitch2, yaw2, x_mm3, y_mm3, z_mm3, roll3, pitch3, yaw3, x_mm4, y_mm4, z_mm4, roll4, pitch4, yaw4) == 1) return 1; // 调用 control_suction_during_move 函数 control_suction_during_move(x_mm4, y_mm4, z_mm4); sleep(0.8); nh.setParam("/xarm/wait_for_finish", true); while(ros::ok()) { ros::spinOnce(); } return 0; }解释一下

====================[ 构建 | DEMO.elf | Debug ]=================================== /Users/mac/Applications/CLion.app/Contents/bin/cmake/mac/aarch64/bin/cmake --build /Users/mac/NewFolder/DEMO_副本/cmake-build-debug --target DEMO.elf -- -j 6 [ 4%] Building C object CMakeFiles/DEMO.elf.dir/Core/Src/main.c.obj /Users/mac/NewFolder/DEMO_副本/Core/Src/main.c: In function 'ProcessKeyState': /Users/mac/NewFolder/DEMO_副本/Core/Src/main.c:243:40: error: passing argument 3 of 'LCD_Display_Words' makes pointer from integer without a cast [-Wint-conversion] 243 | LCD_Display_Words(3, 5, keyCtrl.in1Time); | ~~~~~~~^~~~~~~~ | | | uint32_t {aka long unsigned int} In file included from /Users/mac/NewFolder/DEMO_副本/Core/Src/main.c:23: /Users/mac/NewFolder/DEMO_副本/Core/Inc/LCD1602.h:23:55: note: expected 'uint8_t *' {aka 'unsigned char *'} but argument is of type 'uint32_t' {aka 'long unsigned int'} 23 | void LCD_Display_Words(uint8_t x, uint8_t y, uint8_t *str);//显示字; | ~~~~~~~~~^~~ /Users/mac/NewFolder/DEMO_副本/Core/Src/main.c:253:40: error: passing argument 3 of 'LCD_Display_Words' makes pointer from integer without a cast [-Wint-conversion] 253 | LCD_Display_Words(3, 5, keyCtrl.in2Time); | ~~~~~~~^~~~~~~~ | | | uint32_t {aka long unsigned int} /Users/mac/NewFolder/DEMO_副本/Core/Inc/LCD1602.h:23:55: note: expected 'uint8_t *' {aka 'unsigned char *'} but argument is of type 'uint32_t' {aka 'long unsigned int'} 23 | void LCD_Display_Words(uint8_t x, uint8_t y, uint8_t *str);//显示字; | ~~~~~~~~~^~~ make[3]: *** [CMakeFiles/DEMO.elf.dir/Core/Src/main.c.obj] Error 1 make[2]: *** [CMakeFiles/DEMO.elf.dir/all] Error 2 make[1]: *** [CMakeFiles/DEMO.elf.dir/rule] Error 2 make: *** [DEMO.elf] Error 2

#include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <stdlib.h> #include <json/json.h> #include #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "video.h" #include "motor.h" int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == sockfd) { perror("socket"); exit(1); } struct sockaddr_in ali_addr; memset(&ali_addr, 0, sizeof(ali_addr)); ali_addr.sin_family = AF_INET; ali_addr.sin_port = htons(ALI_PORT); ali_addr.sin_addr.s_addr = inet_addr(ALI_ADDR); //connect ali server if (connect(sockfd, (struct sockaddr *)&ali_addr, sizeof(ali_addr)) < 0) { perror("connect ali server failure"); exit(1); } //create json object struct json_object *obj = (struct json_object *)json_object_new_object(); json_object_object_add(obj, "cmd", json_object_new_string("info")); json_object_object_add(obj, "deviceid", json_object_new_string("0001")); const char *s = (const char *)json_object_to_json_string(obj); if (send(sockfd, s, strlen(s), 0) < 0) { perror("send to ali failure"); exit(1); } //recv server port info char buf[256] = {0}; if (recv(sockfd, buf, sizeof(buf), 0) < 0) { perror("recv from server failure"); exit(1); } struct json_object *json = json_tokener_parse(buf); struct json_object *cmd, *port; int server_udp_port; cmd = json_object_object_get(json, "cmd"); port = json_object_object_get(json, "port"); if (!strcmp((const char *)json_object_get_string(cmd), "port_info")) { server_udp_port = json_object_get_int(port); } else { printf("recv from server error\n"); } //start new thread, send video data to ali server pthread_t tid; pthread_create(&tid, NULL, send_video_data, &server_udp_port); while (1) { memset(buf, 0, sizeof(buf)); if (recv(sockfd, buf, sizeof(buf), 0) < 0) { perror("recv failure"); } json = json_tokener_parse(buf); struct json_object *cmd, *action; cmd = json_object_object_get(json, "cmd"); action = json_object_object_get(json, "action"); if (!strcmp((const char *)json_object_get_string(cmd), "control")) { const char *act = json_object_get_string(action); if (!strcmp(act, "left")) //left { motor_turn_left(); } else if (!strcmp(act, "right")) { motor_turn_right(); } else if (!strcmp(act, "up")) { motor_turn_up(); } else if (!strcmp(act, "down")) { motor_turn_down(); } } } return 0; }注释代码

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H ----------------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } 以上两个是.h和.cpp代码 --------------------------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>628</height> </rect> <string>MainWindow</string> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="pb_connect"> <rect> <x>40</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>连接</string> </widget> <widget class="QPushButton" name="pb_led0"> <rect> <x>40</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>led0_on</string> </widget> <widget class="QPushButton" name="pb_led1"> <rect> <x>40</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>led1_on</string> </widget> <widget class="QPushButton" name="pb_led2"> <rect> <x>40</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>led2_on</string> </widget> <widget class="QPushButton" name="pb_feng"> <rect> <x>40</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>feng_on</string> </widget> <widget class="QPushButton" name="pb_buzzer"> <rect> <x>140</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>蜂鸣器_on</string> </widget> <widget class="QPushButton" name="pb_humiture"> <rect> <x>140</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>温湿度_on</string> </widget> <widget class="QPushButton" name="pb_photosensitive"> <rect> <x>140</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>光敏_on</string> </widget> <widget class="QPushButton" name="pb_infrared"> <rect> <x>140</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>人体红外_on</string> </widget> <widget class="QPushButton" name="pb_camera"> <rect> <x>140</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>摄像头_on</string> </widget> <widget class="QTextBrowser" name="textBrowser"> <rect> <x>350</x> <y>10</y> <width>421</width> <height>211</height> </rect> </widget> </widget> <widget class="QMenuBar" name="menubar"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>28</height> </rect> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> 以上是.ui代码 --------------------------------------------------------- 目前项目进度: 当前项目结构如下: DXM1txst: DXM1txst.pro Headers: fsmpBeeper.h fsmpElectric.h fsmpEvents.h fsmpFan.h fsmpLed.h fsmpLight.h fsmpProximity.h fsmpsevensegLed.h fsmpTempHum.h fsmpvibrator.h mainwindow.h Sources: main.cpp mainwindow.cpp Forms: mainwindow.ui qtcreator内:ui界面中已经有组件:pb_connect(连接按钮)、pb_led0(电灯1开关按钮)、pb_led1(电灯2开关按钮)、pb_led2(电灯3开关按钮)、pb_feng(风扇开关按钮)、pb_buzzer(蜂鸣器开关按钮)、pb_humiture(温湿度传感器开关按钮)、pb_photosensitive(光敏传感器开关按钮)、pb_infrared(人体红外传感器开关按钮)、pb_camera(摄像头开关按钮)、textBrowser(用于接收和发布的消息显示)。 华清远见元宇宙实验中心物联网仿真系统内:所需的所以硬件的3D场景设计完毕,M4网关单元的Mqtt配置为: 地址:mqtt.yyzlab.com.cn 端口:1883 与应用层、云端交互的Topic: 订阅:1752365375766/APP2AIOTSIM 发布:1752365375766/AIOTSIM2APP 与硬件交互的Topic: 订阅:1752365382482/Device2AIOTSIM 发布:1752365382482/AIOTSIM2Device 与华清远见元宇宙实验中心物联网仿真系统内硬件开关发布的控制码为:电灯0开:{"lamp":true,"id":0},电灯0关:{"lamp":false,"id":0},电灯1开:{"lamp":true,"id":1},电灯1关:{"lamp":false,"id":1},电灯2开:{"lamp":true,"id":2},电灯2关:{"lamp":false,"id":2},风扇开:{"fan":true,"id":0},风扇关:{"fan":false,"id":0},人体红外传感器开:{"infrared ":true,"id":0},人体红外传感器关:{"infrarrared ":false,"id":0},温湿度传感器:{"tem":38.8,"hum":65.7,"id":0},光敏传感器:{"light":43037.0,"id":0} Stm32mp157开发板:所有需要的硬件部署完毕,硬件的.h代码如下(硬件的.h代码已经放入qtcreator项目下的Headers文件夹下,且硬件的所有.h文件内代码都不能再进行修改): fsmpBeeper.h: #ifndef FSMPBEEPER_H #define FSMPBEEPER_H /*************************************************************************** * * 类名:fsmpBeeper * 功能说明:扩展板 蜂鸣器 * 公有函数: * fsmpBeeper() * bool setRate(uint32_t rate) 设置频率 * bool start(void) 启动蜂鸣器 * bool stop(void) 关闭蜂鸣器 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> /* FSMP开发板(linux)蜂鸣器操作类 v0 2023/1/9 by 张城 */ class fsmpBeeper:public QObject{ Q_OBJECT public: explicit fsmpBeeper(const char *device = "/dev/input/event0", QObject *parent = nullptr) :QObject(parent) { event.type = EV_SND; time.tv_sec = 1; time.tv_usec = 0; event.time = time; beeper_fd = ::open(device,O_RDWR); if(beeper_fd < 0) { perror("open_beeper"); return; } }; ~fsmpBeeper() { ::close(beeper_fd); } /* * Description: 设置频率值 * input: rate 频率 * output: null * return: 成功true/失败false */ bool setRate(uint32_t rate = 1000) { if(rate > 0) { event.code = SND_TONE; event.value = rate; return true; } return false; } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ bool start(void) { int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool stop(void) { struct input_event event; event.type = EV_SND; event.code = SND_BELL; event.value = 0000; time.tv_sec = 1; time.tv_usec = 0; event.time = time; int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } private: int beeper_fd; //设备文件描述符 struct input_event event; struct timeval time; }; #endif // FSMPBEEPER_H ------------------------------------------------------- fsmpElectric.h: #ifndef ELC_H #define ELC_H /*************************************************************************** * * 类名:fsmpElectric * 功能说明:扩展板 电气信息检测 * 公有函数: * fsmpElectric() * float voltagemV(void) 获取电压mv(旋钮控制) * float currentmA(void) 获取电流ma(板载设备真实电流) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpElectric:public QObject{ Q_OBJECT public: explicit fsmpElectric(QObject *parent = nullptr) :QObject(parent) { } ~fsmpElectric(){ } float voltagemV(void) { electric_fd1 = open("/sys/bus/iio/devices/iio:device3/in_voltage1_raw",O_RDONLY|O_NONBLOCK); if(electric_fd1 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd1,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd1); return (float)3300 * val / 65536; } float currentmA(void) { electric_fd0 = open("/sys/bus/iio/devices/iio:device3/in_voltage0_raw",O_RDONLY|O_NONBLOCK); if(electric_fd0 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd0,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd0); return ((((float)3300 * val) /65536)/(10 + 100*1000 + 1000)) * 1000 / 0.1; } private: int electric_fd0; //设备文件描述符 int electric_fd1; //设备文件描述符 }; #endif // ELC_H ------------------------------------------------------- fsmpEvents.h: #ifndef ENV_H #define ENV_H /*************************************************************************** * * 类名:fsmpEvents * 功能说明:扩展板 按钮、人体红外、光闸管、火焰 * 公有函数: * fsmpEvents() * 信号: * void lightTriggered(); 光闸管阻隔 * void flameDetected(); 火焰检测 * void peopleDetected(bool); 人体红外发现true/离开false * void keyPressed(int keynum); 按键按下 keynum: 1、2、3 * void keyRelessed(int keynum); 按键释放 keynum: 1、2、3 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QTimer> #include #include <sys/ioctl.h> #include <QDebug> #include <QProcess> #include <QThread> #include <stdio.h> #include <stdlib.h> class fsmpEvents:public QObject{ Q_OBJECT signals: /* edge trigle !!!*/ void lightTriggered();//光电开关 void flameDetected();//火焰检测 void peopleDetected(bool);//人体红外 void keyPressed(int keynum); void keyRelessed(int keynum); public: explicit fsmpEvents(QObject *parent = nullptr):QObject(parent) { this->gpio_F_open(); this->gpio_E_open(); fs_timer = new QTimer(this); connect(fs_timer,SIGNAL(timeout()),this,SLOT(time_out())); fs_timer->start(10); }; private: bool gpio_F_open(const char *device = "/dev/gpiochip5") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 9; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE|GPIOEVENT_REQUEST_RISING_EDGE; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_1_fd = event_req.fd; int flags = fcntl(key_1_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_1_fd,F_SETFL,flags); event_req.lineoffset = 8; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_3_fd = event_req.fd; flags = fcntl(key_3_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_3_fd,F_SETFL,flags); #if 0 event_req.lineoffset = 5; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } fire_fd = event_req.fd; flags = fcntl(fire_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(fire_fd,F_SETFL,flags); #endif // fire req.lineoffsets[0] = 5; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "fire"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } fire_fd = req.fd; // key2 req.lineoffsets[0] = 7; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } key_2_fd = req.fd; // people req.lineoffsets[0] = 12; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } people_fd = req.fd; return true; } bool gpio_E_open(const char *device = "/dev/gpiochip4") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 15; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } light_trigger_fd = event_req.fd; int flags = fcntl(light_trigger_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(light_trigger_fd,F_SETFL,flags); return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool close(void); public slots: void time_out() { static int key_1_flag = 0; static int key_2_flag = 0; static int key_3_flag = 0; static int light_trigger_flag = 0; static int people_flag = 0; static int flame_flag = 0; //捕获key_1按下 read(key_1_fd,&event_data,sizeof (event_data)); if(event_data.id == 2) { key_1_flag = 1; emit(this->keyPressed(1)); //qDebug()<<"key_1 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_1_flag==1) { key_1_flag = 0; emit keyRelessed(1); //qDebug()<<"key_1 relessed"; } event_data.id = 0; //捕获key_2按下 int ret = ioctl(key_2_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << "==========" << data.values[0]; if(data.values[0] ==0&&key_2_flag==0) { emit(this->keyPressed(2)); key_2_flag = 1; //qDebug()<<"key_2 pressed"; } else if(data.values[0] ==1&&key_2_flag==1) { key_2_flag = 0; emit keyRelessed(2); //qDebug()<<"key_2 relessed"; } //event_data.id = 0; //捕获key_3按下 read(key_3_fd,&event_data,sizeof (event_data)); //qDebug() << "key3 "<< event_data.id; if(event_data.id == 2 && key_3_flag==0) { key_3_flag = 1; emit(this->keyPressed(3)); //qDebug()<<"key_3 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_3_flag==1) { key_3_flag = 0; emit keyRelessed(3); //qDebug()<<"key_3 relessed"; } event_data.id = 0; //捕获光电开关 read(light_trigger_fd,&event_data,sizeof (event_data)); if(event_data.id == 1 && light_trigger_flag==0) { //qDebug()<<"light triggered"; light_trigger_flag = 1; emit(this->lightTriggered()); } else light_trigger_flag = 0; event_data.id = 0; //捕获people coming ret = ioctl(people_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } if(data.values[0] ==1&&people_flag==0) { emit(this->peopleDetected(true)); people_flag = 1; //qDebug()<<"people coming"; } else if(data.values[0] ==0&&people_flag==1) { people_flag = 0; emit(this->peopleDetected(false)); //qDebug()<<"people leave"; } #if 0 //捕获火焰检测 read(fire_fd,&event_data,sizeof (event_data)); qDebug() << "------------------"<<event_data.id; if(event_data.id == 2 && flame_flag == 0) { qDebug()<<"flamedetection on"; flame_flag = 1; emit(this->flameDetected(true)); event_data.id = 0; } else if(event_data.id == 0 && flame_flag == 1) { qDebug()<<"flamedetection off"; flame_flag = 0; emit(this->flameDetected(false)); event_data.id = 0; } #endif //捕获key_2按下 ret = ioctl(fire_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << data.values[0]; if(data.values[0] ==1&&flame_flag==0) { emit(this->flameDetected()); flame_flag = 1; //qDebug()<<"flame on"; } else flame_flag = 0; } private: struct gpiohandle_request req; struct gpiohandle_data data; struct gpiochip_info chip_info; struct gpioevent_request event_req; struct gpioevent_data event_data; struct gpiod_chip *gpiochip5; struct gpiod_line *gpioline5_7; int key_1_fd; //设备文件描述符 int key_2_fd; int key_3_fd; int light_trigger_fd; int people_fd; int fire_fd; QTimer * fs_timer; }; #endif //ENV_H ------------------------------------------------------- fsmpFan.h: #ifndef FAN_H #define FAN_H /*************************************************************************** * * 类名:fsmpFan * 功能说明:扩展板 风扇控制 * 公有函数: * fsmpFan() * void start(void) 开启风扇) * void stop(void) 关闭风扇 * void setSpeed(int speed) 设置风扇速度(0-255) * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpFan:public QObject{ Q_OBJECT public: explicit fsmpFan(QObject *parent = nullptr):QObject(parent) { const char *device = "/sys/class/hwmon/hwmon1/pwm1"; fan_fd = ::open(device,O_WRONLY|O_TRUNC); if(fan_fd < 0) { perror("open fan"); return; } fan_speed = 0; }; ~fsmpFan(){ ::close(fan_fd); } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ void stop(void) { write(fan_fd,"0",strlen("0")); } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ void start(void) { char speedstr[100] = {0}; sprintf(speedstr, "%d", fan_speed); write(fan_fd, speedstr, strlen(speedstr)); } /* * Description: 控制风扇转速 * intput: speed 转速 * output: null * return: null */ void setSpeed(int speed) { fan_speed = speed%255; } private: int fan_fd; //设备文件描述符 int fan_speed; }; #endif // FAN_H ------------------------------------------------------- fsmpLeds.h: #ifndef LED_H #define LED_H /*************************************************************************** * * 类名:fsmpLeds * 功能说明:扩展板 3颗灯泡 * 公有函数: * fsmpLeds() * bool on(lednum x) 开灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * bool off(lednum x) 关灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpLeds:public QObject{ Q_OBJECT public: enum lednum{ LED1, LED2, LED3 }; explicit fsmpLeds(QObject *parent = nullptr) :QObject(parent) { led_fd1 = ::open("/sys/class/leds/led1/brightness",O_WRONLY|O_TRUNC); if(led_fd1 < 0) { perror("open led1"); return ; } led_fd2 = ::open("/sys/class/leds/led2/brightness",O_WRONLY|O_TRUNC); if(led_fd2 < 0) { perror("open led2"); return ; } led_fd3 = ::open("/sys/class/leds/led3/brightness",O_WRONLY|O_TRUNC); if(led_fd3 < 0) { perror("open led3"); return ; } } ~fsmpLeds() { ::close(led_fd1); ::close(led_fd2); ::close(led_fd3); } /* * Description: 开启设备,默认/sys/class/leds/led1/brightness * input: lednum * output: null * return: 成功true/失败false */ bool on(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"1",1); if(ret < 0) { return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool off(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"0",1); if(ret < 0) { return false; } return true; } private: int led_fd1; //设备文件描述符 int led_fd2; //设备文件描述符 int led_fd3; //设备文件描述符 }; #endif // LED_H ------------------------------------------------------- fsmpLight.h: #ifndef LIGHT_H #define LIGHT_H /*************************************************************************** * * 类名:fsmpLight * 功能说明:扩展板 光照强度检测 * 公有函数: * fsmpLight() * double getValue(void) 获取光照强度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpLight:public QObject{ Q_OBJECT public: explicit fsmpLight(QObject *parent = nullptr) :QObject(parent) { light_fd = ::open("/sys/bus/iio/devices/iio:device1/in_illuminance_input",O_RDONLY|O_NONBLOCK); if(light_fd < 0) { perror("open"); return; } } ~fsmpLight() { ::close(light_fd); } /* * Description: 获取光照强度 * input: null * output: null * return: current light */ double getValue(void) { char buf[10] = {0}; int ret = read(light_fd,buf,10); if(ret < 0) { perror("read"); return false; } double num; sscanf(buf, "%lf", &num); lseek(light_fd, 0, SEEK_SET); return num; } private: int light_fd; //设备文件描述符 }; #endif // LIGHT_H ------------------------------------------------------- fsmpProximity.h: #ifndef FSMPPROXIMITY_H #define FSMPPROXIMITY_H /*************************************************************************** * * 类名:fsmpProximity * 功能说明:扩展板 红外接近传感器(和光照传感器一起) * 公有函数: * fsmpProximity() * double getValue(void) 获取接近情况(0-2048越接近数据越大) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpProximity:public QObject{ Q_OBJECT public: explicit fsmpProximity(QObject *parent = nullptr) :QObject(parent) { proximity_fd = ::open("/sys/bus/iio/devices/iio:device1/in_proximity_raw",O_RDONLY|O_NONBLOCK); if(proximity_fd < 0) { perror("open"); return; } } ~fsmpProximity() { ::close(proximity_fd); } /* * Description: 获取distence * input: null * output: null * return: current light */ int getValue(void) { char buf[10] = {0}; int ret = read(proximity_fd,buf,10); if(ret < 0) { perror("read"); return false; } int num; sscanf(buf, "%d", &num); lseek(proximity_fd, 0, SEEK_SET); return num; } private: int proximity_fd; //设备文件描述符 }; #endif // FSMPPROXIMITY_H ------------------------------------------------------- fsmpSevensegLed.h: #ifndef FSMPSEVENSEGLED_H #define FSMPSEVENSEGLED_H /*************************************************************************** * * 类名:fsmpSevensegLed * 功能说明:扩展板 七段数码管 * 公有函数: * fsmpSevensegLed() * void display(int value) 显示4位以内整数 * void display(const char *str) 显示4位字符,注:仅支持 a、b、c、d、e * * 信号: * 无 * * *************************************************************************/ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include #include #include <QThread> #include <stdlib.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) class fsmpSevensegLed:public QThread{ Q_OBJECT public: explicit fsmpSevensegLed(QObject *parent = nullptr) :QThread(parent) { memset(data, 0, sizeof(data)); device = "/dev/spidev0.0"; bits = 8; speed = 400000; delay = 0; } void display(int value) { data[3] = value%10; data[2] = value/10%10; data[1] = value/100%10; data[0] = value/1000%10; } //"abcde" void display(const char *str) { data[3] = (strlen(str)-1 >= 0)?(str[strlen(str)-1] - 'a')+10:0; data[2] = (strlen(str)-2 >= 0)?(str[strlen(str)-2] - 'a')+10:0; data[1] = (strlen(str)-3 >= 0)?(str[strlen(str)-3] - 'a')+10:0; data[0] = (strlen(str)-4 >= 0)?(str[strlen(str)-4] - 'a')+10:0; } private: void run() { int ret = 0; int fd; fd = open(device, O_RDWR); //打开设备文件 if (fd < 0) pabort("can't open device"); /* * spi mode //设置spi设备模式 */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); //写模式 if (ret == -1) pabort("can't set spi mode"); /* * bits per word //设置每个字含多少位 */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); //写每个字含多少位 if (ret == -1) pabort("can't set bits per word"); /* * max speed hz //设置速率 */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); //写速率 if (ret == -1) pabort("can't set max speed hz"); //打印模式,每字多少位和速率信息 printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); //transfer(fd); //传输测试 int i = 0; int pos = 0; unsigned char buf[2]; while(1) { pos = 1 << (i % 4); buf[0] = pos; buf[1] = num[data[i]]; if (write(fd, buf, 2) < 0) perror("write"); i++; if (i == 4) { i = 0; } usleep(3500); } } static void pabort(const char *s) { perror(s); abort(); } const char *device; uint8_t mode; uint8_t bits; uint32_t speed; uint16_t delay; int data[4]; unsigned char num[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; }; #endif // FSMPSEVENSEGLED_H ------------------------------------------------------- fsmpTempHum.h: #ifndef TEMPHUM_H #define TEMPHUM_H /*************************************************************************** * * 类名:fsmpTempHum * 功能说明:扩展板 温度湿度 * 公有函数: * fsmpTempHum() * double temperature(void) 提取温度 * double humidity(void) 提取湿度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpTempHum:public QObject{ Q_OBJECT public: explicit fsmpTempHum(QObject *parent = nullptr) :QObject(parent) { } double temperature(void) { int temp_raw = 0; int temp_offset = 0; float temp_scale = 0; open_device_int("iio:device0","in_temp_raw",&temp_raw); open_device_int("iio:device0","in_temp_offset",&temp_offset); open_device_float("iio:device0","in_temp_scale",&temp_scale); return (temp_raw + temp_offset) * temp_scale / 1000; } double humidity(void) { int hum_raw = 0; int hum_offset = 0; float hum_scale = 0; open_device_int("iio:device0","in_humidityrelative_raw",&hum_raw); open_device_int("iio:device0","in_humidityrelative_offset",&hum_offset); open_device_float("iio:device0","in_humidityrelative_scale",&hum_scale); return (hum_raw + hum_offset) * hum_scale / 1000; } private: bool open_device_int(const char *device, const char *filename, int *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%d",val); ::close(fd); return true; } bool open_device_float(const char *device, const char *filename, float *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%f",val); ::close(fd); return true; } private: int temp_hum_fd;; //设备文件描述符 }; #endif // TEMPHUM_H ------------------------------------------------------- fsmpVibrator.h: #ifndef VIBRATOR_H #define VIBRATOR_H /*************************************************************************** * * 类名:fsmpVibrator * 功能说明:扩展板 振动马达 * 公有函数: * fsmpVibrator() * bool setParameter(int strong_magnitude, int timems) 设置振动强度(0-0xffff)及时长(ms) * bool start(void) 启动马达 * bool stop(void) 停止马达 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <sys/ioctl.h> #include <QDebug> class fsmpVibrator:public QObject{ Q_OBJECT public: explicit fsmpVibrator(QObject *parent = nullptr) :QObject(parent) { vibrator_fd = ::open("/dev/input/event1", O_RDWR|O_NONBLOCK); if(vibrator_fd < 0) { perror("open vibrator"); } } ~fsmpVibrator() { ::close(vibrator_fd); } /* * Description:设置 * input:频率 * output:null * return:成功true/失败false */ bool setParameter(int strong_magnitude = 0xFFFF, int timems = 5000) { //qDebug()<<strong_magnitude<<timems; effect.type = FF_RUMBLE, effect.id = -1, effect.u.rumble.strong_magnitude = strong_magnitude; effect.u.rumble.weak_magnitude = 0; effect.replay.length = timems; effect.replay.delay = 0; if (ioctl(vibrator_fd, EVIOCSFF, &effect) < 0) { printf("Error creating new effect: %s\n", strerror(errno)); return false; } return true; } bool start(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 1 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator on"); return false; } //qDebug()<<"start"; return true; } bool stop(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 0 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator off"); return false; } //qDebug()<<"stop"; return true; } private: int vibrator_fd;//设备文件描述符 struct ff_effect effect; }; #endif // VIBRATOR_H ------------------------------------------------------- 项目目的: 在Linux下通过qtcreator编写后通过st-mp1构建部署到远程Linux主机后,在Stm32mp157开发板上能够控制本身的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。并且通过Desktop Qt5.12.12 GCC64bit构建部署到Deploy Configuration时,能够控制Stm32mp157开发板上的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。 设计要求: 1. 通过点击pb_connect(连接按钮)按钮可以连接到云端mqtt,连接成功则弹出小窗提示连接成功并自动绑定订阅与发布功能、连接失败则弹出小窗提示连接失败,弹出的小窗有一个确定键,点击确定关闭小窗。 2. 点击按钮pb_led0打开Stm32mp157开发板上的LD1灯且同步打开华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(初始化为led0_on)变更为led0_off。再次点击按钮pb_led0时关闭Stm32mp157开发板上的LD1灯且同步关闭华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(此时为led0_off)变更为led0_on。按钮pb_led1和pb_led2也是相同理论。 3. 点击按钮pb_feng打开Stm32mp157开发板上的风扇且同步打开华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(初始化为feng_on)变更为feng_off。再次点击按钮pb_feng时关闭Stm32mp157开发板上的风扇且同步关闭华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(此时为feng_off)变更为feng_on。 4. 点击按钮pb_buzzer打开Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(初始化为:蜂鸣器_on)变更为蜂鸣器_off。再次点击按钮pb_buzzer时关闭Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(此时为:蜂鸣器_off)变更为蜂鸣器_on。 5. 点击按钮pb_humiture时,打开Stm32mp157开发板上的温湿度传感器并将数据显示在textBrowser组件上。此时按钮pb_humiture上的文本(初始化为:温湿度_on)变更为温湿度_off。再次点击按钮pb_humiture时关闭Stm32mp157开发板上的温湿度传感器,此时按钮pb_humiture上的文本(此时为:温湿度_off)变更为温湿度_on。(需添加功能:打开Stm32mp157开发板上的温湿度传感器后,当温度超过30度时蜂鸣器会立即开启,低于30度或者直接点击按钮pb_buzzer都可关闭蜂鸣器) 6. 点击按钮pb_photosensitive时,打开Stm32mp157开发板上的光敏传感器并将数据显示在textBrowser组件上。此时按钮pb_photosensitive上的文本(初始化为:光敏_on)变更为光敏_off。再次点击按钮pb_photosensitive时关闭Stm32mp157开发板上的光敏传感器,此时按钮pb_photosensitive上的文本(此时为:光敏_off)变更为光敏_on。 7. 点击按钮pb_infrared时,打开Stm32mp157开发板上的人体红外传感器并将数据显示在textBrowser组件上。此时按钮pb_infrared上的文本(初始化为:人体红外_on)变更为人体红外_off。再次点击按钮pb_infrared时关闭Stm32mp157开发板上的人体红外传感器,此时按钮pb_infrared上的文本(此时为:人体红外_off)变更为人体红外_on。 8. 点击按钮pb_camera时打开Stm32mp157开发板上的摄像头并将采集到的图像在屏幕界面的右侧显示出来(目前项目中没有设计用于显示摄像头采集图像显示的组件,需要添加)。此时按钮pb_camera上的文本(初始化为:摄像头_on)变更为摄像头off。再次点击按钮pb_camera时关闭Stm32mp157开发板上的摄像头,此时按钮pb_camera上的文本(此时为:摄像头_off)摄像头_on,并关闭摄像头采集的图像显示界面。 结合以上代码及要求,进行完整详细的项目开发,如有需要可以添加项目结构内缺失的文件(项目结构内缺失硬件的.cpp文件),硬件.h文件不可进行修改。整合后将项目的所有文件发我,让我复制粘贴就能直接使用

大家在看

recommend-type

公开公开公开公开-openprotocol_specification 2.7

LY-WCS-2012-01-06-01 V 1.0 公开公开公开公开 产品名称:产品名称:产品名称:产品名称: WCS 系统简介系统简介系统简介系统简介-公开版公开版公开版公开版 共共共共 13 页页页页 WCSWCSWCSWCS 系统简介系统简介系统简介系统简介 ((((客户交流用客户交流用客户交流用客户交流用)))) 文文文文 档档档档 作作作作 者:者:者:者: 王 超 日期:日期:日期:日期:2012/01/06 开发开发开发开发/测试经理:测试经理:测试经理:测试经理: 程 达 日期:日期:日期:日期:2012/01/06 项项项项 目目目目 经经经经 理:理:理:理: 程 达 日期:日期:日期:日期:2012/01/06 文文文文 档档档档 编编编编 号:号:号:号: ___________ ___ LY-WCS-2012-01-06-01______________ 上海朗因智能科技有限公司上海朗因智能科技有限公司上海朗因智能科技有限公司上海朗因智能科技有限公司 版权所有版权所有版权所有版权所有 不得复制不得复制不得复制不得复制
recommend-type

中国联通OSS系统总体框架

中国联通OSS系统总体框架。中国联通OSS系统总体框架。
recommend-type

基于 ADS9110的隔离式数据采集 (DAQ) 系统方案(待编辑)-电路方案

描述 该“可实现最大 SNR 和采样率的 18 位 2Msps 隔离式数据采集参考设计”演示了如何应对隔离式数据采集系统设计中的典型性能限制挑战: 通过将数字隔离器引入的传播延迟降至最低,使采样率达到最大 通过有效地减轻数字隔离器引入的 ADC 采样时钟抖动,使高频交流信号链性能 (SNR) 达到最大 特性 18 位、2Msps、1 通道、差分输入、隔离式数据采集 (DAQ) 系统 利用 ADS9110 的 multiSPI:trade_mark: 数字接口实现 2MSPS 采样率,同时保持低 SPI 数据速率 源同步 SPI 数据传输模式,可将隔离器传播延迟降至最低并提高采样率 可降低隔离器引入的抖动的技术,能够将 SNR 提高 12dB(100kHz Fin,2MSPS) 经测试的设计包含理论和计算、组件选择、PCB 设计和测量结果 原理图 附件文档: 方案相关器件: ISO1541:低功耗、双向 I2C 隔离器 ISO7840:高性能 5.7kVRMS 增强型四通道数字隔离器 ISO7842:高性能 5.7kVRMS 增强型四通道数字隔离器
recommend-type

自动化图书管理系统 v7.0

自动化图书馆管理系统包含了目前图书馆管理业务的每个环节,能同时管理图书和期刊,能打印条码、书标,并制作借书证,最大藏书量在300万册以上。系统采用CNMARC标准及中图法第四版分类,具有Web检索与发布功能,条码扫描,支持一卡通,支持触摸屏。系统包括系统管理、读者管理、编目、流通、统计、查询等功能。能够在一个界面下实现图书、音像、期刊的管理,设置假期、设置暂离锁(提高安全性)、暂停某些读者的借阅权、导入导出读者、交换MARC数据、升级辅助编目库等。安装本系统前请先安装SQL 2000SQL 下载地址 http://pan.baidu.com/s/145vkr安装过程如有问题可咨询: TEL 13851381727  QQ 306404635
recommend-type

MOXA UPort1110drvUSB转串口驱动

MOXA UPort1110drvUSB转串口驱动,解决没有com口的烦恼

最新推荐

recommend-type

{团队建设}网络渠道部团队规划手册.pdf

{团队建设}网络渠道部团队规划手册.pdf
recommend-type

快速付里叶变换FFTFastFourietTransformer(1).pptx

快速付里叶变换FFTFastFourietTransformer(1).pptx
recommend-type

Wamp5: 一键配置ASP/PHP/HTML服务器工具

根据提供的文件信息,以下是关于标题、描述和文件列表中所涉及知识点的详细阐述。 ### 标题知识点 标题中提到的是"PHP集成版工具wamp5.rar",这里面包含了以下几个重要知识点: 1. **PHP**: PHP是一种广泛使用的开源服务器端脚本语言,主要用于网站开发。它可以嵌入到HTML中,从而让网页具有动态内容。PHP因其开源、跨平台、面向对象、安全性高等特点,成为最流行的网站开发语言之一。 2. **集成版工具**: 集成版工具通常指的是将多个功能组合在一起的软件包,目的是为了简化安装和配置流程。在PHP开发环境中,这样的集成工具通常包括了PHP解释器、Web服务器以及数据库管理系统等关键组件。 3. **Wamp5**: Wamp5是这类集成版工具的一种,它基于Windows操作系统。Wamp5的名称来源于它包含的主要组件的首字母缩写,即Windows、Apache、MySQL和PHP。这种工具允许开发者快速搭建本地Web开发环境,无需分别安装和配置各个组件。 4. **RAR压缩文件**: RAR是一种常见的文件压缩格式,它以较小的体积存储数据,便于传输和存储。RAR文件通常需要特定的解压缩软件进行解压缩操作。 ### 描述知识点 描述中提到了工具的一个重要功能:“可以自动配置asp/php/html等的服务器, 不用辛辛苦苦的为怎么配置服务器而烦恼”。这里面涵盖了以下知识点: 1. **自动配置**: 自动配置功能意味着该工具能够简化服务器的搭建过程,用户不需要手动进行繁琐的配置步骤,如修改配置文件、启动服务等。这是集成版工具的一项重要功能,极大地降低了初学者的技术门槛。 2. **ASP/PHP/HTML**: 这三种技术是Web开发中常用的组件。ASP (Active Server Pages) 是微软开发的服务器端脚本环境;HTML (HyperText Markup Language) 是用于创建网页的标准标记语言;PHP是服务器端脚本语言。在Wamp5这类集成环境中,可以很容易地对这些技术进行测试和开发,因为它们已经预配置在一起。 3. **服务器**: 在Web开发中,服务器是一个运行Web应用程序并响应客户端请求的软件或硬件系统。常见的服务器软件包括Apache、Nginx等。集成版工具提供了一个本地服务器环境,使得开发者可以在本地测试他们的应用程序。 ### 标签知识点 标签中仅出现了“PHP”一个关键词,这意味着该工具专注于与PHP相关的开发环境配置。 ### 压缩包子文件的文件名称列表知识点 1. **wamp.exe**: 这是Wamp5集成版工具的可执行文件,用户通过运行这个文件,即可启动Wamp5环境,开始进行PHP等相关开发。 2. **使用说明文档.txt**: 通常这样的文本文件包含了软件的安装指南、功能介绍、常见问题解答以及操作教程等内容。它是用户了解和使用软件的重要辅助资料,可以帮助用户快速上手。 ### 总结 Wamp5作为一个PHP集成版工具,为PHP开发者提供了一个便捷的本地开发环境。它通过自动化配置减少了开发者在搭建环境时的麻烦,整合了Web开发的关键组件,从而使得开发者能够专注于代码的编写,而不是环境配置。此外,它还提供了详尽的使用文档,帮助用户理解和运用这一工具,有效地提高了开发效率。对于希望快速入门PHP或需要一个简单易用的本地开发环境的开发者来说,Wamp5是一个非常好的选择。
recommend-type

【数据融合技术】:甘肃土壤类型空间分析中的专业性应用

# 摘要 数据融合技术作为一种集成多源数据信息的方法,在土壤类型空间分析中发挥着关键作用。本文介绍了数据融合技术的基本概念及其理论基础,阐述了数据预处理、同步整合及冲突解决等关键技术,并详细描述了甘肃土壤类型数据准备的流程,包括数据采集、质量评估、空间化处理及融合实践准备。通过具体案例分析,展示了数据融合在土壤类型空间分布分析、土壤质量评估及土壤保护规划中的应用。同时,文
recommend-type

sht20温湿度传感器使用什么将上拉电阻和滤波电容引出

<think>好的,我需要解决用户关于SHT20温湿度传感器的上拉电阻和滤波电容的引出方法问题。首先,我得回忆一下SHT20的基本特性和常见电路设计。SHT20是数字传感器,通常使用I2C接口,所以上拉电阻是必须的,用于确保数据线和时钟线的稳定。根据引用[2],SHT10是通过SCK和DATA线与单片机通信,而SHT30在引用[3]中使用I2C协议,需要上拉电阻。虽然用户问的是SHT20,但SHT系列通常设计类似,所以可以推断SHT20也需要类似的上拉电阻配置。通常I2C总线的上拉电阻值在4.7kΩ到10kΩ之间,但具体值可能取决于总线速度和电源电压。需要确认数据手册中的推荐值,但用户可能没有
recommend-type

Delphi仿速达财务软件导航条组件开发教程

Delphi作为一款历史悠久的集成开发环境(IDE),由Embarcadero Technologies公司开发,它使用Object Pascal语言,被广泛应用于Windows平台下的桌面应用程序开发。在Delphi中开发组件是一项核心技术,它允许开发者创建可复用的代码单元,提高开发效率和软件模块化水平。本文将详细介绍如何在Delphi环境下仿制速达财务软件中的导航条组件,这不仅涉及到组件的创建和使用,还会涉及界面设计和事件处理等技术点。 首先,需要了解Delphi组件的基本概念。在Delphi中,组件是一种特殊的对象,它们被放置在窗体(Form)上,可以响应用户操作并进行交互。组件可以是可视的,也可以是不可视的,可视组件在设计时就能在窗体上看到,如按钮、编辑框等;不可视组件则主要用于后台服务,如定时器、数据库连接等。组件的源码可以分为接口部分和实现部分,接口部分描述组件的属性和方法,实现部分包含方法的具体代码。 在开发仿速达财务软件的导航条组件时,我们需要关注以下几个方面的知识点: 1. 组件的继承体系 仿制组件首先需要确定继承体系。在Delphi中,大多数可视组件都继承自TControl或其子类,如TPanel、TButton等。导航条组件通常会继承自TPanel或者TWinControl,这取决于导航条是否需要支持子组件的放置。如果导航条只是单纯的一个显示区域,TPanel即可满足需求;如果导航条上有多个按钮或其他控件,可能需要继承自TWinControl以提供对子组件的支持。 2. 界面设计与绘制 组件的外观和交互是用户的第一印象。在Delphi中,可视组件的界面主要通过重写OnPaint事件来完成。Delphi提供了丰富的绘图工具,如Canvas对象,使用它可以绘制各种图形,如直线、矩形、椭圆等,并且可以对字体、颜色进行设置。对于导航条,可能需要绘制背景图案、分隔线条、选中状态的高亮等。 3. 事件处理 导航条组件需要响应用户的交互操作,例如鼠标点击事件。在Delphi中,可以通过重写组件的OnClick事件来响应用户的点击操作,进而实现导航条的导航功能。如果导航条上的项目较多,还可能需要考虑使用滚动条,让更多的导航项能够显示在窗体上。 4. 用户自定义属性和方法 为了使组件更加灵活和强大,开发者通常会为组件添加自定义的属性和方法。在导航条组件中,开发者可能会添加属性来定义按钮个数、按钮文本、按钮位置等;同时可能会添加方法来处理特定的事件,如自动调整按钮位置以适应不同的显示尺寸等。 5. 数据绑定和状态同步 在财务软件中,导航条往往需要与软件其他部分的状态进行同步。例如,用户当前所处的功能模块会影响导航条上相应项目的选中状态。这通常涉及到数据绑定技术,Delphi支持组件间的属性绑定,通过数据绑定可以轻松实现组件状态的同步。 6. 导航条组件的封装和发布 开发完毕后,组件需要被封装成独立的单元供其他项目使用。封装通常涉及将组件源码保存为pas文件,并在设计时能够在组件面板中找到。发布组件可能还需要编写相应的安装包和使用文档,方便其他开发者安装和使用。 7. Delphi IDE的支持 Delphi IDE提供了组件面板编辑器(Component Palette),允许开发者将开发好的组件添加到组件面板中。在组件面板编辑器中,可以自定义组件的图标和分类,使得组件在Delphi中的使用更为便捷。 通过以上的知识点梳理,可以看出Delphi仿速达导航条组件的开发涉及到的不仅仅是简单的代码编写,还涉及到用户界面设计、事件驱动编程、组件封装等多个方面。掌握这些知识点,对于一名Delphi开发者而言,是十分重要的。
recommend-type

【空间分布规律】:甘肃土壤类型与农业生产的关联性研究

# 摘要 本文对甘肃土壤类型及其在农业生产中的作用进行了系统性研究。首先概述了甘肃土壤类型的基础理论,并探讨了土壤类型与农业生产的理论联系。通过GIS技术分析,本文详细阐述了甘肃土壤的空间分布规律,并对其特征和影响因素进行了深入分析。此外,本文还研究了甘肃土壤类型对农业生产实际影响,包括不同区域土壤改良和作物种植案例,以及土壤养分、水分管理对作物生长周期和产量的具体影响。最后,提出了促进甘肃土壤与农业可持续发展的策略,包括土壤保护、退化防治对策以及土壤类型优化与农业创新的结合。本文旨在为
recommend-type

常见运放电路的基本结构和基本原理

<think>首先,用户的问题是关于运算放大器电路的基本结构和工作原理。我需要根据系统级指令来构建回答。系统级指令:-所有行内数学表达式必须使用$...$格式。-独立公式必须使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添加引用标识,例如[^1]。-回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。参考站内引用:-引用[1]:关于运算放大器基本电路用法,特别是反相放大器电路。-引用[2]:关于uA741运算放大器电路的基本原理,包括输入级、输出级等。用户的问题:"我想了解运放电路的基本结构和工作原理请问运算放大器电路
recommend-type

ASP.NET2.0初学者个人网站实例分享

标题:“ASP.NET 2.0个人网站”指向了一个网站开发项目,这个项目是使用ASP.NET 2.0框架构建的。ASP.NET 2.0是微软公司推出的一种用于Web开发的服务器端技术,它是.NET Framework的一部分。这个框架允许开发者构建动态网站、网络应用程序和网络服务。开发者可以使用C#或VB.NET等编程语言来编写应用程序。由于这被标签为“2.0”,我们可以假设这是一个较早版本的ASP.NET,相较于后来的版本,它可能没有那么先进的特性,但对于初学者来说,它提供了基础并且易于上手的工具和控件来学习Web开发。 描述:“个人练习所做,适合ASP.NET初学者参考啊,有兴趣的可以前来下载去看看,同时帮小弟我赚些积分”提供了关于该项目的背景信息。它是某个个人开发者或学习者为了实践和学习ASP.NET 2.0而创建的个人网站项目。这个项目被描述为适合初学者作为学习参考。开发者可能是为了积累积分或网络声誉,鼓励他人下载该项目。这样的描述说明了该项目可以被其他人获取,进行学习和参考,或许还能给予原作者一些社区积分或其他形式的回报。 标签:“2.0”表明这个项目专门针对ASP.NET的2.0版本,可能意味着它不是最新的项目,但是它可以帮助初学者理解早期ASP.NET版本的设计和开发模式。这个标签对于那些寻找具体版本教程或资料的人来说是有用的。 压缩包子文件的文件名称列表:“MySelf”表示在分享的压缩文件中,可能包含了与“ASP.NET 2.0个人网站”项目相关的所有文件。文件名“我的”是中文,可能是指创建者以“我”为中心构建了这个个人网站。虽然文件名本身没有提供太多的信息,但我们可以推测它包含的是网站源代码、相关资源文件、数据库文件(如果有的话)、配置文件和可能的文档说明等。 知识点总结: 1. ASP.NET 2.0是.NET Framework下的一个用于构建Web应用程序的服务器端框架。 2. 它支持使用C#和VB.NET等.NET支持的编程语言进行开发。 3. ASP.NET 2.0提供了一组丰富的控件,可帮助开发者快速构建Web表单、用户界面以及实现后台逻辑。 4. 它还提供了一种称作“Web站点”项目模板,使得初学者能够方便地开始Web开发项目。 5. ASP.NET 2.0是微软.NET历史上一个重要的里程碑,引入了许多创新特性,如成员资格和角色管理、主题和皮肤、网站导航和个性化设置等。 6. 在学习ASP.NET 2.0的过程中,初学者可以了解到如HTTP请求和响应、服务器控件、状态管理、数据绑定、缓存策略等基础概念。 7. 本项目可作为ASP.NET初学者的实践平台,帮助他们理解框架的基本结构和工作流程,从而为学习更高版本的ASP.NET打下坚实基础。 8. 个人网站项目的构建可以涵盖前端设计(HTML, CSS, JavaScript)和后端逻辑(C#或VB.NET)的综合应用。 9. 在学习过程中,初学者应该学会如何配置和使用IIS(Internet Information Services)来部署ASP.NET网站。 10. “赚取积分”可能指的是在某个在线社区、论坛或代码托管平台上,通过分享项目来获得一定的积分或奖励,这通常是用来衡量用户对社区贡献大小的一种方式。 综上所述,该“ASP.NET 2.0个人网站”项目不仅为初学者提供了一个实用的学习资源,同时体现了开发者对于开源共享精神的实践,对社区贡献出自己的力量。通过这样的实践,初学者能够更好地理解ASP.NET框架的运作,逐步建立起自己的Web开发技能。
recommend-type

【制图技术】:甘肃高质量土壤分布TIF图件的成图策略

# 摘要 本文针对甘肃土壤分布数据的TIF图件制作进行了系统研究。首先概述了甘肃土壤的分布情况,接着介绍了TIF图件的基础知识,包括其格式特点、空间数据表达以及质量控制方法。随后,文中构建了成图策略的理论框架,分析了土壤分布图的信息需求与数据处理流程,并探讨了成图原则与标准。在实践操作部分,详细阐述了制图软