PlatformLocalTrajectoryController.cpp
Go to the documentation of this file.
2
3#include <string>
4
5#include <Ice/Current.h>
6#include <IceUtil/Time.h>
7
8#include <VirtualRobot/VirtualRobot.h>
9
14#include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
15#include <ArmarXCore/interface/observers/ObserverInterface.h>
16#include <ArmarXCore/interface/observers/VariantBase.h>
17#include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
19
25#include <RobotAPI/interface/units/RobotUnit/NJointController.h>
26#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
27
28#include <armarx/control/interface/ConfigurableNJointControllerInterface.h> // IWYU pragma: keep
31#include <armarx/navigation/platform_controller/aron/PlatformLocalTrajectoryControllerConfig.aron.generated.h>
33
35{
38
40 const NJointControllerConfigPtr& config,
42 {
43 ARMARX_IMPORTANT << "Creating "
46 // config
47 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
49 // ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
50
51 ARMARX_CHECK_EXPRESSION(robotUnit);
52
53 const auto robot = useSynchronizedRtRobot();
54
55 platformTarget = useControlTarget(robotUnit->getRobotPlatformName(),
56 ControlModes::HolonomicPlatformVelocity)
58 ARMARX_CHECK_EXPRESSION(platformTarget)
59 << "The actuator " << robotUnit->getRobotPlatformName() << " has no control mode "
60 << ControlModes::HolonomicPlatformVelocity;
61
62 const auto configData = ::armarx::fromAron<arondto::Config, Config>(cfg->config);
63 const auto trajectoryFollowingControllerParams = configData.params;
64
66 configBuffer_updateConfigToAdditionalTask.reinitAllBuffers(configData);
67 configBuffer_updateConfigToOnPublish.reinitAllBuffers(configData);
68
69 trajectoryFollowingController.emplace(trajectoryFollowingControllerParams);
70
71 ARMARX_INFO << "Init done.";
72 }
73
74 std::string
80
81 void
82 Controller::rtRun(const IceUtil::Time& sensorValuesTimestamp,
83 const IceUtil::Time& timeSinceLastIteration)
84 {
86
87 // update control devices
88 platformTarget->velocityX = rtGetControlStruct().twistCommanded.linear.x();
89 platformTarget->velocityY = rtGetControlStruct().twistCommanded.linear.y();
90 platformTarget->velocityRotation = rtGetControlStruct().twistCommanded.angular;
91
92 // read data (for non-rt)
93 robotStateBuffer_rtToAdditionalTask.getWriteBuffer().global_T_robot.matrix() =
94 rtGetRobot()->getGlobalPose();
95 robotStateBuffer_rtToAdditionalTask.commitWrite();
96 }
97
98 void
99 Controller::updateConfig(const ::armarx::aron::data::dto::DictPtr& dto,
100 const Ice::Current& iceCurrent)
101 {
102 ARMARX_INFO << "Controller::updateConfig";
103
104 // TODO maybe update pid controller
105
107
108 configBuffer_updateConfigToAdditionalTask.getWriteBuffer() = updateConfig;
109 configBuffer_updateConfigToAdditionalTask.commitWrite();
110
111 configBuffer_updateConfigToOnPublish.getWriteBuffer() = updateConfig;
112 configBuffer_updateConfigToOnPublish.commitWrite();
113
114 ARMARX_VERBOSE << "Trajectory with " << updateConfig.targets.trajectory.points().size();
115
116 ARMARX_VERBOSE << "done Controller::updateConfig";
117 }
118
119 void
121 {
122 ARMARX_CHECK(trajectoryFollowingController.has_value());
123
124 const auto& configBuffer =
125 configBuffer_updateConfigToAdditionalTask.getUpToDateReadBuffer();
126
127 // if trajectory is empty, set velocity to 0
128 if (configBuffer.targets.trajectory.points().empty())
129 {
130 ARMARX_INFO << "Trajectory is empty!";
131
132 filteredTwist.reset();
133
134 getWriterControlStruct().twistCommanded.reset();
137 return;
138 }
139
141
142 // make sure the parameters are up to date
143 // i.e. velocityFactor and limits, as they can be changed on the fly
144 trajectoryFollowingController->updateParams(configBuffer.params);
145
146 // update controller
147 const traj_ctrl::local::TrajectoryControllerResult result = trajectoryFollowingController->control(
148 configBuffer.targets.trajectory,
149 robotStateBuffer_rtToAdditionalTask.getUpToDateReadBuffer().global_T_robot);
150
151 // low-pass filter
152 {
153 const float alpha = configBuffer.params.alpha;
154 filteredTwist.linear =
155 alpha * filteredTwist.linear + (1. - alpha) * result.twist.linear.head<2>();
156 filteredTwist.angular =
157 alpha * filteredTwist.angular + (1. - alpha) * result.twist.angular.z();
158 }
159
160 // store result
161 {
162 auto& writeBuffer = getWriterControlStruct();
163 writeBuffer.twistRaw = result.twist;
164 writeBuffer.twistCommanded = filteredTwist;
165 writeBuffer.result = result;
166 }
168
169 // store results (onPublish)
170 {
171 auto& writeBuffer = targetBuffer_additionalTaskToOnPublish.getWriteBuffer();
172 writeBuffer.twistRaw = result.twist;
173 writeBuffer.twistCommanded = filteredTwist;
174 writeBuffer.result = result;
175 }
176 targetBuffer_additionalTaskToOnPublish.commitWrite();
177 }
178
179 void
181 const DebugDrawerInterfacePrx& debugDrawer,
182 const DebugObserverInterfacePrx& debugObservers)
183 {
184 StringVariantBaseMap datafields;
185
186 const auto& targets = targetBuffer_additionalTaskToOnPublish.getUpToDateReadBuffer();
187
188 datafields["vx"] = new Variant(targets.twistCommanded.linear.x());
189 datafields["vy"] = new Variant(targets.twistCommanded.linear.y());
190 datafields["v_linear"] = new Variant(targets.twistCommanded.linear.norm());
191 datafields["vyaw"] = new Variant(targets.twistCommanded.angular);
192
193 datafields["vx_raw"] = new Variant(targets.twistRaw.linear.x());
194 datafields["vy_raw"] = new Variant(targets.twistRaw.linear.y());
195 datafields["v_linear_raw"] = new Variant(targets.twistRaw.linear.norm());
196 datafields["vyaw_raw"] = new Variant(targets.twistRaw.angular.z());
197
198 datafields["idx"] = new Variant(targets.result.target.idx);
199
200 if(not configBuffer_updateConfigToOnPublish.getUpToDateReadBuffer().targets.trajectory.points().empty())
201 {
202 datafields["dt_front"] = new Variant((armarx::Clock::Now() - configBuffer_updateConfigToOnPublish.getUpToDateReadBuffer().targets.trajectory.points().front().timestamp).toSecondsDouble());
203 }
204
205 datafields["trajectory_points"] =
206 new Variant(configBuffer_updateConfigToOnPublish.getUpToDateReadBuffer()
207 .targets.trajectory.points()
208 .size());
209
210 debugObservers->setDebugChannel(
212 datafields);
213 }
214
215 void
217 {
218 runTask("PlatformTrajectoryControllerAdditionalTask",
219 [&]
220 {
221 CycleUtil c(10);
222 getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
223 ARMARX_IMPORTANT << "Create a new thread alone PlatformTrajectory controller";
224 while (getState() == eManagedIceObjectStarted)
225 {
226 if (isControllerActive() and rtReady.load())
227 {
228 ARMARX_VERBOSE << "additional task";
230 }
231 c.waitForCycleDuration();
232 }
233 });
234
235 ARMARX_INFO << "PlatformTrajectoryVelocityController::onInitNJointController";
236 }
237
238 void
240 {
241 // additionalTask() is not executed. Thus, we can access lastTwist without mutex.
242 filteredTwist.reset();
243
244 robotStateBuffer_rtToAdditionalTask.getWriteBuffer().global_T_robot.matrix() =
245 rtGetRobot()->getGlobalPose();
246 robotStateBuffer_rtToAdditionalTask.commitWrite();
247
248 rtReady.store(true);
249 }
250
251 void
253 {
254 rtReady.store(false);
255 }
256
257 Controller::~Controller() = default;
258
260 Controller::getConfig(const ::Ice::Current&)
261 {
262 ARMARX_ERROR << "NYI";
263 return nullptr;
264 }
265} // namespace armarx::navigation::platform_controller::platform_local_trajectory
constexpr T c
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
Brief description of class ControlTargetHolonomicPlatformVelocity.
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
The Variant class is described here: Variants.
Definition Variant.h:224
::armarx::aron::data::dto::DictPtr getConfig(const ::Ice::Current &=::Ice::emptyCurrent) override
Controller(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void onPublish(const SensorAndControl &sac, const DebugDrawerInterfacePrx &debugDrawer, const DebugObserverInterfacePrx &debugObservers) override
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
std::string getClassName(const Ice::Current &iceCurrent=Ice::emptyCurrent) const override
void rtPreActivateController() override
This function is called before the controller is activated.
Brief description of class targets.
Definition targets.h:39
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::Handle< Dict > DictPtr
const simox::meta::EnumNames< ControllerType > ControllerTypeNames
const NJointControllerRegistration< Controller > Registration(common::ControllerTypeNames.to_name(common::ControllerType::PlatformLocalTrajectory))
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
#define ARMARX_TRACE
Definition trace.h:77