[ROS 系列学习教程] 建模与仿真 - 使用 ros_control 控制差速轮式机器人
ROS 系列学习教程(总目录)
本文目录
- 一、差速轮式机器人
- 二、差速驱动机器人运动学模型
- 三、对外接口
- 3.1 输入接口
- 3.2 输出接口
- 四、控制器参数
- 五、配置控制器参数
- 六、编写硬件抽象接口
- 七、控制机器人移动
- 八、源码
ros_control 提供了多种控制器,其中 diff_drive_controller
用于控制差速驱动轮式机器人。
一、差速轮式机器人
差速轮式机器人是一种移动机器人,其运动基于机器人身体两侧的两个独立驱动轮。因此,它可以通过改变轮子的相对旋转速度来改变方向,不需要额外的转向运动。具有这种驱动器的机器人通常有一个或多个脚轮,以防止车辆倾斜。
如果两个轮子以相同的方向和速度驱动,机器人将沿直线行驶。如果两个轮子以相同的速度朝相反的方向转动,如所示图所示,机器人将绕轴的中心点旋转。否则,根据旋转速度和方向,旋转中心可能落在由两个轮胎接触点定义的线上的任何位置。当机器人沿直线行驶时,旋转中心距离机器人无限远。由于机器人的方向取决于两个驱动轮的旋转速度和方向,因此应精确感测和控制这些量。

差速转向机器人与汽车中使用的差速 齿轮类似,两个车轮可以有不同的转速,但与差速齿轮系统不同,差速转向系统将为两个车轮提供动力。差速轮式机器人在机器人技术中得到广泛应用,因为它们的运动易于编程并且可以很好地控制。当今市场上几乎所有的消费机器人都使用差速转向,主要是因为它成本低且简单。
二、差速驱动机器人运动学模型
如下图为轮式机器人的差速驱动运动学模型示意图:

