项目实训 - 智能车系统 - 第十二周记录

项目实训 - 智能车系统 - 第十二周记录

日期:5.9 – 5.15

项目进度

本周工作进展:

  • 修改信号量销毁(如果不是第一次创建,不赋值 修改lastnumber+nownumber) 与可视化对接信号量的一系列问题
  • 测试雷达+雷达驱动测试
  • 总体测试

1、信号量版本修改

在与可视化对接的时候,由于可视化的编写原因,需要将信号量销毁之后才能退出程序。所以需要添加销毁函数:

int destory_sem(int semid)
{
    if (semctl(semid, 0, IPC_RMID)>=0)
    {
        return 0;
    }
    else
    {
        perror("Destory error");
        return -1;
    }
}

在程序入口处添加signal函数,捕捉ctrl+c信号,回调函数中销毁信号量,从而使可视化正常退出。

eg:

signal(SIGINT, exit_process);    


static void exit_process(int sig)
    {

        destory_sem(pubImuOdometry_sharemem_image->pub_sem_id);
        destory_sem(pubImuOdometry_sharemem_image->sub_sem_id);

        destory_sem(pubImuOdometry_sharemem_imu->pub_sem_id);
        destory_sem(pubImuOdometry_sharemem_imu->sub_sem_id);


        destory_sem(pubCloudImuPath_sharemem->pub_sem_id);
        destory_sem(pubCloudImuPath_sharemem->sub_sem_id);

        destory_sem(pubCloudImuPath_sharemem_navigation->pub_sem_id);
        destory_sem(pubCloudImuPath_sharemem_navigation->sub_sem_id);

        destory_sem(pubCloudImuPath_sharemem_recorder->pub_sem_id);
        destory_sem(pubCloudImuPath_sharemem_recorder->sub_sem_id);



        exit(0);


    }

在测试中发现问题:接收端会被阻塞,检查后发现,是在创建信号量和获取信号量的操作时,我的函数实现都会将信号量重新赋值,从而导致信号量混乱。

  • 解决:通过修改信号量的创建方式,判断信号量是否为首次创建。如果是,则赋初始值;如果不是,则不赋值。

问题2:仍会出现阻塞问题。经过排查,发现是与上一个通信机制版本的判断方式发生冲突,进行简单修改后即可。

解决上述问题后,调试成功。

通信机制最终版:

#include "communicator1.h"


/**
 * @brief used to define share memory
 * @param fd:共享内存区域ID
 * @param point:共享内存区域首地址
 * 
 */


key_t get_id(const string fileName)
{
    key_t ret = 0;
    for(int i = 0; i < fileName.size(); i++)
    {
        ret += fileName[i];
    }
     //cout<<fileName<<' '<<ret<<endl;
    return ret + 1000000;
}

/**
 * @brief Create a Sem object
 * 
 * @param sem_key 
 * @return int 返回信号量标识符;失败返回-1
 * 如果未创建信号量,则创建新信号量;否则不做处理
 */
int createSem(const string sem_key)
{
    key_t key = get_id(sem_key);
    cout<<"sem id "<<get_id(sem_key)<<endl;
    int sem_flag = IPC_CREAT | IPC_EXCL | 0666;
    return semget(key, 1, sem_flag);
}

/**
 * @brief Get the Sem object
 * 
 * @param sem_key 
 * @return int 
 * 同 createSem
 */
int getSem(const string sem_key)
{
    return createSem(sem_key);
}

union semun{  
    int val;  //使用的值
    struct semid_ds *buf;  //IPC_STAT、IPC_SET 使用的缓存区
    unsigned short *arry;  //GETALL,、SETALL 使用的数组
    struct seminfo *__buf; // IPC_INFO(Linux特有) 使用的缓存区 
};
/**
 * @brief init sem
 * 
 * @param semid 
 * @param val 
 * @return int 初始化失败返回-1;否则返回0
 * 默认初始化信号量集中的第一个 0 (只有一个)
 */
int initSem(int semid, int val)
{
    union semun _semun;
    _semun.val = val;
    if (semctl(semid, 0, SETVAL, _semun)<0)
    {
        perror("InitSem");
        return -1;
    }
    return 0;
}

