APM_ArduCopter源码解析学习(三)——无人机类型

  • 一、前言
  • 二、class AP_HAL::HAL
  • 三、class AP_Vehicle
    • 3.1 .h
    • 3.2 .cpp
  • 四、class Copter
    • 4.1 .h
    • 4.2 .cpp
  • 五、总结

一、前言

本文就主要来讲一讲APM里面的无人机类型好了,当然是以Copter作为主要对象,不过前面的继承关系和基类基本都是一致的,也可以作为参考。

Copter类定义在Copter.h 文件内部,其向上继承自 AP_Vechile 类,这是所有无人机类型(Copter、Rover…)的父类。同样,AP_Vechile向上也有相应的继承关系,具体来说,用下面这种方式表达:

AP_HAL::HAL::Callbacks
  |---- AP_Vechile
    |---- Copter

因此,为了能对Copter类的无人机类型进行深入了解,我们还是得回到最源头讲起。

二、class AP_HAL::HAL

该类定义于 libraries/AP_HAL/HAL.h 路径下,命名空间为AP_HAL(具体查看 AP_HAL_Namespace.h),该类内部由各种最基础的底层外设抽象组合而成,构成了一个HAL抽象基类组件的集合。

class AP_HAL::HAL {public:HAL(AP_HAL::UARTDriver* _uartA, // consoleAP_HAL::UARTDriver* _uartB, // 1st GPSAP_HAL::UARTDriver* _uartC, // telem1AP_HAL::UARTDriver* _uartD, // telem2AP_HAL::UARTDriver* _uartE, // 2nd GPSAP_HAL::UARTDriver* _uartF, // extra1AP_HAL::UARTDriver* _uartG, // extra2AP_HAL::UARTDriver* _uartH, // extra3AP_HAL::I2CDeviceManager* _i2c_mgr,AP_HAL::SPIDeviceManager* _spi,AP_HAL::AnalogIn*   _analogin,AP_HAL::Storage*    _storage,AP_HAL::UARTDriver* _console,AP_HAL::GPIO*       _gpio,AP_HAL::RCInput*    _rcin,AP_HAL::RCOutput*   _rcout,AP_HAL::Scheduler*  _scheduler,AP_HAL::Util*       _util,AP_HAL::OpticalFlow*_opticalflow,AP_HAL::Flash*      _flash,AP_HAL::DSP*        _dsp,
#if HAL_NUM_CAN_IFACES > 0AP_HAL::CANIface* _can_ifaces[HAL_NUM_CAN_IFACES])
#elseAP_HAL::CANIface** _can_ifaces)
#endif:uartA(_uartA),uartB(_uartB),uartC(_uartC),uartD(_uartD),uartE(_uartE),uartF(_uartF),uartG(_uartG),uartH(_uartH),i2c_mgr(_i2c_mgr),spi(_spi),analogin(_analogin),storage(_storage),console(_console),gpio(_gpio),rcin(_rcin),rcout(_rcout),scheduler(_scheduler),util(_util),opticalflow(_opticalflow),flash(_flash),dsp(_dsp){#if HAL_NUM_CAN_IFACES > 0if (_can_ifaces == nullptr) {for (uint8_t i = 0; i < HAL_NUM_CAN_IFACES; i++)can[i] = nullptr;} else {for (uint8_t i = 0; i < HAL_NUM_CAN_IFACES; i++)can[i] = _can_ifaces[i];}
#endifAP_HAL::init();}struct Callbacks {virtual void setup() = 0;virtual void loop() = 0;};struct FunCallbacks : public Callbacks {FunCallbacks(void (*setup_fun)(void), void (*loop_fun)(void));void setup() override { _setup(); }void loop() override { _loop(); }private:void (*_setup)(void);void (*_loop)(void);};virtual void run(int argc, char * const argv[], Callbacks* callbacks) const = 0;AP_HAL::UARTDriver* uartA;AP_HAL::UARTDriver* uartB;AP_HAL::UARTDriver* uartC;AP_HAL::UARTDriver* uartD;AP_HAL::UARTDriver* uartE;AP_HAL::UARTDriver* uartF;AP_HAL::UARTDriver* uartG;AP_HAL::UARTDriver* uartH;AP_HAL::I2CDeviceManager* i2c_mgr;AP_HAL::SPIDeviceManager* spi;AP_HAL::AnalogIn*   analogin;AP_HAL::Storage*    storage;AP_HAL::UARTDriver* console;AP_HAL::GPIO*       gpio;AP_HAL::RCInput*    rcin;AP_HAL::RCOutput*   rcout;AP_HAL::Scheduler*  scheduler;AP_HAL::Util        *util;AP_HAL::OpticalFlow *opticalflow;AP_HAL::Flash       *flash;AP_HAL::DSP         *dsp;
#if HAL_NUM_CAN_IFACES > 0AP_HAL::CANIface* can[HAL_NUM_CAN_IFACES];
#elseAP_HAL::CANIface** can;
#endif
};

参考:Ardupilot之cpu外设基础抽象聚合类 HAL.h

三、class AP_Vehicle

3.1 .h

该类定义于 libraries/AP_Vehicle/AP_Vehicle.h,派生自AP_HAL::HAL::Callbacks接口类,因此拥有 setup() 和 loop() 两种行为。该类的主要目的就是作为各种具体无人机类型的基类,提供最基本的功能,并在具象化特定无人机时提供相应的接口。

代码有点长,一些必要的地方已经备注,请大家耐心看完


class AP_Vehicle : public AP_HAL::HAL::Callbacks {public:AP_Vehicle() {if (_singleton) {AP_HAL::panic("Too many Vehicles");}AP_Param::setup_object_defaults(this, var_info);_singleton = this;}/* Do not allow copies */AP_Vehicle(const AP_Vehicle &other) = delete;AP_Vehicle &operator=(const AP_Vehicle&) = delete;static AP_Vehicle *get_singleton();// setup() is called once during vehicle startup to initialise the// vehicle object and the objects it contains.  The// AP_HAL_MAIN_CALLBACKS pragma creates a main(...) function// referencing an object containing setup() and loop() functions.// A vehicle is not expected to override setup(), but// subclass-specific initialisation can be done in init_ardupilot// which is called from setup().void setup(void) override final;// HAL::Callbacks implementation.void loop() override final;bool virtual set_mode(const uint8_t new_mode, const ModeReason reason) = 0;uint8_t virtual get_mode() const = 0;/*common parameters for fixed wing aircraft*/struct FixedWing {AP_Int8 throttle_min;AP_Int8 throttle_max; AP_Int8 throttle_slewrate;AP_Int8 throttle_cruise;AP_Int8 takeoff_throttle_max;AP_Int16 airspeed_min;AP_Int16 airspeed_max;AP_Int32 airspeed_cruise_cm;AP_Int32 min_gndspeed_cm;AP_Int8  crash_detection_enable;AP_Int16 roll_limit_cd;AP_Int16 pitch_limit_max_cd;AP_Int16 pitch_limit_min_cd;        AP_Int8  autotune_level;AP_Int8  stall_prevention;AP_Int16 loiter_radius;struct Rangefinder_State {bool in_range:1;bool have_initial_reading:1;bool in_use:1;float initial_range;float correction;float initial_correction;float last_stable_correction;uint32_t last_correction_time_ms;uint8_t in_range_count;float height_estimate;float last_distance;};// stages of flightenum FlightStage {FLIGHT_TAKEOFF       = 1,FLIGHT_VTOL          = 2,FLIGHT_NORMAL        = 3,FLIGHT_LAND          = 4,FLIGHT_ABORT_LAND    = 7};};/*common parameters for multicopters*/struct MultiCopter {AP_Int16 angle_max;};void get_common_scheduler_tasks(const AP_Scheduler::Task*& tasks, uint8_t& num_tasks);// implementations *MUST* fill in all passed-in fields or we get// Valgrind errorsvirtual void get_scheduler_tasks(const AP_Scheduler::Task *&tasks, uint8_t &task_count, uint32_t &log_bit) = 0;/*set the "likely flying" flag. This is not guaranteed to beaccurate, but is the vehicle codes best guess as to the whetherthe vehicle is currently flying*/void set_likely_flying(bool b) {if (b && !likely_flying) {_last_flying_ms = AP_HAL::millis();}likely_flying = b;}/*get the likely flying status. Returns true if the vehicle codethinks we are flying at the moment. Not guaranteed to beaccurate*/bool get_likely_flying(void) const {return likely_flying;}/*return time in milliseconds since likely_flying was settrue. Returns zero if likely_flying is currently false*/uint32_t get_time_flying_ms(void) const {if (!likely_flying) {return 0;}return AP_HAL::millis() - _last_flying_ms;}// returns true if the vehicle has crashedvirtual bool is_crashed() const;/*methods to control vehicle for use by scripting*/virtual bool start_takeoff(float alt) { return false; }virtual bool set_target_location(const Location& target_loc) { return false; }virtual bool set_target_velocity_NED(const Vector3f& vel_ned) { return false; }virtual bool set_target_angle_and_climbrate(float roll_deg, float pitch_deg, float yaw_deg, float climb_rate_ms, bool use_yaw_rate, float yaw_rate_degs) { return false; }// get target location (for use by scripting)virtual bool get_target_location(Location& target_loc) { return false; }// set steering and throttle (-1 to +1) (for use by scripting with Rover)virtual bool set_steering_and_throttle(float steering, float throttle) { return false; }// control outputs enumerationenum class ControlOutput {Roll = 1,Pitch = 2,Throttle = 3,Yaw = 4,Lateral = 5,MainSail = 6,WingSail = 7,Walking_Height = 8,Last_ControlOutput  // place new values before this};// get control output (for use in scripting)// returns true on success and control_value is set to a value in the range -1 to +1virtual bool get_control_output(AP_Vehicle::ControlOutput control_output, float &control_value) { return false; }// write out harmonic notch log messagesvoid write_notch_log_messages() const;// update the harmonic notchvirtual void update_dynamic_notch() {};// zeroing the RC outputs can prevent unwanted motor movement:virtual bool should_zero_rc_outputs_on_reboot() const { return false; }// reboot the vehicle in an orderly manner, doing various cleanups// and flashing LEDs as appropriatevoid reboot(bool hold_in_bootloader);protected:virtual void init_ardupilot() = 0;virtual void load_parameters() = 0;virtual void set_control_channels() {}// board specific configAP_BoardConfig BoardConfig;#if HAL_MAX_CAN_PROTOCOL_DRIVERS// board specific config for CAN busAP_CANManager can_mgr;
#endif// main loop schedulerAP_Scheduler scheduler{FUNCTOR_BIND_MEMBER(&AP_Vehicle::fast_loop, void)};virtual void fast_loop();// IMU variables// Integration time; time last loop took to runfloat G_Dt;// sensor driversAP_GPS gps;AP_Baro barometer;Compass compass;AP_InertialSensor ins;AP_Button button;RangeFinder rangefinder;AP_RSSI rssi;
#if HAL_RUNCAM_ENABLEDAP_RunCam runcam;
#endif
#if HAL_GYROFFT_ENABLEDAP_GyroFFT gyro_fft;
#endifAP_VideoTX vtx;AP_SerialManager serial_manager;AP_Relay relay;AP_ServoRelayEvents ServoRelayEvents;// notification object for LEDs, buzzers etc (parameter set to// false disables external leds)AP_Notify notify;// Inertial Navigation EKF
#if AP_AHRS_NAVEKF_AVAILABLEAP_AHRS_NavEKF ahrs;
#elseAP_AHRS_DCM ahrs;
#endif#if HAL_HOTT_TELEM_ENABLEDAP_Hott_Telem hott_telem;
#endif#if HAL_VISUALODOM_ENABLEDAP_VisualOdom visual_odom;
#endifAP_ESC_Telem esc_telem;#if HAL_MSP_ENABLEDAP_MSP msp;
#endif#if GENERATOR_ENABLEDAP_Generator_RichenPower generator;
#endifstatic const struct AP_Param::GroupInfo var_info[];static const struct AP_Scheduler::Task scheduler_tasks[];private:// delay() callback that processing MAVLink packetsstatic void scheduler_delay_callback();// if there's been a watchdog reset, notify the world via a// statustext:void send_watchdog_reset_statustext();bool likely_flying;         // true if vehicle is probably flyinguint32_t _last_flying_ms;   // time when likely_flying last went truestatic AP_Vehicle *_singleton;
};

需要注意的是在公有部分内部声明的两个函数setup()和loop()。之前查了很多博客,包括截至写博客期间的官方手册,讲述的都是以前的版本。以前版本的APM源码在对应的具体车辆类型中(如Copter等)是在主文件中(如Copter.cpp)中通过setup()完成初始化,loop()完成主循环。现在的话主循环完成在fast_loop()里面。

此外在protected部分,需要注意的是init_ardupilot()和fast_loop()两个方法。

virtual void init_ardupilot() = 0;
...
virtual void fast_loop();
  • 1
  • 2
  • 3

3.2 .cpp

在对应的AP_Vechile.cpp文件中实现了setup(),loop()和fast_loop()函数。

/*setup is called when the sketch starts*/
void AP_Vehicle::setup()
{// load the default values of variables listed in var_info[]AP_Param::setup_sketch_defaults();// initialise serial portserial_manager.init_console();hal.console->printf("\n\nInit %s""\n\nFree RAM: %u\n",AP::fwversion().fw_string,(unsigned)hal.util->available_memory());load_parameters();// initialise the main loop schedulerconst AP_Scheduler::Task *tasks;uint8_t task_count;uint32_t log_bit;get_scheduler_tasks(tasks, task_count, log_bit);AP::scheduler().init(tasks, task_count, log_bit);// time per loop - this gets updated in the main loop() based on// actual loop rateG_Dt = scheduler.get_loop_period_s();// this is here for Plane; its failsafe_check method requires the// RC channels to be set as early as possible for maximum// survivability.set_control_channels();// initialise serial manager as early as sensible to get// diagnostic output during boot process.  We have to initialise// the GCS singleton first as it sets the global mavlink system ID// which may get used very early on.gcs().init();// initialise serial portsserial_manager.init();gcs().setup_console();// Register scheduler_delay_cb, which will run anytime you have// more than 5ms remaining in your call to hal.scheduler->delayhal.scheduler->register_delay_callback(scheduler_delay_callback, 5);#if HAL_MSP_ENABLED// call MSP init before init_ardupilot to allow for MSP sensorsmsp.init();
#endif// init_ardupilot is where the vehicle does most of its initialisation.init_ardupilot();gcs().send_text(MAV_SEVERITY_INFO, "ArduPilot Ready");// gyro FFT needs to be initialized really late
#if HAL_GYROFFT_ENABLEDgyro_fft.init(AP::scheduler().get_loop_period_us());
#endif
#if HAL_RUNCAM_ENABLEDruncam.init();
#endif
#if HAL_HOTT_TELEM_ENABLEDhott_telem.init();
#endif
#if HAL_VISUALODOM_ENABLED// init library used for visual position estimationvisual_odom.init();
#endifvtx.init();#if AP_PARAM_KEY_DUMPAP_Param::show_all(hal.console, true);
#endif
}
void AP_Vehicle::loop()
{scheduler.loop();G_Dt = scheduler.get_loop_period_s();
}
  • 1
  • 2
  • 3
  • 4
  • 5
/*所有无人机的快速循环回调。 这将在任何特定于无人机的快速循环结束时调用。*/
void AP_Vehicle::fast_loop()
{#if HAL_GYROFFT_ENABLEDgyro_fft.sample_gyros();
#endif
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

总结:

  • 在setup()里面完成了如串口和参数表等部分设备的初始化内容,但是具体的无人机设备初始化需要在init_ardupilot()中完成。
  • loop()函数较短,内部实现的是对任务循环并且获取任务单词循环时的时间(以s为单位)。
  • fast_loop()见注释。

四、class Copter

4.1 .h

内容实在是有点多,为了排版和阅读方便,这边就不全部放上来了,挑一些重点说一下。

public:friend class GCS_MAVLINK_Copter;friend class GCS_Copter;friend class AP_Rally_Copter;friend class Parameters;friend class ParametersG2;friend class AP_Avoidance_Copter;#if ADVANCED_FAILSAFE == ENABLEDfriend class AP_AdvancedFailsafe_Copter;
#endiffriend class AP_Arming_Copter;friend class ToyMode;friend class RC_Channel_Copter;friend class RC_Channels_Copter;friend class AutoTune;friend class Mode;friend class ModeAcro;friend class ModeAcro_Heli;friend class ModeAltHold;friend class ModeAuto;friend class ModeAutoTune;friend class ModeAvoidADSB;friend class ModeBrake;friend class ModeCircle;friend class ModeDrift;friend class ModeFlip;friend class ModeFlowHold;friend class ModeFollow;friend class ModeGuided;friend class ModeLand;friend class ModeLoiter;friend class ModePosHold;friend class ModeRTL;friend class ModeSmartRTL;friend class ModeSport;friend class ModeStabilize;friend class ModeStabilize_Heli;friend class ModeSystemId;friend class ModeThrow;friend class ModeZigZag;friend class ModeAutorotate;Copter(void);

首先是公有部分,内部声明了多个个友元类,这些类中的成员函数能够访问Copter类中的私有成员。构造函数Copter()在Copter.cpp文件中实现。

    // primary input control channelsRC_Channel *channel_roll;RC_Channel *channel_pitch;RC_Channel *channel_throttle;RC_Channel *channel_yaw;

这部分上一篇博客已经提过了,但是这边还是想说一下,此处表示的是Copter的主要输入控制通道。

4.2 .cpp

Copter.cpp文件中实现了Copter类的构造,代码如下

Mode::Number control_mode;

定义control_mode为STABILIZE。而Mode::Number是一个枚举类,具体在ArduCopter路径下的mode.h中进行定义

/*constructor for main Copter class*/
Copter::Copter(void): logger(g.log_bitmask),flight_modes(&g.flight_mode1),control_mode(Mode::Number::STABILIZE),simple_cos_yaw(1.0f),super_simple_cos_yaw(1.0),land_accel_ef_filter(LAND_DETECTOR_ACCEL_LPF_CUTOFF),rc_throttle_control_in_filter(1.0f),inertial_nav(ahrs),param_loader(var_info),flightmode(&mode_stabilize)
{// init sensor error logging flagssensor_health.baro = true;sensor_health.compass = true;
}

在这份文件内主要是通过Copter的构造函数实现了其他组件对象初始化,以上的所有参数均在Copter.h中有所声明。

 // Auto Pilot Modes enumerationenum class Number : uint8_t {STABILIZE =     0,  // manual airframe angle with manual throttleACRO =          1,  // manual body-frame angular rate with manual throttleALT_HOLD =      2,  // manual airframe angle with automatic throttleAUTO =          3,  // fully automatic waypoint control using mission commandsGUIDED =        4,  // fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commandsLOITER =        5,  // automatic horizontal acceleration with automatic throttleRTL =           6,  // automatic return to launching pointCIRCLE =        7,  // automatic circular flight with automatic throttleLAND =          9,  // automatic landing with horizontal position controlDRIFT =        11,  // semi-automous position, yaw and throttle controlSPORT =        13,  // manual earth-frame angular rate control with manual throttleFLIP =         14,  // automatically flip the vehicle on the roll axisAUTOTUNE =     15,  // automatically tune the vehicle's roll and pitch gainsPOSHOLD =      16,  // automatic position hold with manual override, with automatic throttleBRAKE =        17,  // full-brake using inertial/GPS system, no pilot inputTHROW =        18,  // throw to launch mode using inertial/GPS system, no pilot inputAVOID_ADSB =   19,  // automatic avoidance of obstacles in the macro scale - e.g. full-sized aircraftGUIDED_NOGPS = 20,  // guided mode but only accepts attitude and altitudeSMART_RTL =    21,  // SMART_RTL returns to home by retracing its stepsFLOWHOLD  =    22,  // FLOWHOLD holds position with optical flow without rangefinderFOLLOW    =    23,  // follow attempts to follow another vehicle or ground stationZIGZAG    =    24,  // ZIGZAG mode is able to fly in a zigzag manner with predefined point A and point BSYSTEMID  =    25,  // System ID mode produces automated system identification signals in the controllersAUTOROTATE =   26,  // Autonomous autorotation};

关于各个飞行模式,具体可以参考官方手册中对Copter飞行模式的说明:Full list of flight modes

需要注意的是Copter类实现了对AP_Vehicle类的继承,但是其并为对setup()和loop()进行修改或者重写,而相对应的,在其内部另外声明了私有部分函数fast_loop()和init_ardupilot(),并在Copter.cpp和system.cpp中对两个函数进行了具体的实现。以下是Copter.h中对于这两个函数的引用部分。

   void fast_loop() override;// system.cppvoid init_ardupilot() override;

五、总结

总的来说,Copter类中实现的就是关于无人机相关功能以及传感器的最初定义。以上内容部分可能过于浅显,也可能会有出错之处,希望大家多多包涵(如有错误请务必留言指出)。后续应该还会再修改整理一下的(第一次更新:2020/12/02), 现在就先将就看看吧。

感谢博主:https://blog.csdn.net/moumde/article/details/108848428

APM_ArduCopter源码解析学习(三)——无人机类型相关推荐

  1. Ardusub源码解析学习(三)——车辆类型

    APM_Sub源码解析学习(三)--车辆类型 一.前言 二.class AP_HAL::HAL 三.class AP_Vehicle 3.1 .h 3.2 .cpp 四.class Sub 4.1 . ...

  2. Ardusub源码解析学习(一)——Ardusub主程序

    APM_Sub源码解析学习(一)--Ardusub主程序 前言 一.准备工作 二.Ardusub.cpp解析 2.1 scheduler table 2.2 scheduler get_schedul ...

  3. Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(三)

    Tightly Coupled LiDAR Inertial Odometry and Mapping源码解析(三) 3. Joint optimization 3.2 IMU preintegrat ...

  4. 【DETR源码解析】三、Transformer模块

    目录 前言 一.Transformer整体结构 二.TransformerEncoder 2.1.TransformerEncoderLayer 三.TransformerDecoder 3.1.Tr ...

  5. solrlucene3.6.0源码解析(三)

    solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下 从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用 UpdateRequestProcessor相当于责任链模式 ...

  6. dubbo源码解析(三十五)集群——cluster

    集群--cluster 目标:介绍dubbo中集群容错的几种模式,介绍dubbo-cluster下support包的源码. 前言 集群容错还是很好理解的,就是当你调用失败的时候所作出的措施.先来看看有 ...

  7. ThinkPHP路由源码解析(三)

    本文接着上文继续来解读路由源码,如果你看到本文可以先看一下之前写的路由文章,共计俩篇. ThinkPHP路由源码解析 前言 一.检测路由-合并分组参数.检查分组路由 二.检测URL变量和规则路由是否匹 ...

  8. springboot启动源码解析(三):初始化启动上下文、初始化监听器列表、发布开始启动事件

    此章节主要对springboot启动过程中,发生的[初始化启动上下文].[初始化监听器列表].[发布springboot开始启动事件]进行源码解析,对应的代码如图1所示: 图1: // 首先初始化一个 ...

  9. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

最新文章

  1. BZOJ1295 [SCOI2009]最长距离
  2. GitHub热门:程序员的架构师封神之路
  3. js 获取sessionid_百战卓越班学员学习经验分享:页面js代码
  4. pythonurllib模块-Python urllib模块 网络资源访问安装下载
  5. 吴教主深度学习和神经网络课程总纲
  6. 网络OS显神威 认识Linux远程桌面控制
  7. python3中朴素贝叶斯_贝叶斯统计:Python中从零开始的都会都市
  8. java.lang.relect.Array 类
  9. iOS开发笔记--Layer 图层圆角、边框 、底纹其他常用操作
  10. ssh 远程登录_C.4 彻底解决-新版本Sentaurus TCAD的SSH远程登录问题!!!
  11. python3.7适用的opencv_通过python3.7.3使用openCV截图一个区域
  12. 从SVN资源库下载项目
  13. python隐式调用_c#隐式调用python_C#调用python脚本样例
  14. leetcode探索动态规划(一)
  15. 一起写一个Android图片轮播控件
  16. html添加哔哩哔哩视频,哔哩哔哩在线视频编辑器使用教程汇总
  17. Android入门基础教程1
  18. 记录自己的鬼压床——长发
  19. 第七章产品生命周期管理
  20. PHP快速输出26大小写字母

热门文章

  1. hp服务器基本系统设备驱动,hp 服务器 设置硬盘驱动
  2. php医院挂号系统源码
  3. 移动Excel表格指定数据
  4. Excel通过网站页面导入数据
  5. 拓嘉启远:如何利用多多场景引流
  6. 电影《入殓师》观后感-20211108
  7. Win10看不到局域网内其他电脑怎么办
  8. 首先从键盘上两个矩阵的行数n和列数m,然后输入两个矩阵A和B的元素值,最后求出两个矩阵的和C并输出其元素值。
  9. 腾信微信公众号初步开发应用
  10. 猜猜这是icpc20年那一场的a题,高斯消元re