ON_COMMAND_RANGE()使用注意事项

本文详细介绍了ON_COMMAND_RANGE宏的使用方法及注意事项。此宏用于将一系列连续的命令ID映射到同一个处理函数中,适用于处理类似命令的情况。文章还特别提到了ID范围限制以及如何在成员函数中正确处理这些命令。

ON_COMMAND_RANGE

ON_COMMAND_RANGE( id1, id2, memberFxn )

参数:

id1 一个连续范围的命令ID的起始值。
id2 一个连续范围的命令ID的结束值。
memberFxn 该命令被映射到的消息处理函数的名字。


说明:
使用这个宏把一个连续范围的命令ID映射到单个命令处理函数。ID的范围从id1开始,到id2结束。
用ON_COMMAND_RANGE把一个范围的命令ID映射到一个成员函数。用ON_COMMAND把单个命令ID映射到成员函数。每个给定的命令ID只能有一个消息映射入口。这就是说,不能把命令映射到多于一个的处理函数。关于映射消息范围的更多信息参见“Visual C++程序员指南”中的“消息映射范围的处理函数”。
ClassWizard不支持消息映射范围,所以你必须自己写入这个宏。确保你把它写在了消息映射的//{{AFX_MSG_MAP分界符外面。

 

注:memberFxn 这个afx_msg函数带一个UINT uID参数,当然你也可以在后面追加些你其他想要的参数, 这个uID是在 id1,id2之间的,但是MFC提供的这个 id1,id2是有个范围的,最大为65535个,所以用户在创建动态菜单,BUTTON时,在资源文件中定义这些宏时请最好不要超过这些范围,如果硬是要超过65535,那麽在memberFxn(UINT uID)函数判断的时候 需要取余 uID%65535 处理。 

 

资源发生了修改需要重新buildAll一下