// struct sembuf{  
//     short sem_num;   //除非使用一组信号量,否则它为0  
//     short sem_op;   //信号量在一次操作中需要改变的数据,通常是两个数,                                         
//                     //一个是-1,即P(等待)操作,  
//                     //一个是+1,即V(发送信号)操作。  
//     short sem_flg; //通常为SEM_UNDO,使操作系统跟踪信号量,  
//                   //并在进程没有释放该信号量而终止时,操作系统释放信号量  
// };

int pSem(int semid)
{
    struct sembuf _sf;
    _sf.sem_num = 0;
    _sf.sem_op = -1;
    _sf.sem_flg = 0;
    if(semop(semid, &_sf, 1) < 0) {
        perror("P error");
        return -1;
    }

}

int vSem(int semid)
{
    struct sembuf _sf;
    _sf.sem_num = 0;
    _sf.sem_op = 1;
    _sf.sem_flg = 0;
    if(semop(semid, &_sf, 1) < 0) {
        perror("V error");
        return -1;
    }
}

int destory_sem(int semid)
{
    if (semctl(semid, 0, IPC_RMID)>=0)
    {
        return 0;
    }
    else
    {
        perror("Destory error");
        return -1;
    }
}






int createSem_second(const string sem_key)
{
    key_t key = get_id(sem_key);
    int sem_flag = IPC_CREAT | 0666;
    return semget(key, 1, sem_flag);
}




/**
 * @brief 创建共享内存的同时
 * 
*/


/**
 * @brief Create a shm object
 * 
 * @param shm_key 共享内存键值
 * @param shm_num 共享内存字节长度
 * @param shm_flag 权限 (默认权限为读写权限)
 * 
 * @param sem_key pub信号量
 * @return void* 
 */
MemoryDefinition* createShareMemory(const string shm_key, size_t shm_num,const string sem_key)//, int shm_flag = 1)
{
    //cout<<"size "<<shm_num<<endl;
    MemoryDefinition* shm_point = new MemoryDefinition();;
    int shm_flag = IPC_CREAT | 0666;
    int fd = shmget(get_id(shm_key), shm_num, shm_flag);
    void* point;
    if(fd != -1) {
        //
        point = shmat(fd, 0, 0);
        if((int*)point != (int*)-1) {
            //初始化
            memset(point, 0, shm_num);


            shm_point->fd = fd;
            shm_point->point = point;
            // return shm_point;
        } else {
            perror("get shareMemory error1");
            //exit(EXIT_FAILURE); 
        }
    } else {
        perror("get shareMemory error2");
        //exit(EXIT_FAILURE); 
    }

    //创建信号量 两个信号量
    int temp_semid_pub = createSem(sem_key+"pub");
    if(temp_semid_pub < 0) {
        // //创建失败
        // perror("create sem error");

        //说明之前已经创建过,不需要init了
        //重新创建一次
        temp_semid_pub = createSem_second(sem_key+"pub");
        if(temp_semid_pub < 0) {
            perror("create second sem error");
        } else {
            shm_point->pub_sem_id = temp_semid_pub;
        }
    } 
    else {
        //初始值
        int temp_init_semid = initSem(temp_semid_pub, 1); // 发布者创建的信号量 对应生产者 初值为1
        if(temp_init_semid < 0) {
            perror("init sem error");
        } else {
            //赋初始值成功
            shm_point->pub_sem_id = temp_semid_pub;
        }
    }

    int temp_semid_sub = getSem(sem_key+"sub");
    if(temp_semid_sub < 0) {
        //创建失败
        temp_semid_sub = createSem_second(sem_key+"sub");
        if(temp_semid_sub < 0) {
            perror("create second sem error");
        } else {
            shm_point->sub_sem_id = temp_semid_sub;
        }
    } else {
        //初始值
        int temp_init_semid = initSem(temp_semid_sub, 0); // 发布者创建的信号量 对应生产者 初值为1
        if(temp_init_semid < 0) {
            perror("init sem error");
        } else {
            //赋初始值成功
            shm_point->sub_sem_id = temp_semid_sub;
        }
    }
    cout<<"sem: "<<sem_key<<" "<<shm_point->sub_sem_id<<" "<<shm_point->pub_sem_id<<endl;

    return shm_point;
}

