/****************************************************************************
*
- Copyright © 2018 PX4 Development Team. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
-
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- Neither the name PX4 nor the names of its contributors may be
- used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
****************************************************************************/
#include “rotary_wing.h”
int RotaryWing::print_usage(const char *reason)
{
if (reason) {
PX4_WARN("%s\n", reason);
}
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
Description
Section that describes the provided module functionality.
This is a template for a module running as a task in the background with start/stop/status functionality.
Implementation
Section describing the high-level implementation of this module.
Examples
CLI usage example:
$ module start -f -p 42
)DESCR_STR");
PRINT_MODULE_USAGE_NAME("module", "system");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAM_FLAG('f', "Optional example flag", true);
PRINT_MODULE_USAGE_PARAM_INT('p', 0, 0, 1000, "Optional example parameter", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
return 0;
}
int RotaryWing::print_status()
{
PX4_INFO(“Running”);
// TODO: print additional runtime information about the state of the module
return 0;
}
int RotaryWing::custom_command(int argc, char argv[])
{
/
if (!is_running()) {
print_usage(“not running”);
return 1;
}
// additional custom commands can be handled like this:
if (!strcmp(argv[0], "do-something")) {
get_instance()->do_something();
return 0;
}
*/
return print_usage("unknown command");
}
int RotaryWing::task_spawn(int argc, char *argv[])
{
_task_id = px4_task_spawn_cmd(“rotary_wing”,
SCHED_DEFAULT,
SCHED_PRIORITY_ATTITUDE_CONTROL,
1700,
(px4_main_t)&run_trampoline,
(char *const *)argv);
if (_task_id < 0) {
_task_id = -1;
return -errno;
}
return 0;
}
RotaryWing *RotaryWing::instantiate(int argc, char *argv[])
{
int example_param = 0;
bool example_flag = false;
bool error_flag = false;
int myoptind = 1;
int ch;
const char *myoptarg = nullptr;
// parse CLI arguments
while ((ch = px4_getopt(argc, argv, "p:f", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'p':
example_param = (int)strtol(myoptarg, nullptr, 10);
break;
case 'f':
example_flag = true;
break;
case '?':
error_flag = true;
break;
default:
PX4_WARN("unrecognized flag");
error_flag = true;
break;
}
}
if (error_flag) {
return nullptr;
}
RotaryWing *instance = new RotaryWing();
if (instance == nullptr) {
PX4_ERR("alloc failed");
}
return instance;
}
RotaryWing::RotaryWing()
: ModuleParams(nullptr)
{
}
void RotaryWing::parameter_update_poll()
{
bool updated;
/* Check if parameters have changed */
orb_check(_params_sub, &updated);
if (updated) {
struct parameter_update_s param_update;
orb_copy(ORB_ID(parameter_update), _params_sub, ¶m_update);
//updateParams();
//parameters_updated();
}
}
void RotaryWing::sensor_mag_update_poll()
{
bool updated;
orb_check(_sensor_mag_sub, &updated);
if (updated) {
orb_copy(ORB_ID(sensor_mag), _sensor_mag_sub, &_sensor_mag);
}
}
void RotaryWing::rc_channels_update_poll()
{
bool updated;
orb_check(_rc_channels_sub, &updated);
if (updated) {
orb_copy(ORB_ID(rc_channels), _rc_channels_sub, &_rc_channels);
}
}
void RotaryWing::run()
{
_params_sub = orb_subscribe(ORB_ID(parameter_update));
_sensor_mag_sub = orb_subscribe(ORB_ID(sensor_mag));
_rc_channels_sub = orb_subscribe(ORB_ID(rc_channels));
px4_pollfd_struct_t fds={};
fds.events = POLLIN;
while (!should_exit()) {
// wait for up to 100ms for data
int pret = px4_poll(&fds, 1, 100);
if (pret == 0) {
continue;
}
if (pret < 0) {
// this is undesirable but not much we can do
PX4_ERR("poll error %d, %d", pret, errno);
usleep(100000);
continue;
}
if (fds.revents & POLLIN) {
usleep(10000);
sensor_mag_update_poll();
rc_channels_update_poll();
float heading = atanf(_sensor_mag.y/_sensor_mag.x);
if (_sensor_mag.x < 0.0f) {
heading += (float)M_PI;
}
if (heading > (float)M_PI) {
heading = (float)M_PI-heading;
}
PX4_INFO("Magnetometer heading:\t%8.4f, rc0:\t%8.4f, rc1:\t%8.4f, rc2:\t%8.4f, rc3:\t%8.4f",
(double)heading*(double)180.0f/M_PI,
(double)_rc_channels.channels[0],
(double)_rc_channels.channels[1],
(double)_rc_channels.channels[2],
(double)_rc_channels.channels[3]);
_actuators.control[0] = _rc_channels.channels[0]*cosf(heading)+_rc_channels.channels[1]*sinf(heading);
_actuators.control[1] = -_actuators.control[0];
_actuators.control[3] = _rc_channels.channels[2];
if (_actuators_0_pub != nullptr) {
orb_publish(ORB_ID(actuator_controls_0), _actuators_0_pub, &_actuators);
} else {
_actuators_0_pub = orb_advertise(ORB_ID(actuator_controls_0), &_actuators);
}
}
//parameters_update(parameter_update_sub);
}
orb_unsubscribe(_sensor_mag_sub);
orb_unsubscribe(_params_sub);
orb_unsubscribe(_rc_channels_sub);
}
void RotaryWing::parameters_update(int parameter_update_sub, bool force)
{
bool updated;
struct parameter_update_s param_upd;
orb_check(parameter_update_sub, &updated);
if (updated) {
orb_copy(ORB_ID(parameter_update), parameter_update_sub, ¶m_upd);
}
if (force || updated) {
updateParams();
}
}
int rotary_wing_main(int argc, char *argv[])
{
return RotaryWing::main(argc, argv);
}