其中,
V − 机器人线速度 ω − 机器人角速度 X O Y − 世界坐标系 X B Y B − 机器人坐标系 φ − 机器人在世界坐标系的角度 r − 车轮半径 b − 轮距 I C R − 瞬时旋转中心 R − 瞬心到机器人中心的距离 v L , v R − 左右轮接地点切向线速度 ω L , ω R − 左右轮角速度 V - 机器人线速度\\ \omega - 机器人角速度\\ XOY - 世界坐标系\\ X_BY_B - 机器人坐标系\\ \varphi - 机器人在世界坐标系的角度\\ r - 车轮半径\\ b - 轮距\\ ICR - 瞬时旋转中心\\ R - 瞬心到机器人中心的距离\\ v_L,v_R - 左右轮接地点切向线速度\\ \omega_L,\omega_R - 左右轮角速度 V−机器人线速度ω−机器人角速度XOY−世界坐标系XBYB−机器人坐标系φ−机器人在世界坐标系的角度r−车轮半径b−轮距ICR−瞬时旋转中心R−瞬心到机器人中心的距离vL,vR−左右轮接地点切向线速度ωL,ωR−左右轮角速度
有如下关系:
ω ⋅ ( R + b / 2 ) = v R ω ⋅ ( R − b / 2 ) = v L \omega \cdot (R + b/2) = v_R\\ \omega \cdot (R - b/2) = v_L ω⋅(R+b/2)=vRω⋅(R−b/2)=vL
解这两个方程可得 ω \omega ω 和 R R R :
ω = ( v R − v L ) / b R = b / 2 ⋅ ( v R + v L ) / ( v R − v L ) \omega = (v_R-v_L)/b\\ R = b/2 \cdot(v_R+v_L)/(v_R-v_L) ω=(vR−vL)/bR=b/2⋅(vR+vL)/(vR−vL)
利用角速度方程可得机器人瞬时速度 V V V :
V = ω ⋅ R = ( v R + v L ) / 2 V = \omega \cdot R = (v_R+v_L)/2 V=ω⋅R=(vR+vL)/2
车轮切向速度也可以写成:
v R = r ⋅ ω R v L = r ⋅ ω L v_R = r \cdot \omega_R\\ v_L = r \cdot \omega_L vR=r⋅ωRvL=r⋅ωL
则机器人在本体坐标系中的运动学模型为:
[ x ˙ B y ˙ B φ ˙ ] = [ v ⋅ x B v ⋅ y B ω ] = ⏞ v = r ω [ r 2 r 2 0 0 − r b r b ] [ ω L ω R ] \begin{bmatrix} \dot{x}_B \\ \dot{y}_B \\ \dot{\varphi} \end{bmatrix} = \begin{bmatrix} v \cdot x_B \\ v \cdot y_B \\ \omega \end{bmatrix} \overbrace{=}^{v=r\omega} \begin{bmatrix} \frac r2 & \frac r2 \\ 0 & 0 \\ -\frac rb & \frac rb \end{bmatrix} \begin{bmatrix} \omega_L \\ \omega_R \end{bmatrix} x˙By˙Bφ˙ = v⋅xBv⋅yBω = v=rω 2r0−br2r0br [ωLωR]
再通过坐标变换,最终可以得到机器人在世界坐标中的运动学模型:
[ x ˙ y ˙ φ ˙ ] = [ cos φ 0 sin φ 0 0 1 ] [ V ω ] \begin{bmatrix} \dot{x} \\ \dot{y} \\ \dot{\varphi} \end{bmatrix} = \begin{bmatrix} \cos\varphi & 0 \\ \sin\varphi & 0 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} V \\ \omega \end{bmatrix} x˙y˙φ˙ = cosφsinφ0001 [Vω]
其中, V V V 和 ω \omega ω 为控制变量。
通常我们需要通过机器人的速度和结构参数逆解出左右轮的转速,用于控制电机。在这种情况下,可以很容易地重新表述前面提到的方程。使用如下方程:
R = V / ω ω R = v R / r ω L = v L / r R = V/\omega\\ \omega_R = v_R/r\\ \omega_L = v_L/r R=V/ωωR=vR/rωL=vL/r
可得左右轮角速度方程:
ω R = V + ω ⋅ b / 2 r ω L = V − ω ⋅ b / 2 r \omega_R = \frac{V+\omega \cdot b/2}{r} \\ \omega_L = \frac{V-\omega \cdot b/2}{r} ωR=rV+ω⋅b/2ωL=rV−ω⋅b/2
三、对外接口
diff_drive_controller
主要通过订阅速度命令作为模块的输入,然后解析运动学模型控制电机,达到控制机器人的目的。
3.1 输入接口
-
cmd_vel(geometry_msgs/Twist)
位于控制器的命名空间下,给机器人发布速度
3.2 输出接口
-
odom(nav_msgs/Odometry)
位于控制器的命名空间下,根据硬件反馈计算的里程计信息
-
/tf(tf/tfMessage)
从 odom 转换为 base_link
-
cmd_vel_out(geometry_msgs/TwistStamped)
当
publish_cmd
参数设置为True
时可用。在控制器的输入上应用限制器后的 Twist。
四、控制器参数
diff_drive_controller
提供了一些参数,用于配置机器人控制。
参数 | 数据类型 | 说明 |
---|---|---|
left_wheel | string /string[…] | 左轮关节名称或关节名称列表 |
right_wheel | string /string[…] | 右轮关节名称或关节名称列表 |
pose_covariance_diagonal | double[6] | 用于里程计位姿发布的协方差矩阵的对角线 |
twist_covariance_diagonal | double[6] | 用于里程计 twist 发布的协方差矩阵的对角线 |
publish_rate | double | 发布里程计的频率,用于 tf 和 odom(单位:Hz,默认值: 50.0) |
wheel_separation | double | 轮距,左轮和右轮之间的距离。如果未指定此参数,diff_drive_controller 将尝试从 URDF 读取值 |
wheel_separation_multiplier | double | 轮距参数的系数。用于解释机器人模型和真实机器人之间的差异。(默认值:1.0) |
wheel_radius | double | 车轮半径。默认两侧车轮都具有相同的尺寸。如果未指定此参数,diff_drive_controller 将尝试从 URDF 读取值。 |
wheel_radius_multiplier | double | 车轮半径参数的系数。用于解释机器人模型和真实机器人之间的差异。(默认值:1.0) |
cmd_vel_timeout | double | 两个连续速度命令之间允许的时间间隔。此延迟后,将向车轮发送零速命令。(单位:s,默认值:0.5) |
base_frame_id | string | 用于填充Odometry消息和TF的child_frame_id(默认值:“base_link”) |
linear | object | 线性速度配置参数 |
+ x | object | x轴,两轮差速机器人线速度只有x轴 |
++ has_velocity_limits | bool | 控制器是否限制线速度。(默认值: false) |
++ max_velocity | double | 最大线速度(单位:m/s) |
++ min_velocity | double | 最小线速度(单位:m/s)。未指定时,使用max_velocity |
++ has_acceleration_limits | bool | 控制器是否限制线加速度。(默认值: false) |
++ max_acceleration | double | 最大线加速度(单位:m/s^2) |
++ min_acceleration | double | 最小线加速度(单位:m/s^2)。未指定时,使用max_acceleration |
++ has_jerk_limits | bool | 控制器是否限制线加速度的变化快慢(默认值: false) |
++ max_jerk | double | 最大 jerk(单位:m/s^3) |
angular | object | 角速度配置参数 |
+ z | object | z轴,两轮差速机器人角速度只有z轴 |
++ has_velocity_limits | bool | 控制器是否应该限制角速度(默认值: false) |
++ max_velocity | double | 最大角速度(单位:rad/s) |
++ min_velocity | double | 最小角速度(单位:rad/s)。将其设置为 0.0 将禁用逆时针旋转。未指定时,将使用max_velocity |
++ has_acceleration_limits | bool | 控制器是否应该限制角加速度(默认值: false) |
++ max_acceleration | double | 最大角加速度(单位:rad/s^2) |
++ min_acceleration | double | 最小角加速度(单位为 rad/s^2)。未指定时,使用max_acceleration。 |
++ has_jerk_limits | bool | 控制器是否限制角加速度的变化快慢(默认值: false) |
++ max_jerk | double | 最大 jerk(单位:rad/s^3) |
enable_odom_tf | bool | 是否直接发布到 TF(默认值: true ) |
odom_frame_id | string | 里程计的frame_id(默认值:“/odom”) |
publish_cmd | bool | 发布要执行的速度命令。用于监控限制器对控制器输入的影响。(默认值: False) |
allow_multiple_cmd_vel_publishers | bool | 将其设置为 true 将允许输入接口 ~/cmd_vel 有多个发布者。如果将其设置为 false,则如果 ~/cmd_vel 有多个发布者,则会导致控制器停止运行。(默认值: False) |
velocity_rolling_window_size | int | 用于计算里程计 twist.linear.x 和 twist.angular.z 速度的平均速度样本数量(默认值: 10) |
五、配置控制器参数
最小配置示例(即必要配置项):
diff_drive_controller:type: "diff_drive_controller/DiffDriveController"left_wheel: "left_wheel_joint"right_wheel: "right_wheel_joint"pose_covariance_diagonal: [0.001, 0.001, 0.001, 0.001, 0.001, 0.03]twist_covariance_diagonal: [0.001, 0.001, 0.001, 0.001, 0.001, 0.03]
该差速轮式机器人完整配置:
# 用于控制器硬件接口配置
hardware_interface:joints:- left_wheel_joint- right_wheel_joint- front_caster_joint- back_caster_joint# joint_state_controller 控制器,用于发布各关节状态
joint_state_controller:type: "joint_state_controller/JointStateController"publish_rate: 50# diff_drive_controller 控制器
diff_drive_controller:type: "diff_drive_controller/DiffDriveController"left_wheel: "left_wheel_joint"right_wheel: "right_wheel_joint"publish_rate: 50pose_covariance_diagonal: [0.001, 0.001, 0.001, 0.001, 0.001, 0.03]twist_covariance_diagonal: [0.001, 0.001, 0.001, 0.001, 0.001, 0.03]cmd_vel_timeout: 100velocity_rolling_window_size: 1publish_cmd: truebase_frame_id: base_linkenable_odom_tf: trueodom_frame_id: odom# 轮间距和轮半径wheel_separation: 0.38wheel_radius: 0.06wheel_separation_multiplier: 1.0wheel_radius_multiplier: 1.0# 速度和加速度限制linear:x:has_velocity_limits: truemax_velocity: 1.0 # m/shas_acceleration_limits: truemax_acceleration: 3.0 # m/s^2angular:z:has_velocity_limits: truemax_velocity: 2.0 # rad/shas_acceleration_limits: truemax_acceleration: 6.0 # rad/s^2
六、编写硬件抽象接口
下面写一个两轮差速硬件接口,使用速度控制接口 VelocityJointInterface
控制 joint 的速度,使用 JointStateInterface
获取 joint 的位置、速度、力等信息。
硬件抽象接口头文件:diff_drive_hardware_interface.h
#ifndef DIFF_DRIVE_HARDWARE_INTERFACE_H
#define DIFF_DRIVE_HARDWARE_INTERFACE_H#include <ros/ros.h>
#include <hardware_interface/joint_command_interface.h>
#include <hardware_interface/joint_state_interface.h>
#include <hardware_interface/robot_hw.h>
#include <controller_manager/controller_manager.h>class DiffDriveHWInterface : public hardware_interface::RobotHW
{
public:struct JointInfo{std::string name;double cmd;double pos;double vel;double eff;JointInfo() : name(""), cmd(0.0), pos(0.0), vel(0.0), eff(0.0){}JointInfo(std::string name_) : name(name_), cmd(0.0), pos(0.0), vel(0.0), eff(0.0){}JointInfo(std::string name_, double cmd_, double pos_, double vel_, double dff_) : name(name_), cmd(cmd_), pos(pos_), vel(vel_), eff(dff_){}};public:DiffDriveHWInterface(ros::NodeHandle &nh);void init();void read(const ros::Duration &period);void write(const ros::Duration &period);private:ros::NodeHandle m_nh;hardware_interface::JointStateInterface m_jnt_state_interface;hardware_interface::VelocityJointInterface m_jnt_vel_interface;std::vector<JointInfo> m_joints;
};#endif // DIFF_DRIVE_HARDWARE_INTERFACE_H
源文件:diff_drive_hardware_interface.cpp
#include "diff_drive_control/diff_drive_hardware_interface.h"DiffDriveHWInterface::DiffDriveHWInterface(ros::NodeHandle &nh) : m_nh(nh)
{
}/*** @brief 初始化关节信息* 注册抽象硬件接口* */
void DiffDriveHWInterface::init()
{std::vector<std::string> joint_names;m_nh.getParam("/hardware_interface/joints", joint_names);for (std::string name : joint_names){m_joints.push_back(JointInfo(name));}for (auto &joint : m_joints){ROS_INFO("get joint: %s", joint.name.c_str());// Initialize hardware interfacehardware_interface::JointStateHandle state_handle(joint.name, &joint.pos, &joint.vel, &joint.eff);m_jnt_state_interface.registerHandle(state_handle);hardware_interface::JointHandle vel_handle(m_jnt_state_interface.getHandle(joint.name), &joint.cmd);m_jnt_vel_interface.registerHandle(vel_handle);}registerInterface(&m_jnt_state_interface);registerInterface(&m_jnt_vel_interface);
}void DiffDriveHWInterface::read(const ros::Duration &period)
{// Read the state of the hardware (e.g., from sensors)
}void DiffDriveHWInterface::write(const ros::Duration &period)
{// Send the command to the hardware (e.g., to actuators)for (auto &joint : m_joints){joint.pos += joint.vel * period.toSec();// if (joint.vel != joint.cmd)// {// ROS_INFO("write, joint: %s, cmd: %lf", joint.name.c_str(), joint.cmd);// }joint.vel = joint.cmd;}
}
控制节点:diff_drive_control_node.cpp
#include <ros/ros.h>
#include <controller_manager/controller_manager.h>
#include "diff_drive_control/diff_drive_hardware_interface.h"int main(int argc, char **argv)
{ros::init(argc, argv, "diff_drive_control_node");ros::NodeHandle nh;DiffDriveHWInterface diff_drive(nh);diff_drive.init();controller_manager::ControllerManager cm(&diff_drive, nh);ros::Rate rate(50.0);ros::AsyncSpinner spinner(1);spinner.start();while (ros::ok()){ros::Duration period = rate.expectedCycleTime();diff_drive.write(period);cm.update(ros::Time::now(), period);rate.sleep();}return 0;
}
七、控制机器人移动
机器人模型与硬件接口都准备好了,接下来开始编写业务代码控制机器人。
我们仅给机器人发送速度指令,模拟机器人移动任务,如下:
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>geometry_msgs::Twist moveRobot(const double& linear, const double& angular)
{geometry_msgs::Twist msg;msg.linear.x = linear; // 线速度msg.linear.y = 0.0;msg.linear.z = 0.0;msg.angular.x = 0.0;msg.angular.y = 0.0;msg.angular.z = angular; // 角速度ROS_INFO("moveRobot, linear: %.3lf, angular: %.1lf", linear, angular*180/M_PI);return msg;
}int main(int argc, char** argv)
{ros::init(argc, argv, "diff_drive_business");ros::NodeHandle nh;ros::Publisher velPub = nh.advertise<geometry_msgs::Twist>("/diff_drive_controller/cmd_vel", 10);ros::Rate rate(10);while (ros::ok()){velPub.publish(moveRobot(0.5, 0));ros::Duration(3.0).sleep();velPub.publish(moveRobot(0, 1.57));ros::Duration(1.0).sleep();rate.sleep();}return 0;
}
编译执行该节点,在rviz中的可视化结果如下:
八、源码
项目源码
相关文章:

[ROS 系列学习教程] 建模与仿真 - 使用 ros_control 控制差速轮式机器人
ROS 系列学习教程(总目录) 本文目录 一、差速轮式机器人二、差速驱动机器人运动学模型三、对外接口3.1 输入接口3.2 输出接口 四、控制器参数五、配置控制器参数六、编写硬件抽象接口七、控制机器人移动八、源码 ros_control 提供了多种控制器,其中 diff_drive_cont…...
Ubuntu22.04使用Systemd设置ROS 2开机自启动遇到的问题
在查找网上的各种开机自启动资料配置好开机自启动后,使用ros2 topic list不能显示话题。 1、问题解决:用户问题与domenID问题2、ROS2开机自启动服务教程3、多个ROS2开机自启动服务教程 1、问题解决:用户问题与domenID问题 在root用户下能看到…...
AI安全研究滞后?清华专家团来支招
在21世纪的科技浪潮中,人工智能(AI)无疑是最为耀眼的一抹亮色。随着技术的不断突破,AI正以前所未有的速度融入我们的日常生活,重塑着社会、经济乃至人类文明的面貌。然而,在这股汹涌澎湃的发展洪流中&#…...
12寸FAB 信息部内外工作职责的一些划分构思
FAB的信息部,也常被称为IT部门或信息化部门,承担着确保整个制造工厂的信息技术系统高效、安全运行的职责。以下是 一、FAB信息部的一些关键部门职责: 1. 战略规划:制定和实施信息技术战略,以支持FAB的长期业务目标和增…...

css做旋转星球可举一反三
<!DOCTYPE html> <html lang"en"><head> <meta charset"UTF-8" /> <title>旋转的星球</title> <style type"text/css">.box {/*position: relative;*/position: absolute;width: 139px;height: 139p…...

AcWing 1256:扩展二叉树
【题目来源】https://www.acwing.com/problem/content/1258/【题目描述】 由于先序、中序和后序序列中的任一个都不能唯一确定一棵二叉树,所以对二叉树做如下处理,将二叉树的空结点用 补齐,如图所示。 我们把这样处理后的二叉树称为原二叉树…...

三维家:SaaS的IT规模化降本之道|OceanBase 《DB大咖说》(十一)
OceanBase《DB大咖说》第 11 期,我们邀请到了三维家的技术总监庄建超,来分享他对数据库技术的理解,以及典型 SaaS 场景在数据库如何实现规模化降本的经验与体会。 庄建超,身为三维家的技术总监,独挑大梁,负…...
ai智能语音机器人是如何影响客户体验的?电销机器人部署
随着人工智能技术的进步,越来越多的企业在寻求如何将人工智能技术融合到现有的商业模式上,进而实现自动化、智能化。在通信行业大量使用智能语音机器人、聊天机器人、客服机器人时,它能和“客户体验”并驾齐驱吗,还是可以让客户体…...

vue3使用v-html实现文本关键词变色
首先看应用场景 这有一段文本内容,是项目的简介,想要实现将文本中的关键词进行变色处理 有如下关键词 实现思路 遍历文本内容,找到关键词,并使用某种方法更改其字体样式。经过搜寻资料决定采用v-html实现,但是v-h…...
C#面:举列 a=10,b=15,在不用第三方变量的前提下,把a,b的值互换
要在不使用第三方变量的前提下交换a和b的值,可以使用异或运算。异或运算的特性是,对于两个相同的数进行异或运算,结果为0;对于任意数与0进行异或运算,结果为该数本身。因此,可以通过多次异或运算来实现变量…...

编写动态库
1.创建库.c .h文件 2.编写Makefile文件 3.make之后形成.so文件 4.make output,形成mylib 5.把mylib拷贝到test里面 mv mylib /test 6.编译 gcc main.c -I mylib/include -L mylib/lib -lmymethod形成a.out 但是直接执行会出现以下问题 很显然没有找到动态库 7.解决加载找不…...

记一次阿里云服务器java应用无法响应且无法远程连接的问题排查
问题表现 java服务无响应,无法远程链接到服务器。 今天中午12点多,应用直接崩溃。后续进入到服务器,发现java进程都不在了, 排查过程 先安装atop工具 安装、配置并使用atop监控工具 等下次再出现时看相关时间点日志ÿ…...

雷池WAF+Modsecurity安装防护及系统加固
君衍. 一、雷池WAF1、什么是雷池2、什么是WAF3、雷池的功能4、WAF部署架构5、整体检测流程 二、雷池WAF环境依赖1、查看本地CPU架构2、Docker安装2.1 卸载旧版本2.2 安装yum-utils工具包2.3 设置镜像仓库2.4 安装docker2.5 启动docker并查看版本 3、Docker Compose安装3.1 卸载…...

【Python】已解决:SyntaxError: positional argument follows keyword argument
文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决:SyntaxError: positional argument follows keyword argument 一、分析问题背景 在Python编程中,当我们在调用函数时混合使用位置参数(p…...

leetcode-20-回溯-切割、子集
一、[131]分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ] 分析&…...

利用深度学习模型进行语音障碍自动评估
语音的产生涉及器官的复杂协调,因此,语音包含了有关身体各个方面的信息,从认知状态和心理状态到呼吸条件。近十年来,研究者致力于发现和利用语音生物标志物——即与特定疾病相关的语音特征,用于诊断。随着人工智能&…...
TP8 JS(html2canvas) 把DIV内容生成二维码并与背景图、文字组合生成分享海报
方法一:前端JS生成(推荐) 注意: 1.这个网页只能截图图片效果代码,其它任何html效果都不能有,不然截图就不准确 2.如果要生成的图片DIV内容中引用了第三个方的图片,就是不使用同一个域名下的图片,需要把后…...
计算机科学中的接口(Interface)介绍
计算机科学中的接口(Interface)介绍 计算机科学中,接口是一个广泛的概念,在不同上下文中有不同含义: 1.任何两电路或设备间的连接电路,用于连接CPU与内存、CPU与外设之间。这是一个重要的硬件层面的接口概…...

大创项目推荐 题目:基于深度学习卷积神经网络的花卉识别 - 深度学习 机器视觉
文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 基…...

黑芝麻科技A1000简介
文章目录 1. A1000 简介2. 感知能力评估3. 竞品对比4. 系统软件1. A1000 简介...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...