3.5RC_Channel 과 SRVchannel

17392 단어 Ardupilot
머리말
          ROVER        ,        ,               ,    、  、    ...       ;

데이터 구조
          Rover::read_radio()     ,                        :
void Rover::read_radio()
{
//1      RC  ,      
  if (!hal.rcin->new_input()) {
  control_failsafe(channel_throttle->get_radio_in());
  return;
  }

  failsafe.last_valid_rc_ms = AP_HAL::millis();

  //    RC  ,          [angle/range]           control_in 
  RC_Channels::set_pwm_all();

  control_failsafe(channel_throttle->get_radio_in());

  //2        
  SRV_Channels::set_output_scaled(SRV_Channel::k_throttle,channel_throttle->get_control_in());

  // Check if the throttle value is above 50% and we need to nudge
  // Make sure its above 50% in the direction we are travelling
  ....
  ...
  ..

  //3      
  if (g.skid_steer_in) {
  // convert the two radio_in values from skid steering values

  float motor1 = channel_steer->norm_input();
  float motor2 = channel_throttle->norm_input();
  float steering_scaled = motor1 - motor2;
  float throttle_scaled = 0.5f*(motor1 + motor2);
  int16_t steer = channel_steer->get_radio_trim();
  int16_t thr = channel_throttle->get_radio_trim();
  channel_steer->set_pwm(steer);
  channel_throttle->set_pwm(thr);
  ....
  ...
  ..

  //4      
  rudder_arm_disarm_check();
}

여기에 관련 된 몇 개의 대상 을 단독으로 나열 하여 분석 하 다: RCChannel RC_Channels SRV_Channel SRV_Channels
RC_Channels
    RC_Channels,                   ,         RC_Channel       ,RC_Channels::set_pwm_all(void)         hal.rcin   range/angle      control_in ;        。
/*
  class RC_Channels. Hold the full set of RC_Channel objects
*/
class RC_Channels {
public:
  friend class SRV_Channels;                          #  SRV_Channels     
  // constructor
  RC_Channels(void);                                  #    ,  channels[i].ch_in     

  static const struct AP_Param::GroupInfo var_info[];

  static RC_Channel *rc_channel(uint8_t chan) {      #  RC_Channles[chan]  
  return (chan < NUM_RC_CHANNELS)?&channels[chan]:nullptr;
  }

  static void set_pwm_all(void);

private:
  // this static arrangement is to avoid static pointers in AP_Param tables
  static RC_Channel *channels;                       #  obj_channels[NUM_RC_CHANNELS]    
  RC_Channel obj_channels[NUM_RC_CHANNELS];
};

전반적 으로 RC채널 스 는 RC 를 정의 한 것 입 니 다.Channel 배열 길이 [16] 모든 채널 을 조작 하 는 출력 클래스 가 있 습 니 다.
RC_Channel
      RC_Channel,                ,            ;
/// @class RC_Channel
/// @brief Object managing one RC channel
class RC_Channel {
public:
  friend class SRV_Channels;
  friend class RC_Channels;
  // Constructor
  RC_Channel(void);

  // used to get min/max/trim limit value based on _reverse
  enum LimitValue {
  RC_CHANNEL_LIMIT_TRIM,
  RC_CHANNEL_LIMIT_MIN,
  RC_CHANNEL_LIMIT_MAX
  };

  // startup
  void load_eeprom(void);
  void save_eeprom(void);
  void save_trim(void);

  // setup the control preferences,          /  /     
  void set_range(uint16_t high);
  void set_angle(uint16_t angle);
  bool get_reverse(void) const;
  void set_default_dead_zone(int16_t dzone);
  uint16_t get_dead_zone(void) const { return dead_zone; }

  // get the center stick position expressed as a control_in value
  int16_t get_control_mid() const;

  // read input from hal.rcin - create a control_in value
  void set_pwm(int16_t pwm);
  void set_pwm_no_deadzone(int16_t pwm);

  // calculate an angle given dead_zone and trim. This is used by the quadplane code
  // for hover throttle
  int16_t pwm_to_angle_dz_trim(uint16_t dead_zone, uint16_t trim);

  /*
  return a normalised input for a channel, in range -1 to 1,
  centered around the channel trim. Ignore deadzone.
           [-1,1]
  */
  float norm_input();

  /*
  return a normalised input for a channel, in range -1 to 1,
  centered around the channel trim. Take into account the deadzone
           [-1,1],    
  */
  float norm_input_dz();

  uint8_t percent_input();
  int16_t pwm_to_range();
  int16_t pwm_to_range_dz(uint16_t dead_zone);

  // read the input value from hal.rcin for this channel,         RC  
  uint16_t read() const;

  // read input from hal.rcin and set as pwm input for channel
  void input();

  static const struct AP_Param::GroupInfo var_info[];

  // return true if input is within deadzone of trim
  bool in_trim_dz();

  int16_t get_radio_in() const { return radio_in;}
  void set_radio_in(int16_t val) {radio_in = val;}

  int16_t get_control_in() const { return control_in;}
  void set_control_in(int16_t val) { control_in = val;}

  // get control input with zero deadzone
  int16_t get_control_in_zero_dz(void);

  int16_t get_radio_min() const {return radio_min.get();}
  void set_radio_min(int16_t val) { radio_min = val;}

  int16_t get_radio_max() const {return radio_max.get();}
  void set_radio_max(int16_t val) {radio_max = val;}

  int16_t get_radio_trim() const { return radio_trim.get();}
  void set_radio_trim(int16_t val) { radio_trim.set(val);}
  void save_radio_trim() { radio_trim.save();}

  bool min_max_configured() const
  {
  return radio_min.configured() && radio_max.configured();
  }

private:

  // pwm is stored here
  // RC             
  int16_t radio_in;

  // value generated from PWM normalised to configured scale
  // RC                   
  int16_t control_in;

  AP_Int16 radio_min;     #RC         
  AP_Int16 radio_trim;    #RC         
  AP_Int16 radio_max;     #RC         

  AP_Int8 reversed;       #RC      
  AP_Int16 dead_zone;     #RC    

  uint8_t type_in;        #RC            
  int16_t high_in;

  // the input channel this corresponds to
  uint8_t ch_in;          #RC   

  int16_t pwm_to_angle();
  int16_t pwm_to_angle_dz(uint16_t dead_zone);
};
                ,RC_Channel   RC          ,               ...

초기 채널 번호 가 분 배 될 때 RCMapper rcmap 도 언급 되 었 습 니 다. 이것 은 주로 채널 맵 입 니 다. 구조 함수 에서 const AP 를 통 해Param::GroupInfo RCMapper::var_infor [] 는 구성원 변 수 를 할당 하고 근본적으로 채널 을 매 핑 합 니 다.
RCMapper
class RCMapper
{
public:
  /// Constructor
  ///
  RCMapper();

  /// roll - return input channel number for roll / aileron input
  uint8_t roll() const { return _ch_roll; }

  /// pitch - return input channel number for pitch / elevator input
  uint8_t pitch() const { return _ch_pitch; }

  /// throttle - return input channel number for throttle input
  uint8_t throttle() const { return _ch_throttle; }

  /// yaw - return input channel number for yaw / rudder input
  uint8_t yaw() const { return _ch_yaw; }

  /// forward - return input channel number for forward input
  uint8_t forward() const { return _ch_forward; }

  /// lateral - return input channel number for lateral input
  uint8_t lateral() const { return _ch_lateral; }

  static const struct AP_Param::GroupInfo var_info[];

private:
  // channel mappings
  AP_Int8 _ch_roll;
  AP_Int8 _ch_pitch;
  AP_Int8 _ch_yaw;
  AP_Int8 _ch_throttle;
  AP_Int8 _ch_forward;
  AP_Int8 _ch_lateral;
};
const AP_Param::GroupInfo RCMapper::var_info[] = {
  // @Param: ROLL
  // @DisplayName: Roll channel
  // @Description: Roll channel number.
  // @Range: 1 8
  // @Increment: 1
  // @User: Advanced
  // @RebootRequired: True
  AP_GROUPINFO("ROLL", 0, RCMapper, _ch_roll, 1),
  AP_GROUPINFO("PITCH", 1, RCMapper, _ch_pitch, 2),
  AP_GROUPINFO("THROTTLE", 2, RCMapper, _ch_throttle, 3),
  AP_GROUPINFO("YAW", 3, RCMapper, _ch_yaw, 4),
  AP_GROUPINFO_FRAME("FORWARD", 4, RCMapper, _ch_forward, 6, AP_PARAM_FRAME_SUB),
  AP_GROUPINFO_FRAME("LATERAL", 5, RCMapper, _ch_lateral, 7, AP_PARAM_FRAME_SUB),
};

최종 사용 시: 1. RC 하나만 정의 하면 됩 니 다.채널 의 지침;2. 그리고 RCChannels::rc_channel () 은 실제 채널 지침 을 되 돌려 줍 니 다.3. 실제 채널 포인터 의 맵 은 RCMapper: var 에 존재 합 니 다.info[]; 위의 세 가 지 를 사용 하면 기본적으로 사용 할 수 있 습 니 다. 그 다음 에 깊이 들 어가 면 이 PWM 의 값 이 어떻게 생 겼 는 지, RC 에서채널 클래스 에서 발견 하기 어렵 지 않 습 니 다:
void
RC_Channel::input()
{
  radio_in = hal.rcin->read(ch_in);
}

uint16_t
RC_Channel::read() const
{
  return hal.rcin->read(ch_in);
}
                hal.rcin, RCInput        ,         orb_copy(ORB_ID(input_rc), _rc_sub, &_rcin);          RC    ;
void PX4RCInput::_timer_tick(void)
{
  perf_begin(_perf_rcin);
  bool rc_updated = false;
  if (orb_check(_rc_sub, &rc_updated) == 0 && rc_updated) {
  pthread_mutex_lock(&rcin_mutex);
  orb_copy(ORB_ID(input_rc), _rc_sub, &_rcin);
  pthread_mutex_unlock(&rcin_mutex);
  }
  // note, we rely on the vehicle code checking new_input()
  // and a timeout for the last valid input to handle failsafe
  perf_end(_perf_rcin);
}
            PX4Firmware/src/driver/px4_fmu/fmu.cpp        ,   _rc_in    void

PX4FMU::fill_rc_in () 으로 채 우 는 것, 즉 우리 가 얻 은 원시 pwm 를 포함 하 는 값 입 니 다.
void
PX4FMU::cycle_trampoline(void *arg)
{
PX4FMU *dev = reinterpret_cast(arg);

dev->cycle();
}

cycle 에 서 는 UORB 를 통 해 input 을 발표 합 니 다.rc 의 화제, 동시에 work 호출quue 순환 을 하면 자세히 보면 이 함수 안에 안전 스위치 에 대한 조작 이 있 음 을 알 수 있 습 니 다.
// slave safety from IO
...
..
/* check arming state */
...
..

if (rc_updated) {
/* lazily advertise on first publication */
if (_to_input_rc == nullptr) {
     _to_input_rc = orb_advertise(ORB_ID(input_rc), &_rc_in);

} else {
     orb_publish(ORB_ID(input_rc), _to_input_rc, &_rc_in);
}
}

work_queue(HPWORK, &_work, (worker_t)&PX4FMU::cycle_trampoline, this, USEC2TICK(SCHEDULE_INTERVAL - main_out_latency)); 여기까지 기본적으로 알 수 있 는 것 은 px4fmu 도 공공 계승 CDev 의 클래스 는 이전의 I2C, SPI 와 마찬가지 로 모두 문자 구동 에 속한다.동일 상황 px4io 도 마찬가지 로 공공 이 CDev 의 문자 류 구동 을 계승 했다.nsh 의 단말기 에서 'ls dev' 를 통 해 알 수 있 듯 이 px 는 fmu 와 io 에 대한 추상 적 이 고 홈 페이지 설명 에 따 르 면 fmu 와 io 는 직렬 로 통신 되 며 fmu 의 workquue 에서 관련 소스 코드 가 발견 되 지 않 았 습 니 다.여 기 는 정리 가 필요 합 니 다.
SRV_Channel
 SRV_Channel               ,     PWM  ;     SRV_Channel             ,                  ;
/*
  class SRV_Channel. The class SRV_Channels contains an array of
  SRV_Channel objects. This is done to fit within the AP_Param limit
  of 64 parameters per object.
*/
class SRV_Channel {
public:
  friend class SRV_Channels;
  // constructor
  SRV_Channel(void);

  static const struct AP_Param::GroupInfo var_info[];

  typedef enum
  {
  k_none = 0, ///< disabled
  k_manual = 1, ///< manual, just pass-thru the RC in signal
  k_flap = 2, ///< flap
  k_flap_auto = 3, ///< flap automated
  k_aileron = 4, ///< aileron
  k_unused1 = 5, ///< unused function
  k_mount_pan = 6, ///< mount yaw (pan)
  k_mount_tilt = 7, ///< mount pitch (tilt)
  k_mount_roll = 8, ///< mount roll
  k_mount_open = 9, ///< mount open (deploy) / close (retract)
  k_cam_trigger = 10, ///< camera trigger
  k_egg_drop = 11, ///< egg drop
  k_mount2_pan = 12, ///< mount2 yaw (pan)
  k_mount2_tilt = 13, ///< mount2 pitch (tilt)
  k_mount2_roll = 14, ///< mount2 roll
  k_mount2_open = 15, ///< mount2 open (deploy) / close (retract)
  k_dspoiler1 = 16, ///< differential spoiler 1 (left wing)
  k_dspoiler2 = 17, ///< differential spoiler 2 (right wing)
  k_aileron_with_input = 18, ///< aileron, with rc input
  k_elevator = 19, ///< elevator
  k_elevator_with_input = 20, ///< elevator, with rc input
  k_rudder = 21, ///< secondary rudder channel
  k_sprayer_pump = 22, ///< crop sprayer pump channel
  k_sprayer_spinner = 23, ///< crop sprayer spinner channel
  k_flaperon1 = 24, ///< flaperon, left wing
  k_flaperon2 = 25, ///< flaperon, right wing
  k_steering = 26, ///< ground steering, used to separate from rudder
  k_parachute_release = 27, ///< parachute release
  k_gripper = 28, ///< gripper
  k_landing_gear_control = 29, ///< landing gear controller
  k_engine_run_enable = 30, ///< engine kill switch, used for gas airplanes and helicopters
  k_heli_rsc = 31, ///< helicopter RSC output
  k_heli_tail_rsc = 32, ///< helicopter tail RSC output
  k_motor1 = 33, ///< these allow remapping of copter motors
  k_motor2 = 34,
  k_motor3 = 35,
  k_motor4 = 36,
  k_motor5 = 37,
  k_motor6 = 38,
  k_motor7 = 39,
  k_motor8 = 40,
  k_motor_tilt = 41, ///< tiltrotor motor tilt control
  k_rcin1 = 51, ///< these are for pass-thru from arbitrary rc inputs
  k_rcin2 = 52,
  k_rcin3 = 53,
  k_rcin4 = 54,
  k_rcin5 = 55,
  k_rcin6 = 56,
  k_rcin7 = 57,
  k_rcin8 = 58,
  k_rcin9 = 59,
  k_rcin10 = 60,
  k_rcin11 = 61,
  k_rcin12 = 62,
  k_rcin13 = 63,
  k_rcin14 = 64,
  k_rcin15 = 65,
  k_rcin16 = 66,
  k_ignition = 67,
  k_choke = 68,
  k_starter = 69,
  k_throttle = 70,
  k_tracker_yaw = 71, ///< antennatracker yaw
  k_tracker_pitch = 72, ///< antennatracker pitch
  k_throttleLeft = 73,
  k_throttleRight = 74,
  k_nr_aux_servo_functions ///< This must be the last enum value (only add new values _before_ this one)
  } Aux_servo_function_t;

  // used to get min/max/trim limit value based on reverse
  enum LimitValue {
  SRV_CHANNEL_LIMIT_TRIM,
  SRV_CHANNEL_LIMIT_MIN,
  SRV_CHANNEL_LIMIT_MAX,
  SRV_CHANNEL_LIMIT_ZERO_PWM
  };

  // set the output value as a pwm value            PWM 
  void set_output_pwm(uint16_t pwm);

  // get the output value as a pwm value          PWM 
  uint16_t get_output_pwm(void) const { return output_pwm; }

  // set angular range of scaled output       PWM   ,      
  void set_angle(int16_t angle);

  // set range of scaled output. Low is always zero       PWM   ,      
  void set_range(uint16_t high);

  // return true if the channel is reversed         
  bool get_reversed(void) const {
  return reversed?true:false;
  }

  // set MIN/MAX parameters       PWM     
  void set_output_min(uint16_t pwm) {
  servo_min.set(pwm);
  }
  void set_output_max(uint16_t pwm) {
  servo_max.set(pwm);
  }

  // get MIN/MAX/TRIM parameters      PWM     
  uint16_t get_output_min(void) const {
  return servo_min;
  }
  uint16_t get_output_max(void) const {
  return servo_max;
  }
  uint16_t get_trim(void) const {
  return servo_trim;
  }

private:
  AP_Int16 servo_min;
  AP_Int16 servo_max;
  AP_Int16 servo_trim;
  // reversal, following convention that 1 means reversed, 0 means normal
  AP_Int8 reversed;
  AP_Int8 function;

  // a pending output value as PWM
  uint16_t output_pwm;

  // true for angle output type
  bool type_angle:1;

  // set_range() or set_angle() has been called
  bool type_setup:1;

  // the hal channel number
  uint8_t ch_num;

  // high point of angle or range output
  uint16_t high_out;

  // convert a 0..range_max to a pwm  PWM     
  uint16_t pwm_from_range(int16_t scaled_value) const;

  // convert a -angle_max..angle_max to a pwm  PWM     
  uint16_t pwm_from_angle(int16_t scaled_value) const;

  // convert a scaled output to a pwm value   output_scaled[  、  ]   PWM set_output_pwm();
  void calc_pwm(int16_t output_scaled);

  // output value based on function,   hal.rcout    PWM
  void output_ch(void);

  // setup output type and range based on function
  void aux_servo_function_setup(void);

  // return PWM for a given limit value
  uint16_t get_limit_pwm(LimitValue limit) const;

  // get normalised output from -1 to 1
  float get_output_norm(void);

  // a bitmask type wide enough for NUM_SERVO_CHANNELS
  typedef uint16_t servo_mask_t;

  // mask of channels where we have a output_pwm value. Cleared when a
  // scaled value is written.
  static servo_mask_t have_pwm_mask;
};

SRV_Channels
  SRV_Channel     ,         SRV_Channels    ,       SRV_Channel   ,      、       ....

다음은 간단 한 예 를 분석 하 겠 습 니 다.
      function(      )     value,        functions[function].output_scaled ;
void SRV_Channels::set_output_scaled(SRV_Channel::Aux_servo_function_t function, int16_t value);
 |
 V
SCHED_TASK(set_servos, 50, 1500),//  PWM         ,       RC  /       
 |
 V
   SRV_Channels::calc_pwm();
   SRV_Channels::output_ch_all();
 |
 V
channels[i].output_ch();//     SRV_Channel    channels[i]  
 |
 V
hal.rcout->write(ch_num, output_pwm);//  AP_HAL    ;
/// map a function to a servo channel and output it
void SRV_Channel::output_ch(void)
{
  int8_t passthrough_from = -1;

  // take care of special function cases,             ,1,[51,66]k_rcin1~k_rcin16      
  switch(function)
  {
  case k_manual: // manual
    passthrough_from = ch_num;
  break;
  case k_rcin1 ... k_rcin16: // rc pass-thru,         0~15
    passthrough_from = int8_t(function - k_rcin1);
  break;
  case k_motor1 ... k_motor8:
    // handled by AP_Motors::rc_write()
  return;
  }
  if (passthrough_from != -1) {
  // we are doing passthrough from input to output for this channel
  RC_Channel *rc = RC_Channels::rc_channel(passthrough_from);
  if (rc) {
  if (SRV_Channels::passthrough_disabled()) {
       output_pwm = rc->get_radio_trim();
  } else {
       output_pwm = rc->get_radio_in();
  }
  }
  }
  hal.rcout->write(ch_num, output_pwm);//         ,          AP_HAL_PX  RCOutput.cpp
}

총결산
RC_Channel、RC_Channels、SRV_Channel、SRV_채널 스 라 는 네 가지 유형 은 모두 hal. rcin 과 hal. rcout 을 바탕 으로 하드웨어 와 소통 하 는 것 이다.

좋은 웹페이지 즐겨찾기