@@ -39,10 +39,12 @@ const double TO_ACCELERATION_TO_RAD_PER_SS = TO_ACCELERATION_TO_RAD_PER_MM / 360
3939const double DXL_ACCELERATION_FROM_RAD_PER_SS = 1.0 / TO_ACCELERATION_TO_RAD_PER_SS;
4040const int DXL_MAX_ACCELERATION = 32767 ;
4141const double TO_CURRENT_AMPERE = 0.00269 ;
42+ const double TO_DXL_CURRENT = 1.0 / TO_CURRENT_AMPERE;
4243const double TO_VOLTAGE_VOLT = 0.1 ;
4344
4445// Dynamixel XM Series address table
4546const uint16_t ADDR_OPERATING_MODE = 11 ;
47+ const uint16_t ADDR_CURRENT_LIMIT = 38 ;
4648const uint16_t ADDR_MAX_POSITION_LIMIT = 48 ;
4749const uint16_t ADDR_MIN_POSITION_LIMIT = 52 ;
4850const uint16_t ADDR_TORQUE_ENABLE = 64 ;
@@ -100,6 +102,12 @@ bool Hardware::load_config_file(const std::string& config_yaml) {
100102 std::cerr << " positionもsync_readするようにコンフィグファイルを修正して下さい." << std::endl;
101103 return false ;
102104 }
105+ if (group->sync_write_current_enabled () && !group->sync_read_position_enabled ()) {
106+ std::cerr << group_name << " グループはcurrentをsync_writeしますが, " ;
107+ std::cerr << " positionをsync_readしません." << std::endl;
108+ std::cerr << " positionもsync_readするようにコンフィグファイルを修正して下さい." << std::endl;
109+ return false ;
110+ }
103111 }
104112
105113 std::cout << " Config file '" << config_yaml << " ' loaded." << std::endl;
@@ -109,6 +117,12 @@ bool Hardware::load_config_file(const std::string& config_yaml) {
109117 std::cout << " \t " << joint_name;
110118 std::cout << " , id:" << std::to_string (joints_.joint (joint_name)->id ());
111119 std::cout << " , mode:" << std::to_string (joints_.joint (joint_name)->operating_mode ());
120+ std::cout << " , modified max_position_limit:" << std::to_string (
121+ joints_.joint (joint_name)->max_position_limit ());
122+ std::cout << " , modified min_position_limit:" << std::to_string (
123+ joints_.joint (joint_name)->min_position_limit ());
124+ std::cout << " , current_limit_when_position_exceeds_limit:" << std::to_string (
125+ joints_.joint (joint_name)->current_limit_when_position_exceeds_limit ());
112126 std::cout << std::endl;
113127 }
114128 }
@@ -129,8 +143,8 @@ void Hardware::disconnect() {
129143 return ;
130144 }
131145
132- // 速度指示モードの場合は、goal_velocityを0にする
133146 for (const auto & [group_name, group] : joints_.groups ()) {
147+ // 速度指示モードの場合は、goal_velocityを0にする
134148 if (group->sync_write_velocity_enabled ()) {
135149 std::cout << group_name << " グループにはvelocityのsync_writeが設定されています." << std::endl;
136150 std::cout << " 安全のため, disconnect()関数内で目標速度 0 rad/sを書き込みます." << std::endl;
@@ -139,6 +153,15 @@ void Hardware::disconnect() {
139153 }
140154 sync_write (group_name);
141155 }
156+ // 電流指示モードの場合は、goal_currentを0にする
157+ if (group->sync_write_current_enabled ()) {
158+ std::cout << group_name << " グループにはcurrentのsync_writeが設定されています." << std::endl;
159+ std::cout << " 安全のため, disconnect()関数内で目標速度 0 Aを書き込みます." << std::endl;
160+ for (const auto & joint_name : group->joint_names ()) {
161+ joints_.joint (joint_name)->set_goal_current (0 );
162+ }
163+ sync_write (group_name);
164+ }
142165 }
143166
144167 comm_->disconnect ();
@@ -282,6 +305,12 @@ bool Hardware::sync_write(const std::string& group_name) {
282305 write_data.push_back (DXL_HIBYTE (DXL_HIWORD (goal_velocity)));
283306 }
284307
308+ if (joints_.group (group_name)->sync_write_current_enabled ()) {
309+ uint16_t goal_current = to_dxl_current (joints_.joint (joint_name)->get_goal_current ());
310+ write_data.push_back (DXL_LOBYTE (goal_current));
311+ write_data.push_back (DXL_HIBYTE (goal_current));
312+ }
313+
285314 auto id = joints_.joint (joint_name)->id ();
286315 if (!comm_->set_sync_write_data (group_name, id, write_data)) {
287316 return false ;
@@ -335,8 +364,8 @@ bool Hardware::stop_thread() {
335364 // リソースを解放
336365 read_write_thread_.reset ();
337366
338- // 速度指示モードの場合は、goal_velocityを0にする
339367 for (const auto & [group_name, group] : joints_.groups ()) {
368+ // 速度指示モードの場合は、goal_velocityを0にする
340369 if (group->sync_write_velocity_enabled ()) {
341370 std::cout << group_name << " グループにはvelocityのsync_writeが設定されています." << std::endl;
342371 std::cout << " 安全のため, stop_thread()関数内で目標速度 0 rad/sを書き込みます." << std::endl;
@@ -345,6 +374,15 @@ bool Hardware::stop_thread() {
345374 }
346375 sync_write (group_name);
347376 }
377+ // 電流指示モードの場合は、goal_currentを0にする
378+ if (group->sync_write_current_enabled ()) {
379+ std::cout << group_name << " グループにはcurrentのsync_writeが設定されています." << std::endl;
380+ std::cout << " 安全のため, stop_thread()関数内で目標電流 0 Aを書き込みます." << std::endl;
381+ for (const auto & joint_name : group->joint_names ()) {
382+ joints_.joint (joint_name)->set_goal_current (0 );
383+ }
384+ sync_write (group_name);
385+ }
348386 }
349387
350388 return true ;
@@ -452,6 +490,36 @@ bool Hardware::set_velocities(const std::string& group_name, std::vector<double>
452490 return joints_.set_velocities (group_name, velocities);
453491}
454492
493+ bool Hardware::set_current (const uint8_t id, const double current) {
494+ if (!thread_enable_) {
495+ std::cerr << " 目標電流を書き込む場合は、" ;
496+ std::cerr << " 安全のためstart_thread()を実行してください." << std::endl;
497+ return false ;
498+ }
499+
500+ return joints_.set_current (id, current);
501+ }
502+
503+ bool Hardware::set_current (const std::string& joint_name, const double current) {
504+ if (!thread_enable_) {
505+ std::cerr << " 目標電流を書き込む場合は、" ;
506+ std::cerr << " 安全のためstart_thread()を実行してください." << std::endl;
507+ return false ;
508+ }
509+
510+ return joints_.set_current (joint_name, current);
511+ }
512+
513+ bool Hardware::set_currents (const std::string& group_name, std::vector<double >& currents) {
514+ if (!thread_enable_) {
515+ std::cerr << " 目標電流を書き込む場合は、" ;
516+ std::cerr << " 安全のためstart_thread()を実行してください." << std::endl;
517+ return false ;
518+ }
519+
520+ return joints_.set_currents (group_name, currents);
521+ }
522+
455523bool Hardware::write_max_acceleration_to_group (const std::string& group_name,
456524 const double acceleration_rpss) {
457525 // 指定されたグループ内のサーボモータの最大動作加速度(radian / s^2)を設定する
@@ -703,6 +771,7 @@ bool Hardware::parse_config_file(const std::string& config_yaml) {
703771
704772 uint32_t dxl_max_pos_limit = 0 ;
705773 uint32_t dxl_min_pos_limit = 0 ;
774+ uint16_t dxl_current_limit = 0 ;
706775 if (!comm_->read_double_word_data (joint_id, ADDR_MAX_POSITION_LIMIT, dxl_max_pos_limit)) {
707776 std::cerr << joint_name << " のMax Position Limitの読み取りに失敗しました." << std::endl;
708777 return false ;
@@ -711,6 +780,10 @@ bool Hardware::parse_config_file(const std::string& config_yaml) {
711780 std::cerr << joint_name << " のMin Position Limitの読み取りに失敗しました." << std::endl;
712781 return false ;
713782 }
783+ if (!comm_->read_word_data (joint_id, ADDR_CURRENT_LIMIT, dxl_current_limit)) {
784+ std::cerr << joint_name << " のCurrent Limitの読み取りに失敗しました." << std::endl;
785+ return false ;
786+ }
714787
715788 // 角度リミット値をラジアンに変換
716789 double max_position_limit = dxl_pos_to_radian (static_cast <int32_t >(dxl_max_pos_limit));
@@ -722,7 +795,18 @@ bool Hardware::parse_config_file(const std::string& config_yaml) {
722795 min_position_limit += config[joint_name][" pos_limit_margin" ].as <double >();
723796 }
724797
725- auto joint = joint::Joint (joint_id, ope_mode, max_position_limit, min_position_limit);
798+ // 電流リミット値をアンペアに変換
799+ double current_limit = dxl_current_to_ampere (dxl_current_limit);
800+ // 電流リミット値にマージンを加算する
801+ if (config[joint_name][" current_limit_margin" ]) {
802+ // current_limitは0以上の値にする
803+ current_limit = std::max (
804+ current_limit - config[joint_name][" current_limit_margin" ].as <double >(),
805+ 0.0 );
806+ }
807+
808+ auto joint = joint::Joint (
809+ joint_id, ope_mode, max_position_limit, min_position_limit, current_limit);
726810 joints_.append_joint (joint_name, joint);
727811 }
728812 std::vector<std::string> sync_read_targets;
@@ -815,6 +899,33 @@ bool Hardware::limit_goal_velocity_by_present_position(const std::string& group_
815899 return retval;
816900}
817901
902+ bool Hardware::limit_goal_current_by_present_position (const std::string& group_name) {
903+ // ジョイントの現在角度がmax/min position limit を超えた場合、
904+ // goal_currentをcurrent limitに制限する
905+ bool retval = true ;
906+ for (const auto & joint_name : joints_.group (group_name)->joint_names ()) {
907+ auto max_position_limit = joints_.joint (joint_name)->max_position_limit ();
908+ auto min_position_limit = joints_.joint (joint_name)->min_position_limit ();
909+ auto current_limit = joints_.joint (joint_name)->current_limit_when_position_exceeds_limit ();
910+ auto present_position = joints_.joint (joint_name)->get_present_position ();
911+ auto goal_current = joints_.joint (joint_name)->get_goal_current ();
912+ bool has_exceeded_max_pos_limit = present_position > max_position_limit &&
913+ goal_current > current_limit;
914+ bool has_exceeded_min_pos_limit = present_position < min_position_limit &&
915+ goal_current < -current_limit;
916+
917+ if (has_exceeded_max_pos_limit || has_exceeded_min_pos_limit) {
918+ std::cout << joint_name << " ジョイントの現在角度が限界角度に到達しました、" ;
919+ std::cout << " goal_currentを" << current_limit << " Aに制限します." << std::endl;
920+ auto limited_current = std::clamp (goal_current, -current_limit, current_limit);
921+ joints_.joint (joint_name)->set_goal_current (limited_current);
922+ retval = false ;
923+ }
924+ }
925+
926+ return retval;
927+ }
928+
818929bool Hardware::create_sync_read_group (const std::string& group_name) {
819930 // HardwareCommunicatorに、指定されたデータを読むSyncReadGroupを追加する
820931 // できるだけ多くのデータをSyncReadで読み取るため、インダイレクトアドレスを活用する
@@ -909,6 +1020,12 @@ bool Hardware::create_sync_write_group(const std::string& group_name) {
9091020 }
9101021 }
9111022
1023+ if (joints_.group (group_name)->sync_write_current_enabled ()) {
1024+ if (!append (ADDR_GOAL_CURRENT, LEN_GOAL_CURRENT, " goal_current" )) {
1025+ return false ;
1026+ }
1027+ }
1028+
9121029 comm_->make_sync_write_group (group_name, ADDR_INDIRECT_DATA_29, total_length);
9131030
9141031 std::vector<uint8_t > init_data (total_length, 0 );
@@ -957,6 +1074,9 @@ void Hardware::read_write_thread(const std::vector<std::string>& group_names,
9571074 if (joints_.group (group_name)->sync_write_velocity_enabled ()) {
9581075 limit_goal_velocity_by_present_position (group_name);
9591076 }
1077+ if (joints_.group (group_name)->sync_write_current_enabled ()) {
1078+ limit_goal_current_by_present_position (group_name);
1079+ }
9601080 sync_write (group_name);
9611081 }
9621082
@@ -988,6 +1108,10 @@ uint32_t Hardware::to_dxl_velocity(const double velocity_rps) {
9881108 return velocity_rps * DXL_VELOCITY_FROM_RAD_PER_SEC;
9891109}
9901110
1111+ uint16_t Hardware::to_dxl_current (const double current_ampere) {
1112+ return current_ampere * TO_DXL_CURRENT;
1113+ }
1114+
9911115uint32_t Hardware::to_dxl_acceleration (const double acceleration_rpss) {
9921116 // 加速度 rad/s^2をDYNAMIXELのデータに変換する
9931117
0 commit comments