30
30
#include < ignition/gazebo/components/JointPosition.hh>
31
31
#include < ignition/gazebo/components/JointVelocity.hh>
32
32
#include < ignition/gazebo/components/JointVelocityCmd.hh>
33
+ #include < ignition/gazebo/components/JointAxis.hh>
34
+
33
35
#include < ignition/gazebo/components/LinearAcceleration.hh>
34
36
#include < ignition/gazebo/components/Name.hh>
35
37
#include < ignition/gazebo/components/ParentEntity.hh>
36
38
#include < ignition/gazebo/components/Pose.hh>
37
39
#include < ignition/gazebo/components/Sensor.hh>
38
40
41
+ // pid stuff
42
+ #include < gz/math/PID.hh>
43
+
39
44
#include < ignition/transport/Node.hh>
40
45
41
46
@@ -67,6 +72,9 @@ struct jointData
67
72
// / \brief handles to the joints from within Gazebo
68
73
ignition::gazebo::Entity sim_joint;
69
74
75
+ // / \brief PID for position and velocity control
76
+ gz::math::PID pid;
77
+
70
78
// / \brief Control method defined in the URDF for each joint.
71
79
ign_ros2_control::IgnitionSystemInterface::ControlMethod joint_control_method;
72
80
};
@@ -276,7 +284,8 @@ bool IgnitionSystem::initSim(
276
284
" Joint '" << joint_name << " 'is mimicking joint '" << mimicked_joint << " ' with mutiplier: "
277
285
<< mimic_joint.multiplier );
278
286
this ->dataPtr ->mimic_joints_ .push_back (mimic_joint);
279
- suffix = " _mimic" ;
287
+ // TODO (livanov93): add parameter if suffix is used or not
288
+ // suffix = "_mimic";
280
289
}
281
290
282
291
RCLCPP_INFO_STREAM (this ->nh_ ->get_logger (), " \t State:" );
@@ -339,6 +348,37 @@ bool IgnitionSystem::initSim(
339
348
if (!std::isnan (initial_position)) {
340
349
this ->dataPtr ->joints_ [j].joint_position_cmd = initial_position;
341
350
}
351
+
352
+ // init position PID
353
+
354
+ // assuming every joint has axis
355
+ const auto * jointAxis =
356
+ this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointAxis>(
357
+ this ->dataPtr ->joints_ [i].sim_joint );
358
+ // PID parameters
359
+ double p_gain = 100.0 ;
360
+ double i_gain = 0.0 ;
361
+ double d_gain = 50.0 ;
362
+ // set integral max and min component to 10 percent of the max effort
363
+ double iMax = std::isnan (jointAxis->Data ().Effort ()) ? 1.0 : jointAxis->Data ().Effort () * 0.1 ;
364
+ double iMin = std::isnan (jointAxis->Data ().Effort ()) ? 1.0 : -jointAxis->Data ().Effort () * 0.1 ;
365
+ double cmdMax = std::isnan (jointAxis->Data ().Effort ()) ? 1000.0 : jointAxis->Data ().Effort ();
366
+ double cmdMin = std::isnan (jointAxis->Data ().Effort ()) ? -1000.0 : -jointAxis->Data ().Effort ();
367
+ double cmdOffset = 0.0 ;
368
+
369
+ igndbg << " [JointController " <<joint_name<<" ] Position based PID with Force/Torque output:" << std::endl;
370
+ igndbg << " p_gain: [" << p_gain << " ]" << std::endl;
371
+ igndbg << " i_gain: [" << i_gain << " ]" << std::endl;
372
+ igndbg << " d_gain: [" << d_gain << " ]" << std::endl;
373
+ igndbg << " i_max: [" << iMax << " ]" << std::endl;
374
+ igndbg << " i_min: [" << iMin << " ]" << std::endl;
375
+ igndbg << " cmd_max: [" << cmdMax << " ]" << std::endl;
376
+ igndbg << " cmd_min: [" << cmdMin << " ]" << std::endl;
377
+ igndbg << " cmd_offset: [" << cmdOffset << " ]" << std::endl;
378
+
379
+
380
+ this ->dataPtr ->joints_ [j].pid .Init (p_gain, i_gain, d_gain, iMax, iMin, cmdMax, cmdMin, cmdOffset);
381
+
342
382
} else if (joint_info.command_interfaces [i].name == " velocity" ) {
343
383
RCLCPP_INFO_STREAM (this ->nh_ ->get_logger (), " \t\t velocity" );
344
384
this ->dataPtr ->command_interfaces_ .emplace_back (
@@ -580,9 +620,14 @@ IgnitionSystem::perform_command_mode_switch(
580
620
581
621
hardware_interface::return_type IgnitionSystem::write (
582
622
const rclcpp::Time & /* time*/ ,
583
- const rclcpp::Duration & /* period*/ )
623
+ const rclcpp::Duration & period)
584
624
{
585
625
for (unsigned int i = 0 ; i < this ->dataPtr ->joints_ .size (); ++i) {
626
+ // assuming every joint has axis
627
+ const auto * jointAxis =
628
+ this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointAxis>(
629
+ this ->dataPtr ->joints_ [i].sim_joint );
630
+
586
631
if (this ->dataPtr ->joints_ [i].joint_control_method & VELOCITY) {
587
632
if (!this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointVelocityCmd>(
588
633
this ->dataPtr ->joints_ [i].sim_joint ))
@@ -598,25 +643,28 @@ hardware_interface::return_type IgnitionSystem::write(
598
643
{this ->dataPtr ->joints_ [i].joint_velocity_cmd });
599
644
}
600
645
} else if (this ->dataPtr ->joints_ [i].joint_control_method & POSITION) {
601
- // Get error in position
602
- double error;
603
- error = (this ->dataPtr ->joints_ [i].joint_position -
604
- this ->dataPtr ->joints_ [i].joint_position_cmd ) * *this ->dataPtr ->update_rate ;
605
646
606
- // Calculate target velcity
607
- double target_vel = - this ->dataPtr ->position_proportional_gain_ * error ;
647
+ // calculate error with clamped position command
648
+ double error = this -> dataPtr -> joints_ [i]. joint_position - std::clamp ( this ->dataPtr ->joints_ [i]. joint_position_cmd , jointAxis-> Data (). Lower (), jointAxis-> Data (). Upper ()) ;
608
649
609
- auto vel =
610
- this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointVelocityCmd>(
611
- this ->dataPtr ->joints_ [i].sim_joint );
650
+ // error can be maximal 10 percent of the range
651
+ error = copysign (1.0 , error) * std::clamp (std::abs (error), 0.0 , std::abs (jointAxis->Data ().Upper () - jointAxis->Data ().Lower ())*0.1 );
612
652
613
- if (vel == nullptr ) {
614
- this ->dataPtr ->ecm ->CreateComponent (
615
- this ->dataPtr ->joints_ [i].sim_joint ,
616
- ignition::gazebo::components::JointVelocityCmd ({target_vel}));
617
- } else if (!vel->Data ().empty ()) {
618
- vel->Data ()[0 ] = target_vel;
619
- }
653
+ // calculate target force/torque
654
+ double target_force = this ->dataPtr ->joints_ [i].pid .Update (error, std::chrono::duration<double >(period.to_chrono <std::chrono::nanoseconds>()));
655
+
656
+ auto forceCmd =
657
+ this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointForceCmd>(this ->dataPtr ->joints_ [i].sim_joint );
658
+
659
+ if (forceCmd == nullptr )
660
+ {
661
+ this ->dataPtr ->ecm ->CreateComponent (
662
+ this ->dataPtr ->joints_ [i].sim_joint ,
663
+ ignition::gazebo::components::JointForceCmd ({0 }));
664
+ } else {
665
+ *forceCmd = ignition::gazebo::components::JointForceCmd (
666
+ {target_force});
667
+ }
620
668
} else if (this ->dataPtr ->joints_ [i].joint_control_method & EFFORT) {
621
669
if (!this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointForceCmd>(
622
670
this ->dataPtr ->joints_ [i].sim_joint ))
@@ -631,7 +679,7 @@ hardware_interface::return_type IgnitionSystem::write(
631
679
*jointEffortCmd = ignition::gazebo::components::JointForceCmd (
632
680
{this ->dataPtr ->joints_ [i].joint_effort_cmd });
633
681
}
634
- } else {
682
+ } /* else {
635
683
// Fallback case is a velocity command of zero
636
684
double target_vel = 0.0;
637
685
auto vel =
@@ -647,39 +695,46 @@ hardware_interface::return_type IgnitionSystem::write(
647
695
} else if (!vel->Data().empty()) {
648
696
vel->Data()[0] = target_vel;
649
697
}
650
- }
698
+ }*/
651
699
}
652
700
653
701
// set values of all mimic joints with respect to mimicked joint
654
702
for (const auto & mimic_joint : this ->dataPtr ->mimic_joints_ ) {
655
703
for (const auto & mimic_interface : mimic_joint.interfaces_to_mimic ) {
704
+ // assuming every mimic joint has axis
705
+ const auto * jointAxis =
706
+ this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointAxis>(
707
+ this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint );
708
+
656
709
if (mimic_interface == " position" ) {
657
710
// Get the joint position
658
- double position_mimicked_joint =
659
- this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointPosition>(
660
- this ->dataPtr ->joints_ [mimic_joint.mimicked_joint_index ].sim_joint )->Data ()[0 ];
711
+ double position_mimicked_joint = this ->dataPtr ->joints_ [mimic_joint.mimicked_joint_index ].joint_position ;
661
712
662
- double position_mimic_joint =
663
- this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointPosition>(
664
- this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint )->Data ()[0 ];
713
+ double position_mimic_joint = this ->dataPtr ->joints_ [mimic_joint.joint_index ].joint_position ;
665
714
666
- double position_error =
667
- position_mimic_joint - position_mimicked_joint * mimic_joint.multiplier ;
715
+ // calculate error with clamped position command
716
+ double position_error =
717
+ position_mimic_joint - std::clamp (position_mimicked_joint * mimic_joint.multiplier , jointAxis->Data ().Lower (), jointAxis->Data ().Upper ());
668
718
669
- double velocity_sp = (-1.0 ) * position_error * (*this ->dataPtr ->update_rate );
719
+ // error can be maximal 10 percent of the range
720
+ position_error = copysign (1.0 , position_error) * std::clamp (std::abs (position_error), 0.0 , std::abs (jointAxis->Data ().Upper () - jointAxis->Data ().Lower ())*0.1 );
670
721
671
- auto vel =
672
- this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointVelocityCmd>(
673
- this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint );
722
+ // calculate target force/torque
723
+ double target_force = this ->dataPtr ->joints_ [mimic_joint.joint_index ].pid .Update (position_error, std::chrono::duration<double >(period.to_chrono <std::chrono::nanoseconds>()));
674
724
675
- if (vel == nullptr ) {
676
- this ->dataPtr ->ecm ->CreateComponent (
677
- this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint ,
678
- ignition::gazebo::components::JointVelocityCmd ({velocity_sp}));
679
- } else if (!vel->Data ().empty ()) {
680
- vel->Data ()[0 ] = velocity_sp;
681
- }
682
- }
725
+ auto forceCmd =
726
+ this ->dataPtr ->ecm ->Component <ignition::gazebo::components::JointForceCmd>(this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint );
727
+
728
+ if (forceCmd == nullptr )
729
+ {
730
+ this ->dataPtr ->ecm ->CreateComponent (
731
+ this ->dataPtr ->joints_ [mimic_joint.joint_index ].sim_joint ,
732
+ ignition::gazebo::components::JointForceCmd ({0 }));
733
+ } else {
734
+ *forceCmd = ignition::gazebo::components::JointForceCmd (
735
+ {target_force});
736
+ }
737
+ }/*
683
738
if (mimic_interface == "velocity") {
684
739
// get the velocity of mimicked joint
685
740
double velocity_mimicked_joint =
@@ -720,7 +775,7 @@ hardware_interface::return_type IgnitionSystem::write(
720
775
{mimic_joint.multiplier *
721
776
this->dataPtr->joints_[mimic_joint.mimicked_joint_index].joint_effort});
722
777
}
723
- }
778
+ }*/
724
779
}
725
780
}
726
781
0 commit comments