no gpu, how to speed up? """ FSM State Implementations Concrete implementations of different FSM states """ from typing import Dict import numpy as np import onnxruntime as ort from FSM.fsm_base import FSMState, FSMStateName from common.joystick import XboxFlag from common.robot_data import RobotData import math import os import yaml class FSMStateMLP(FSMState): """MLP策略状态实现 - 与C++版本完全一致""" def __init__(self, robot_data: RobotData): super().__init__(robot_data) # 获取包路径 current_dir = os.path.dirname(os.path.abspath(__file__)) config_path = os.path.join(current_dir, "config", "mlp.yaml") with open(config_path, 'r') as f: policy_config = yaml.safe_load(f) # Load configuration exactly like C++ self.action_num_ = policy_config.get('actions_size', 12) self.motor_num_ = policy_config.get('motor_num', 29) self.dt_ = policy_config.get('dt', 0.002) # Size configuration size_config = policy_config.get('size', {}) self.num_hist_ = size_config.get('num_hist', 15) self.obs_size_ = size_config.get('observations_size', 47) # Control configuration control_config = policy_config.get('control', {}) self.action_scale_ = control_config.get('action_scale', 0.5) self.gait_cycle_period_ = control_config.get('gait_cycle_period', 0.9) self.decimation_ = control_config.get('decimation', 5) # Normalization configuration norm_config = policy_config.get('normalization', {}) clip_config = norm_config.get('clip_scales', {}) obs_config = norm_config.get('obs_scales', {}) self.clip_obs_ = clip_config.get('clip_observations', 100.0) self.clip_act_ = clip_config.get('clip_actions', 100.0) self.lin_vel_scale_ = obs_config.get('lin_vel', 2.0) self.ang_vel_scale_ = obs_config.get('ang_vel', 1.0) self.dof_pos_scale_ = obs_config.get('dof_pos', 1.0) self.dof_vel_scale_ = obs_config.get('dof_vel', 0.05) # Read default joint angles (only action_num_ elements like C++) init_config = policy_config.get('init_state', {}) default_angles_list = init_config.get('default_joint_angles', [0.0] * self.action_num_) self.default_joint_angles_ = np.array(default_angles_list[:self.action_num_], dtype=np.float32) # Read kp/kd gains gains_config = policy_config.get('gains', {}) self.kp = np.array(gains_config.get('kp', [300.0] * self.motor_num_)) self.kd = np.array(gains_config.get('kd', [10.0] * self.motor_num_)) # Initialize buffers and actions self.observations_ = np.zeros(self.obs_size_ * self.num_hist_, dtype=np.float32) self.proprio_hist_buf_ = np.zeros(self.obs_size_ * self.num_hist_, dtype=np.float32) self.last_actions_ = np.zeros(self.action_num_, dtype=np.float32) self.actions_ = np.zeros(self.action_num_, dtype=np.float32) # Flags matching C++ self.is_first_obs_ = True self.is_first_action_ = True self.phase_locked = False # Initialize ONNX session self.model_path = os.path.join(current_dir, "model", policy_config["model_path"]) self._init_onnx_session() def _init_onnx_session(self): """初始化ONNX推理会话""" try: self.ort_session_ = ort.InferenceSession(self.model_path) print(f"[FSMStateMLP-ONNX] ONNX model loaded successfully: {self.model_path}") except Exception as e: print(f"[FSMStateMLP] Failed to load ONNX model: {e}") self.ort_session_ = None def on_enter(self): """进入MLP状态""" print("[FSMStateMLP] enter") self.is_first_obs_ = True self.is_first_action_ = True def run(self, flag: XboxFlag): """运行MLP状态 - 与C++版本完全一致""" print("[FSMStateMLP] run") # Only run policy inference every decimation_ steps if int(self.robot_data_.time_now_ / self.dt_) % self.decimation_ == 0: self.compute_observation(flag) self.compute_actions() # Set joint commands exactly like C++ for i in range(self.action_num_): # C++: robot_data_->q_d_(35 - motor_num_ + i) joint_idx = 35 - self.motor_num_ + i self.robot_data_.q_d_[joint_idx] = ( self.actions_[i] * self.action_scale_ + self.default_joint_angles_[i] ) self.robot_data_.q_dot_d_[joint_idx] = 0.0 self.robot_data_.tau_d_[joint_idx] = 0.0 self.last_actions_[i] = self.actions_[i] # Set kp/kd gains self.robot_data_.joint_kp_p_[:self.motor_num_] = self.kp self.robot_data_.joint_kd_p_[:self.motor_num_] = self.kd def compute_observation(self, flag: XboxFlag): """计算观测量 - 与C++版本完全一致""" t_now = float(self.robot_data_.time_now_) # Phase calculation exactly like C++ phase = math.fmod(t_now, self.gait_cycle_period_) cmd_norm = math.sqrt( flag.x_speed_command * flag.x_speed_command + flag.y_speed_command * flag.y_speed_command + flag.yaw_speed_command * flag.yaw_speed_command ) if cmd_norm >= 0.05: self.phase_locked = False tolerance = 0.1 if cmd_norm < 0.05 and abs(phase - self.gait_cycle_period_) < tolerance: self.phase_locked = True if self.phase_locked: phase = 0 # Command vector exactly like C++ command = np.array([ math.sin(2 * math.pi * phase), math.cos(2 * math.pi * phase), flag.x_speed_command, flag.y_speed_command, flag.yaw_speed_command ], dtype=np.float32) print(f'Input command: {command}') # IMU data exactly like C++ rpy = np.array([ self.robot_data_.imu_data_[2], # roll self.robot_data_.imu_data_[1], # pitch self.robot_data_.imu_data_[0] # yaw ], dtype=np.float32) * 1.0 gyro = np.array([ self.robot_data_.imu_data_[3], self.robot_data_.imu_data_[4], self.robot_data_.imu_data_[5] ], dtype=np.float32) * self.ang_vel_scale_ # Construct proprio observation exactly like C++ # proprio << command, (joint_pos - default) * scale, joint_vel * scale, last_actions, gyro, rpy joint_start_idx = 35 - self.motor_num_ # Same as C++ joint_pos = ( self.robot_data_.q_a_[joint_start_idx:joint_start_idx + 12].astype(np.float32) - self.default_joint_angles_ ) * self.dof_pos_scale_ joint_vel = ( self.robot_data_.q_dot_a_[joint_start_idx:joint_start_idx + 12].astype(np.float32) ) * self.dof_vel_scale_ # Concatenate exactly like C++ proprio = np.concatenate([ command, # 5 elements joint_pos, # 12 elements joint_vel, # 12 elements self.last_actions_, # 12 elements gyro, # 3 elements rpy # 3 elements ]) # Total: 47 elements # History buffer management exactly like C++ if self.is_first_obs_: for i in range(self.num_hist_): start_idx = i * self.obs_size_ end_idx = start_idx + self.obs_size_ self.proprio_hist_buf_[start_idx:end_idx] = proprio self.is_first_obs_ = False else: # Shift history: head((num_hist-1)*obs_size) = tail((num_hist-1)*obs_size) shift_size = (self.num_hist_ - 1) * self.obs_size_ self.proprio_hist_buf_[:shift_size] = self.proprio_hist_buf_[self.obs_size_:] self.proprio_hist_buf_[shift_size:] = proprio # Clip observations exactly like C++ self.observations_ = np.clip(self.proprio_hist_buf_, -self.clip_obs_, self.clip_obs_) def compute_actions(self): """使用ONNX模型计算动作 - 与C++版本完全一致""" if self.ort_session_ is None: return try: # Prepare input tensor input_data = self.observations_.reshape(1, -1).astype(np.float32) # ONNX inference input_name = self.ort_session_.get_inputs()[0].name outputs = self.ort_session_.run(None, {input_name: input_data}) # Extract and clip actions exactly like C++ output_data = outputs[0][0] for i in range(self.action_num_): self.actions_[i] = np.clip(output_data[i], -self.clip_act_, self.clip_act_) if self.is_first_action_: print("[FSMStateMLP-ONNX] First Observation:") for i in range(self.obs_size_): print(f"{self.observations_[i]:.6f} ", end="") print() self.is_first_action_ = False except Exception as e: print(f"[FSMStateMLP] ONNX Runtime inference error: {e}") def on_exit(self): """退出MLP状态""" print("[FSMStateMLP] exit") def check_transition(self, flag: XboxFlag) -> FSMStateName: """检查状态转换""" if flag.fsm_state_command == "gotoSTOP": return FSMStateName.STOP elif flag.fsm_state_command == "gotoMLP": return FSMStateName.MLP # elif flag.fsm_state_command == "gotoMLPH": # return FSMStateName.MLPH # elif flag.fsm_state_command == "gotoMLPREF": # return FSMStateName.MLPREF # elif flag.fsm_state_command == "gotoMLP1": # return FSMStateName.MLP1 elif flag.fsm_state_command == "gotoZERO": return FSMStateName.ZERO # elif flag.fsm_state_command == "gotoSTANDUP": # return FSMStateName.STANDUP # elif flag.fsm_state_command == "gotoGETUP": # return FSMStateName.GETUP # elif flag.fsm_state_command == "gotoAMP": # return FSMStateName.AMP # elif flag.fsm_state_command == "gotoMLPHA": # return FSMStateName.MLPHA else: return None # 无状态转换
10-21
把下面脚本转换为在window系统可运行脚本 import subprocess import re import sys is_online = input("在线或离线计算亮度转换(0: online, 1: offline): ") type = input("请输入待转换类型(0: nit->brightness, 1: brightness->nit, 2: brightness_float->brightness_int, 3: brightness_int->brightness_float): ") num = float(input("请输入待转换亮度: ")) command_result = "" if is_online == "1" and type == "1": command_result = input("请输入执行findstr /I /R \"mBrightnessToNitsSpline\"后的过滤结果(整体复制输入): ") elif is_online == "1" and type == "0": command_result = input("请输入执行findstr /I /R \"mNitsToBrightnessSpline\"后的过滤结果(整体复制输入): ") elif is_online == "1": max_brt = input('请输入待转换设备最大亮度整型值即config_screenBrightnessSettingMaximum_hyper对应的值: ') # 待运行shell命令 nit_to_brightness_command = "adb shell dumpsys display|findstr /I /R \"mNitsToBrightnessSpline\"" brightness_to_nit_command = "adb shell dumpsys display|findstr /I /R \"mBrightnessToNitsSpline\"" max_brightness_command = "adb shell cmd overlay lookup --verbose android android:integer/config_screenBrightnessSettingMaximum_hyper" max_brightness_command_below_v = "adb shell cmd overlay lookup --verbose android android:integer/config_screenBrightnessSettingMaximum" android_version_command = "adb shell getprop ro.build.version.release" device_command = "adb devices" current_min_brightness = "adb shell dumpsys display | findstr /I /R \"mCachedBrightnessInfo.brightnessMin=\"" current_max_brightness = "adb shell dumpsys display|findstr /I /R \"mCachedBrightnessInfo.brightnessMax=\"" result = "" def run_command(command): result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) return result def map_range(value, from_min, from_max, to_min, to_max): # 将一个值从一个区间映射到另一个区间 from_range = from_max - from_min to_range = to_max - to_min scaled_value = float(value - from_min) / float(from_range) if scaled_value > 1.0: scaled_value = 1.0 elif scaled_value < 0.0: scaled_value = 0.0 return to_min + (scaled_value * to_range) def brightnessToIntForLowLevel(brightness:float): curMin = float(run_command(current_min_brightness).stdout.split('=')[1]) curMax = float(run_command(current_max_brightness).stdout.split('=')[1]) res = map_range(brightness, curMin, curMax, 1.0, 255.0) return str(int(res+0.5)) def extract_integers(text): return [int(num) for num in re.findall(r'\d+', text)] device = run_command(device_command) is_connected = bool(re.search(r"\d", device.stdout)) if not is_connected and is_online == "0": print('\033[31m请连上待转换的设备后计算!\033[0m') sys.exit(0) version = run_command(android_version_command).stdout res = None if int(version) <=14: res = run_command(max_brightness_command_below_v).stdout else: res = run_command(max_brightness_command).stdout max_array = extract_integers(str(res)) max_brightness = -1.0 if is_online == '1': max_brightness = float(max_brt) else: max_brightness= max_array[len(max_array)-1] brt_int = -1.0 if type == '1' and is_online == '0' and num > 1.0: brt_int = num num = round(float((num -1)/(max_brightness - 1)),10) if type == '0': result = run_command(nit_to_brightness_command) elif type == '1': result = run_command(brightness_to_nit_command) elif type == '2': if num > 1.0 or num < 0.0: print('\033[31m输入亮度浮点值数据超出转换范围!\033[0m') sys.exit(0) brightness_int = num*max_brightness+1 print('-----------------------answer------------------------------') print(str(num)+' 对应的'+str(max_brightness)+'级亮度整型值为: '+str(round(brightness_int))+", 对应255级亮度整型值为: "+brightnessToIntForLowLevel(num)) print('-----------------------------------------------------------') sys.exit(0) elif type == '3': brightness_float = (num-1) / (max_brightness-1) print('-----------------------answer------------------------------') print(str(num)+' 对应的亮度浮点值为: '+str(brightness_float)+", 对应255级亮度整型值为: "+brightnessToIntForLowLevel(num)) print('-----------------------------------------------------------') sys.exit(0) else: print('\033[31m输入的类型错误!\033[0m') sys.exit(0) # 获取命令的输出和错误信息 output = result.stdout if is_online == "1": if len(command_result) == 0: print('\033[31m离线执行输入数据不正确!\033[0m') sys.exit(0) output = command_result # 取浮点数 float_list = re.findall(r"\d+\.\d+E[+-]\d+|\d+\.\d+", output) brt_list = [] for brt in float_list: brt_list.append('{:.11f}'.format(float(brt))) print('-----------------------answer------------------------------') start = -1.0 end = -1.0 for i in range(0,len(float_list),3): if (i+3>=len(float_list)): if num == end: if type == "0": print(str(num)+" nit对应的亮度浮点值为: 1.0,对应的亮度整型值为: "+str(max_brightness)) elif type == "1": print(str(num)+" 亮度值对应的理论亮度为: "+str(float('{:.11f}'.format(float(float_list[i+1]))))+" nit") break start = float('{:.11f}'.format(float(float_list[i]))) end = float('{:.11f}'.format(float(float_list[i+3]))) if num >= start and num < end: ans = (num-start)*float('{:.11f}'.format(float(float_list[i+2])))+float('{:.11f}'.format(float(float_list[i+1]))) if type == "0": print(str(num)+" nit对应的亮度浮点值为: "+str(round(ans,9))+",对应的"+str(max_brightness)+"级亮度整型值为: "+str(round(ans*(max_brightness-1)+1))+", 对应255级亮度整型值为: "+brightnessToIntForLowLevel(ans)) elif type == "1": str_temp = str(num)+' 对应的'+str(max_brightness)+'级亮度整型值为: '+str(round(num*max_brightness+1))+', ' if brt_int == -1.0 else str(brt_int)+' 对应的亮度浮点值为: '+str(num)+', ' print(str_temp+" 亮度值对应的理论亮度为: "+str(round(ans,2))+" nit"+", 对应255级亮度整型值为: "+brightnessToIntForLowLevel(num)) break print('-----------------------------------------------------------')
10-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值