/**
 * @brief 连接共享内存
 * 
 * @param shm_key 共享内存键值
 * @param shm_num 共享内存字节长度
 * @param shm_flag 权限 (默认权限为读写权限)
 * @return void* 
 */
MemoryDefinition* connectShareMemory(const string shm_key, size_t shm_num, const string sem_key)//, int shm_flag = 1)
{
    //cout<<"size "<<shm_num<<endl;
    MemoryDefinition* shm_point = new MemoryDefinition();
    int shm_flag = IPC_CREAT | 0666;
    int fd = shmget(get_id(shm_key), shm_num, shm_flag);
    void* point;
    if(fd != -1) {
        //
        point = shmat(fd, 0, 0);
        if((int*)point != (int*)-1) {
            shm_point->fd = fd;
            shm_point->point = point;
            // return shm_point;
        } else {
            perror("get shareMemory error3");
            //exit(EXIT_FAILURE); 
        }
    } else {
        perror("get shareMemory error4");
        //exit(EXIT_FAILURE); 
    }


    
    //创建信号量
    int temp_semid_sub = getSem(sem_key+"sub");
    if(temp_semid_sub < 0) {
        //创建失败
        temp_semid_sub = createSem_second(sem_key+"sub");
        if(temp_semid_sub < 0) {
            perror("create second sem error");
        } else {
            shm_point->sub_sem_id = temp_semid_sub;
        }
    } else {
        //初始值
        int temp_init_semid = initSem(temp_semid_sub, 0); // 发布者创建的信号量 对应生产者 初值为1
        if(temp_init_semid < 0) {
            perror("init sem error");
        } else {
            //赋初始值成功
            shm_point->sub_sem_id = temp_semid_sub;
        }
    }

    int temp_semid_pub = createSem(sem_key+"pub");
    if(temp_semid_pub < 0) {
        // //创建失败
        // perror("create sem error");

        //说明之前已经创建过,不需要init了
        //重新创建一次
        temp_semid_pub = createSem_second(sem_key+"pub");
        if(temp_semid_pub < 0) {
            perror("create second sem error");
        } else {
            shm_point->pub_sem_id = temp_semid_pub;
        }
    } 
    else {
        //初始值
        int temp_init_semid = initSem(temp_semid_pub, 1); // 发布者创建的信号量 对应生产者 初值为1
        if(temp_init_semid < 0) {
            perror("init sem error");
        } else {
            //赋初始值成功
            shm_point->pub_sem_id = temp_semid_pub;
        }
    }

    cout<<"sem: "<<sem_key<<" "<<shm_point->sub_sem_id<<" "<<shm_point->pub_sem_id<<endl;
    return shm_point;
}

void unMap(const MemoryDefinition* definition)
{
    //size_t write_size = sizeof(ExampleList);
    shmdt(definition->point);

    // cout << "...Finish unmap share Memory and close the normal file!" << endl;
}

并且实践中发现:当一对多时,无需开辟多块内存空间,可以公用一块,只开多对信号量即可。

并且在项目中使用配置文件,设置本次项目启动后,一对多的信号量中哪些需要开启。

接收端:

在这里插入图片描述

接收完毕:

在这里插入图片描述

发布端:

在这里插入图片描述

2、测试雷达+雷达驱动测试

首先使用rslidar的ros版本驱动测试雷达的正确性。

需要雷达和板子在一个局域网下,给板子配置静态IP。连接后启动驱动,结果:

在这里插入图片描述

之后修改驱动:进行去除ros代码、修改cmake文件

重新编译、调bug后,调试成功:

在这里插入图片描述

安装参考:https://blog.csdn.net/weixin_53073284/article/details/122680587

3、总体测试

整个智能车系统的流程如下:

在这里插入图片描述

目前由于条件收到限制,所以现在的测试在上述中进行简化:

  • 原始数据采集由数据包提供
  • 下发速度那里暂不测试
  • 上位机控制端尚未完善,暂不测试
  • 数据部分由于数据包中的车道线信息无,所以单独测试

之后按照上述流程进行进一步测试。

技术难点

整合项目

bug记录

没啥大bug

其他

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值